1. 我们会用到什么模型呢?
; s0 a! q' w1 Z! {4 x在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
4 l( e y1 D( b9 b$ [我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
& V* Z' y- J: T+ X5 D" n/ x/ N//| https://www.mql5.com |& J1 }; |$ i+ n1 C, Z; q
//+------------------------------------------------------------------+
; h5 e/ Q. c0 i( i0 S8 T//--- price movement prediction; V) T2 U5 _6 k# J5 X# A) R
#define PRICE_UP 01 }1 U! s0 C' T
#define PRICE_SAME 1
/ v k: _0 ?) O) c* {, g7 [1 u% x#define PRICE_DOWN 2. b) P( d, A' O+ X& j
//+------------------------------------------------------------------+0 |" D) [1 z- J* b0 C9 s3 C' Q+ p
//| Base class for models based on trained symbol and period |5 W3 H/ s0 G+ V3 J
//+------------------------------------------------------------------+
0 V$ {) I6 t9 A: o; lclass CModelSymbolPeriod
. R! I/ F# k; _& L/ {8 M; f' Y6 {- q{& e) p- d; \7 S4 ^: ^4 g
protected:1 [0 i" U3 u% J! ?2 f
long m_handle; // created model session handle* s* |: S, C4 F# @( B4 ]" G& F# r
string m_symbol; // symbol of trained data- Z ~& k2 x$ d! G
ENUM_TIMEFRAMES m_period; // timeframe of trained data
8 h. p9 ]0 q4 R7 B; }2 f, v! Jdatetime m_next_bar; // time of next bar (we work at bar begin only)6 n/ W) O' k0 M3 l g
double m_class_delta; // delta to recognize "price the same" in regression models
# x) V6 |/ W) f; B+ J H4 [public:4 U( t& v2 P% Z3 }7 d+ Y
//+------------------------------------------------------------------+* p( O* i" T& u
//| Constructor |+ C$ u2 D+ v8 H- E4 @% H
//+------------------------------------------------------------------+
8 ^1 p4 _! o/ iCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
+ g$ [ C7 J- r4 }{
( N$ ]/ l; \) L0 n7 Rm_handle=INVALID_HANDLE;, Z$ V2 i! c/ A' w0 \1 G
m_symbol=symbol;
$ u! S8 }& b9 J, x3 Q, sm_period=period;
) A J0 N. S+ I3 T6 e& r, ?# Ym_next_bar=0;! ?; W. n+ c" c8 x5 N
m_class_delta=class_delta;: b7 K) r6 y" V' w( N( E5 F# Z8 W! ?3 Y
}8 I0 N, D$ q/ ], j2 ^: x
//+------------------------------------------------------------------+% X" d3 W$ T# _7 _
//| Destructor |) z7 E: M z0 A
//| Check for initialization, create model |) J- A! r" F, _
//+------------------------------------------------------------------+; j; K; a" P2 b4 ?. T
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])/ g6 k$ p& k7 @4 T8 |
{
: t) {. m4 G7 R% j/ r, ?//--- check symbol, period
. I/ G" q% }) w+ f0 tif(symbol!=m_symbol || period!=m_period)8 j+ N0 z. e, k+ m- D
{
, K/ E2 Y' Y3 s3 sPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
, Z% k D- t3 ?/ O' i! e% j6 l% X5 Preturn(false);0 H# D- B3 m$ G% ~; a% }
}
( {7 _+ l, E+ y1 J//--- create a model from static buffer
9 }1 @$ g2 t' `$ y3 Q6 a: Cm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
0 y% C- y( O4 y u* g6 a+ x' t% n1 r- iif(m_handle==INVALID_HANDLE)/ E! e5 Q9 j# o' w# U8 X
{
+ v6 f$ k( p Z5 G/ QPrint("OnnxCreateFromBuffer error ",GetLastError());
' c/ P$ {( S/ b6 Breturn(false);: z1 F4 L% A6 s b- ~: U8 u
}
1 k) G: @7 Y: G- Z ~//--- ok& N/ e( v) U. L R9 Q
return(true);
* I: G' C9 r9 f0 k) f2 m}: H8 m3 O% u& r: w
//+------------------------------------------------------------------+
) }- Y1 ]$ J5 l* X. r9 qm_next_bar=TimeCurrent();
) U9 f/ P! o, Tm_next_bar-=m_next_bar%PeriodSeconds(m_period);+ w4 ]# t, t2 t' `3 d( K7 W, n0 s
m_next_bar+=PeriodSeconds(m_period);
7 R9 ~7 N; g |+ \//--- work on new day bar1 l- Q; z$ Z( S. I0 w. b }- g
return(true);
: ~' u% T" W) n; h4 a, N. H8 U}
7 K$ b5 R8 G9 S2 u//+------------------------------------------------------------------+0 T/ I$ u4 H4 ^% \
//| virtual stub for PredictPrice (regression model) |2 c& W+ t/ s8 D% N
//+------------------------------------------------------------------+
+ E# @: o& D$ F* `) J% n$ Z K4 svirtual double PredictPrice(void)
, k( {9 J( P; i& W1 A% C- s{; d/ z3 l2 ?. |# K: g. u2 X
return(DBL_MAX);" O0 W8 C3 `3 T3 O, b( k7 L+ b
}' y& k6 ?- J: l! ^, c3 c
//+------------------------------------------------------------------+4 Z. y8 d( [; b! [$ @0 Z
//| Predict class (regression -> classification) |9 C' f; k2 _7 j4 u$ h
//+------------------------------------------------------------------+. o% V" [# B5 `5 D) U$ Y! ^
virtual int PredictClass(void)/ ^! W6 U, [& R, G' X
{; ~( r8 W1 ~8 ?$ Z3 Z1 H$ o
double predicted_price=PredictPrice();8 C/ Y, f& t9 T: g8 N# s5 ]
if(predicted_price==DBL_MAX)
8 f& \; A0 O0 yreturn(-1);
4 T7 j4 s! j* A# e# L4 E5 Mint predicted_class=-1;0 _4 E* X- n: o$ @" {+ _% c
double last_close=iClose(m_symbol,m_period,1);4 U/ h& ~& s$ o9 V
//--- classify predicted price movement
4 `3 L$ N* z% Y P- \3 gdouble delta=last_close-predicted_price;) J* c5 g0 R) m. z
if(fabs(delta)<=m_class_delta)
, [. q" j4 b: F+ x" M8 |predicted_class=PRICE_SAME;
( L- }( D q- R+ N# Y; }& `$ Selse
2 v% e: p1 m9 D% N0 U* M, ~private:( C3 K- L1 @$ U+ L4 T" q
int m_sample_size;! f: G! s7 h% `
//+------------------------------------------------------------------+
# R! V9 }4 q/ B* w3 m# R5 E1 K5 Y8 Qvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)4 A. Z M' O8 X
{
" A6 S% d) _- x& K/ r//--- check symbol, period, create model, S X2 m+ l* Z+ }
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class)): U5 F$ \: d4 V/ W9 x1 v" y: ^: B$ @
{% Q- R8 F5 ?; V. z( {, F
Print("model_eurusd_D1_10_class : initialization error");
0 x7 T2 [9 u: F) nreturn(false);
. Y0 \7 d$ f. X' r1 Z# m}' f/ }/ E, s6 g6 J( a8 Q
//--- since not all sizes defined in the input tensor we must set them explicitly
, ~$ ]' h1 b, R7 K3 J//--- first index - batch size, second index - series size, third index - number of series (OHLC), O2 `+ q6 l# o& m
const long input_shape[] = {1,m_sample_size,4};' z) q, f5 I/ \
if(!OnnxSetInputShape(m_handle,0,input_shape))
3 s4 ^* T$ `3 k8 S4 J% ^; D* c{$ J5 O$ [1 `# M# h
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
: a: a5 Q4 F9 E4 Yreturn(false);
1 H* q" d4 X/ D$ `. @1 W! A}% V% o w g' l% K* f9 g
//--- since not all sizes defined in the output tensor we must set them explicitly
1 {! O; }* b# f) j1 {# W//--- first index - batch size, must match the batch size of the input tensor4 o9 X. D$ P, E: g$ f( I
//--- second index - number of classes (up, same or down)
' p2 A$ M8 I8 h2 X. Aconst long output_shape[] = {1,3};
3 G) h! ]6 ?% }: ?5 yif(!OnnxSetOutputShape(m_handle,0,output_shape))
I; I8 ]6 N9 d/ q& {2 z0 W{& x, l- y0 h; k' [
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());2 N- b9 L) D) ?0 l4 f
return(false);, b' p& c/ ~( _
}
1 a8 N; S5 E( g6 q8 q# v//--- ok
/ l/ u: W4 o+ G; u; \: `7 k5 Vreturn(true);
- [0 T/ G4 P( e' s7 [}
2 {& \ q& h* k S/ D- V//+------------------------------------------------------------------+6 Z7 o# _+ d) K6 T3 O
//| Predict class |( ~) ~2 N8 J4 i, v
//+------------------------------------------------------------------+8 h; N- K8 Q N
virtual int PredictClass(void)
1 U) S. m- B+ e{ |