1. 我们会用到什么模型呢?% D, X# p0 q3 k2 `0 f! `$ a7 _
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。4 J/ s; E: P% ]3 E
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
1 W* Q( k) C; e) _; _* n//| https://www.mql5.com |
5 D) @8 o3 H0 C' E! k, O//+------------------------------------------------------------------+
D! N7 b: g/ i+ k ]) B3 U- S8 }//--- price movement prediction1 t4 g( F* F( N& k, m
#define PRICE_UP 0' F2 K. d3 d9 R# L5 B5 t
#define PRICE_SAME 1: ]8 v \' k; Z* f
#define PRICE_DOWN 2
* z9 r1 ?( A9 h; ]3 w3 W( c8 X5 r//+------------------------------------------------------------------+
' ^: `# Z- D( V% p//| Base class for models based on trained symbol and period |
1 H8 @" l8 q. w4 ~4 C! b- j! T& L//+------------------------------------------------------------------+$ H" t3 y' P7 a: Z5 |
class CModelSymbolPeriod
. K! j* N! Y$ R( y{4 ]& z# ]5 R6 B6 c/ C; l* [& Z" w
protected:
+ a( ^! ~8 I. |7 }. P- klong m_handle; // created model session handle G+ T# a" ]1 r
string m_symbol; // symbol of trained data7 d. } i) b& |
ENUM_TIMEFRAMES m_period; // timeframe of trained data) }6 Q* F7 ]0 {; R2 c9 f
datetime m_next_bar; // time of next bar (we work at bar begin only)
1 F5 H, C. T0 ]double m_class_delta; // delta to recognize "price the same" in regression models
9 z- Z" t q( N* Jpublic:2 V( R2 `# P: a7 l8 S5 e' L2 J* x* R
//+------------------------------------------------------------------+3 U& n; P: i3 M& m# R/ e/ D3 Q
//| Constructor |! i( v% D) B* f! m$ m
//+------------------------------------------------------------------+
3 J# }2 \* c0 J$ sCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
2 G/ r: v6 D! ]3 H+ v6 W1 b7 O* Q4 \{8 o. H% S$ O' M
m_handle=INVALID_HANDLE;
6 G; F) a. z+ j ~* D+ Sm_symbol=symbol;$ K2 C/ Q3 D+ G, k
m_period=period;
2 D: u1 H6 `1 `2 x1 }- N8 n0 U3 am_next_bar=0;% a$ Q1 W2 V: D: F* B
m_class_delta=class_delta;7 t# ^: z) y. k; X/ f) r+ k8 s3 g
}1 q8 F" D: I# ? Z" e
//+------------------------------------------------------------------+
6 s! U$ W; `0 y3 P7 q3 J3 V//| Destructor |
% D9 o _$ T9 U4 B8 M7 m//| Check for initialization, create model |
$ J3 V0 N6 c+ u$ _; h" t//+------------------------------------------------------------------+
; P0 Q3 S) c. ^0 j% z, ybool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])$ G& M$ z7 Z- D
{
8 h1 O' C+ [5 l i+ z$ M//--- check symbol, period% A4 S/ d( s: f5 M; U# R. i' S
if(symbol!=m_symbol || period!=m_period)
2 t; _7 `( y3 X5 I, Q9 y( c* }6 j{& b1 v j# R) D3 ?
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
8 _& r$ L- X; q8 ]return(false);3 c+ C4 M3 x, b+ H, N
}
& x3 s6 `. I( W' H//--- create a model from static buffer" g+ }- g) M3 O$ R
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);, c# d* i$ d1 C- B) O
if(m_handle==INVALID_HANDLE)4 w0 I2 y( i: {; a) J# L* u& ^
{
2 Q" e$ I% j: c+ zPrint("OnnxCreateFromBuffer error ",GetLastError());
9 k' P5 I" \" \$ `+ P' ?return(false);1 h/ C2 f2 Z4 y1 m- U
}
1 \3 t) a1 s. Z9 x, U& H9 a//--- ok# u' _. N. v+ V# w* L! g, G
return(true); U: Y; Z/ i' d
}
" x: ~- M4 x$ Z# I+ X" t//+------------------------------------------------------------------+
8 r3 L# z6 }1 u- f, J' Rm_next_bar=TimeCurrent();
3 H2 M# d" }* z* ?m_next_bar-=m_next_bar%PeriodSeconds(m_period);
* [% ?" {# D/ e# F& X( p$ `) Am_next_bar+=PeriodSeconds(m_period);" c. [) U6 H: `+ V* E4 L8 K
//--- work on new day bar$ @; H% m% ^6 {& X
return(true);# r x) T- s% D8 o( N- ]' a
}4 {7 P# M; ~$ F D" E: a* O
//+------------------------------------------------------------------+! |0 M5 I+ C1 e
//| virtual stub for PredictPrice (regression model) |' u) ^- p. d1 T& M; ]+ r
//+------------------------------------------------------------------+
2 }7 f6 v4 R) R1 M }7 E( Vvirtual double PredictPrice(void)
0 h8 g! z' j9 t) i{4 e* W( u6 e" {- y \8 x
return(DBL_MAX);
+ N- v* `/ ]* ]. E* x; I}
% b7 G* t3 |# C6 D: q3 p2 G. C//+------------------------------------------------------------------+4 Q: R1 `$ v4 W4 G/ F8 G
//| Predict class (regression -> classification) |+ i6 T& Q. E1 A& o
//+------------------------------------------------------------------+% p, O" g+ P, i# Z
virtual int PredictClass(void)" n* A& E2 C6 o. q
{4 m! }* r; [8 k+ H: P
double predicted_price=PredictPrice();
' t# {; y+ }) R$ h! t' Xif(predicted_price==DBL_MAX)
7 Y6 _6 A8 L0 }8 C1 Areturn(-1);
' {2 X" e3 t9 Cint predicted_class=-1;
! E) |. n6 B! l, Pdouble last_close=iClose(m_symbol,m_period,1);1 z, d/ E. S! E" I9 l0 b3 X
//--- classify predicted price movement
' R& K6 M8 \9 Mdouble delta=last_close-predicted_price;
$ F3 f ?; |/ ^) lif(fabs(delta)<=m_class_delta)$ q0 U$ g8 I# V# X% u
predicted_class=PRICE_SAME;8 @ _' ?2 q$ K- _- K+ R
else
" O& f9 |) f6 Q {4 V. A* B4 Aprivate:( t$ h5 r g# e" N' g7 X9 |% m
int m_sample_size;* r! y$ S0 l2 t5 t' F/ C
//+------------------------------------------------------------------+& t9 s5 Y: S# d3 g7 r$ @& b
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
% {2 J, |& R5 t9 ?8 ^$ j; B' F& q9 R. z{
5 h s. }& D. W0 n5 s: l//--- check symbol, period, create model: z/ z6 H% n" e T' B0 }
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
% Q" I" V/ x1 ^+ ]& b{+ R$ s8 @3 ?! u9 O$ j1 d( T
Print("model_eurusd_D1_10_class : initialization error");
2 I) x9 ]0 `) {/ T" L/ ]1 xreturn(false);7 H- E; j: Q5 W6 w- t0 x
}
# g- Z! e, @/ W4 I- f7 n% S/ s" {//--- since not all sizes defined in the input tensor we must set them explicitly
. v# y3 G9 u+ }( L//--- first index - batch size, second index - series size, third index - number of series (OHLC)
2 o( C. I/ ]3 Z" ?. E" Zconst long input_shape[] = {1,m_sample_size,4};
( l, [0 V/ [9 h/ z8 Dif(!OnnxSetInputShape(m_handle,0,input_shape))
r# R, b" L3 C2 ]3 ?! b{5 i; h+ |, `0 o, c4 m" R6 D
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());4 r9 F0 L: y' g
return(false);
& N, E7 v2 J! N% v) e8 b. f! u} m% q0 k2 K5 f8 r7 A/ c
//--- since not all sizes defined in the output tensor we must set them explicitly/ y' {; o) J3 w4 k+ N
//--- first index - batch size, must match the batch size of the input tensor) d3 K; k5 |$ I& ~, W3 A+ y
//--- second index - number of classes (up, same or down)
! h8 D4 }8 _8 `! ?const long output_shape[] = {1,3};
0 R( v$ G4 [' \ A! _% Oif(!OnnxSetOutputShape(m_handle,0,output_shape)): G3 H$ M- {6 C( x5 K
{ u/ `3 x) R1 p: O$ f- f7 t
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
1 R. f9 ]3 G# _9 X# b# Z3 _return(false);
5 m/ E! ~( g% D& N}) x" R8 P+ [0 x# i9 o
//--- ok
; y9 R4 P. w. F6 D/ F/ mreturn(true);
9 L: F) `: R0 T6 H- R}
7 @ i3 p, `* g4 ^ ^7 I//+------------------------------------------------------------------+
; r, Y1 X5 M5 i) r//| Predict class |( F( K8 B9 z/ \% |+ S
//+------------------------------------------------------------------+
2 j9 Q- Z3 {* z+ w2 A, bvirtual int PredictClass(void)
9 K! c( d" o4 l8 D$ t, h{ |