1. 我们会用到什么模型呢?
4 [' Z6 ~$ Y3 U3 I, Y ^3 J, ]在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。+ f: u' I1 ^- l) K6 M
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进' T( a4 t$ r' m+ L, L
//| https://www.mql5.com |+ I! b( I7 o; R$ {9 g) s" A" W
//+------------------------------------------------------------------+
2 l0 p3 P$ ^( ?$ _: M//--- price movement prediction; g; {+ G, _# P: l
#define PRICE_UP 0
- u7 O* R9 `: |2 u#define PRICE_SAME 1
3 o/ d3 Q1 G/ l: J0 G#define PRICE_DOWN 2! C: Z D, M. ]# o; n
//+------------------------------------------------------------------+5 ~9 a( }% q4 f+ O: c
//| Base class for models based on trained symbol and period |
9 w% I/ t5 z4 N0 X% z$ q//+------------------------------------------------------------------+
1 _7 C: \) F+ N8 j( Wclass CModelSymbolPeriod
( i( d8 r: j6 b" I2 o6 f* h3 a{
7 v' Q, r. q* Eprotected:
* y+ I* }5 E* ?0 {& G' h- Elong m_handle; // created model session handle
6 K! {1 X& @. q( F1 astring m_symbol; // symbol of trained data
" u1 V) N3 {! C! z2 [ENUM_TIMEFRAMES m_period; // timeframe of trained data
3 j ^ h3 ^$ Z/ Ldatetime m_next_bar; // time of next bar (we work at bar begin only)
5 @0 X( E# F5 `1 a( k. x+ {8 P* `double m_class_delta; // delta to recognize "price the same" in regression models+ w E, v3 J6 N% w9 F* J$ T
public:
" g& m" \' M& g" Y+ t# a3 G//+------------------------------------------------------------------+
$ o+ C# _5 K+ O" L! A( h s! V//| Constructor |* a7 {6 j( v9 R/ \ y
//+------------------------------------------------------------------+
8 Z: _* B; ]3 \' V& q7 W; S% ~CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
: c9 o4 {, | s{& a/ m/ |. b( [" ]2 ?, }+ z1 E
m_handle=INVALID_HANDLE;* @/ @2 ?* W1 C8 h4 p9 k
m_symbol=symbol;
7 x% U3 \8 L; K/ @, [m_period=period;
* x, R3 H- l* Jm_next_bar=0;; H* ^) A1 `8 `- }4 I
m_class_delta=class_delta;- b( z* y4 ~% m5 h2 u
}1 q& L k2 a- V. d
//+------------------------------------------------------------------+6 k6 x. R0 M% \6 ~% C" r
//| Destructor |
- |$ B- _9 H& ?; J1 t, B# K l' p//| Check for initialization, create model |) I( X7 g1 ^! ?8 O* K3 {$ K
//+------------------------------------------------------------------+
7 E8 [0 u2 T) C" y" vbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[]). ^; C' V; j, Q2 p5 P/ u. \
{4 g, i: b! I$ R
//--- check symbol, period1 d' }5 v" F5 t" C4 _) b% V7 @6 X. o2 Z
if(symbol!=m_symbol || period!=m_period)8 G% W; L# I% O3 O! f+ U: Z; F
{( r5 _; y: S L! ?" S
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));! {! c0 l1 d: _4 h
return(false);( r# ^5 W/ _0 f1 u) R* Q) d
}+ p& A1 f% q, v
//--- create a model from static buffer5 f( |, q* _2 l# T6 z# R5 x) q6 p
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
2 B( Q0 p& O; Hif(m_handle==INVALID_HANDLE)( g v4 `& A/ t6 O
{
. n0 W+ ^/ T( D, u$ ` [* m. i2 uPrint("OnnxCreateFromBuffer error ",GetLastError());
3 E0 U" l% a, W, p; ^- d! n, Wreturn(false);
0 J/ y ]7 E- M8 d, h9 ]- {}
( s% T+ u9 b1 I- v//--- ok) x, A4 V7 X% ^6 V% J
return(true);
4 P4 u# ]- @7 F6 p8 c% p}0 A) S R) S5 q3 @' z
//+------------------------------------------------------------------+
8 I8 M4 d* v. E) l- O3 g& Im_next_bar=TimeCurrent();
/ `* g3 {+ ]# }8 i$ X% u- ]7 s! Km_next_bar-=m_next_bar%PeriodSeconds(m_period);+ u5 J/ q3 ^4 K5 s& M. f4 _
m_next_bar+=PeriodSeconds(m_period);
8 S5 _# X+ E6 }- \- a//--- work on new day bar
; J0 x' @) t+ {4 N B- Treturn(true);7 h6 ?3 i8 H/ ^" D, X8 `
}* A1 Z8 O0 S& K% c9 u1 |0 t
//+------------------------------------------------------------------+
2 A$ G& U7 u2 v//| virtual stub for PredictPrice (regression model) |% z$ w/ Y: E: `4 h2 ` Y/ S8 K6 [1 k
//+------------------------------------------------------------------+
7 {( i4 U9 I# S" B v; l& Uvirtual double PredictPrice(void)
5 S, w5 C# w' w( N1 ^$ u0 U{
+ b6 x) P0 C, ^+ ?! b% Mreturn(DBL_MAX);& I) t5 J1 V2 q% Y! B
}
$ ]" F; H) x+ S$ } R& s0 A//+------------------------------------------------------------------+8 P3 o* q6 o7 P# v, K; k" `
//| Predict class (regression -> classification) |4 A1 k5 |! Z4 [
//+------------------------------------------------------------------+
* U6 c8 u' v5 N" l4 S2 M; ^, j- Yvirtual int PredictClass(void)
$ U. v# Q* B' m( h" V{
6 I1 i9 N. o1 j4 v9 {# i. P& s" ]double predicted_price=PredictPrice();
5 W3 a0 W2 i, _if(predicted_price==DBL_MAX)
A% i9 J; S1 c; g7 K+ R) L8 _/ qreturn(-1);
3 @* P+ z: O& [8 D$ s; V$ Hint predicted_class=-1;
: K" c! n4 ?9 u+ R) H0 y Pdouble last_close=iClose(m_symbol,m_period,1);' Z" q$ k& A7 | D; j G
//--- classify predicted price movement% m# l; o5 s8 B: G. z
double delta=last_close-predicted_price;2 D- K- N/ N% D' m% ^
if(fabs(delta)<=m_class_delta)
: m$ B% {' K; v# ypredicted_class=PRICE_SAME;
2 r2 o3 r+ b9 F4 H: H) zelse5 \3 o8 C9 C4 R3 i# F8 `( r5 J1 l
private:
* X4 Z/ V$ C+ W; [; ?int m_sample_size;% t) N$ Q- q& w( T! Y( B' u
//+------------------------------------------------------------------+
& `* n8 }/ A$ f* {virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period): P7 O3 n2 D; S' D9 A& P& i: E( \
{
7 ]/ Z' }- J' v# c) b//--- check symbol, period, create model
8 T' Q ~$ H: zif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
- n* a4 }- Y" K- C1 V# w{
, \. w% u. k2 ?5 O$ ?# R3 X9 FPrint("model_eurusd_D1_10_class : initialization error");5 F( n _) M. e/ W$ r* L0 t" ~
return(false);
: U- H, k# Q- N. C: ~2 V}
7 S0 \% `2 W$ b; l9 L, O//--- since not all sizes defined in the input tensor we must set them explicitly
" d4 m6 [4 q2 x//--- first index - batch size, second index - series size, third index - number of series (OHLC)
) k. o- `# i: j4 B2 V9 tconst long input_shape[] = {1,m_sample_size,4};+ c) ^7 S; L# f$ s# q5 @& p
if(!OnnxSetInputShape(m_handle,0,input_shape))( O- R$ e& j$ t' K# ]4 d
{
; B2 f- i) s2 L0 T4 }8 L5 b5 wPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
. ~: S# ~& ^! r9 r3 M E) rreturn(false);- \+ D+ x4 w$ R# Y+ z
}
4 u% S3 W, P' m. e5 f' {//--- since not all sizes defined in the output tensor we must set them explicitly
$ d$ y* ]/ p" ?6 c5 _9 ?//--- first index - batch size, must match the batch size of the input tensor, Q& }, o* s* t' J! _8 V
//--- second index - number of classes (up, same or down)5 g) d$ ]$ v& }5 D" D
const long output_shape[] = {1,3};
! }) ]" t { u2 Q9 T& Bif(!OnnxSetOutputShape(m_handle,0,output_shape))2 D& R' O, r2 ^/ P2 H6 R) A
{
0 m7 A+ U* p6 H$ ]; u& u9 wPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());- I- K* e6 @% C. Y9 H
return(false);8 W. w( |) C; O! f% e
}
* [* z+ t3 x8 V//--- ok/ z1 _* Q. U |1 B( W* R/ G9 _" D
return(true);5 J9 _: {+ I3 [ W- ^" u
}
4 Z3 K- y& M& h0 x$ j' i; n% c- c//+------------------------------------------------------------------+
' ], E. Z, B/ a9 t6 i//| Predict class |( R7 g! @7 H1 T, y7 e1 T' X% H: C
//+------------------------------------------------------------------+
7 q5 b& Y4 r/ O: B3 e7 S/ hvirtual int PredictClass(void)
6 @* K! i. E" E9 U1 v, @{ |