1. 我们会用到什么模型呢?
?8 L+ g2 P1 [在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
( f. i" ^; a% a0 A5 G- \" v我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
* c/ S1 ^1 r* V( L( A# X//| https://www.mql5.com |# ?0 V% `; p7 Z4 E
//+------------------------------------------------------------------+
1 G4 W' y9 i+ i. J5 e6 _( _//--- price movement prediction9 T3 a! Z( T' i. i3 }
#define PRICE_UP 0" }: M3 q# I! r2 u: Z
#define PRICE_SAME 1
8 t! F4 Y, |' ^' K' S4 _#define PRICE_DOWN 29 @ B) L# V3 n* q# s2 h
//+------------------------------------------------------------------+3 P X/ H. o% V6 y" e$ ] @' w
//| Base class for models based on trained symbol and period |
: W4 v, \4 T5 }" x5 U- K//+------------------------------------------------------------------+0 G: d/ x5 c) N, _7 \
class CModelSymbolPeriod# v) Q8 z( h) X1 Z+ k
{
. F: y/ Z2 j4 @protected:
# y3 s1 O7 L+ h2 G4 L2 [long m_handle; // created model session handle
" s5 @3 E9 @' C' m4 Ystring m_symbol; // symbol of trained data
" N- p( _3 E9 u8 UENUM_TIMEFRAMES m_period; // timeframe of trained data
" f& D2 F; F8 H; s$ W3 Z; C1 v$ Q9 adatetime m_next_bar; // time of next bar (we work at bar begin only)) B3 a1 E; G1 z+ c; p0 u
double m_class_delta; // delta to recognize "price the same" in regression models3 j7 t: \; S4 R& ]& b# w- q
public:# P" H% U2 Z5 ~. [
//+------------------------------------------------------------------+* T% v' n) r v* @1 W/ ^
//| Constructor |5 | f+ ]/ }6 x: G' Z9 z' f
//+------------------------------------------------------------------+
/ W$ g! k. \: uCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001) E/ `, ?) p, R* ?4 d
{; G. E1 S6 |8 o6 q3 }" M# X P
m_handle=INVALID_HANDLE;& H" T. T! M& q: S
m_symbol=symbol;, F. n4 `6 I) u9 B: z( Q2 z. Z
m_period=period;7 y: j% I! x! S
m_next_bar=0;
/ u# _3 ?# b( _1 Vm_class_delta=class_delta;! \3 p: R! \$ s9 n# w
}% [" }1 E" i# z
//+------------------------------------------------------------------+
# l+ x9 `! U6 ]( N r1 E//| Destructor |3 }7 f5 L' R3 s: Y" d) h& v/ |
//| Check for initialization, create model |$ i3 e! j6 Z- H+ Q+ k5 ~
//+------------------------------------------------------------------+) x/ M6 M2 n: |
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
6 T) g- S$ V1 T" u3 h{
Y: Y3 Y# l5 {3 z5 d7 Z0 R: D//--- check symbol, period
; p2 C1 z& {: k6 |if(symbol!=m_symbol || period!=m_period)
9 l+ p# o2 V3 K/ Z3 w{+ G2 H: F% x* O4 A' e) @
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));3 F( V. {5 o5 e" B9 E) S+ B: S/ K
return(false);4 V+ t# c4 e, X' U
}- [) g4 p) d B- B5 ~
//--- create a model from static buffer
2 I- b/ F% s9 v( ?. ~+ P" n; Um_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
& R# h7 \! F) Nif(m_handle==INVALID_HANDLE)
! L/ h% }/ a9 Z `/ o6 i/ o{* l/ C, l+ ]: O* p
Print("OnnxCreateFromBuffer error ",GetLastError());3 _1 _( M( P- [' h; R
return(false);
* t0 w1 _6 b0 ~( g# A}
) r3 d! G7 Q5 t! h& H5 K; o# }//--- ok
* m% ?5 C$ R& Q6 J+ J# j1 {' G3 _# Rreturn(true);& A! O1 h# t2 |- @& V$ C
}
4 T$ Z, V! q- s; }# _* s7 V [//+------------------------------------------------------------------+
# f: S9 _, ]4 C, {6 i6 S& \m_next_bar=TimeCurrent();+ l* H9 ^/ g- _! Q6 J, L' w
m_next_bar-=m_next_bar%PeriodSeconds(m_period);/ u% i1 U4 p" J8 v' Y& w1 m; h# C
m_next_bar+=PeriodSeconds(m_period);3 d# h3 T; m, D9 b; ]3 q
//--- work on new day bar
2 y% @) W) z. r2 b6 J5 t8 Ereturn(true);; E! }; V) m. d% {( w% i) b
}' y5 I# `* q( ^3 i9 \7 B1 n( R* R: h
//+------------------------------------------------------------------+5 B. t5 p$ o3 ~; z; h" T
//| virtual stub for PredictPrice (regression model) |
# C* E; |) @, C% H9 `1 L: `+ K. x//+------------------------------------------------------------------+# S ]/ y$ N: d) g- j6 [
virtual double PredictPrice(void)
/ |/ s5 h( g% S" S6 q3 _{3 g L: q; l8 z. N9 Z- }' f# _, n7 V
return(DBL_MAX);
% G6 l- g# b2 p2 k}
3 p% j2 A& y' `& X$ o4 D//+------------------------------------------------------------------+& t" T. ~& Q* ]: m, r: J
//| Predict class (regression -> classification) |" _1 i: s; e% E
//+------------------------------------------------------------------+
1 Y6 J# ?9 s" gvirtual int PredictClass(void)
4 T4 Y5 @. p$ D) ~{4 `9 M# ^# [' Z- p, C4 ?" G: F& K
double predicted_price=PredictPrice();5 }/ X7 c& b2 a# q1 c3 r9 }- r+ h2 t
if(predicted_price==DBL_MAX) J0 p7 E) d1 e' S9 l
return(-1);
" j1 R% i3 f Vint predicted_class=-1;0 K! _8 ?* V& |$ \$ u0 k
double last_close=iClose(m_symbol,m_period,1);
( Q( h4 X2 D0 x% z; A//--- classify predicted price movement
, Q$ o8 [( A adouble delta=last_close-predicted_price;
) D- W$ P5 _, q, s3 B& `& n$ ^if(fabs(delta)<=m_class_delta)
- p% j# _' P/ U$ G* y, spredicted_class=PRICE_SAME;
2 x* l7 n; i+ R' t$ qelse$ ^/ G6 G3 O0 A
private:2 [1 ?# R% t# y" j; l
int m_sample_size;$ H/ S% A: [8 }7 `0 n2 F# a1 T% f
//+------------------------------------------------------------------+
; v5 G' u+ e8 ]# Kvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
4 V% ]8 V( I2 F{+ O4 h) H. @: X8 U2 ]1 o l
//--- check symbol, period, create model
/ p, O- f. Q' R$ o0 b \if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
! ]3 E; t4 h! [- g{
5 W1 `- | W1 a4 w) wPrint("model_eurusd_D1_10_class : initialization error");
: n0 T% x9 b o: K1 r$ rreturn(false);
: N1 |0 V$ z' }% x/ e9 p0 n}
! ?' u" U5 X6 X//--- since not all sizes defined in the input tensor we must set them explicitly/ ~) Q! n% ]/ H7 ~7 _
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
# ?! \1 H- g8 Z1 T& uconst long input_shape[] = {1,m_sample_size,4};
4 a+ v; H1 n& d: V$ E; Kif(!OnnxSetInputShape(m_handle,0,input_shape))! H( q3 F! {5 \ h/ ^# P
{! u4 j/ }& ^% U5 T
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
( l6 i3 a% X( z8 q: P6 @/ xreturn(false);. q8 _1 z6 j2 l: K% k4 q, S% @1 Q
}
& z$ ] o) N% _( W//--- since not all sizes defined in the output tensor we must set them explicitly
. m b7 h$ d9 I0 c//--- first index - batch size, must match the batch size of the input tensor
' O/ ?8 a( e! m, d3 V E" t//--- second index - number of classes (up, same or down). T$ h" u6 Q# u3 H: |3 r
const long output_shape[] = {1,3};8 l5 R* N& z1 H: y
if(!OnnxSetOutputShape(m_handle,0,output_shape))( n. k* n# b/ j( L( e" ]# z
{+ Y. }5 _9 ~- E' M7 [
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());# S0 [8 A: O5 F3 B' l. i" A
return(false);
+ o s8 l y" [- c k& z% v& x8 ?& `}
+ l k$ l1 Q! A0 w0 ]8 w4 t//--- ok
. \3 W0 h& J: p+ ^( Y1 V2 \: E9 ~return(true);3 @: A( E0 x1 b/ c2 N0 K
}
: E& \' f* r7 G) z/ p: p$ L1 Q ?- P//+------------------------------------------------------------------+
& V; r( `' h0 N3 g, v1 H; Z//| Predict class |0 d/ N- M6 X( ?0 Z: i
//+------------------------------------------------------------------+
# n$ Y; a5 \; c; n$ Qvirtual int PredictClass(void)
7 d9 R1 A! t0 i1 H& m' \{ |