1. 我们会用到什么模型呢?
0 K7 T% N6 [$ Y' {% U+ H0 n. r: C在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
" T. M' @/ g0 m& f我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进: _" G# c0 {& y2 s1 G# x
//| https://www.mql5.com |
: v& h7 M9 g- j//+------------------------------------------------------------------+$ ^0 o& v& X8 j2 i) e
//--- price movement prediction
4 x, c7 q7 d4 m: Z#define PRICE_UP 0
/ A; Q1 D# W6 a0 z J8 {#define PRICE_SAME 1# x8 W: \' l0 R. Z4 }
#define PRICE_DOWN 22 D1 F% M1 j) K$ G1 U& w. e
//+------------------------------------------------------------------+$ Z7 f% T0 `1 l' w o. R) X
//| Base class for models based on trained symbol and period |$ }) \" }+ O7 h3 |+ W
//+------------------------------------------------------------------+4 r: a v" R, a9 @
class CModelSymbolPeriod
7 ?! Y1 l3 y, a% }% x{
u) K: T2 Y% c: Q5 ^' n3 m* m$ Q mprotected:1 o; [; f2 e& m8 y4 s. I
long m_handle; // created model session handle0 [# A; [7 |( j( U
string m_symbol; // symbol of trained data
( @- \3 y c2 I7 YENUM_TIMEFRAMES m_period; // timeframe of trained data
' [9 A8 i( z" _. J! |datetime m_next_bar; // time of next bar (we work at bar begin only)) e( @5 T" W* Z; F' G* A3 a
double m_class_delta; // delta to recognize "price the same" in regression models
6 e* E. D, { y) D+ fpublic:0 q$ a8 Q9 c# w0 N
//+------------------------------------------------------------------+1 u6 v: E; Q/ f9 J/ f
//| Constructor |
9 K# D2 j# o9 [ \& z% _7 L//+------------------------------------------------------------------+
5 ^% c/ [% ~2 E; |CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
3 p" n+ l* N: a4 B9 y/ I{) g X! ~+ W9 @/ @5 k+ r
m_handle=INVALID_HANDLE;
2 ^ ]+ d9 ^$ O3 n- {( z7 em_symbol=symbol;
- T" D& I" }" e( P9 X) Sm_period=period;
8 Q, H+ V4 }- b" T* o" xm_next_bar=0;
% p2 l& c) i0 [/ F) gm_class_delta=class_delta;
/ Z" R- {9 {% F, }" }}9 R% ?" p+ {0 U
//+------------------------------------------------------------------+
; _4 k3 d' x9 J: S1 U! W* Z" z//| Destructor |# N8 H. X6 r% q1 A
//| Check for initialization, create model |" s% V }4 U. a+ ?4 e' N
//+------------------------------------------------------------------++ H9 Z- b) f4 P2 S+ _
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
* e9 p$ V, c3 ?0 K; ~" |( ^{* D! {+ [, ]( ?0 u9 A6 ?) f. ]
//--- check symbol, period
1 H H( {# w' u0 Oif(symbol!=m_symbol || period!=m_period)! T% ^9 E5 j6 Q
{2 M: d. R! C- @+ o1 n( Z2 N
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));' j+ T* v. Z; M, a+ Z3 i
return(false);. |7 G5 v4 O8 A4 ]
}* R6 P' h I: {0 ? c. v* ]; O
//--- create a model from static buffer3 Q" h4 T$ [% [8 f- B- H
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);1 i( H3 p V! _, P, [
if(m_handle==INVALID_HANDLE)$ ?& @& \ a& ?7 J* j/ X
{
: M5 v0 o5 h5 |: a APrint("OnnxCreateFromBuffer error ",GetLastError());3 H; u- b& m/ X5 ]5 r/ x W+ b$ B
return(false);3 F4 d% }" S; F2 U! b
}
' `: Q* x9 A; X; ?1 [5 _//--- ok/ P! r4 s, U* c( h0 T
return(true);
7 K5 @4 f5 r) L}' R5 |: g. T% w: [
//+------------------------------------------------------------------+
( z3 ]9 _! i& `8 r7 m3 nm_next_bar=TimeCurrent();3 ]" K: B e4 `# u: N1 m
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
0 @, V+ ^% k6 ^ `8 r- z+ d/ jm_next_bar+=PeriodSeconds(m_period);
4 B2 \$ q- \: Y//--- work on new day bar& w& I: \9 C) l& N
return(true);& y# H( ~ k1 }, F( w( j: w) m
}& Y% a/ |7 B6 X5 x9 Z, N! D
//+------------------------------------------------------------------+ z: A! j8 O( v1 X! ~+ i. V
//| virtual stub for PredictPrice (regression model) |# h( W% B$ z" d1 x$ r
//+------------------------------------------------------------------+8 J% W9 u4 w7 F. J P1 U
virtual double PredictPrice(void)
+ q3 [3 ~. @; e+ M/ O& }: k{
# L$ r" c z7 N, p- c) {return(DBL_MAX);
+ n+ F; t! h/ b$ k: Y}4 Y' e4 f( v! d, I/ R3 A9 i7 e; ~
//+------------------------------------------------------------------+
) M$ V% D% f- d1 O) z//| Predict class (regression -> classification) |
5 M6 g. {# T: X4 ?//+------------------------------------------------------------------+
4 D$ Q' t$ I' z3 }1 T0 O, x# `virtual int PredictClass(void)6 M* S: F! d9 K( Z$ Q' Q' f: v) _% a
{7 o" g3 V9 Q: H; Z9 f& `
double predicted_price=PredictPrice();
% T9 {& R& g+ Z0 ?) gif(predicted_price==DBL_MAX)7 `$ U4 A. m* [/ s1 c
return(-1);3 u6 ~5 z# C% j1 i& Y! ?
int predicted_class=-1;+ T, S$ K5 j; G7 s) j6 T
double last_close=iClose(m_symbol,m_period,1);
5 z, ]0 h; S( H0 h. y! }9 O! s//--- classify predicted price movement
" s/ L2 u9 o) g7 Z4 ^% Q+ R, Kdouble delta=last_close-predicted_price;4 a$ f) ]7 D$ c" @
if(fabs(delta)<=m_class_delta)( D% A$ N) ]* P' C# I3 M8 h2 r, ]
predicted_class=PRICE_SAME;
; r4 w4 X' ]" [, J5 O. xelse
% X9 R% |' Y7 ]/ l7 |9 gprivate:3 Y% j6 Z3 e8 q' H! n0 X* e5 A+ r
int m_sample_size;8 v4 c) S8 j2 d4 s5 m2 Z8 b' D' q4 x2 V
//+------------------------------------------------------------------+3 E- ~0 |, K7 o" r, ]. {& S. O9 L
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
& y1 |; I9 A6 }! X8 c3 l# c1 @{4 Z/ t$ _+ k) ^& w7 L
//--- check symbol, period, create model
- L% h/ T, W0 a- o4 eif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))8 o- U, b1 P ?; W; u
{
, x2 S# r8 I9 x: ZPrint("model_eurusd_D1_10_class : initialization error");8 o) f$ U' F2 L: O+ k
return(false);
; T: A$ o( H5 h}
k) A4 h5 r( c, T+ Z//--- since not all sizes defined in the input tensor we must set them explicitly
0 V+ d0 z3 A: D/ H2 p6 C$ S//--- first index - batch size, second index - series size, third index - number of series (OHLC)
& K1 d, W6 H+ D7 @& S, i' S Dconst long input_shape[] = {1,m_sample_size,4};1 ^& ?$ I' m7 a! c' L3 {
if(!OnnxSetInputShape(m_handle,0,input_shape))/ |$ \9 I) p3 `! C" r0 k1 i
{
! r0 Q" ~- a$ K) R1 |; G$ kPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
, m4 m8 l1 p0 \$ o Lreturn(false);3 h! t4 m+ G" B9 i Q1 s
}5 C2 d6 o! `3 o
//--- since not all sizes defined in the output tensor we must set them explicitly2 }% o5 W# v8 u$ ^
//--- first index - batch size, must match the batch size of the input tensor
! v. v x8 c+ G( p5 u3 c4 D }' w1 u//--- second index - number of classes (up, same or down)
) b) Y6 `/ p- p& y2 l( k: B0 U3 Vconst long output_shape[] = {1,3};
8 x. I% O# N5 e Q, Q/ H7 h5 x- Wif(!OnnxSetOutputShape(m_handle,0,output_shape))
/ k* H( _4 D1 T) J2 b- R8 |{: B/ r3 F2 b. X. {* r8 }+ q
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());" o4 }8 @3 S+ N' E6 i z' N
return(false);" x! ?7 W }. a5 @ Z
}
( P; [% b5 J1 Z! y3 S8 T//--- ok0 a6 u% M: Q( r5 t
return(true);' [- w" [$ U% [' }3 D* ]
}
# c3 u( h" l+ s/ J* m# y: O//+------------------------------------------------------------------+
! x# G4 K& Q1 N//| Predict class |
5 K% E7 ~7 x. B/ o' a5 W0 T//+------------------------------------------------------------------+$ @- |4 e% R4 ~7 K7 H5 l* q0 J
virtual int PredictClass(void)
k- l3 e! L! |6 R2 r9 ~{ |