1. 我们会用到什么模型呢?
, H6 p6 h% S3 W m! P在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
' U! `) \! `! F5 K) H1 {9 @ S我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进5 K( S! C6 w5 e: Q7 x" x7 v) J
//| https://www.mql5.com |: U8 {8 p0 V) ~0 } A6 k7 ~! X6 c& O
//+------------------------------------------------------------------+. W: z" ~8 D1 k' ~4 y/ W2 s4 o
//--- price movement prediction0 o8 d: f0 {6 @: {$ Y! N2 k: d
#define PRICE_UP 0: O# ]2 q g" w+ L8 p% } `6 V
#define PRICE_SAME 1" U5 v, a) ~8 q2 G
#define PRICE_DOWN 2
% M5 ^0 A7 j7 r' O//+------------------------------------------------------------------+
7 s% M- p2 p E& f* |# i" E3 P, o/ z//| Base class for models based on trained symbol and period |& C6 Z, N r, O: p3 ~. E2 {
//+------------------------------------------------------------------+: h' w3 h! M! A
class CModelSymbolPeriod% ]0 k' S; x2 h! _
{
' y. U3 o8 Y0 z8 I' ^protected:* ]# M$ x" c1 d1 T- o
long m_handle; // created model session handle/ P# z6 }' H5 z
string m_symbol; // symbol of trained data* Z- x* f1 O1 g# |, r h
ENUM_TIMEFRAMES m_period; // timeframe of trained data) e4 i1 `. u/ T) z/ n
datetime m_next_bar; // time of next bar (we work at bar begin only): m; i5 o5 q2 b7 ^
double m_class_delta; // delta to recognize "price the same" in regression models% v( r9 \1 l! e% x
public:
5 D: I* i4 C- f. { F& h$ h, j5 }//+------------------------------------------------------------------+
2 \0 ^4 S3 i5 Z2 v1 ^+ i//| Constructor |
- g9 O' C$ H8 q/ o7 b! u Z, [6 R//+------------------------------------------------------------------+
4 O/ D6 \' i' |8 B( lCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)$ _0 g. C2 j7 ]8 n% [% y
{
. W- Y4 ~/ m3 l5 G3 z" f: Qm_handle=INVALID_HANDLE;
r+ |# i6 H; F. t9 f4 c% _' A0 Lm_symbol=symbol;
* q9 ?6 x* [4 o O" @m_period=period;
7 V: K5 ~, H7 Q9 U; P, E" lm_next_bar=0;& D. l9 C- n H. P! P; u
m_class_delta=class_delta;3 p& ?! Z, ^" s# \
}- b) E3 t! E% V+ X% x% O4 `: @
//+------------------------------------------------------------------+
& q4 V6 Z- U# g) d//| Destructor |# u0 T" w2 ?% A) O* C
//| Check for initialization, create model |1 q% N( p2 N% o* X
//+------------------------------------------------------------------+1 \0 T4 P1 Z; f
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
$ P3 @3 z8 J6 h7 P7 T% a- I{
P# i, N3 V- g8 \, I. ?* U//--- check symbol, period
4 n' ]1 ]- b' T. V9 ]if(symbol!=m_symbol || period!=m_period)
' H& W! y4 t6 @7 ~% E{6 T* Q& Z* m7 C9 J9 o% {9 f. _! a
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
9 w& x7 `$ S4 b- jreturn(false);
. {0 P; k3 U7 V3 w4 v}
$ A1 O5 l3 q# n& `" V: Y& |$ A//--- create a model from static buffer
7 d1 N6 a( M4 x2 c9 Gm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
! [ R# t/ Q& C7 k- |5 z4 sif(m_handle==INVALID_HANDLE)
2 s7 O6 e1 Q4 S{. }8 c, N* D, C* d
Print("OnnxCreateFromBuffer error ",GetLastError());6 c& O6 ?2 p% {6 Z) i
return(false);
6 @* O0 P7 m1 r}- P6 U5 I" N# D5 a
//--- ok" D" a8 h$ N, l- i$ \
return(true);
: ^( h! a; V! Q$ x9 P% K) F}7 g& U( N& Z5 K/ E& |/ p
//+------------------------------------------------------------------+
! [" u! i8 j) B% Y* j+ b; {! om_next_bar=TimeCurrent();
- Z1 z7 {0 m! z$ {m_next_bar-=m_next_bar%PeriodSeconds(m_period);$ D( G9 w' w& j+ `. D. m2 _, J
m_next_bar+=PeriodSeconds(m_period);
' b5 M0 x3 F: _; H1 z//--- work on new day bar1 [6 s8 @4 R$ I! R9 |9 ^
return(true);: c& m4 F( ?4 B4 ~* i U7 h' ]
}
$ Q. W) b& O) |! E& f//+------------------------------------------------------------------+
" l0 s8 v9 w. h5 A+ @//| virtual stub for PredictPrice (regression model) |) b$ {+ t2 H- Z1 G6 d7 ?$ A: E* _8 q
//+------------------------------------------------------------------+/ [/ U9 v1 r2 F8 V
virtual double PredictPrice(void)) Z: W# W' G9 D* h* G" E* r
{: V0 y2 `8 n' L& A g
return(DBL_MAX);
9 T4 |# h* X7 w: r0 C7 `' S}5 B9 ?8 z# e# H/ | h
//+------------------------------------------------------------------+
8 ^* K- p k3 v//| Predict class (regression -> classification) |8 A9 U. ~. t; H! Z3 i b
//+------------------------------------------------------------------+
/ E2 C$ N- [) \) k8 f8 mvirtual int PredictClass(void)$ w* o" N" R! F
{
3 Q' ^9 ~; f8 }5 i; G2 [' }double predicted_price=PredictPrice();, L! m* [# G) r( `! D- K6 B( Q
if(predicted_price==DBL_MAX)
, [2 S1 J! ~' a+ H* F1 }# creturn(-1);
+ a) J2 f% u2 p8 N& [* o. m2 b. Aint predicted_class=-1;
8 p1 S/ P( `0 w% O& A$ `double last_close=iClose(m_symbol,m_period,1);
6 t* o+ X, w3 x, b//--- classify predicted price movement
. \7 w, c! m4 |4 m" w6 wdouble delta=last_close-predicted_price;
. r4 h, E0 y7 w3 A2 }9 f) S4 @9 \if(fabs(delta)<=m_class_delta)
^$ H& [4 ^& h5 O( q7 qpredicted_class=PRICE_SAME;. z' c, [$ `- Y: z; Z1 y
else
c7 p; M4 o" L0 J$ x+ oprivate:
, T, e( {" Y5 x8 j4 N% t( Bint m_sample_size;
8 p# R. Q7 o# @/ x* J) i" k2 ^/ X$ J//+------------------------------------------------------------------+# D. {" C- \( X! t7 u+ ^
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
0 e! I" |/ v9 ?{
" W# T% K% I" p" O% m D3 c//--- check symbol, period, create model! E/ ]( c! V/ ~& c" h* A/ |
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
2 [0 [" o! |) i, _; |{
, u6 h' S2 J* F- c& E8 p! HPrint("model_eurusd_D1_10_class : initialization error");
4 T H( }' d* T9 Z1 ureturn(false);4 H% Q. [' A4 w7 b) ]3 f8 i
}+ c) n& @, a# p! s( T& ]4 A4 J( l
//--- since not all sizes defined in the input tensor we must set them explicitly
( Y% f# T7 d% \( u$ I& O//--- first index - batch size, second index - series size, third index - number of series (OHLC)2 R+ c0 M* a$ w" X( v L
const long input_shape[] = {1,m_sample_size,4};- x" G3 } ?6 g
if(!OnnxSetInputShape(m_handle,0,input_shape))
+ E, o$ r; a3 B8 D3 }{
1 L8 T5 m9 v- K( x. |Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());" r- j& S# p: e% g% n& x3 h3 p
return(false);
* o( e& g& ~7 B" K}" {: C. O0 `( @7 G9 w, i
//--- since not all sizes defined in the output tensor we must set them explicitly
5 z2 ]5 u U2 L1 g( s1 X! I( n, d3 ^//--- first index - batch size, must match the batch size of the input tensor
0 L+ @/ b3 T. W" q//--- second index - number of classes (up, same or down)- s: C( k! ]' l) B6 t3 d
const long output_shape[] = {1,3};+ D. z5 J8 H% {: [9 T- h B& c0 G a
if(!OnnxSetOutputShape(m_handle,0,output_shape))2 }$ B) k% e' _9 i! Z+ D A
{
' p$ f' [4 s+ o0 B; PPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
/ h0 g; {0 q: h/ a6 m. X& Ureturn(false);
0 m9 n. B) s# T6 G% V7 Z+ B% h}
" v" a9 n7 s, H+ O//--- ok9 V+ D( a1 t- h
return(true);
, L5 ]+ v$ {* o" q+ T/ ~# K/ i}9 O S0 |' _' k4 v: U$ ?0 f2 ]
//+------------------------------------------------------------------+
$ S7 p; X: n- J! |0 E: J//| Predict class |
, K" k( ^$ s! O% |8 s//+------------------------------------------------------------------+
0 r6 Q3 S( X& e8 Nvirtual int PredictClass(void)
' O6 q$ H b! w. C9 A. v{ |