1. 我们会用到什么模型呢?
# u8 {/ s3 S; N- s1 i* q5 m) {2 _在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。6 T, J; V1 @" k: W' { s y
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进/ r, o2 C0 {5 C! }' k( U
//| https://www.mql5.com |- I+ P" @% m/ c. j F1 Y$ v0 c
//+------------------------------------------------------------------+) m; ^' G1 f1 M0 Q3 F A* x G* H
//--- price movement prediction
0 _% j5 u: S* o+ ]( ]) ^: L#define PRICE_UP 0# i2 Z" n4 \6 s# {% V/ x% I
#define PRICE_SAME 1) S* G$ K& z8 l9 o" N& U
#define PRICE_DOWN 24 _1 }6 \2 o) N/ B0 }6 \# ?
//+------------------------------------------------------------------+
, a9 X% E2 R$ j Z. @8 ?8 f2 t//| Base class for models based on trained symbol and period |
3 A5 j D2 n' X, ]! S5 `( `//+------------------------------------------------------------------+
& S2 T" | O: m8 W9 |1 J3 a( E8 bclass CModelSymbolPeriod$ _1 Z4 d c/ [" W1 b
{
' a/ O* s% W, h) k$ N9 D. kprotected:
7 |! d+ v% |! i' f/ e. mlong m_handle; // created model session handle
. s: G9 m7 O1 ~' C5 [+ `1 ?string m_symbol; // symbol of trained data4 g' @7 R* {. j( V* v0 o
ENUM_TIMEFRAMES m_period; // timeframe of trained data. Z2 `0 \1 g# g; T
datetime m_next_bar; // time of next bar (we work at bar begin only)) M6 O5 p! f$ d8 y
double m_class_delta; // delta to recognize "price the same" in regression models& A* O a7 s6 B' b0 i
public:' ~5 D2 r' o3 r- T+ o
//+------------------------------------------------------------------+2 d0 {7 u+ ]8 F6 i% c
//| Constructor |
+ t$ i9 U6 N$ ^/ V) V1 }//+------------------------------------------------------------------+9 F! S4 C$ ^) x5 w [" r
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)/ Y4 ?' W' C x% {: K
{% E. G' c7 Y. _1 _
m_handle=INVALID_HANDLE;# X* @/ P: H6 w7 i+ @
m_symbol=symbol;
, g% n/ I+ \5 f9 L4 Nm_period=period;
6 a, d" K9 u! i- a' [$ @( rm_next_bar=0;
6 H; q2 N0 q3 |+ j& s2 @; ?m_class_delta=class_delta;
! @7 W. B+ o( I1 Z& c" y}
5 M, r+ z) W. s M5 ?//+------------------------------------------------------------------+0 A3 ^0 h7 i$ O
//| Destructor |- q; h! Z w! u2 ~
//| Check for initialization, create model |1 q* ^5 y1 M1 ~$ I. w
//+------------------------------------------------------------------+
+ g9 P& V* B0 M4 N% i* W$ q+ n3 Cbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])6 R* C2 h' E& A4 l( w7 u
{- f3 \# q- V- U2 B& w7 c+ T. c4 ]
//--- check symbol, period D& C; |8 O. o' U5 x0 R9 k
if(symbol!=m_symbol || period!=m_period)
+ f6 H( n* a2 c{
* Y2 o. W( N" PPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));% v0 b$ i# r' c+ \: L5 }: P$ Y% [0 G/ }
return(false);8 c; Y) X: y4 S4 z# T# B
}0 T Y: Z4 e- o( ?5 b4 i* w% c
//--- create a model from static buffer
* _6 T4 x( Z9 v6 a* C3 b# J: t* @. C% om_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);8 |+ \2 t& W% ^, l0 @
if(m_handle==INVALID_HANDLE), `6 {+ o, m$ k2 f
{& J7 z7 N' Q: k
Print("OnnxCreateFromBuffer error ",GetLastError());- V) s# l: ~; O! s
return(false);
. [8 Z: `) ?5 V. B! f}; e9 D2 I9 [$ j0 B
//--- ok3 a) E! ~# y- `& G, N) d, d* n
return(true);0 L" Y/ |) E: d( D
}% _7 ^' ?+ M$ E Y, X
//+------------------------------------------------------------------+; I2 g, ]% z L7 U0 R
m_next_bar=TimeCurrent();
+ S6 g N1 n4 C6 b8 A( bm_next_bar-=m_next_bar%PeriodSeconds(m_period);1 G( [7 f4 t2 d0 G! e# _
m_next_bar+=PeriodSeconds(m_period);
6 S! w/ v& I# {3 O//--- work on new day bar
: x( w1 P+ D% breturn(true); b X: g0 l- d! ]5 ^
}# c' u# s$ B' ]% W, L& M* i
//+------------------------------------------------------------------+3 u, M5 V+ G' Z$ K, T0 \
//| virtual stub for PredictPrice (regression model) |, l9 p0 a7 F. w0 Y, M' O
//+------------------------------------------------------------------+2 L8 z+ V( Q/ m# ^# a
virtual double PredictPrice(void), I: n0 ^8 ~$ y0 V) _! W2 l) ]6 p: I
{
1 D' R, ^) l+ l5 X8 Ureturn(DBL_MAX);
% l8 B2 `) o f: A}7 P) Z( X* _: \6 p5 S$ E* p7 v) K
//+------------------------------------------------------------------+
# T; l0 u9 G1 ^# _3 w' O2 b//| Predict class (regression -> classification) |- T$ c$ x/ V% @: H$ q
//+------------------------------------------------------------------+
5 k! j" _9 O, c$ K$ n9 N/ Tvirtual int PredictClass(void)4 T7 D2 X* A2 B) C, ^
{
G: v" k/ r* l d8 {, d, f0 Mdouble predicted_price=PredictPrice();
- Q9 p! u; O: h6 A5 I/ C+ Pif(predicted_price==DBL_MAX)4 K4 \% | B% B% Z
return(-1);
& O5 Y6 v- k. Z+ ^0 j( ^( \: Oint predicted_class=-1;
0 P4 X2 V) C5 ]0 V8 e9 wdouble last_close=iClose(m_symbol,m_period,1);2 o0 |# q* }+ b0 h* h! N
//--- classify predicted price movement0 B5 |3 r7 G. ~* k8 H7 t4 y! f
double delta=last_close-predicted_price;& p+ D$ I; M3 w! K4 \4 A
if(fabs(delta)<=m_class_delta)
7 W! B& F- o. p+ R7 Wpredicted_class=PRICE_SAME;2 U$ X7 A# k, G8 N- S8 [. |7 w
else
) K' p# q7 u+ lprivate:
" ], U* s: `0 W9 D% {int m_sample_size;
: T; N! P" m) H i//+------------------------------------------------------------------+' K, A, y0 M: S1 P# y
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
0 ~* \" G8 H! R% d C- G{
3 W+ x/ \6 |$ A, |* H9 c( G& ~9 ]//--- check symbol, period, create model, w3 O, a) O1 M2 |
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
" [( z. s6 ^# `{+ Z5 Q1 R; y/ w# w6 |7 c4 y' U, P4 h
Print("model_eurusd_D1_10_class : initialization error");# k4 f7 r$ [, i
return(false);) P' w. D- `8 {" [$ j+ z
}" m+ I0 j5 M0 V1 l% U
//--- since not all sizes defined in the input tensor we must set them explicitly' U4 z/ v0 H' y
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 U) F4 x0 v6 [6 l4 W9 h& kconst long input_shape[] = {1,m_sample_size,4};
4 H: @( u* c8 a2 b _if(!OnnxSetInputShape(m_handle,0,input_shape))
0 X* P) {) t# q" D1 D# i$ E& ^{
2 e$ d, e- b" {) JPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());! x; l& T9 |) c7 F
return(false);- I+ |5 H: B, T# X( P& J0 \% I7 A
}
4 i3 T- b- y% I3 x) y( x: u/ X; f//--- since not all sizes defined in the output tensor we must set them explicitly
9 `1 o9 R) H6 D9 m# O//--- first index - batch size, must match the batch size of the input tensor! D& { [" b7 A" M$ E! G: [6 {8 w
//--- second index - number of classes (up, same or down)4 A% {5 m* `0 K4 S
const long output_shape[] = {1,3};
; H" k# l) g1 ]- S. k+ Sif(!OnnxSetOutputShape(m_handle,0,output_shape))
3 Z4 F& p9 m+ `- g0 Z{
% h: c! ]5 V' ?- O& J8 C/ NPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
. R {7 W$ n9 Z! Y+ n3 ]% V6 U+ [return(false);
" B9 O# Q' t0 W9 O}" I% @# M" c* N$ J
//--- ok0 F B2 l% V9 ]( }$ r+ T& V1 F
return(true);) C4 l' N, F' C
}" s6 ]. `- z* Q! b
//+------------------------------------------------------------------+
2 X& J' q8 L( X0 @- m3 v, m/ C0 ]//| Predict class |# [8 P9 O0 _# F% U4 ^ O1 ]5 |6 d
//+------------------------------------------------------------------+5 a. G, w0 z+ o
virtual int PredictClass(void)
7 {2 {5 x7 V' @9 r. Z/ v, k. V{ |