1. 我们会用到什么模型呢?. Y" W4 N- Z! i8 A( {! t- C8 m
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。- c# s/ I1 r& L, s& A+ |
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
/ A. I, H; G/ z1 H' U& d! r- D//| https://www.mql5.com |! f) j; L/ I! ^
//+------------------------------------------------------------------+
+ o5 ]2 n8 a: M' D! X//--- price movement prediction
1 H3 l. q; I9 B& H6 D#define PRICE_UP 0; a& I/ |5 t/ u6 J1 Q4 L6 C) j" }
#define PRICE_SAME 15 F8 o- p1 P* [* D1 \
#define PRICE_DOWN 29 @/ g7 Q# A# N# B4 R* p% p
//+------------------------------------------------------------------+5 g* m; j& [2 Y( g" O
//| Base class for models based on trained symbol and period |
8 w! c# u0 F1 z+ [- |- Z//+------------------------------------------------------------------+: N! j0 V: n' L# d; I
class CModelSymbolPeriod9 T) s) K5 v! |9 @* o( L
{
) E1 p- X8 B0 @' t! Xprotected:
( K& k8 W2 q' Y, A6 @0 H9 m# U! Plong m_handle; // created model session handle* Y, u2 P3 j8 {) ]7 |, o8 ~
string m_symbol; // symbol of trained data
$ }5 J! L0 X6 h" T! s* a8 \ENUM_TIMEFRAMES m_period; // timeframe of trained data
e; L$ y" `5 i4 s! fdatetime m_next_bar; // time of next bar (we work at bar begin only): D. j) ?3 ^; U' M6 I$ m% |! h
double m_class_delta; // delta to recognize "price the same" in regression models5 e$ B4 a9 N1 ]* @ H
public: F. ]; a F6 k1 P
//+------------------------------------------------------------------+
( ]+ `: E( a0 m4 F/ ?: B//| Constructor |
n. z9 g* o9 z" [//+------------------------------------------------------------------+" i7 K! g9 k# j$ z
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
! I9 ~+ T$ I5 Q( k0 {{
9 O: A; M3 L, j# B; N, E( Wm_handle=INVALID_HANDLE;
3 @3 c( `. F* M; Q& |m_symbol=symbol;
# T, d* ~) d# f- l' a8 Km_period=period; W6 T% X7 T W8 }
m_next_bar=0;
" T+ u6 E7 b9 Dm_class_delta=class_delta;' I5 H5 R+ R- @0 p
}1 f B$ g/ h# ~' E' \1 T! w
//+------------------------------------------------------------------+ Q* j' }# a: L
//| Destructor |2 ~6 O/ `- p. _+ G$ I
//| Check for initialization, create model |
3 k) x8 a7 Q- ?7 h% i2 r9 k( N3 N//+------------------------------------------------------------------+* |# {8 J+ ~6 t4 ?& q
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
' u x a& c$ @- \: N7 z{3 [3 `6 R& h0 e2 i: g& c3 m
//--- check symbol, period
1 ]6 s/ F( Z1 L* d: u% L. fif(symbol!=m_symbol || period!=m_period)
. t! L$ N U1 ]! A{
1 \ B' y, u% cPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
8 Z" `% \5 n6 Rreturn(false);
! {9 b M6 E# E r}
( y" i% l7 a' ?+ `//--- create a model from static buffer% q5 s! o% `- n# J
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
8 d) u, @- b! z- f4 c( aif(m_handle==INVALID_HANDLE); ^+ B6 |) X% o: {
{
: e: f. ?0 [: A, C( K+ k# {Print("OnnxCreateFromBuffer error ",GetLastError());
' c$ H# |( R# L5 k. j9 x Dreturn(false);
2 X, }' L/ ~9 @. m) K; S% S}* U! w! C8 W9 g
//--- ok% y+ j* ^1 J/ u ?. Z
return(true);9 o% |9 X3 p: E0 |+ W
}
7 S+ Y! _$ u! Q4 W//+------------------------------------------------------------------+ D. N8 W+ j, _0 i; b0 E
m_next_bar=TimeCurrent();
' ?: u& T/ K# v8 sm_next_bar-=m_next_bar%PeriodSeconds(m_period);! k1 W" y; [+ g% _/ r
m_next_bar+=PeriodSeconds(m_period);% _: H5 O- g5 l
//--- work on new day bar4 q4 e! _/ @4 U. f& T1 s
return(true);
9 q5 O2 u) |+ D% e5 D}
* ?5 c- w4 u5 t, m//+------------------------------------------------------------------+, d$ ?! c' Q8 q+ T; B5 N
//| virtual stub for PredictPrice (regression model) |
' `# t5 c3 J3 j% y! M8 i) B//+------------------------------------------------------------------+& B- z: P6 ? u% ~8 h; l
virtual double PredictPrice(void)+ G, `6 d+ \4 N$ a* }" n
{3 X( d& [) ?& N0 V, h' E4 g
return(DBL_MAX);9 U5 P0 Q% F, v V. J0 w2 I% k
}! ?% g5 r9 H1 Q2 `1 _" i0 k4 h
//+------------------------------------------------------------------+
! r8 K- ~. W9 y. v//| Predict class (regression -> classification) |+ A9 D9 y0 y5 d$ H# ]# g* a6 M5 o
//+------------------------------------------------------------------+
3 k1 n. R: g+ R" j: Nvirtual int PredictClass(void)# N& `' _7 e: v. O! M! O
{( J- q9 Q3 G h0 e
double predicted_price=PredictPrice();
5 Z. c8 z- _' |: U2 [# b Mif(predicted_price==DBL_MAX)0 a$ y! V0 O7 t* T8 a! \
return(-1);
7 N) t4 V& N2 w. x! _$ t* k7 rint predicted_class=-1;9 i9 n h8 U; D. U: l
double last_close=iClose(m_symbol,m_period,1);# g- U. {7 L) e! _# E" d
//--- classify predicted price movement
2 x: e' d1 }3 G9 C1 V; H z/ S, Ldouble delta=last_close-predicted_price;2 T1 o. m' u7 w/ j. u! U0 {
if(fabs(delta)<=m_class_delta)3 n) d r- `' V2 q
predicted_class=PRICE_SAME;' p8 S. Y1 d% F, |$ `/ D
else
5 O! ?; ^$ v( Y' u( V: c: ~private:9 e7 e; a) {4 Q6 O
int m_sample_size;
6 U) N5 ~$ @% b. M7 u9 _4 j- o7 _//+------------------------------------------------------------------+
/ Q, _4 f3 T( M% j. ]virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)8 T. `) C! w9 }" p1 l! F& D4 U. u
{
2 O# _5 _! h& e* S//--- check symbol, period, create model$ p, S8 W7 |# d7 Q- p( M
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
% n" z& Z( r4 v) _{
' l& m' e% [5 R. E$ Y3 F( G2 tPrint("model_eurusd_D1_10_class : initialization error");
( u0 F2 M$ f6 i# ^# U! i6 |7 Zreturn(false);
+ e2 }( k8 q4 n7 u" W}
9 _8 K9 {5 T' s: r//--- since not all sizes defined in the input tensor we must set them explicitly
* p" W! n8 t. E/ T/ Y+ B5 @//--- first index - batch size, second index - series size, third index - number of series (OHLC)& U* P1 D6 T2 q( `$ V
const long input_shape[] = {1,m_sample_size,4};; ?' V$ j: m1 q4 i, H" H
if(!OnnxSetInputShape(m_handle,0,input_shape))
5 z& }+ y* o& \( c H. R{) c. b# [" K7 ~+ M1 b
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
9 W2 |+ c* X# u) ureturn(false);5 ^ X \$ T6 J$ ?$ F g5 x! |
}
2 s' }7 |0 X. C% S! v$ Y//--- since not all sizes defined in the output tensor we must set them explicitly3 E F4 @. M* ]7 J7 [- }( F# W
//--- first index - batch size, must match the batch size of the input tensor
* j& J7 X3 c" n" F' \% h//--- second index - number of classes (up, same or down)( l% {5 m( x, C% E! v! l
const long output_shape[] = {1,3};4 M& `9 q! Q' w. |
if(!OnnxSetOutputShape(m_handle,0,output_shape))
* X5 P# b: j' }+ o1 e{: ]% W3 f; o; o7 \
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());0 O: v) c3 p" A2 S4 x" u: u
return(false);# v& X+ B) W3 J. e* a$ P1 |: A
}6 z+ b4 h- d5 n6 U+ l# c
//--- ok$ d2 B& D9 t( p0 v; h# c% i
return(true);' S5 `) R6 M' q
}! u7 t" X% o% L9 e* F$ d, J% O
//+------------------------------------------------------------------+
2 ]# v2 u6 ^& N, D* Z9 `! F9 P7 k; F//| Predict class |+ ]! _! x _1 d' O" K: T/ H
//+------------------------------------------------------------------+( O8 v7 G5 R: X/ O
virtual int PredictClass(void)6 T* `/ Z/ F, m# Y; |/ b" L0 @" v
{ |