1. 我们会用到什么模型呢?
& i O2 i1 Y' P( [在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
' I1 e7 g U% k; l" T我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进) b M; L$ T4 ^8 s
//| https://www.mql5.com |
' H9 J% ?$ K7 z//+------------------------------------------------------------------+
4 D/ ~$ T! [' ^4 ^9 e" z1 J8 W* ?( j//--- price movement prediction
! B0 @7 j# i- n8 V3 n#define PRICE_UP 05 T7 r" j; y+ k+ \
#define PRICE_SAME 1
1 g* d8 B% n$ U* O, @#define PRICE_DOWN 2
# y' Z# M3 O7 f" J# ?! ]; T//+------------------------------------------------------------------+
8 N& u% Q% \$ m8 F2 l5 n3 s//| Base class for models based on trained symbol and period |
7 |( T+ l* w4 d1 O# w6 \/ ~( F//+------------------------------------------------------------------+
0 F/ o G; W' [class CModelSymbolPeriod
& t0 F, v$ Y2 }& z{
4 n& I9 @( L, ^( i8 W% bprotected:
1 e3 ~5 ~( a$ }# ? ^$ |. _long m_handle; // created model session handle1 Q! A3 u- A. Y3 E! T& Y3 ~
string m_symbol; // symbol of trained data
, ~* g7 @) p9 V* {) N, i& D0 _ENUM_TIMEFRAMES m_period; // timeframe of trained data! d6 b# c: B6 ~+ M
datetime m_next_bar; // time of next bar (we work at bar begin only)
* Z4 \* c4 ?. i9 w5 N" k: N5 M- R9 Pdouble m_class_delta; // delta to recognize "price the same" in regression models
/ L0 H7 i2 |; t" q. n, dpublic:4 Z. O4 g4 S8 j, Z$ r: f
//+------------------------------------------------------------------+
' w3 X' {# [5 O//| Constructor |
6 f7 B2 {& j8 Z" Z9 x* @//+------------------------------------------------------------------+/ }/ {8 [6 }! e
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)6 O9 |: S" B3 X8 e
{0 _+ s, b2 ?) r1 @/ ?6 n
m_handle=INVALID_HANDLE;
+ r! O# Q1 L K0 x- mm_symbol=symbol;
- Q* S3 T. \% F! b3 [' ym_period=period;
( P3 _" B& v, r# [5 y. H6 D4 lm_next_bar=0;
" k! s+ }+ G' V* [7 V4 nm_class_delta=class_delta;" [ f& x; H/ L3 S2 x
}
( ^4 s2 C: _* j( ~2 f//+------------------------------------------------------------------+0 _4 S- q4 S6 {0 V
//| Destructor |
0 |5 n9 i6 l, ^1 W5 K k/ Y//| Check for initialization, create model |
8 a0 u' A3 f8 u, t- w- G' e//+------------------------------------------------------------------+* B/ f2 B8 Y3 ?# r! e' \: }& I
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
7 d( A/ H, d' }3 j) P{
9 s! E- f1 y& Y6 a: R5 B% ~4 m//--- check symbol, period; J% V$ T1 k& p1 ~ n# _
if(symbol!=m_symbol || period!=m_period)
7 s" v0 u N* X5 u; a/ W{: V# _6 ^9 z- E) Q0 Y1 o
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));$ \7 t9 O; i# z' u( ^* C% S
return(false);
5 l9 H; n4 O: _% e$ y}% C) D! U1 ` E2 N( N2 o/ O
//--- create a model from static buffer
! h' C( d* [3 k( o/ [m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);! P9 g% b) a' Z: ?$ Z
if(m_handle==INVALID_HANDLE)( ~! f( t7 ?4 m( m1 T
{
! g( T7 [8 E/ S$ I9 ^Print("OnnxCreateFromBuffer error ",GetLastError());
& g/ {/ w' M/ I8 G4 G$ `return(false);9 _: J) m# R7 x6 Q& o4 A
}
5 l- G3 w+ @* J//--- ok/ ?0 K4 k3 t" \ \" j- g' x
return(true);" F; F2 v; d$ {" f( Y6 b
}
# ^3 |! i8 f- H//+------------------------------------------------------------------+
h" l- e2 Q" I* Gm_next_bar=TimeCurrent();
9 u( K4 X: z% b, g5 ^m_next_bar-=m_next_bar%PeriodSeconds(m_period);
& C, E! k8 Y$ w: Em_next_bar+=PeriodSeconds(m_period);% O8 ^& e9 y) e& t' P
//--- work on new day bar" A$ R3 K: [$ p+ m+ s# a
return(true);
/ j l, T- ~+ i$ w: {}
! p m0 Z! Y# ?+ y$ U, n; v% o. |& \//+------------------------------------------------------------------+
) F$ H' u) ] K$ ~# `, Z/ ?//| virtual stub for PredictPrice (regression model) |5 k3 j% O, s4 o7 |+ g4 V
//+------------------------------------------------------------------+
/ K: o; m$ ?) ]" Hvirtual double PredictPrice(void)
3 Z3 s7 \6 T% Y! Q& Y5 k) v{; g! S2 j, f0 C x4 S# s) u
return(DBL_MAX);
+ \! ^% ^- e. Y9 t}# X: r& U! u$ A0 E1 V, @" S6 b
//+------------------------------------------------------------------+. X* y. F# W* d( c/ Y
//| Predict class (regression -> classification) |
9 E8 `' u& T" |* C- p/ l# r- Y//+------------------------------------------------------------------+; J; C, W. q' y/ M, \! _" Y
virtual int PredictClass(void)
+ u1 Z9 G* A6 E- Y{" w! [( s- \2 E9 B7 a$ r
double predicted_price=PredictPrice();& y9 W& O2 n1 L! a
if(predicted_price==DBL_MAX) T2 W6 b( v: A& N; W- U! ^. a
return(-1);, D& r0 Q, V5 l2 z: X$ n! s- m0 }4 x
int predicted_class=-1;2 K0 ^& j! z, V$ p5 U2 p; X
double last_close=iClose(m_symbol,m_period,1);
& B4 D d O5 c3 ^//--- classify predicted price movement5 d* ?3 B2 p# P5 Q) j* M# k
double delta=last_close-predicted_price;* l* r# R% l( C
if(fabs(delta)<=m_class_delta)
2 ~( G8 W( b( f5 e: L# c7 ?' {predicted_class=PRICE_SAME;
" C0 j, n: F& i5 |: {- |else
. x( p3 ?7 W/ u( q# s' Dprivate:
+ a: r7 C, _8 p Iint m_sample_size;' {* c5 t. ?& s9 X4 `; C; h
//+------------------------------------------------------------------+
3 h4 {8 r' `" Y/ V8 L* wvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
; z% E" \ R5 T M9 T{2 W% a) `. p: j+ L+ r% D
//--- check symbol, period, create model1 p( S5 p% {2 e. D/ E
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
) H/ M2 K: w8 ^9 d' S; r, e2 {0 U{
* a- |/ V; \. ]. n) WPrint("model_eurusd_D1_10_class : initialization error");- z! Q, R- e) p& P4 H" y
return(false);1 g! Q N6 A- U& A. [0 e1 n6 C0 y6 c
}+ n. ?! g( Z+ d2 d$ U; W& E; c; H6 \
//--- since not all sizes defined in the input tensor we must set them explicitly' i3 S# Z3 g; B4 |% F$ u
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
) A: ?# m) B i4 vconst long input_shape[] = {1,m_sample_size,4};5 H- z3 m y& ?
if(!OnnxSetInputShape(m_handle,0,input_shape))
! z% S9 ^" `( j) X{. ]( o; x, ]/ g2 z! |! D; u
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
; o9 K7 h0 W0 F2 }( |; Rreturn(false);/ a4 p: E6 J9 n5 Q+ A
}
; U* I4 q/ O. Y/ I, a. A//--- since not all sizes defined in the output tensor we must set them explicitly, ~4 ]6 W8 k% u6 E- V
//--- first index - batch size, must match the batch size of the input tensor0 {/ {1 {/ H8 c
//--- second index - number of classes (up, same or down)
, W4 f* X8 C; t% a) Qconst long output_shape[] = {1,3};
, u. ?2 n% z/ l, ]5 zif(!OnnxSetOutputShape(m_handle,0,output_shape))7 ?2 G9 \1 \! Z+ _2 I7 d2 j! ]. a
{4 P; R- A% r) R; k3 s
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
' m3 ]3 j7 s5 m0 Q8 a9 _return(false);( `* B5 J. s7 B( A, n
}7 L9 y% u( J7 x
//--- ok" y4 E% o) B% u
return(true);5 G0 L4 T7 }) B/ w" z1 H, k
}( c- `$ k8 }2 @( B+ G7 n4 B; z
//+------------------------------------------------------------------+7 l& R- ]' x, r' T( _9 Q0 `* O- S
//| Predict class |
: c* K3 _, q, P( M0 _( d! ^//+------------------------------------------------------------------+
8 {( T; o, f1 ^* `; w: }virtual int PredictClass(void)5 c, p5 r' ~' i
{ |