1. 我们会用到什么模型呢?
/ A; [4 H- y1 Q7 a) r* ]& I3 M在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
3 \0 C7 Z7 J0 l& Y9 j+ u. Q我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
6 F6 g p3 C; T) b: ?$ a//| https://www.mql5.com |( n: G5 z- @8 |/ Y7 J
//+------------------------------------------------------------------+
9 C# v# _1 u3 N//--- price movement prediction4 @0 ?# l# `2 f% _
#define PRICE_UP 0
& ?1 l8 ^- w) D#define PRICE_SAME 1# w% Y/ Z; A# F2 G: I
#define PRICE_DOWN 2
0 [9 G8 `; F1 K m( [' X1 K+ L# j) S//+------------------------------------------------------------------+
" w2 m$ K) X/ r9 A//| Base class for models based on trained symbol and period |
% x: P$ k" x( p3 t' z//+------------------------------------------------------------------+$ x3 l* L; H) _1 E% g( [; b! |
class CModelSymbolPeriod
" F U" ~2 O! G( E9 v4 j{
; T. U$ G+ O* P' v _5 \7 hprotected:
1 c8 c& q4 s. W" I8 Wlong m_handle; // created model session handle
. {5 T& e3 F# ~+ Y( Zstring m_symbol; // symbol of trained data* W/ Y% `) ]* V& a
ENUM_TIMEFRAMES m_period; // timeframe of trained data
- R! `5 i- {; E' O& e% Wdatetime m_next_bar; // time of next bar (we work at bar begin only). G% _5 O3 y- S
double m_class_delta; // delta to recognize "price the same" in regression models
$ g7 z8 f& u r. N0 { b0 k# {public:0 q* t8 ?( F0 k8 t9 h1 y0 ^
//+------------------------------------------------------------------+
# S3 r7 F" y" G//| Constructor |1 _: N" L W M
//+------------------------------------------------------------------+
& I9 f/ D9 S) M+ u0 \1 @/ M( vCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
7 d* G) J0 P4 O+ r8 }" U{; |/ l; {1 L# t8 Q5 a7 u x
m_handle=INVALID_HANDLE;1 k3 T9 _) ?4 \: S" `; r
m_symbol=symbol;9 X3 C% Y/ G* k1 `" H
m_period=period;
6 L0 _6 }+ ?/ L: L' Ym_next_bar=0;, @" A5 Z, {9 B% H* X/ l% {
m_class_delta=class_delta;
3 {& K' G, o. q( q; J}8 ~. w, c+ X3 u6 {4 c3 }
//+------------------------------------------------------------------++ @6 m, N' G) f5 E. ?2 ?# K
//| Destructor |
6 O1 L- [4 ^" S3 j, i//| Check for initialization, create model |
7 A8 x$ X5 I- s" G( W! | n( S& L; Y//+------------------------------------------------------------------+
- v: X) f w" `# y4 H* c3 M4 zbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])- b# c2 p7 @/ f
{2 A4 e! D$ I0 [# B/ A G
//--- check symbol, period! `: ]2 V+ n9 ?# Q0 H
if(symbol!=m_symbol || period!=m_period)
/ ~, e4 H! ^$ K: ?; E{& S, C6 s' i' o" a
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));% g7 O6 s" F! T' ]
return(false);- X, @7 G, t/ l* r) R3 _, G4 x
}
0 {& v" L9 T* j/ \//--- create a model from static buffer
& v9 N! G. K$ z3 _) Fm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);. `7 ~7 j4 Q9 G+ m) q
if(m_handle==INVALID_HANDLE)
% I. b o& |9 X% V4 Y, O$ l( m I{. c" a0 ?: N; V& Q
Print("OnnxCreateFromBuffer error ",GetLastError());$ X3 U# t4 u. U' X
return(false);
0 T1 a, l' C, t$ t* E}! T$ Q3 e! u1 K' B# C, B1 g3 K
//--- ok* \# A% w# H6 }' @# O0 K
return(true);
3 A! h5 G, m( `, B9 y) R' q}
6 b l! |4 @6 C6 l. n/ _% R//+------------------------------------------------------------------+
, F+ D$ E0 c* ^$ y8 Bm_next_bar=TimeCurrent();6 T! j6 _7 J9 M5 J; @
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
, C4 A; T1 h% I1 ym_next_bar+=PeriodSeconds(m_period);8 n3 n k; i' C l
//--- work on new day bar+ Q. E* _- d+ Z c' _) W0 Q& r
return(true);" M# h3 w W0 P3 Y \+ Y1 X
}
& V" I9 S. Z, I6 \1 X//+------------------------------------------------------------------+
) Z( s5 b& k) F3 C' U0 P//| virtual stub for PredictPrice (regression model) |9 a# }. T! ?2 h# c7 x
//+------------------------------------------------------------------+
, w U( }" A# F# L. i+ Mvirtual double PredictPrice(void)
; [ |# z9 }8 F7 ^2 b9 i{, W. B8 ?& z( w/ M% K8 G
return(DBL_MAX);- |3 f" l3 [2 v- ?& V/ \
}9 N' U, {- g. \2 y1 M) f7 F, Q0 ~$ i2 |
//+------------------------------------------------------------------+. d4 d/ |3 Y6 X# {3 ?9 H
//| Predict class (regression -> classification) |
6 Y# K% b( R/ b+ W, _+ D//+------------------------------------------------------------------+
' H, O" J0 A7 Y7 X1 y2 m3 uvirtual int PredictClass(void)% z- J. u' u6 |0 E4 r
{" ]* E+ @3 [# P( `. \% o& ~. A
double predicted_price=PredictPrice();
[. V- E! c/ J% [4 }4 xif(predicted_price==DBL_MAX)* A' ?/ P z5 p, ~/ ?& A
return(-1);
) z2 ^7 w2 _3 }8 w( {int predicted_class=-1;
# a2 p _' |9 a# ?. t; Y" Cdouble last_close=iClose(m_symbol,m_period,1);
7 Z, J: D4 e$ B( @4 x) \//--- classify predicted price movement3 }' Y3 G% l) s2 l
double delta=last_close-predicted_price;
9 d4 E3 b' o% ^) jif(fabs(delta)<=m_class_delta)
. m4 k, J+ F! opredicted_class=PRICE_SAME;9 h' G9 A% `8 f) E# S2 z
else; [& {9 t* b" y
private:
. g# v3 h% r3 j9 Lint m_sample_size;7 z$ P8 T1 U$ ?6 }6 ]5 |
//+------------------------------------------------------------------+
& ? |2 l7 P* n% Cvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)4 G: ]+ O. n7 h
{; Q8 `( l, J c* m, R3 Z
//--- check symbol, period, create model
( A E! @( a4 o! Y; K5 u5 I- J- Cif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
( x% X; p8 F7 T- W+ Q, M{3 k, h# Z9 `7 ^# [! o& x
Print("model_eurusd_D1_10_class : initialization error");4 Z7 f' s7 k" x8 i; C" d
return(false);/ [2 u/ {* i0 ~8 j
}+ v# k8 ` }# y R3 d
//--- since not all sizes defined in the input tensor we must set them explicitly9 d& B& z7 K3 t% G
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
% C) M c3 L; u7 i' E' Bconst long input_shape[] = {1,m_sample_size,4};
5 `$ s1 _9 T9 @2 w" bif(!OnnxSetInputShape(m_handle,0,input_shape))- Z) P2 b- @$ `" w$ x: {) \
{
. R; c% u; d9 aPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
' W- H: R6 f1 G; g( V( Vreturn(false);! e8 x: k0 T& W6 g. v: y4 {8 E
}
4 _* B9 \( O! m+ G//--- since not all sizes defined in the output tensor we must set them explicitly
% O( \2 P; u! k4 \ n) c//--- first index - batch size, must match the batch size of the input tensor
# f; R! D2 ?2 M* o) j//--- second index - number of classes (up, same or down)( ~% z) j- D- f7 |0 O
const long output_shape[] = {1,3};' c4 U( r1 \& J6 s2 K5 |, q+ j
if(!OnnxSetOutputShape(m_handle,0,output_shape))& [* c7 f5 @6 c: K* n2 S1 F
{# o# o- R( A: J. O" |6 U0 E, [; F" }: B
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
+ C( k5 q% S. w% V) F1 s+ }return(false);; E1 m; j- O! [2 L9 F
}
5 s2 B$ ?+ g e' R0 }//--- ok
, \# q3 S: S: x2 `3 L2 K8 xreturn(true);+ n% I' ~5 d" K
}
. c5 q: Q8 T8 U( `' Z//+------------------------------------------------------------------+
0 v1 N% ?" g' q7 R t//| Predict class |: R/ P: `0 u3 [
//+------------------------------------------------------------------+
3 w. X: l2 V0 y+ x1 h0 Y7 B- Cvirtual int PredictClass(void)
. K' |) i$ `. {' D{ |