1. 我们会用到什么模型呢?, u3 G# [ I* g+ z8 r, j9 y
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
0 u/ f% g) h5 @: q我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进2 |: T4 G6 ?- R% g0 v" N6 u
//| https://www.mql5.com |
. Q2 d' C8 c# s" a3 E4 j1 W" y- }//+------------------------------------------------------------------+
5 V& @, w# r' f+ u//--- price movement prediction
$ }2 c3 x: Y+ E: _% v2 p: {- l#define PRICE_UP 09 l% w' R I$ g$ H/ O% w
#define PRICE_SAME 1. v' p0 N7 v b2 v. V |4 L
#define PRICE_DOWN 2
1 x) Z0 I8 t2 K+ E/ O6 P/ D//+------------------------------------------------------------------+
8 r6 J2 o# H% M! `1 i- A//| Base class for models based on trained symbol and period |2 I' w' g* A% D; _# V% R7 r
//+------------------------------------------------------------------+4 {) Y1 X$ W% e; ^+ @
class CModelSymbolPeriod2 c4 C, g2 ]! h8 H( M& j
{
+ K" |( c9 }& R' x6 L/ Z; b* }protected:/ B, i' {8 r" w
long m_handle; // created model session handle
6 k% d( }0 N- C+ e' ostring m_symbol; // symbol of trained data: U M; H9 ~9 F8 m5 ~
ENUM_TIMEFRAMES m_period; // timeframe of trained data' ^" N$ u$ ^, T9 O, F% H
datetime m_next_bar; // time of next bar (we work at bar begin only)2 F" [$ A8 X m( T
double m_class_delta; // delta to recognize "price the same" in regression models5 K( l- e$ [9 W. I, k0 ~6 l
public:
, z2 c! k: |# _( @# B; `//+------------------------------------------------------------------+
, F( n. _, n- z' |//| Constructor |
$ ^7 j8 J3 H7 G# \1 b. S3 u//+------------------------------------------------------------------+% R8 ]7 g- H3 ~ t& D# h+ c3 {
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)# {! c8 i: G) J# O) l
{: M+ ^, E8 T: l' D1 [. w$ k/ l6 q
m_handle=INVALID_HANDLE;
4 ? O% u; {( I3 J5 Jm_symbol=symbol;% c) x2 P: q# ~7 e
m_period=period;
) c6 T0 h4 s/ L3 wm_next_bar=0;$ G) I( O6 m% K, d; Z
m_class_delta=class_delta;
- ]- r# z5 R5 s5 L- j) n" n}# ]/ K- q( @# B% M3 R- N8 s
//+------------------------------------------------------------------+. z1 t1 X& c2 }& P
//| Destructor |
9 T: N5 c1 z4 z" R% e//| Check for initialization, create model |
) x# G1 i7 v$ a2 y! {5 j2 m( K h/ F//+------------------------------------------------------------------+) J3 V/ H! {/ T
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
9 Y" [: E: o- s: v& x" |{
7 U7 ~* T8 \& P4 ^6 N" T0 h6 }$ H: Q//--- check symbol, period
+ ]6 v W' s* D; [2 C, ^if(symbol!=m_symbol || period!=m_period)
; A% G: g( l1 ], {. ~2 h{5 c5 q1 {2 l) Z# [5 l
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));' r& q* s. }8 \. ]* p8 n
return(false);
8 C# {) `- h: O7 G. L/ z}3 e# Z' T" Q1 w! W6 ]! N
//--- create a model from static buffer
7 T8 ^9 V! c5 W8 R, d8 @m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);- U% ]: A% h6 n* Y
if(m_handle==INVALID_HANDLE)4 q8 g' n- I: I/ N1 Y: N0 ]
{& |" h9 x* O3 l+ b \6 D" N% M% ?
Print("OnnxCreateFromBuffer error ",GetLastError());1 }( ~) x/ n) T0 E
return(false);: {/ I |3 ~- c+ c4 k" S0 N; v
}* f2 E Q' `0 V
//--- ok6 G8 ]% [0 [; y8 \4 J
return(true);, b$ H0 r b$ K* M! M* c P
}) N/ ~7 k* ~2 l9 L8 ?0 j$ T
//+------------------------------------------------------------------+& M1 M: o$ A' S2 H
m_next_bar=TimeCurrent();* T Y" ~+ s1 F- M7 f5 R: ]/ ]
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
0 ?: e2 E; ?# t9 {# d" L, I/ Wm_next_bar+=PeriodSeconds(m_period);
. m: O$ d6 X$ M" q! f+ c# K f//--- work on new day bar$ K! v" c: I8 A# X
return(true);
" O6 b9 s6 N0 z}
/ G4 A/ c+ c6 D2 G/ g//+------------------------------------------------------------------+
9 O3 H& I3 c/ u+ \//| virtual stub for PredictPrice (regression model) |
( l; p' F' B* l; }//+------------------------------------------------------------------+( ?: S; ]$ V2 q! `/ i8 B o* y
virtual double PredictPrice(void)4 Z5 B) f5 P3 d0 p) P4 n+ N& i* p
{' u- m( {# c( b
return(DBL_MAX);8 }0 ?+ i2 t6 r7 k
}; M& w$ K' v' F( @) B
//+------------------------------------------------------------------+
7 j5 M# W/ N8 N% e//| Predict class (regression -> classification) |
- a) `' w8 |2 H7 t//+------------------------------------------------------------------+: i; F: m% z* E! o
virtual int PredictClass(void)
3 G4 j4 i1 i' g" b/ ^# v b{
6 W9 {, T s, @double predicted_price=PredictPrice();+ K3 r: H) m: C, S2 a6 M5 s
if(predicted_price==DBL_MAX)
0 \1 Z" J+ ^! ^return(-1);
$ Y3 E: R0 k# t4 {/ O* `8 v% ^int predicted_class=-1;
, S8 ?4 t% R' o8 e$ e |double last_close=iClose(m_symbol,m_period,1);* G2 O6 ?8 {/ a) C/ v4 K, ^7 I
//--- classify predicted price movement2 b/ }3 R7 ?$ ?. i" b0 m
double delta=last_close-predicted_price;1 ~" |8 D& r" F, m9 @4 c) I; j8 y
if(fabs(delta)<=m_class_delta)
9 G8 k3 A) O( b2 ]predicted_class=PRICE_SAME;" v- v/ }; f d/ F0 S: \9 ?
else* J3 G: |5 b4 Q* Z
private:
2 s( J( ?, }+ {+ f" F3 m3 \5 aint m_sample_size;% G! G# v0 A$ ^0 p6 J4 K
//+------------------------------------------------------------------+
& d, F$ h9 p$ A# ?virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)8 u+ C) j$ o; z, H: F& b
{4 t" M4 E9 P6 P9 S5 J$ [# z& c7 p
//--- check symbol, period, create model. K; W( ~& k/ ~
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))6 P- j+ W, `6 L( g4 m
{7 h8 d" a9 t( b9 L9 `
Print("model_eurusd_D1_10_class : initialization error");, ?, M3 e0 R( J O7 J' x# L5 L f+ H
return(false);
3 r, C/ A+ `9 [}. R! y3 K( d; N
//--- since not all sizes defined in the input tensor we must set them explicitly
* @" P9 O5 J' ~8 p//--- first index - batch size, second index - series size, third index - number of series (OHLC), D. v4 ~: C+ ~! l+ V
const long input_shape[] = {1,m_sample_size,4};& R8 V* j m5 P- Y
if(!OnnxSetInputShape(m_handle,0,input_shape))
6 g5 i1 {) X3 k% c5 Y{
+ R* k( _# j* n: J PPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());% t0 c- g1 h2 ^6 J% g
return(false);" i' T* ?1 U3 }3 S. Z. Y' Y/ ~
}
3 l6 S( k0 u* I8 p//--- since not all sizes defined in the output tensor we must set them explicitly
" e9 j+ j! K: c7 Q* O//--- first index - batch size, must match the batch size of the input tensor
$ Q: }0 B' \# P8 Y//--- second index - number of classes (up, same or down)
* y1 r2 w) x! L- s o7 x. lconst long output_shape[] = {1,3};
" k% y) c3 O$ |: h; jif(!OnnxSetOutputShape(m_handle,0,output_shape))
4 S( W( M$ P* X5 c- V5 X8 R" W5 \{
! P! r0 f& W9 L6 UPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());* }( p- J p! b, V
return(false);' Z' h: F# F6 }
}
) V8 Y. W5 r1 Q; x' |- I* \# k//--- ok3 I9 A# r& z9 l( t. d
return(true);
% F6 U- H8 [6 K) r9 a}
- j9 U. B$ q3 @//+------------------------------------------------------------------+
- Q/ H$ a! n9 F//| Predict class |
1 H% F0 E4 M$ x: D//+------------------------------------------------------------------++ Y7 O1 A* @6 h
virtual int PredictClass(void)% r6 m0 t% O7 a! i
{ |