1. 我们会用到什么模型呢?0 c4 `' p" F) |- r
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。) i5 h9 h. I3 {* M+ }7 j" {; f
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
( e6 T2 P9 ]( o; {- L//| https://www.mql5.com | P: J' X- `/ w% i8 E, H- m- s8 a
//+------------------------------------------------------------------+
P' L, F1 I# _/ a! c//--- price movement prediction! d p. x2 G" |' I
#define PRICE_UP 0. C6 b$ j! m& y( w9 Y! s
#define PRICE_SAME 1
4 P+ ?- A6 \0 \2 }7 ]5 Y- l$ \#define PRICE_DOWN 29 E; B4 ~! H x5 e6 b
//+------------------------------------------------------------------+
7 h5 }2 J4 [3 z9 S* q$ [/ h//| Base class for models based on trained symbol and period |7 r2 K" e( P5 U& f
//+------------------------------------------------------------------+* e. l' u6 P, q7 @" F
class CModelSymbolPeriod$ Y* O3 s8 L9 y0 c( i
{6 }2 {3 i3 I" H6 d5 w/ b% l: Q
protected:
3 o6 y4 Z- l+ J7 }long m_handle; // created model session handle; f4 g9 ~3 R4 {( f
string m_symbol; // symbol of trained data
- ]- D+ I2 a, GENUM_TIMEFRAMES m_period; // timeframe of trained data
# ]. A+ u6 g0 p1 Tdatetime m_next_bar; // time of next bar (we work at bar begin only): Z% o1 \7 T k! z3 Q, o& @/ l& C+ x
double m_class_delta; // delta to recognize "price the same" in regression models
( o" U/ g/ R0 \! C/ ?2 ~) ppublic:+ a8 t& U/ {& x% C
//+------------------------------------------------------------------+
2 D% O- G# q* @( \$ _8 f1 y6 F. s. Q//| Constructor |
7 d4 U3 f8 F0 y4 R1 z. T% z3 S. b B//+------------------------------------------------------------------+0 N7 G7 Z2 H$ j8 E
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)3 `8 ^- \: n+ Y" L
{
: ^ n) n( z, i8 ?( d1 C$ {# |m_handle=INVALID_HANDLE;
( J; i! ~0 z0 {m_symbol=symbol;
0 o0 N2 r, j6 i" i; j: k& jm_period=period;
b6 h! {- a! ~ Xm_next_bar=0;+ I' g6 m9 s' }- u
m_class_delta=class_delta;
# M0 i3 d% A9 o}
5 ^! [8 Q/ A' z( V//+------------------------------------------------------------------+$ m4 a: t' [0 _. T; \- l
//| Destructor |
) D; ^) e1 S% d8 V" i//| Check for initialization, create model |% |) o# V1 }: }) r( `9 f
//+------------------------------------------------------------------+) d6 d: s4 h+ H" N" w6 e) O% h" L
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
* A1 y! a, o0 w+ x9 T% g{$ G5 s; u" \8 R% Q; J. E
//--- check symbol, period& W! m' a/ Y. k6 w( }6 q
if(symbol!=m_symbol || period!=m_period) l- |& q+ Z6 E" @
{% c9 ?( ~4 h, h" Z, f% j4 m4 {
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));0 a( I9 N2 N5 O/ _1 l& D4 w
return(false);
1 h; }2 |3 l0 V5 W}* n" Y4 J! i$ W" _! T5 H
//--- create a model from static buffer. R- q, K# ]# A8 Q k8 W
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
/ V1 s3 u* Q- G6 Nif(m_handle==INVALID_HANDLE)" i9 |+ k( X% f5 }
{
+ m: A5 r( z) |5 P' I! \Print("OnnxCreateFromBuffer error ",GetLastError());
5 z/ W$ p6 b# I8 g' A8 _! Mreturn(false);
l, @$ w: |/ T( D}
6 m% }9 X# q6 a0 Z; ?//--- ok
# X) y# d1 _+ G' l# F; X6 ?4 |8 v. [return(true);
+ e' ?7 S$ X, O" a2 K6 R3 `; ^6 P}
. F5 h5 W# Z5 D( a" \//+------------------------------------------------------------------+7 o9 o! G1 `- Q! q* X- U/ o% R
m_next_bar=TimeCurrent();) w: m1 f' k; T4 |
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
* {# @1 {: D. T% rm_next_bar+=PeriodSeconds(m_period);
1 a3 u9 m2 S. E" i2 Z//--- work on new day bar2 E {6 S5 D6 R
return(true);3 @2 r& b7 ~* `' M
}
. x2 o+ N {# _0 g//+------------------------------------------------------------------+' |% s7 A ?! d" L9 @# \1 ^: M+ J2 J/ h
//| virtual stub for PredictPrice (regression model) |
8 c; d- B* m3 j9 ?# ]5 w$ { a- V' H//+------------------------------------------------------------------+
7 M) N& \ Q' Wvirtual double PredictPrice(void); m6 W) J8 r9 v( C0 o* ^
{( I0 }% F9 I3 U7 H
return(DBL_MAX);& s8 m1 y' K; F% D+ U' Z- _/ t
}, J: u+ ~9 B% X
//+------------------------------------------------------------------+! y6 U3 n' y* b7 D( A% Z9 Z
//| Predict class (regression -> classification) |, r# H! w& h! h2 o4 c1 J
//+------------------------------------------------------------------+
8 O: Q% |: I3 Z9 s4 u# {virtual int PredictClass(void)$ u# o# k( x& a
{# ~; J6 g' |' a+ ]0 p8 m
double predicted_price=PredictPrice();
7 j9 c+ u0 \) [7 }if(predicted_price==DBL_MAX)
5 _' m2 o$ H4 c" V! @return(-1);
6 F b5 [( L: H/ nint predicted_class=-1;
+ N, A9 }; O1 C) l5 C3 vdouble last_close=iClose(m_symbol,m_period,1);
& |" @7 h/ L. S0 J/ Q. O" t//--- classify predicted price movement$ J6 Y- D# d3 h( t( @0 j
double delta=last_close-predicted_price;4 U7 D6 {6 y7 e! [6 v
if(fabs(delta)<=m_class_delta)
3 y4 A+ w8 q2 d& m; A2 ppredicted_class=PRICE_SAME;- i7 L* q7 p$ T* L" s3 }/ @
else% v; ^9 \$ s0 R% f# H
private:2 E$ l( c5 @2 @: S4 r% x% M( Z2 o
int m_sample_size;, x1 B; ]/ s/ s( s- D4 K9 k1 J/ |! h6 v
//+------------------------------------------------------------------+
' h1 U. |% C+ Mvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
1 B' e& s1 u( i, P3 P( i' ]{
8 S( E0 {0 t! p//--- check symbol, period, create model) A9 L' l. d" U4 \2 Y+ z0 D
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
" z0 O, ^# O2 C{ d* \& `& f, ^, g% t8 ?2 A
Print("model_eurusd_D1_10_class : initialization error");
$ `2 _# Z; u7 x( A' G7 kreturn(false);
" c2 i4 |" ]/ ]' z& ~5 Z5 b0 Z}
; l( r3 ^8 Z# z6 O" b) P//--- since not all sizes defined in the input tensor we must set them explicitly* p. B0 D6 v W, z
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 f7 d9 X) j! Wconst long input_shape[] = {1,m_sample_size,4};- ?$ V. U1 T8 _
if(!OnnxSetInputShape(m_handle,0,input_shape))# @9 Y/ l6 t$ w5 ^2 s
{
9 [: R, z+ `0 d3 I( gPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());1 S. J( }8 v3 O; _3 i u( {8 A7 E1 b
return(false);
, [' D7 L0 l$ ?}3 Z2 D- l) c- N
//--- since not all sizes defined in the output tensor we must set them explicitly2 {' I( `3 L6 P, J
//--- first index - batch size, must match the batch size of the input tensor
' `; L l$ y$ |; F0 K//--- second index - number of classes (up, same or down)
& j v5 M: [: Lconst long output_shape[] = {1,3};1 F! j* R$ @ T5 m' l+ u
if(!OnnxSetOutputShape(m_handle,0,output_shape))
3 q' f* q9 O5 k% _- R/ e9 v$ D7 m{; e/ ?0 N% a" i$ c3 X) h( x
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());+ e+ o2 k2 ]3 R+ i; q/ ]
return(false);0 H( O1 c1 {5 H% R% d, R! g0 Q
}
, s2 j* B6 x. T( W//--- ok, o1 J* y0 x& o7 A
return(true);# a3 z0 \: D- a1 P- z% w+ l9 @
}
5 Z/ n* k y' Q. j' s3 N//+------------------------------------------------------------------+; D& Z" g! \ H! s# o; F$ m* n
//| Predict class |
T' Q8 L1 l- \. r* v, h: e//+------------------------------------------------------------------+) O' J& O) j7 c8 ^" e
virtual int PredictClass(void): C$ z c/ E1 q0 \ A
{ |