1. 我们会用到什么模型呢?
" s( q. S! e! P+ i0 u5 S3 h在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
6 P' ^3 j2 y t9 M5 g$ Z我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进$ {' O; _; C. P8 k* L6 `. q0 g! t% i
//| https://www.mql5.com |
* T7 k& a$ g& g1 r//+------------------------------------------------------------------+
# c' Z2 o U: [( `/ L1 l+ B//--- price movement prediction
; L! ~% M& s4 r0 f, E#define PRICE_UP 0
- x/ n! U) _3 k! D, @4 A#define PRICE_SAME 1/ E1 e9 Q: p) a1 w" @" N
#define PRICE_DOWN 2$ B7 t' S; C9 u6 G4 [) @
//+------------------------------------------------------------------+
8 R# \( r3 w( ^//| Base class for models based on trained symbol and period |
. \2 k9 X$ \/ i- l# r2 }! H//+------------------------------------------------------------------+% L- o" [4 c5 W t# C/ c
class CModelSymbolPeriod1 l6 Y' g9 Q$ @- F
{: ]* _" A% m$ s$ M, I. Q
protected:
6 m' F0 y7 _. L! s1 J1 llong m_handle; // created model session handle( e% Z- {6 }- n j. }2 l R
string m_symbol; // symbol of trained data3 K2 B- ?: o3 q7 ~, o3 `
ENUM_TIMEFRAMES m_period; // timeframe of trained data
( W/ t; b! _) L4 M3 n; odatetime m_next_bar; // time of next bar (we work at bar begin only)! |) E( Y: E9 d/ a; X1 g
double m_class_delta; // delta to recognize "price the same" in regression models
9 o& G) f' o rpublic:3 F9 z3 a+ [+ S2 k: |
//+------------------------------------------------------------------+
- h) r# k4 E a- V: Z+ c//| Constructor |/ w Z+ s+ V/ f/ B; X9 t
//+------------------------------------------------------------------+. d! ]& H1 Q4 c& F+ b
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)+ l. `, B6 t* ?+ u: X
{& ?6 \% `4 ]- i, D
m_handle=INVALID_HANDLE;
9 k. E8 F8 _9 n% \m_symbol=symbol;
2 T( y- ^$ K6 y; r, u6 V' r* U& Em_period=period;
7 x, w4 `" Z2 T0 |3 vm_next_bar=0;
4 ?/ d! R+ e- _) `% um_class_delta=class_delta;
9 d% y, U$ p. k% I* Z( b; ^; T, D}( b6 {& B& L8 L0 Q5 n+ V( S( r
//+------------------------------------------------------------------+
: d* W6 a7 H$ ]% m//| Destructor |5 a- I) W" i; J8 a- A2 P
//| Check for initialization, create model |! G, a' X. @; K/ [/ W, H
//+------------------------------------------------------------------+" k x' c1 u2 H; V
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
! X& `- R: i, Z0 m7 c{: i! H* K: X0 W- r) J( F1 V: {
//--- check symbol, period
. b/ K! [6 y0 x! s8 K1 s* z- Rif(symbol!=m_symbol || period!=m_period)% g1 m. l) E* d: y4 y6 ]
{9 `5 V+ b3 D$ B; T* x g/ \+ Y
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));0 {9 E7 d7 m! h5 X( ^
return(false);. I0 O8 l5 Q. _. y9 f. c
}/ x) V+ I% x5 G
//--- create a model from static buffer& F, f* Y' f( |% K7 @
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);; U4 p5 J7 |7 d4 B2 N7 c
if(m_handle==INVALID_HANDLE)
2 g' J* A5 J# x6 H/ H{
3 i Z7 ~8 M1 ^8 O" r- rPrint("OnnxCreateFromBuffer error ",GetLastError());
7 e* n5 f* W' j- jreturn(false);
" ], Z2 F, }4 }/ y. U}
' Y6 d! F/ s P& j//--- ok1 e: ] X+ \- L2 X$ g
return(true);0 h( ^1 p0 r" k' Y# d3 Y' _
}
6 }6 _7 k" u' o7 H! w, u//+------------------------------------------------------------------+
. O; J6 {) [ M2 b5 Em_next_bar=TimeCurrent();( J, F; |$ D8 `( r, b B
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
9 y7 M, ]1 [0 J) X6 u0 {m_next_bar+=PeriodSeconds(m_period);
' @! b9 w8 u# }/ c7 F7 L4 y//--- work on new day bar
: U% T6 h& p$ A! kreturn(true);6 ^$ m4 B8 P7 r, I; Y5 {$ N: u3 y( c
}
~5 l+ M& @7 r/ ]//+------------------------------------------------------------------+
3 R0 e; f5 e7 f* ^! c( i//| virtual stub for PredictPrice (regression model) |
/ p* Q# g5 [# t r4 `! r2 Y//+------------------------------------------------------------------+
3 `# N4 H2 U( ^0 x7 Evirtual double PredictPrice(void), a6 d5 h# s3 a/ b+ t! Y, Y
{
0 V( } k3 K. S2 V* a4 z2 Rreturn(DBL_MAX);3 x2 S; \+ T0 w/ a
}3 N2 g$ k% D9 L
//+------------------------------------------------------------------+
# s) ?6 N* h; e: Z//| Predict class (regression -> classification) |/ c& H2 Z% r' c5 _' O( J9 G, a
//+------------------------------------------------------------------+: ^4 |7 o: m' l) f { Q( O4 c
virtual int PredictClass(void)
. Q% Z7 P; r! ?+ Q% [; y0 [{
, E8 ~: a. `* L Y. v" j0 W7 |double predicted_price=PredictPrice();/ h* Y1 I' @5 E: A
if(predicted_price==DBL_MAX)
' J4 R- S9 z/ @% G& s9 sreturn(-1);+ H: d: r9 p5 v, K! \$ Z
int predicted_class=-1;0 r+ P! B/ O) B
double last_close=iClose(m_symbol,m_period,1);8 l1 B& U3 k4 X4 @( V
//--- classify predicted price movement
& H5 B0 K) p" e6 Sdouble delta=last_close-predicted_price;
/ t- V1 M' O4 s2 y+ U: H9 Cif(fabs(delta)<=m_class_delta)
5 Z. l( }6 h% a* B4 vpredicted_class=PRICE_SAME;# b" T7 g, U9 R9 Z- _) b3 D
else
* w7 e; j& W0 @% ]- Fprivate:, _1 u) v& A9 S: A/ D" f
int m_sample_size;7 P8 V, \7 g& V0 Y1 z! S
//+------------------------------------------------------------------+
) i6 i: M3 ~8 Q8 V5 `/ Nvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
0 w9 u s6 ~9 d{( u0 N% v6 h# Z/ a1 F" }( E
//--- check symbol, period, create model" d) [/ W9 @- @( X% w. X+ x: o
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
/ i1 T5 a# h! [/ }$ n, W, p{* l1 E9 d4 z* \9 |' v/ `* N
Print("model_eurusd_D1_10_class : initialization error");' Y' W9 h3 w; c9 A( z R
return(false);
$ M0 W T. \$ v/ a1 ^9 o% ~! [6 [$ q} @, d3 J* u: \
//--- since not all sizes defined in the input tensor we must set them explicitly5 b+ L+ \$ N6 ^5 N {( X; x. g
//--- first index - batch size, second index - series size, third index - number of series (OHLC)# T5 i* @$ Q' j/ {5 s( f/ ]
const long input_shape[] = {1,m_sample_size,4};
7 s2 z3 b0 [+ s& xif(!OnnxSetInputShape(m_handle,0,input_shape))
- N4 j& ~1 G# W6 D: @& _$ K: ]' {{1 o L# @ j) M& O3 ~. \
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
. W. O: ]& J8 Q5 p; a9 Jreturn(false);7 g9 ~6 Y% H! ]$ C2 _+ Z* `+ F
}$ ]. _! t. g/ @; C, H
//--- since not all sizes defined in the output tensor we must set them explicitly
" F$ m! M6 K) ]* S X, j3 ]//--- first index - batch size, must match the batch size of the input tensor, @7 Q4 g$ K: r# |
//--- second index - number of classes (up, same or down)% x- q; G3 d% H9 V. K
const long output_shape[] = {1,3};) N* C. V0 i7 p
if(!OnnxSetOutputShape(m_handle,0,output_shape))
% |/ J8 s; a2 X{
8 a; s0 h1 q3 x9 FPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());& V4 S c8 k- \- z% O1 @: H
return(false);5 Z5 _7 o# p1 u( e( N
}2 K& x- e0 f/ a0 A# _2 x ~7 Q: i) L
//--- ok' B: j1 ~, \1 m# L
return(true);
. Y3 N. v! H8 p}
7 F H4 G" P/ p8 C+ t3 x: f//+------------------------------------------------------------------+2 L1 p% K1 D. u
//| Predict class |) q: M% n/ [/ p+ D: W, g; I( U
//+------------------------------------------------------------------+
6 z6 E1 J% B- n1 x7 e; lvirtual int PredictClass(void)# {" J+ ~6 v" p* ^$ \, `( S
{ |