1. 我们会用到什么模型呢? C' ^, X. I) ]3 c! X
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。" x6 a% I: N' h8 K- W6 B% Q7 f
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
! W. ]' p( U* V1 K/ J! a* _//| https://www.mql5.com |
/ p- u4 _1 e% y1 H# O' H//+------------------------------------------------------------------+
4 ^- x; t4 a2 C5 k+ B# A//--- price movement prediction
! G' Q9 }7 \& l0 C B5 U+ J#define PRICE_UP 0; ?* b% y+ [; Y$ x) e
#define PRICE_SAME 1
8 ^# N" a4 G# A, G0 g8 e#define PRICE_DOWN 2
+ {# a% h2 Y) x9 z+ u//+------------------------------------------------------------------+7 v- Q6 W: i6 r- ^. |: l% U2 N
//| Base class for models based on trained symbol and period |
7 D* v/ P+ _! N+ ~//+------------------------------------------------------------------+
$ B6 Z6 {$ V( A, l$ C- h _, k& uclass CModelSymbolPeriod/ M, y4 n- E9 [0 B
{
8 W- C* b( t) T$ x* I, `3 [8 Y0 ?; ~protected:6 j8 H+ H* M& n) F9 c1 u
long m_handle; // created model session handle
) c: K" I$ ]$ C+ y6 S% nstring m_symbol; // symbol of trained data, n( {; e! Z+ \ J. [
ENUM_TIMEFRAMES m_period; // timeframe of trained data
. [ I' Q& k, W2 Udatetime m_next_bar; // time of next bar (we work at bar begin only)* ^$ i, m) @" \) w7 A
double m_class_delta; // delta to recognize "price the same" in regression models
4 Y: x# [, d& J/ A0 M; ipublic:8 F( g2 ~ t4 E4 y+ C# p) @4 j
//+------------------------------------------------------------------+
4 C' v1 V0 _6 y+ ^& L//| Constructor |8 n2 ~" c8 w- q- y7 f( k
//+------------------------------------------------------------------+
7 k9 z1 f& u* U' C. }- K* CCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)8 e# z& e8 `8 b- H' g: v) r7 z' k
{+ r, I9 S5 j p3 [& j; n3 n; r
m_handle=INVALID_HANDLE;
; S6 U& v+ R( [* }1 X$ l' Em_symbol=symbol;
) y* z$ Z6 c3 h- E& P ]m_period=period;
9 F" D" E- r5 k+ {$ S( V' U7 lm_next_bar=0;' q8 c$ g! o. R: |
m_class_delta=class_delta;
2 O. e' g$ w# }}
0 v$ n+ {- p( m0 z//+------------------------------------------------------------------+
+ B& T8 S9 }8 |$ m5 p//| Destructor |
; v; w: G) \: ?0 o* \0 z//| Check for initialization, create model |* [/ @" K- c; d* ^8 J6 _0 @: l1 T
//+------------------------------------------------------------------++ U! [% \* u9 {3 Z( a
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
7 d2 J+ P7 V; q; M- f, }{- \6 R. J3 z# U W4 I2 T
//--- check symbol, period0 P! R: F2 j0 K8 A
if(symbol!=m_symbol || period!=m_period)
" O' o* r0 A+ O{
) X, t) ~- F- {' `3 {* B' }- ?PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));4 K' F" i& ~" \# H$ p( E
return(false);
& M3 ]' f: f5 ^' [' f5 ]}7 ~6 B! o4 {2 Y6 s' O3 a
//--- create a model from static buffer
I c, S( h. l; sm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);- `5 a) k3 K0 d5 ?
if(m_handle==INVALID_HANDLE)
9 F' L! m. x0 _5 I: @0 C, v{
8 x! q$ C+ ?: B8 V$ ~. LPrint("OnnxCreateFromBuffer error ",GetLastError());; k/ b8 f4 |- }# `( P/ t7 k
return(false);
" S. x4 D" i d. x8 k}
2 [! d) j2 q1 [//--- ok
/ u; R6 @2 V% [5 X5 Z/ [return(true);
8 }+ m( ~& {# T- Z; S4 j3 m}( I8 Y* Z) z- Q+ Q% u! \ g
//+------------------------------------------------------------------+
; @6 L/ Y6 b- q4 n3 k; dm_next_bar=TimeCurrent();
7 i7 ~7 F- h. D7 fm_next_bar-=m_next_bar%PeriodSeconds(m_period);
4 @1 s+ A7 V( W- c* m! W( [m_next_bar+=PeriodSeconds(m_period);
0 o) a" C3 i$ b4 u& K) j. X6 L//--- work on new day bar
- x B% @8 v, `return(true);' b$ U6 A! C# p3 S2 J
}
! F/ J. a6 e: U7 E//+------------------------------------------------------------------+/ I; `2 S. g/ A# V
//| virtual stub for PredictPrice (regression model) |' I, U: l4 c; G8 R3 s6 x: h( q( E/ `
//+------------------------------------------------------------------+, f$ o( q$ T$ y' X& m& u# V* n8 V
virtual double PredictPrice(void)
- J0 k4 H. b( h" Q2 \{! c) ~ h0 X1 x. s( ~+ b
return(DBL_MAX);
& s9 A0 `) C6 `( x}
' _! X( G" Q; `//+------------------------------------------------------------------+
. V& C' l( Q& T2 I$ h//| Predict class (regression -> classification) |
' o9 p. P0 y, N9 ]//+------------------------------------------------------------------+
/ {( w3 V# T Z- \. Jvirtual int PredictClass(void)8 m0 A. R. p; N4 f. p S/ M
{9 h u2 C( P& z. y) k3 u5 q6 w% ^
double predicted_price=PredictPrice();
: S1 C4 X; b; Y: Pif(predicted_price==DBL_MAX)
8 l1 ^9 d) D2 M: r6 O1 V' U$ nreturn(-1);* {6 N5 t. C& S3 K& s, j/ U
int predicted_class=-1;
5 O2 M6 I& m( s4 ^, R) o$ \2 x* P; jdouble last_close=iClose(m_symbol,m_period,1);
1 A4 A' w- E4 _2 F//--- classify predicted price movement
" k2 ^/ b$ c7 _5 Vdouble delta=last_close-predicted_price;- ~$ Q/ _9 c+ W0 ~8 [* O( J
if(fabs(delta)<=m_class_delta)
0 \$ U7 B+ H! l2 gpredicted_class=PRICE_SAME;' |0 W ], F) U U6 u. Q# D
else) K1 T3 ?. i. H! T; k& _" C# O
private:- @; O; F) Q* v+ P7 p, H' Y+ I
int m_sample_size;
" E" G! L/ ^& ?: G//+------------------------------------------------------------------+/ w& u M) J) I1 S
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)# V* B! _# h! Z' [1 B8 B1 B
{
' \+ \+ r/ c! B( i5 J$ |0 [//--- check symbol, period, create model# C6 ^* N# `2 W6 n/ U" J
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))$ L, D5 \% T( x: }$ c% Z% b6 }5 x. [1 n
{
2 k) ~8 J: K# }, g5 G, zPrint("model_eurusd_D1_10_class : initialization error");& V1 ~2 m0 i6 b# m# O5 t2 w% l
return(false);
1 ?3 e0 x) K# }; w* {7 s}
& l1 s* o6 ]( X5 z" ~" ~* y7 V) d//--- since not all sizes defined in the input tensor we must set them explicitly3 f$ t6 M" r+ ]: ?$ V
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
- e# P8 g. ~5 B4 U! e/ d6 _const long input_shape[] = {1,m_sample_size,4};
7 p; o5 v/ A6 Hif(!OnnxSetInputShape(m_handle,0,input_shape)) N# o2 Z1 u, V/ i" ~! l
{2 c7 P3 X( ~& q& Z. G( F6 d# P/ u
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
& i0 r' {2 `& T( b- N6 U" oreturn(false);+ |! b# s0 }: S( ]* I
}& Y. d1 j8 T4 ^' W: c! l- O
//--- since not all sizes defined in the output tensor we must set them explicitly- p' X! V; G8 D; C! H4 n5 r5 t. s
//--- first index - batch size, must match the batch size of the input tensor1 U) t) W8 ?6 k+ P }5 d! U
//--- second index - number of classes (up, same or down)
7 o' x/ ?- ^) zconst long output_shape[] = {1,3};
% t* H1 [/ x3 ]* ^" F0 c ^if(!OnnxSetOutputShape(m_handle,0,output_shape))
1 J; x# `/ U+ A' G* Z$ E3 e{- G$ O: B3 z; N2 c$ x
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
1 _! p9 H: Z* D2 p- }return(false);
2 n0 k7 I/ q, t( f& o}8 K9 N( C( i$ c5 O- ^4 U# `# `
//--- ok
: T p# E$ `4 e5 l% o; B* Rreturn(true);
) D" V# L0 I5 u' l+ {- m8 t4 @}/ \. R) R8 d6 K: O
//+------------------------------------------------------------------+& ~/ [% Z, L( w' t
//| Predict class |, f7 u7 j- Q+ o) _4 l& N* o
//+------------------------------------------------------------------+
& X2 u5 ~6 J, Q5 lvirtual int PredictClass(void)3 i" i3 p7 J E
{ |