1. 我们会用到什么模型呢?
4 A9 v% m4 P9 g在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。9 o7 ~- D' k( I& h3 v1 g# \
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进* K/ h8 w* I& E& ^9 V7 N; v
//| https://www.mql5.com |
7 W2 E5 L S! F3 q) I7 J5 ~ w//+------------------------------------------------------------------+
. e2 C4 ~" m0 }& z0 D3 u6 ]& b//--- price movement prediction
% `6 q! v+ e8 M9 }( r$ n C1 C5 k#define PRICE_UP 06 h5 O5 `. @0 h
#define PRICE_SAME 1
3 `' _; w4 F+ ~5 b/ {+ t/ S; C#define PRICE_DOWN 2
q, Q1 V1 q. o- D3 Q//+------------------------------------------------------------------+
' D( k5 u5 o! @. [# R: `//| Base class for models based on trained symbol and period |
+ [2 g; A! y* Q//+------------------------------------------------------------------+ c: s- ^; l! j& U1 a+ l
class CModelSymbolPeriod# a& ?6 d" \. @0 V
{
; {1 \. l$ W" y: o' e. D- ]protected:
# q9 Z! D; e* P" w) Along m_handle; // created model session handle/ X- u* v: i# \9 ]/ q7 J
string m_symbol; // symbol of trained data
$ Y5 O8 }$ {, C! W% |ENUM_TIMEFRAMES m_period; // timeframe of trained data# ?) q, z4 w$ Z# u5 W5 X j
datetime m_next_bar; // time of next bar (we work at bar begin only). I: K2 A' Z3 p, T1 e8 }/ |' O
double m_class_delta; // delta to recognize "price the same" in regression models
. b4 t8 f" _5 E, hpublic:
4 E D3 I5 X5 r//+------------------------------------------------------------------+$ J: o! K a2 i2 |, `
//| Constructor |
% m j3 X* {" T3 ~! y8 |//+------------------------------------------------------------------+
' G% d' \ A. zCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)- e5 z( L; ?* n$ p' I$ F
{
3 x$ Q9 V( P2 b3 ]/ p' v8 Cm_handle=INVALID_HANDLE;! G7 i2 R$ E$ g0 ^& K
m_symbol=symbol;3 T) N7 a, o$ h) T3 v( M7 g _6 {4 }
m_period=period;
& |$ I9 ~/ N7 Y0 Fm_next_bar=0;
* f/ v& I1 v0 v# k( Dm_class_delta=class_delta;8 b% ?4 I' G, B$ L0 K, t0 W
}3 y# w/ Y) |( U. `
//+------------------------------------------------------------------+, Z& |! f. P+ F9 a/ O' t
//| Destructor |
; j1 W+ M! y3 \" c; m//| Check for initialization, create model |
f/ C q; s' b: ^//+------------------------------------------------------------------+7 S2 G# {& h1 ?; w& j4 ?
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])6 ?& o( i6 d5 C9 n0 m
{
! j9 G0 q' f5 u0 P% X0 ^7 y//--- check symbol, period. ^+ V5 K( O! s; f0 n0 \9 f
if(symbol!=m_symbol || period!=m_period)
& x8 Z" {5 W5 H2 L* X{
* h) i- p/ w+ M7 p( K& B- CPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));- _4 F% Y: O3 N
return(false);
9 c8 b9 ^. {+ h" a3 J6 _* X}
, x! p! t6 z2 J5 V' X1 x9 f; r( k//--- create a model from static buffer
: i1 {6 h4 }" D6 f5 Hm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);1 f% e6 P6 \9 g
if(m_handle==INVALID_HANDLE)! g9 | e7 U ]/ v8 r D& C' N4 C
{. ~# P9 I" k$ M8 o
Print("OnnxCreateFromBuffer error ",GetLastError());1 m4 F+ l! q0 |
return(false);) K& i( k! d6 X/ E0 H- c' y/ g( o
}
! }- R8 F+ Q5 ?" [2 {. L" M) y! Y//--- ok
8 Q9 B( F/ a3 X7 }2 Ireturn(true);3 K6 ^' r+ ^( L" j; E1 w* a4 O' [
}
) K- D0 _7 i: R0 K8 Z9 {) X//+------------------------------------------------------------------+
4 h2 t0 s5 u: P! tm_next_bar=TimeCurrent();
/ Y! T' Z6 b Y- S6 M, ^m_next_bar-=m_next_bar%PeriodSeconds(m_period);
6 g9 r, ]' [1 u T8 |" j$ c% h/ n# am_next_bar+=PeriodSeconds(m_period);6 } s- E8 O1 ^
//--- work on new day bar$ S2 Z/ x% _. b% c5 w" W0 a8 D
return(true);
Z5 |' C( [, D- z1 v}
# O6 @6 Y! B, C' v* O% S% x" O//+------------------------------------------------------------------+
( B) X1 X2 V v1 c$ d//| virtual stub for PredictPrice (regression model) |2 X! Z- S# \- d% |( a1 a
//+------------------------------------------------------------------+
+ f0 b% O+ N+ jvirtual double PredictPrice(void)* t3 u2 N+ e( J; Z( }% g* e6 B8 v" p
{* g& M9 X4 y& w. i# b& M: g" v& D! S: ]
return(DBL_MAX);
. }8 ~/ D t- R1 y& N! f4 M3 U}, w" K! E& p$ V( v
//+------------------------------------------------------------------+
. f" R# N. d' h! W9 `- r2 D: r E# e//| Predict class (regression -> classification) |
% }- q' ^) j- Y% o//+------------------------------------------------------------------+# V8 E! h( G: A3 [0 J
virtual int PredictClass(void)# O/ {$ P L2 G0 G! O
{! R" U' @$ N8 t
double predicted_price=PredictPrice();. w4 `! U: T9 O
if(predicted_price==DBL_MAX)+ l! w/ T$ A% ^" N2 u% ~
return(-1);, n* G6 r2 O+ t) G3 F& h
int predicted_class=-1;
5 Q# `- Q+ b" E* L% \ V$ ^double last_close=iClose(m_symbol,m_period,1);
* H2 `* x/ K9 p7 |//--- classify predicted price movement3 ~7 Q; J. P* I0 N
double delta=last_close-predicted_price;
7 h( A u0 C% I! E$ i2 ?# V. |) kif(fabs(delta)<=m_class_delta): n2 K3 y! q$ s8 a
predicted_class=PRICE_SAME;
" I4 { F, R, Y8 e( h' welse; F& Y! Q9 s0 I& H- V0 I+ d- `9 V
private:& B4 E+ [5 B2 U
int m_sample_size;' i+ e: F$ Q2 C; z1 p* s% Y! `3 |
//+------------------------------------------------------------------+- G# T) G9 C K2 L0 @0 s e
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
; m8 i: K) ~4 G. K( T{0 r% Z+ s ?1 u2 h! j
//--- check symbol, period, create model
5 ~. \. y6 N2 P& U3 T% { [if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
' Q4 t* h$ ~; A5 g2 P7 Y' `# h{
2 g- K6 z3 R/ t/ Z; x7 R j, F& ?Print("model_eurusd_D1_10_class : initialization error");
! m$ W& Q" S5 {# i* T. }. breturn(false);
1 a6 Z0 F# S' C}
) h/ h6 e% M |3 n: \, H* W//--- since not all sizes defined in the input tensor we must set them explicitly
. ^ R: z0 I$ L0 @, @//--- first index - batch size, second index - series size, third index - number of series (OHLC)
y; h3 }4 I" Q Z3 E8 Mconst long input_shape[] = {1,m_sample_size,4};+ S: c- h a: M8 Q
if(!OnnxSetInputShape(m_handle,0,input_shape))
2 U3 E4 y- r+ F( E' K2 ~7 C& R! g2 z{
+ o" G) k9 J" G) EPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
$ V* J# F T4 i7 z$ S9 Vreturn(false);
; v$ b" X' u3 q. y4 r}
r! K. A g0 l' P$ Q//--- since not all sizes defined in the output tensor we must set them explicitly
3 ]3 d6 w, u- Y" t' S( w( Y//--- first index - batch size, must match the batch size of the input tensor
; l. i6 `: n4 ?, N0 O: J//--- second index - number of classes (up, same or down)
0 G4 P) H, L' aconst long output_shape[] = {1,3};
% l' ~8 l% L9 J; E- Gif(!OnnxSetOutputShape(m_handle,0,output_shape))
* k. `: h0 z6 \! s/ B{; r1 A5 F' S" ?- T U' K
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
- n* [8 @/ Q/ xreturn(false);4 c- G H' O: e/ I& m9 O/ A4 f9 B- S
}
$ b6 v' s/ g6 h- H. L# ~//--- ok
# g6 h& t3 c" T7 l; |, Z [return(true);
5 B+ Q2 L2 i, p, ~}
+ x5 S1 B: V: d0 n//+------------------------------------------------------------------+. p- l; a$ X" J6 v: ^# T, p
//| Predict class |
5 F' {2 C$ {1 _+ D C//+------------------------------------------------------------------+& n% } h+ z% F1 t! ]8 ^
virtual int PredictClass(void)
1 D' k ^* L1 M" Y9 x7 e{ |