1. 我们会用到什么模型呢?
$ H/ r! H' [% T% f4 g' f& g# ~在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
; q) R: w) m# l/ S1 p! `5 v9 d我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
6 R" R4 y; s) C$ i9 E//| https://www.mql5.com |
' u, T4 G4 M3 D |//+------------------------------------------------------------------+' m% l! o2 J. D/ q
//--- price movement prediction
' k& P" u3 Y3 M s. L#define PRICE_UP 0
& t' l- z/ G8 J% N/ q: r6 Q/ V#define PRICE_SAME 1+ O0 ^) V! C# c+ P* Q, E$ w6 C+ D
#define PRICE_DOWN 2 K; Z0 M3 K; Y( s* R. g$ e8 C: Q5 D1 X, b
//+------------------------------------------------------------------+4 f2 G6 E' n" h$ \' k
//| Base class for models based on trained symbol and period |
" L! Q' ~0 l. ]1 Z' D//+------------------------------------------------------------------+
# z9 R+ s: f+ I) Uclass CModelSymbolPeriod5 o/ Y. W9 E4 w7 N
{7 l9 q" O0 H: |+ ]+ i" y9 L' ]9 n
protected:
8 J- E6 s* x2 S9 L, r( a$ |/ ^. j/ |long m_handle; // created model session handle9 J7 z/ N* @0 R5 n6 O' [# Z
string m_symbol; // symbol of trained data7 q+ v' n" ?4 Q! A, q w
ENUM_TIMEFRAMES m_period; // timeframe of trained data4 i; M1 C5 @! g. N
datetime m_next_bar; // time of next bar (we work at bar begin only)
& J7 h; ]) v' J; ?: Ldouble m_class_delta; // delta to recognize "price the same" in regression models
( ^+ }# ]8 R, I* H/ R( Q5 k& cpublic:
% U+ O" ~# q% c' a1 @( q//+------------------------------------------------------------------+
$ d7 m8 j: b5 d7 ]//| Constructor |0 q$ |' U. Z8 j
//+------------------------------------------------------------------+
3 ` `0 h. e2 `6 ]0 ]7 ?CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)3 b8 ^6 U9 i# K5 z" ~& H/ c; `
{
. x5 ~8 m& k* a3 hm_handle=INVALID_HANDLE;% _( S8 i* S7 ^9 K; M* m
m_symbol=symbol;+ b: B/ a* E' v- A2 f$ h, |# H
m_period=period;
1 B3 \$ d, w8 a7 r2 @. `m_next_bar=0;
+ _7 l0 o% r; J2 bm_class_delta=class_delta;
! b( l1 j% `3 \/ N1 a& z2 s}. v0 l# A( G- P
//+------------------------------------------------------------------+
t, m* J% p3 t4 O//| Destructor |$ B" R+ P! X# U v L+ Y. G4 y
//| Check for initialization, create model |7 ?8 U8 e8 A* D# a' {
//+------------------------------------------------------------------+* V# W0 b( k. {. W2 y4 b, w
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[]), b/ J( B, j2 h3 c3 g( k
{" M" K. }5 j. W6 w5 r. k
//--- check symbol, period
7 }4 e; K9 j' j% T9 mif(symbol!=m_symbol || period!=m_period)
4 M+ C* ^9 `9 Q! Z3 Y1 E& j{) x; Y. B' H" g
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));6 w4 @+ @* X0 v- ~* n
return(false);7 ^7 @2 Z' N2 J& l9 D% a
}; U( t: t( Q" E' C$ h# @ [8 b$ r
//--- create a model from static buffer
- I' g5 T1 O6 ]; A6 f% J+ E& l* ^* Zm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);' `4 M* l! c. B) i0 ]
if(m_handle==INVALID_HANDLE)
! _+ X0 \, `6 t1 E{: A7 a7 D% Z9 U
Print("OnnxCreateFromBuffer error ",GetLastError());& z9 ]7 K8 K& @6 Z
return(false);9 v A. c% n. ?4 {5 d# \
}* d3 r5 n: N+ J& o* H, g8 Q
//--- ok3 T; W* m0 p8 ]
return(true);) N. j% m, P1 M! j) I
}
% \7 e9 T+ d& V6 x//+------------------------------------------------------------------+
! [- Y D- R [m_next_bar=TimeCurrent();
" n0 r: F% m E9 Tm_next_bar-=m_next_bar%PeriodSeconds(m_period);
* V2 @! B4 V: p5 `# K: m! im_next_bar+=PeriodSeconds(m_period);1 }- E6 x, _+ |/ N% l( p
//--- work on new day bar+ Y# j" L, h2 Y# T
return(true);( b- z5 ^( W, k- |/ k
}
S- @6 x7 N, q% o4 \//+------------------------------------------------------------------+
8 f' P2 Y1 m3 y8 ^//| virtual stub for PredictPrice (regression model) |
: W/ n( Y. x7 l//+------------------------------------------------------------------+
7 g5 p* e2 v( ]virtual double PredictPrice(void)# }2 T- @7 U# e0 ^& g3 W
{ t: p6 R9 k* u# @( J
return(DBL_MAX);
( G7 ]- u# q$ Q}( K, B" H- x% G3 @
//+------------------------------------------------------------------+
; }1 }& E( j9 A& k! v//| Predict class (regression -> classification) |8 I/ B# X4 _# M. Z2 f+ |4 m
//+------------------------------------------------------------------+
" a: _ G% G* D7 o0 \+ s O: avirtual int PredictClass(void)- ?/ w) b2 X( D0 P
{
) P2 L# s/ v8 H* i* w0 Kdouble predicted_price=PredictPrice();
, s0 w/ g, ]( i' Uif(predicted_price==DBL_MAX)9 C5 {+ a0 G6 U3 c, R
return(-1); Y: _; [% T W3 b: m; u/ x
int predicted_class=-1;8 S y4 u$ d1 l
double last_close=iClose(m_symbol,m_period,1);9 P; K0 Z% Y* Z' T$ x
//--- classify predicted price movement
1 J) }2 h, x( K/ idouble delta=last_close-predicted_price;7 F4 n/ k* ^; a
if(fabs(delta)<=m_class_delta)
" w n- ]% D, S$ ppredicted_class=PRICE_SAME;
* R% t% ]9 v a3 I; \: |* M+ velse4 i8 F) N8 p! I/ k* M
private:* `$ B9 w( J5 s( ~% ` m9 K
int m_sample_size;4 _! g/ G- {* }& Y
//+------------------------------------------------------------------+0 v5 ]9 q( h" J- u( G, C0 c! C
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period): V F7 ^! g; N
{
1 H. ]6 E1 k2 d1 [//--- check symbol, period, create model
4 q( K. V& ~- K5 ^if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))9 r+ [/ Y$ ]& h& U) y* m
{
0 D! O6 s( J6 y( @9 r5 D7 @* RPrint("model_eurusd_D1_10_class : initialization error");9 ^# f5 T2 x4 s
return(false);
) b$ \% f# d5 I3 L1 D}
" C; A4 s: P* Y% |* c9 l//--- since not all sizes defined in the input tensor we must set them explicitly/ r! _, _' }' H; z+ \* B
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
+ J0 u8 L$ g, `8 {! zconst long input_shape[] = {1,m_sample_size,4};. q! ~9 ^8 [+ Z
if(!OnnxSetInputShape(m_handle,0,input_shape))
( B- v1 ` T( Z( D) M" \{
0 w5 U* D2 O1 [% {3 P& jPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
( y) y: u/ ]- `4 Areturn(false);& G2 _9 p- k7 T- v
}
\! b- z' i# m//--- since not all sizes defined in the output tensor we must set them explicitly: k9 {1 ?7 m) R2 G0 c
//--- first index - batch size, must match the batch size of the input tensor- D8 B+ s" ~3 p2 W) A. i0 _* _
//--- second index - number of classes (up, same or down)2 U1 F, } y/ ]- E1 ]
const long output_shape[] = {1,3};
' X: B G" h! ?9 T7 g2 Y6 m8 pif(!OnnxSetOutputShape(m_handle,0,output_shape))
- k; j: |. o8 R- e0 P/ z5 C{
5 C# Z' D0 N1 S8 e# IPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
1 z0 E0 X5 t5 }return(false);+ N" g; o+ g3 g
}4 S: j6 u4 I& e% |5 |
//--- ok
/ L! {; y" k, n2 `( e2 d8 Treturn(true);
. ]! v- k+ Z# Z, O" W5 ]}4 i+ S3 K: o( ~+ K3 Y/ B1 V! m
//+------------------------------------------------------------------+
7 R1 E! b- ?8 G; X//| Predict class |8 e1 d5 m) K! A) ?
//+------------------------------------------------------------------+1 \* D' I3 j! N& B, {9 ^+ A8 Z
virtual int PredictClass(void)* a$ w9 i! K$ A. {* a
{ |