1. 我们会用到什么模型呢?
! E8 I* F! v7 U0 W7 ~在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
6 E7 s4 F% A6 g+ u7 Z' g* e我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
1 B2 K0 i b3 r4 |//| https://www.mql5.com |
( M5 W7 i, }$ C$ \" T$ q m//+------------------------------------------------------------------+
4 Z0 L: u) l% ]' Z6 b) v0 ]//--- price movement prediction( s$ U# I4 k# b: m8 i, _
#define PRICE_UP 0& ~: r$ k/ k2 C' N* Y& ]6 H/ t4 P: ]
#define PRICE_SAME 1
2 }- x( d& [# n" V$ F3 \#define PRICE_DOWN 2
) R/ p/ n4 i' _//+------------------------------------------------------------------+& J# e# t4 a9 F1 _
//| Base class for models based on trained symbol and period |
4 O4 p4 ?, p' T6 j; n+ _6 j//+------------------------------------------------------------------+' W: e$ c0 Y9 v# u4 Z* L
class CModelSymbolPeriod. A6 S7 u; N" f& @; ]% i8 `# P0 j# n
{8 h; E! `/ J4 y) {
protected:, H2 R' S8 f! t
long m_handle; // created model session handle
5 ~0 h2 Q+ K) Ostring m_symbol; // symbol of trained data
$ }- { o9 F- O& y* lENUM_TIMEFRAMES m_period; // timeframe of trained data
; j. A+ a/ \( Wdatetime m_next_bar; // time of next bar (we work at bar begin only)
) s2 {- |- W- K4 d( Qdouble m_class_delta; // delta to recognize "price the same" in regression models+ O! ^* r. ?% J
public:
, o- M1 d/ m* O; q, q; A//+------------------------------------------------------------------+$ _9 `& O. I1 @- V& q
//| Constructor |! T% g! W: R. x0 q
//+------------------------------------------------------------------+5 n0 A$ @7 U) @
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)" d/ e/ i5 e$ p9 O. c1 ~( P4 Y
{5 c6 A# ]3 X9 w5 O/ Z2 k
m_handle=INVALID_HANDLE;/ f, _9 ~( _5 l3 q
m_symbol=symbol;
0 t$ c9 o# l8 ^: Jm_period=period;, d3 q. @+ M6 f& c n# M
m_next_bar=0;: Q2 ^+ k( S. T. D
m_class_delta=class_delta;. M9 L% [4 a9 R) ]' ?
}9 c+ W8 I5 Q0 ?9 ~8 i; E1 B# s. l4 i
//+------------------------------------------------------------------+# m* |" s! K$ F+ E. E
//| Destructor |! ?' U2 X+ r' U
//| Check for initialization, create model |; i+ w+ {$ J6 i; Y& u" N7 l
//+------------------------------------------------------------------+
" p+ g4 S* n) h! \2 v8 gbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])( I' v7 Z4 }4 U% Y$ g% W
{6 |$ @8 y9 w. Q0 @' v# C& i
//--- check symbol, period
( z( K- ^9 J# |( @' qif(symbol!=m_symbol || period!=m_period)
L1 T: z' P/ B" H{( _. Q$ z1 u# ^! ?: S4 Z5 Y
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));; b: U9 Z8 |( ?# p2 j
return(false);
& h. k9 Z/ \% y& g4 b( I. s6 g- Y# X}
& O( {+ _! m, |" W, h, m3 f//--- create a model from static buffer* ?$ p7 ]. U. j: ~
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
: ^: A1 W1 \, f% y/ bif(m_handle==INVALID_HANDLE)! c8 _1 O9 t) T' O* j+ r
{2 A( k4 H. c6 v# `; j
Print("OnnxCreateFromBuffer error ",GetLastError());
+ P. q3 s/ z3 ]* B' Q' Ireturn(false);9 }% D$ A" E9 t. \. t8 X( c
}
0 |* O% Q' {; O2 H) s//--- ok
: I+ D5 A) u9 J, `6 b0 vreturn(true);/ t) k2 ?3 a. b3 s% w7 T
}
/ c i+ X E9 n//+------------------------------------------------------------------+
( }8 n4 n4 |0 S( ?# Xm_next_bar=TimeCurrent();
7 j& b7 Y/ G" |; k; Z2 im_next_bar-=m_next_bar%PeriodSeconds(m_period);
+ L5 g7 O4 j mm_next_bar+=PeriodSeconds(m_period);, Y" W' V# C8 Y/ R$ G3 c {5 b. F
//--- work on new day bar
) W! _) q& i8 |: U* }2 mreturn(true);, o1 F, E" p" a
}
$ ?- g W w$ `& U//+------------------------------------------------------------------+. X# ?+ O. C" x7 f9 _# U/ v" r
//| virtual stub for PredictPrice (regression model) |
# r2 `! Y: g1 ^6 ]//+------------------------------------------------------------------+: I% c( j1 |9 k8 z" ]' P' c3 k
virtual double PredictPrice(void)4 b- J$ y0 e" Z% \8 z6 U$ Z
{
0 N/ E) R' ?7 m* L( }return(DBL_MAX);
k E2 ]3 a# X" }9 y6 S w9 P}" ^7 U" U/ c# q( c& {, r% N
//+------------------------------------------------------------------+
* C) l1 [: k2 s c/ P6 i//| Predict class (regression -> classification) |/ s8 N8 t( X7 r" [
//+------------------------------------------------------------------+$ q+ B) s& H- G1 L
virtual int PredictClass(void)5 \- A- v# g. n$ r9 u' ^% }/ i2 M
{
: p. H% N3 |% d4 xdouble predicted_price=PredictPrice();; _+ j% z) U7 G) F$ E
if(predicted_price==DBL_MAX)
8 P: @! T! C% o( h, t0 L8 e( t% Z% nreturn(-1);( O' f9 n) B5 [. _ h% m
int predicted_class=-1;( y* Q' }, f( F; \
double last_close=iClose(m_symbol,m_period,1);
- Y/ f2 ?9 n0 ?. Z' u A4 Z% {9 z//--- classify predicted price movement
# X# y8 B& X' J% I- udouble delta=last_close-predicted_price;- e' Z' H5 U& j* ^
if(fabs(delta)<=m_class_delta)
% g' v0 H# X: w& Qpredicted_class=PRICE_SAME;
& L" v2 `- f7 s6 C% g) w0 {; h2 C# M$ Velse- g1 i, `1 t: T5 N' n" K$ s
private:
: l$ t6 T* y2 V8 V. _6 Wint m_sample_size;0 i; [$ j- g7 d4 Z
//+------------------------------------------------------------------+7 Y/ Z3 R1 f0 v4 V" F
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)+ U7 N9 J1 S1 p
{
# Y9 e( N; P3 x3 J0 I% m. _//--- check symbol, period, create model
; g5 K Q' d/ p; g+ xif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))/ j$ r+ k# W, y! }
{3 B4 N. @% O- @7 y- ^8 e
Print("model_eurusd_D1_10_class : initialization error");
" P% m7 `3 {" X. _1 \; o; V$ q+ Freturn(false);$ o$ j/ B! |, ]: v8 }( T
}
b! \* h7 g8 ]//--- since not all sizes defined in the input tensor we must set them explicitly
' c% e0 V, N' C//--- first index - batch size, second index - series size, third index - number of series (OHLC)- W! y- w3 r; R+ x" `: M5 G* j
const long input_shape[] = {1,m_sample_size,4};
- P. m' A6 `+ {: [2 hif(!OnnxSetInputShape(m_handle,0,input_shape)); [; [- w' a: [9 H
{, L$ U# j' D) U
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());- t* |+ k. N( q3 C8 S; t. {: C* h. F
return(false);) [- `/ U |1 H" R
}8 K9 b5 x. \7 s5 M3 | `
//--- since not all sizes defined in the output tensor we must set them explicitly
- G& V# c7 N& D1 y( @! b2 L' _//--- first index - batch size, must match the batch size of the input tensor; ]3 {; w0 y0 \; C2 L7 S
//--- second index - number of classes (up, same or down)! l% q' o+ d1 ?+ P
const long output_shape[] = {1,3};. V M& H" S) W# l8 K R- s, l+ H
if(!OnnxSetOutputShape(m_handle,0,output_shape))/ ~& \/ P! c7 |2 a0 V4 S9 f6 D
{
& Z7 B# L7 N# G' M, y" H7 U9 aPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
! w/ D5 ^9 G& y) w0 {return(false);) V, P! l+ [& e" }( B
}4 d3 o! Q# _; q9 t! v
//--- ok, Z! d! |' D3 }% C# _
return(true);
; ]1 W& D% E/ p& M}
: F$ c" o. v5 s3 k//+------------------------------------------------------------------+$ j; Y4 h" [; n# c+ q W! |, P5 {6 v
//| Predict class |
( o6 ^# W4 K4 U$ V0 {//+------------------------------------------------------------------+
! H; ~% n5 a* J) Rvirtual int PredictClass(void)
+ y" ~# F( n( L6 [{ |