1. 我们会用到什么模型呢?8 S3 t. B$ U, Y3 K/ I( J7 q- @: H3 L
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
: M. }1 u5 D+ Y- V我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
% {( Y& w( J4 c- [! z7 v) H* i' l//| https://www.mql5.com |
0 J* ?: G! B' i1 `. w+ I//+------------------------------------------------------------------+1 D4 p z/ H5 x
//--- price movement prediction
! ^3 O$ y& H [ |#define PRICE_UP 0$ I0 s3 v6 P9 ?' u; W$ ?3 q
#define PRICE_SAME 1, z$ H- L& z8 P* E: |& Y7 {8 E
#define PRICE_DOWN 2
5 x9 T0 R5 y# }1 s//+------------------------------------------------------------------+
: i$ j* I: A' w9 O ^( T//| Base class for models based on trained symbol and period |
' W( H& ^6 \. m/ m( G6 K! p# l) y//+------------------------------------------------------------------+
2 a) O9 y8 ]7 ~( i- H% fclass CModelSymbolPeriod$ t7 U4 E, }5 _( b+ L. {0 b# z& }" y
{
4 W5 ^- N( x$ o6 G5 O" {4 Eprotected:- ]' z0 U* u. _. ^; @8 S. q- U$ F
long m_handle; // created model session handle' _9 H" v9 }1 C, J
string m_symbol; // symbol of trained data( G+ q+ m' J7 D5 _- t
ENUM_TIMEFRAMES m_period; // timeframe of trained data1 T: h8 l% A9 `
datetime m_next_bar; // time of next bar (we work at bar begin only)9 M1 S2 |3 v; C* A$ W9 r3 O
double m_class_delta; // delta to recognize "price the same" in regression models
# V4 M# v, Z/ }* L3 jpublic:! Y! }! w S1 I2 W" g; Y- x! f
//+------------------------------------------------------------------+6 z, M. k e" l q5 ~/ S
//| Constructor |2 G3 Z* J, b9 a) j8 p6 A" U/ L
//+------------------------------------------------------------------+; g5 t! V2 r5 Y+ G
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)- A1 |* Y* a. U2 W, ]& `; Q. F
{
+ h8 H3 A/ E6 s# h- J/ hm_handle=INVALID_HANDLE;& ~2 X/ X. j4 _7 t' e2 B4 v
m_symbol=symbol;
3 w! [, s; }6 Q! S0 t+ D2 i# Lm_period=period;
- G' I% Q1 |. tm_next_bar=0;
- s4 x1 y; `& c4 wm_class_delta=class_delta;; U+ h! q8 R2 m/ |9 S. {) t
}, g0 f/ g6 K5 _, H
//+------------------------------------------------------------------+! r) B* X0 @+ E* c
//| Destructor |
9 X& u" x7 ^/ f f//| Check for initialization, create model |; f3 |9 _5 s- ^3 x9 o5 S3 ~$ ^
//+------------------------------------------------------------------+7 l9 J/ w2 [/ w/ z
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
" ~" t* L& {% O( _9 l{
0 ]: k' z E! }4 R; k! ?' `//--- check symbol, period
" P1 E0 n- U# C8 z0 L0 {( K3 p8 tif(symbol!=m_symbol || period!=m_period)
. I" O9 U H- ?( d{/ V6 t* R0 R/ s9 J, z3 O
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));- G( A* g* e D+ X" n- M* o
return(false);
6 j0 P& J4 o/ y6 }; g}
! l" z5 C3 q8 U4 r: q- ]//--- create a model from static buffer
2 R; @! T7 | i0 o z; s4 [m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
6 i. R s2 q( h0 hif(m_handle==INVALID_HANDLE)
5 Q, J2 j/ ~6 x% T9 R/ |3 K% }{
9 C7 i$ Z8 S( ~3 m* h2 o/ G8 }. T9 PPrint("OnnxCreateFromBuffer error ",GetLastError());) C6 l( A/ l& ]" ?" F
return(false);
; |! i$ G$ c- P' |6 s! w) E# u}
- l9 R: [5 h$ Y# b+ V7 | Z//--- ok
/ ^* R8 ]$ `6 y" ?: ~8 w0 }3 rreturn(true);# `8 W7 q5 `7 G2 e; ?8 _7 d
}4 f0 _3 i3 S/ h2 Z
//+------------------------------------------------------------------+. Y$ R$ J- Q+ a# q8 ~% o
m_next_bar=TimeCurrent();
Y) K2 N$ g" r4 |2 fm_next_bar-=m_next_bar%PeriodSeconds(m_period);
5 h2 y/ i/ C* u7 cm_next_bar+=PeriodSeconds(m_period);
r7 B7 w, N$ o& c! ?//--- work on new day bar, `0 O9 @+ J' {: t
return(true);
: d1 b5 t6 \5 M! N( P}
& G9 `/ R9 ` K: Z//+------------------------------------------------------------------+
) f6 S2 n0 K: T4 G/ }//| virtual stub for PredictPrice (regression model) |' Y" E P1 O( X7 v" h, ~! Y/ j |
//+------------------------------------------------------------------+
; C: M1 s7 K0 Q- ^& e& avirtual double PredictPrice(void)
1 x. K0 s( T. U( G{$ f0 V V/ |5 ?5 J6 G
return(DBL_MAX);; D$ r" V4 R7 ], k L0 M- G V5 ? \4 U
}& M6 _$ V0 i( o% w% N
//+------------------------------------------------------------------+
6 \5 `2 O9 C" R3 y0 P) s//| Predict class (regression -> classification) |
2 G* n0 \- F" n& T v& h. j y//+------------------------------------------------------------------+
5 S8 z% _, p# u2 c$ l4 p8 Pvirtual int PredictClass(void)8 S- z. @% C4 }' e$ T( @$ R
{- N/ c* i% ?1 x" g* z7 v/ O1 z2 D
double predicted_price=PredictPrice();% {' Y1 q, t* U/ i5 x
if(predicted_price==DBL_MAX)& Q5 m) ^' _8 \( R, o
return(-1);
0 K" U4 U F! g3 m4 P K+ x& q; ^int predicted_class=-1;
7 r8 j/ f/ R/ Jdouble last_close=iClose(m_symbol,m_period,1);
! c" ] e6 k- I) k$ d. W//--- classify predicted price movement
+ E3 }% p- H' A4 Adouble delta=last_close-predicted_price;/ _6 S4 h* t/ d/ F
if(fabs(delta)<=m_class_delta)
, V- W: M( \5 F9 \! _predicted_class=PRICE_SAME;
+ _2 b! K0 e- H' X4 ] V" G1 Velse
% {2 a+ u3 u5 i9 A! Z. x1 L$ Z! s0 Uprivate:
4 A- C0 G) j7 [+ jint m_sample_size;
9 p6 }/ s7 k+ }8 _# [//+------------------------------------------------------------------+
: U- r: U) |/ A. B. e4 D4 Qvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
J4 L% h. U- q" q- p+ Y1 k{
) H& d! L/ s* F3 U//--- check symbol, period, create model! R9 @: ]1 W+ e2 y1 C
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
% F5 T) W4 p# _7 w/ n: e{
) \7 y9 o w6 D1 o8 n7 E4 ~( x4 n% APrint("model_eurusd_D1_10_class : initialization error");+ P# f$ l" W) F
return(false);# ?. }0 [- n7 n( G0 ?0 B/ T
}* B1 m: b2 }# L& j9 R
//--- since not all sizes defined in the input tensor we must set them explicitly
6 q9 [( M! t2 u% l' X4 O/ H//--- first index - batch size, second index - series size, third index - number of series (OHLC)
# Y/ u( R8 n- r7 j1 R( [const long input_shape[] = {1,m_sample_size,4};
+ Z% E* M4 n; v1 b/ ?if(!OnnxSetInputShape(m_handle,0,input_shape))
+ [7 k+ t5 v* a{
' c8 Q P7 o/ n5 `Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
c7 ?( m7 ^3 v! D' ]return(false);
5 w) {7 |6 [) q ~4 v3 S4 t* [}/ {" k2 N0 r2 n/ k
//--- since not all sizes defined in the output tensor we must set them explicitly+ v) a; {. K8 y" X' M- C" G0 ]
//--- first index - batch size, must match the batch size of the input tensor
9 l9 {0 s: u" P; Y3 Q//--- second index - number of classes (up, same or down)* w1 Z; m" p) o! H. _) @
const long output_shape[] = {1,3};2 G$ b* C* }0 d$ I& @; c' |* n
if(!OnnxSetOutputShape(m_handle,0,output_shape))
n& R$ M* ?5 w# P; k" U7 {. f{
7 v7 h; }, j: p) ?2 w _Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
3 a+ @- V( h4 B1 oreturn(false);$ ]6 j7 }/ j) a0 ?# s9 Y6 f
}+ o9 w( g0 s+ r5 C7 S3 Q1 E
//--- ok
- ?9 }1 D) t# w; y# @# Jreturn(true);& K0 K$ }8 }5 _+ h
}
6 Y7 O$ T2 e. a- a//+------------------------------------------------------------------+
6 r4 t7 G0 {9 Q1 a# F1 [//| Predict class |! z' }- U) |4 [
//+------------------------------------------------------------------+
7 j/ A4 P7 |5 A4 {8 H/ Tvirtual int PredictClass(void)
% i! I" i6 h: G; g' a. W{ |