1. 我们会用到什么模型呢?* H6 n+ f/ U! B! N8 F% H5 w! V9 p
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。9 Z/ c+ @3 E! i3 W1 j
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进& j5 x: t$ c3 _
//| https://www.mql5.com |
" t: E5 l" F1 V3 Y//+------------------------------------------------------------------+ E7 r \9 W2 Z) |6 R- }1 t
//--- price movement prediction
8 p. s( V4 r: U0 }0 w#define PRICE_UP 0 W+ Q M6 a/ K8 C7 S5 R
#define PRICE_SAME 1& M: s" j: q& Y) ~
#define PRICE_DOWN 2
% N8 L' R: P3 y$ `3 M) t//+------------------------------------------------------------------+
, v) p7 b) k4 _//| Base class for models based on trained symbol and period |
+ ^$ [: P( r1 \. M1 [) G6 T//+------------------------------------------------------------------+: P# s/ D+ S8 `5 G" K1 ^" ^( i- ?
class CModelSymbolPeriod
+ m( n" f8 X8 d. }{. D* q$ P1 w9 f. p' W3 q; g0 x
protected:
0 v2 C& X, q1 ?) Xlong m_handle; // created model session handle/ M: [: \# p( z4 d$ f: Q
string m_symbol; // symbol of trained data1 }( }- W3 s0 z
ENUM_TIMEFRAMES m_period; // timeframe of trained data
0 a- z* s1 s0 G" ndatetime m_next_bar; // time of next bar (we work at bar begin only)
( @* J K1 q. Q! D1 \double m_class_delta; // delta to recognize "price the same" in regression models* \+ |. ?2 K V" t7 M( D
public:2 Z$ S4 k; _' x& L2 {7 R$ ^5 H
//+------------------------------------------------------------------+9 h4 ?- h! I1 k+ s
//| Constructor |% O5 [0 q: k! E, E( o
//+------------------------------------------------------------------+
/ E! o! y) p0 @( U1 fCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
% ~3 A' D+ `4 a{
, L5 @. E2 Y3 ], K. |2 Om_handle=INVALID_HANDLE;
! M0 S! u' P& D3 mm_symbol=symbol;' f5 s$ D* O' y8 _
m_period=period;
0 m h7 m4 L7 @. |' F! Nm_next_bar=0;
# v9 Q& ?- P [# r) p) ]m_class_delta=class_delta; ]) x8 Z1 z# j- m$ ?
}- a4 r# @. A# y4 s' P# U
//+------------------------------------------------------------------+9 e# O# U8 }3 K; F
//| Destructor |; C- ?0 E; u3 G* F x* y
//| Check for initialization, create model |3 a3 r- L- F7 u
//+------------------------------------------------------------------+/ |: h* |7 D$ ~ B- Y, [8 g4 b
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])4 p* O8 G" ]; v4 `7 Y' c5 V
{
& \' B0 h& l/ u; f//--- check symbol, period
, G& D' f2 i" M" [9 i! X1 x# Vif(symbol!=m_symbol || period!=m_period)
: @: q" z+ _8 M4 u7 H! a{, i$ U' H8 y! J
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
3 W7 ~7 Q1 J+ u$ d- W( ?( c+ Z, preturn(false);
2 G2 Z% p, x; @# h) _& I$ z) P}! L& E7 H, \! v- I |2 U2 K3 W) T
//--- create a model from static buffer
+ U( _) K2 N M; ], y2 Z/ X" S gm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);1 L/ D: z0 t. Z" F; v! ^& ?
if(m_handle==INVALID_HANDLE)
* ] @4 w# @5 l8 E' w' I: @{0 ^2 |( ?7 [+ d- Y
Print("OnnxCreateFromBuffer error ",GetLastError());
* x& K: {6 ], V: c4 lreturn(false);6 A' M" E8 X9 n/ j( p" }0 _ h
}
* Z( W2 J, e0 z, T% v//--- ok2 r- O: u1 ?8 u4 T
return(true);7 m* w" _+ V+ l& ~. v5 V7 p& m$ `5 m
}
) Y3 N# ^6 y' M" g//+------------------------------------------------------------------+6 @. x) |" d. |# Q, U7 z4 D+ k
m_next_bar=TimeCurrent();3 G( ?+ _/ w/ j- J) Q( R
m_next_bar-=m_next_bar%PeriodSeconds(m_period);6 f1 m5 ~% e0 z% A0 `- k
m_next_bar+=PeriodSeconds(m_period);
W) P, X% p# ?1 L0 H//--- work on new day bar
: ?4 J) j' q' j7 g* y( Mreturn(true);9 f# D. C. k3 U# O; a; i9 T; g% a
}
+ m# R" y# u/ F1 p3 t7 {; k1 }//+------------------------------------------------------------------+
4 c8 T. N& q) p1 O3 k9 V//| virtual stub for PredictPrice (regression model) |- @5 c& S+ S5 S8 H% O4 d( B% T
//+------------------------------------------------------------------+
1 T/ n/ j+ s* K: m. ?0 lvirtual double PredictPrice(void)1 J" @/ E( E3 ~! |
{
2 Y" t; T6 i2 n9 M( rreturn(DBL_MAX);
+ v2 `+ d0 g9 \( z2 r8 d}
; O& t7 v& l! P5 q; f" z8 T5 Y//+------------------------------------------------------------------+) z2 e# O* }+ H7 y+ P# X
//| Predict class (regression -> classification) |5 b5 g ]* |: k4 i: L [
//+------------------------------------------------------------------+
; l/ Z2 a `- {. J+ B- g8 Avirtual int PredictClass(void)
9 }0 G7 [9 }: R% Z) v{& l% {9 Z$ `7 {# N% B. d1 n' u* `
double predicted_price=PredictPrice();
& v+ q, `8 U4 v! Xif(predicted_price==DBL_MAX)
2 R) T2 e) B& w! h6 [$ d) Mreturn(-1);
) b ]+ M1 h) ~int predicted_class=-1;6 i6 f5 X3 E K7 S5 Q3 |
double last_close=iClose(m_symbol,m_period,1);
. u0 v! s) {! b/ h" o//--- classify predicted price movement
/ d" K$ v) S Y: n5 k" J8 hdouble delta=last_close-predicted_price;" T; v) A G; q3 k0 V% b }# Z
if(fabs(delta)<=m_class_delta) P- n' ~. V* x6 k
predicted_class=PRICE_SAME;
+ r' v& O9 h7 yelse1 a5 P; b4 h' ]
private:, k6 Y. m' h$ i1 v
int m_sample_size;
2 R) ^+ b" p% {//+------------------------------------------------------------------+7 ]- t$ _# P1 G8 [8 q4 [
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)$ u0 b8 d' h5 D- p4 q/ @
{3 u y3 M6 v; `; q) N+ v. ^
//--- check symbol, period, create model$ f( O3 L; ^, M4 x$ N% a( K
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))9 x7 ~; V+ `+ Q* G6 c ^1 d$ R8 j
{7 M1 r& Z, n% X. q8 c5 A' k
Print("model_eurusd_D1_10_class : initialization error"); z9 V6 S. U \2 I- d
return(false);# x5 R! T) V- p; d
}+ f3 Y( Z0 A) H+ H6 }' T% B
//--- since not all sizes defined in the input tensor we must set them explicitly
( ^. k2 Z# O2 y2 S# Q+ |//--- first index - batch size, second index - series size, third index - number of series (OHLC)
9 G, P) }" u1 G r" wconst long input_shape[] = {1,m_sample_size,4};' R% [7 n! E" f/ I5 |" I
if(!OnnxSetInputShape(m_handle,0,input_shape)). E; |: d- r4 D
{2 d) x O* i0 ~4 T1 e- O- A
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());6 J- k' {, L1 n# M5 }8 U9 M
return(false);6 l# u" Q* p3 t0 w" [3 V
}2 N A0 ?3 u0 O2 j& ?6 x
//--- since not all sizes defined in the output tensor we must set them explicitly; l3 e" g5 K2 i5 S
//--- first index - batch size, must match the batch size of the input tensor) {( }9 H0 _$ h. \0 V/ {5 |
//--- second index - number of classes (up, same or down)
9 R7 H# N. L$ d- L5 `const long output_shape[] = {1,3};& o- u# m( p& H( B( O2 _8 a
if(!OnnxSetOutputShape(m_handle,0,output_shape))" j8 x3 q+ ]* V4 l
{9 X; G' B, o! h7 a
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());' V0 }; n9 A- H/ s
return(false);! O, V7 L0 k$ D+ d$ U
}+ ]6 q/ }3 {; C4 s
//--- ok
) u K" ~ Y- @7 x# @9 c1 E) K4 P9 _return(true);, P! C. J) Q& B& k
}- a2 F# ~& q. ]8 {! C6 |
//+------------------------------------------------------------------+
) |3 \9 i: y3 {" x- h//| Predict class |' S7 R& \$ u) M
//+------------------------------------------------------------------+9 W' V9 l1 |0 ?) W: C7 p
virtual int PredictClass(void)
; _+ B9 y x0 m% _1 b{ |