1. 我们会用到什么模型呢?
* V7 U0 T- ~- }在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
8 y% m0 n) |# ^9 r U/ j5 l. a8 P8 F我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进1 q+ L+ j" ]4 q! R
//| https://www.mql5.com |. a2 E, t! H. a# ]# L1 r2 }$ j) A
//+------------------------------------------------------------------+
0 m' `' O, D5 D$ e3 @% P8 R. y# c1 Y- y//--- price movement prediction# C3 q5 C7 K+ h; j }/ ?
#define PRICE_UP 08 i3 C6 U; W ]8 k+ ]
#define PRICE_SAME 1$ C( B+ F& o% \* a& V' T
#define PRICE_DOWN 26 m7 e4 g6 F' W" o3 t. _; D: z1 R
//+------------------------------------------------------------------+) H9 z D7 z1 D3 m5 f0 t/ J
//| Base class for models based on trained symbol and period |( K" h! P2 U9 C& O v- @9 j6 A! ^
//+------------------------------------------------------------------++ i3 W" x0 R- v! Y4 \' g, b( e+ G
class CModelSymbolPeriod \, C* g8 g2 b( R7 b* S
{
% v" f% M. k. F6 h5 \; t' ?- X, mprotected:
- O+ h8 {; K2 n. N" z g ^long m_handle; // created model session handle9 e. V2 R. c/ f; a
string m_symbol; // symbol of trained data2 Q) L2 J3 L% w3 d$ ]
ENUM_TIMEFRAMES m_period; // timeframe of trained data
5 y) m6 v- C1 f: ^6 W- Kdatetime m_next_bar; // time of next bar (we work at bar begin only)
! ^/ [2 S& J- m' K' j+ Gdouble m_class_delta; // delta to recognize "price the same" in regression models
0 Z% E% [/ Z' p1 s$ K7 [7 V# ^; M- Ipublic: `1 s/ O# g- G* u
//+------------------------------------------------------------------+
: N, z; M$ K" a- d7 S! V//| Constructor |
7 O: ~- u7 x: o: ]+ F//+------------------------------------------------------------------+* h' [6 i) t) e4 G& P8 \
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
9 O6 Q) X: g0 Z4 `5 B# ?{
& O. ^' _; ?1 }! {1 t* Xm_handle=INVALID_HANDLE;
; j5 L$ j2 W0 `$ E6 T. rm_symbol=symbol;
6 F0 x% t6 @9 o' o/ M' em_period=period;" i6 g/ g9 E5 @9 S7 X, A5 l& M! M' x
m_next_bar=0;
6 R( @7 y2 m5 g; Zm_class_delta=class_delta;
1 e7 r2 J9 M# V3 a}9 Y3 {! f2 J. s$ g, g- c
//+------------------------------------------------------------------+9 m" S$ g: `( K% k s+ t3 C- I3 j
//| Destructor |
" n% n8 V, j& f* T3 W/ Y' [3 f//| Check for initialization, create model |2 ~5 q; n. g H' Q. G
//+------------------------------------------------------------------+3 L! {4 m6 [4 o2 b
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
2 O, a" S5 h. s- p{
3 H, A9 C9 p2 x; f7 B7 |, G//--- check symbol, period, T7 X# q/ J, Q# X; P0 z! r# s
if(symbol!=m_symbol || period!=m_period)
3 L4 l( Y* L/ A- i{
" B& `# d/ _6 @% u) kPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
- ]3 `' r$ @" t, W$ O: x' B1 Nreturn(false);
2 L1 T) S: }- U; U$ A e% ^}2 H: m0 F. f, ?$ z
//--- create a model from static buffer
/ V' {& K' X( \4 v3 |m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
3 L$ G9 y, V7 P: [9 kif(m_handle==INVALID_HANDLE)
0 z+ U4 g4 N! Q: Z" H1 b{' }- z% U$ L- |2 P$ N3 w: u! K! k
Print("OnnxCreateFromBuffer error ",GetLastError());3 t7 C* c: ]+ U
return(false);/ r, c; y3 V/ D. _4 w- E2 z
}7 v2 X9 T6 U, c0 s) k+ P6 @- o
//--- ok' p8 h; Y* E/ q5 g) f5 x! ~' X" ~
return(true);5 |+ S2 B' ]/ y0 p- s: [+ Y
}
1 U1 e$ j' u9 m- {//+------------------------------------------------------------------+ ] i3 R4 n5 f" ]
m_next_bar=TimeCurrent();5 q$ Z, a, M2 O
m_next_bar-=m_next_bar%PeriodSeconds(m_period);. y: |, {3 B7 V6 n9 Q7 C5 \
m_next_bar+=PeriodSeconds(m_period);
1 i- j$ {" H- p& W Z8 H//--- work on new day bar1 g1 z/ N$ i8 H* h }
return(true);
6 |6 j7 X7 F+ N$ y7 d- C}$ Q5 O6 p2 {( D" t4 X
//+------------------------------------------------------------------+
7 M- y* ~' `0 e" A/ A% O//| virtual stub for PredictPrice (regression model) |/ g: Z) ^7 e: }$ n3 c
//+------------------------------------------------------------------+6 V8 n/ l [; P3 k- u
virtual double PredictPrice(void); R# t! k! k2 r6 O, |, Z! j
{7 Z3 V, Q2 d5 w4 `- L& n
return(DBL_MAX);
k+ L4 U) M2 \5 c; [# h}& P! [8 d5 R1 j1 @- M# z* e+ W! M
//+------------------------------------------------------------------+
! @$ l9 P. z3 n6 k+ R# P//| Predict class (regression -> classification) |
! u! Y. h$ J+ \& F5 B. p//+------------------------------------------------------------------+
& g* x7 ~0 `' I' J7 ~1 H! {" ?" ?virtual int PredictClass(void)5 s w8 Y" @0 A- R. Z+ g
{
# E1 p$ x- _/ \. ~& T0 N* g8 Wdouble predicted_price=PredictPrice();
) w# o3 k+ W# m kif(predicted_price==DBL_MAX)+ W7 L% V7 n. M9 g, N
return(-1);
8 r+ `. @. w9 H1 x& oint predicted_class=-1;- ~; @+ ^+ }% E2 l3 y) e; Q
double last_close=iClose(m_symbol,m_period,1);
/ E2 _0 Y3 s* y+ B' E$ k4 L+ i//--- classify predicted price movement
+ W$ G. n; N, r: X9 _- Odouble delta=last_close-predicted_price;1 J; {" h3 ~5 p# ~, E m( D
if(fabs(delta)<=m_class_delta)2 ?# T$ }) q( C l7 l) h
predicted_class=PRICE_SAME;
9 E2 k* ]1 q' {+ b/ velse
1 ]+ K( Y# _5 P0 I5 Y4 h# Cprivate: L! m) w I; s$ L" u2 I
int m_sample_size;
, N9 x+ S+ z P//+------------------------------------------------------------------+
& i$ s1 ]) d+ m$ Y% T9 ^+ y; W. h+ L" evirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)/ E5 g7 B H! i# T# Y6 M
{1 j' D+ g: L5 R
//--- check symbol, period, create model. W/ h/ u; b+ P. D3 r
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))3 m& m' ~. K5 d; `
{' C- U+ F/ u( [( e) ~( J
Print("model_eurusd_D1_10_class : initialization error");' ]( |' W8 f& R0 j5 Y# p
return(false);
" _3 G% F8 U) c- l}; `! j2 n$ ?& w4 r: y* w; Z' g0 }
//--- since not all sizes defined in the input tensor we must set them explicitly; k9 g6 b& ~3 {: _% X8 @' i
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
: i- ^; Q( U# B7 v1 r' cconst long input_shape[] = {1,m_sample_size,4};
0 h& o0 J4 u) G6 ]6 ~7 eif(!OnnxSetInputShape(m_handle,0,input_shape))% o$ L9 @ v& \/ c9 o* o
{
' `* e8 N8 F O' A9 r4 pPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
8 T- z# \4 j9 Q6 A8 K4 sreturn(false);% E# t* s: q( g3 s4 f; M; P5 [1 x# g
}
0 s2 N2 _' V7 E4 I//--- since not all sizes defined in the output tensor we must set them explicitly
. f1 d1 z7 n2 f! j4 W+ f//--- first index - batch size, must match the batch size of the input tensor7 F! J2 \. C w4 v; G
//--- second index - number of classes (up, same or down)
) D K" J$ V2 S+ e& g) Wconst long output_shape[] = {1,3};
, m6 h9 X4 o v- T# ~" ~( fif(!OnnxSetOutputShape(m_handle,0,output_shape))
* W- E; W( A/ |& B5 l; O{. [ t- q2 `$ L0 y
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
+ \' v; S/ r; f" mreturn(false);
7 q) v' W# g. b}
& L5 i# L% {; Q6 l" w1 `//--- ok
! N5 A; y$ u$ j1 Hreturn(true);
- }; ?% j+ d0 ?3 K2 Z8 y# p; A; v}
, E7 d) Y. |3 A" Q$ y//+------------------------------------------------------------------+
9 v$ d4 B& g; k, `4 _//| Predict class |
- l2 ~4 [& j8 }+ r//+------------------------------------------------------------------+" _% e' ]4 |2 ~( c. s
virtual int PredictClass(void), J9 ?% I' g6 h4 A0 Z, u
{ |