1. 我们会用到什么模型呢?+ t0 s& u# p) Q- V# i* b
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
9 V6 m* L- p/ v7 X. \我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进/ F( P* Z0 P4 X$ A
//| https://www.mql5.com |
* R U/ w" w7 A6 {$ }5 `//+------------------------------------------------------------------++ T0 q: ~( k7 W" o4 a' g, j& D2 m. s
//--- price movement prediction' ^' F; |. T( I& y) U b, {
#define PRICE_UP 03 ?1 B3 ~; k: S7 H# P
#define PRICE_SAME 1
9 y) t8 R8 ?* h( b( s- j2 p#define PRICE_DOWN 21 A5 m+ W7 H& u
//+------------------------------------------------------------------+
1 M% w# E' D, W+ W6 i/ h# ^//| Base class for models based on trained symbol and period |
' G) L4 ~9 U/ u% R+ j: G1 O4 }//+------------------------------------------------------------------+
( ]1 m. f4 \6 i' M7 _) @class CModelSymbolPeriod
' F9 w* z+ U* i! W$ z/ t% p{
+ A7 F8 H* v, p7 P: \+ Zprotected:" h/ C; s$ R) d; P( \
long m_handle; // created model session handle; U! `( G8 A/ H/ z$ w
string m_symbol; // symbol of trained data
8 n$ r) p& W( l5 B" NENUM_TIMEFRAMES m_period; // timeframe of trained data
# A- g ~9 h, i( Sdatetime m_next_bar; // time of next bar (we work at bar begin only)
' F; @3 Q$ I0 o @. x8 |double m_class_delta; // delta to recognize "price the same" in regression models
4 l( `2 i* T, Ppublic:
4 T, y9 ]8 E/ P5 u$ D. s//+------------------------------------------------------------------+
0 y1 ?6 K. A- b//| Constructor |! _. a8 R+ W5 O, h, N3 U% }
//+------------------------------------------------------------------+, B4 H, U6 E4 [1 A$ f
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
( b- c! @& q% Z{
# L3 E3 N$ d6 Y# q0 tm_handle=INVALID_HANDLE;' ], a& y9 B% N8 f
m_symbol=symbol;7 P" S( |* ]9 X4 E
m_period=period;7 d' b% W1 Z) B" U6 Q
m_next_bar=0;
, R5 B: @) G& U" fm_class_delta=class_delta;) ~: U6 @" l8 B3 A& Z; ?
}
" G0 Z* @, ^& j4 E+ q/ a+ F* `//+------------------------------------------------------------------+# u+ S7 e$ m8 u1 }: w/ Z8 `' A
//| Destructor |
( J+ Z0 v( T8 N* E$ H3 m' S//| Check for initialization, create model |/ S y. o! D0 J
//+------------------------------------------------------------------+4 C& _, X! t1 D/ Z
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[]). g1 e2 V! b: N J, _
{# T( {8 T+ L0 s v/ B1 n
//--- check symbol, period
0 R$ L' P1 x1 J- u1 w2 eif(symbol!=m_symbol || period!=m_period)
~; l& d) Q5 T( b) v. L; Y{% Q0 h" x. g1 _: d0 c, m
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));* G# J: A0 a3 o' f J8 j& j; F
return(false);
1 Y$ T9 @/ t" a" G7 f {+ V# @}
9 ?7 F. S; R# i8 z4 Y* Y- i//--- create a model from static buffer; w) g; f$ \9 X& O/ v
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
[9 z+ Y9 R5 V2 R1 m+ Wif(m_handle==INVALID_HANDLE)- l+ R& b8 Y4 i
{7 U/ K0 Z2 e, E. H
Print("OnnxCreateFromBuffer error ",GetLastError());! Z3 G9 u3 V- c& |9 _
return(false);
$ q2 D! ^$ k% O: [5 D, u}
7 t8 o* K. i$ L) S; O//--- ok e3 U/ |; o1 ~9 I
return(true);+ B- X1 D& Z) _( t1 t; F, I/ L
}- t- f4 S- v. M9 I: ]* H
//+------------------------------------------------------------------+( i! o- K% S3 E2 j
m_next_bar=TimeCurrent();& a7 i# m! v X" J/ b
m_next_bar-=m_next_bar%PeriodSeconds(m_period);8 P( W8 X) `0 [( x- J
m_next_bar+=PeriodSeconds(m_period);
/ F9 y1 W& C$ g! J//--- work on new day bar; T# l: K: o% q
return(true);% x0 W* A5 X# v% b& ~
}
5 ]$ f ]; w9 r4 @! V//+------------------------------------------------------------------+
6 T/ f; {; A+ n4 h$ S; S5 T//| virtual stub for PredictPrice (regression model) |
. B& z( }1 B: R9 x6 _" y//+------------------------------------------------------------------+' j0 ~% k; y8 @) J# A6 X5 G! A3 s* r
virtual double PredictPrice(void)' c Y8 c! S5 q! p$ v/ p5 U
{
; @& E+ F( M; {% T6 \return(DBL_MAX);! K8 k" f: C# |. ^: u& v
}* R6 q) H2 z, A3 @: Z2 t7 g3 C
//+------------------------------------------------------------------+6 u9 w. z( b+ Q8 B
//| Predict class (regression -> classification) |
& m/ k, | O2 T; _8 ?//+------------------------------------------------------------------+
w( O- a( w Y6 s+ w0 A- O+ R2 F( Ivirtual int PredictClass(void)) V' X3 O, _0 J
{# \- F3 ^9 P' b2 p7 [7 J
double predicted_price=PredictPrice();7 @- _) Q, [1 ]9 R& u4 Z
if(predicted_price==DBL_MAX)( n) I6 q2 e; a8 ~5 }
return(-1);
~! o# T# G, G8 N8 @; v$ Fint predicted_class=-1;# ^9 u* O0 N/ ]) B
double last_close=iClose(m_symbol,m_period,1);- ~0 @* Z0 F& E) G3 v
//--- classify predicted price movement
- ]; m% H0 t, d' S, m% ydouble delta=last_close-predicted_price;% m; b- c' E2 ?; e2 Q9 f" n) S
if(fabs(delta)<=m_class_delta)
) l7 u. V2 ~0 ^predicted_class=PRICE_SAME;
' Q" Z' V8 h [+ X: pelse" E( D; K. V% m9 \$ B& n
private:
8 g5 x P( F! N$ Oint m_sample_size;
$ y7 x# g" z8 J' M9 i G% O( [- K//+------------------------------------------------------------------+" V7 h3 t0 ~% M( f+ ^; P. ^
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
0 O1 b1 _. s4 H- h0 f# k{
4 i$ W1 b# r$ F0 e" H' E5 j- y//--- check symbol, period, create model; Q% W8 c" T5 `5 w! V0 x. G6 l
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))$ L9 o" e# o+ C0 a
{
) q/ v% y; p, T" V3 F8 X9 ?Print("model_eurusd_D1_10_class : initialization error");
4 O9 T2 z& `* C; mreturn(false);# _* Y0 [3 i2 K; ]* L% ^
}: ?$ B3 ~% \# b* A' s, L! V" k
//--- since not all sizes defined in the input tensor we must set them explicitly
. y. Z: p. a6 d- z( B6 h//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 E" [1 R) l' ~: P- j5 g+ Mconst long input_shape[] = {1,m_sample_size,4};' X% l8 v/ I2 |! O6 F: O
if(!OnnxSetInputShape(m_handle,0,input_shape))
, q8 J2 U+ \$ N1 k2 a6 n+ `{- j- W* k- I- o" B
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
; \; R/ M; o1 O! d5 E( [return(false);, [/ o* b L2 a
}
/ K! j6 J( I4 L//--- since not all sizes defined in the output tensor we must set them explicitly
! Y8 g4 R( O8 t9 ^//--- first index - batch size, must match the batch size of the input tensor
5 k r( n; o3 Z$ k+ W4 ]1 \9 [* ~- ]//--- second index - number of classes (up, same or down)
- @( Y. ~, ~) k. U8 z7 K% [, cconst long output_shape[] = {1,3};
3 P x) a( I @- _5 e9 Aif(!OnnxSetOutputShape(m_handle,0,output_shape))
/ D( b! r9 x4 d, k7 g1 g{8 F; C9 S, ^) l- H2 w
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());* w2 _5 M$ z9 ^
return(false);; z( O* l8 u( R4 p: n
}
: o' h8 L, V( Y/ F/ q& v# r7 z; n& B//--- ok1 r8 @( X' I# B3 x$ L8 h
return(true);& ~1 d/ R& y# D3 F
}
- j2 N1 k! {. t k# p" k9 @7 J$ k//+------------------------------------------------------------------+
$ P2 Q! N1 C; I//| Predict class |5 m R j' V0 o7 m- K% \
//+------------------------------------------------------------------+
2 e' G- l0 X4 v9 m8 gvirtual int PredictClass(void)
% P0 l7 `: I" A{ |