1. 我们会用到什么模型呢?
+ W. t$ u5 J- \- I& \在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
1 F+ ?$ s5 @& |) y* ?' Z" c# N我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进2 B2 S6 \8 f4 l# o+ t- g
//| https://www.mql5.com |
1 x. ], o/ Q5 V+ z+ [, E' S//+------------------------------------------------------------------+8 t( q" o5 D& }; c+ v
//--- price movement prediction
9 `5 o' t. d# G" b7 S#define PRICE_UP 0
$ f, Y- k w$ u" A! A#define PRICE_SAME 14 M" R# t v6 n
#define PRICE_DOWN 2
* q- I" A6 c( B3 F: V) y//+------------------------------------------------------------------+8 i- n/ }7 n; p. R
//| Base class for models based on trained symbol and period |* Q j5 f) J. u. C
//+------------------------------------------------------------------+
$ J5 k" t4 e8 m7 a Tclass CModelSymbolPeriod
4 U, m' d5 _- J2 P{5 D$ F& [; O% ?
protected:
, a- u2 s! P3 i2 {) G# S& ]long m_handle; // created model session handle
& g6 W) H) m9 j" M0 A! Q5 ostring m_symbol; // symbol of trained data
, ]" L4 l) c2 b1 y, TENUM_TIMEFRAMES m_period; // timeframe of trained data( Q5 r4 |; r4 F1 }: b5 b
datetime m_next_bar; // time of next bar (we work at bar begin only)
; O. b, o8 P8 d- Ydouble m_class_delta; // delta to recognize "price the same" in regression models1 J- q Q) s6 {6 d: B3 y
public:! e& M5 ]: b, |7 C5 `$ I3 P a
//+------------------------------------------------------------------+
7 f8 {& [- E& F# v- |5 d//| Constructor |4 ` o% K& H3 L$ o7 w
//+------------------------------------------------------------------+
3 Y. S! L0 G/ V1 T+ | pCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)% i2 a S: m/ V' W
{
K. H" z9 S$ q1 A+ H& S. \m_handle=INVALID_HANDLE;9 j* j; `9 o" } K, k
m_symbol=symbol;
! `0 A, I; s5 a6 W6 |m_period=period;
/ y; s! ~2 Z9 R7 e) ym_next_bar=0;' p) o6 Y* t* d$ [, q6 U
m_class_delta=class_delta;
5 y/ z: T E& x}- \1 ~5 Z# a d1 \/ ?. F) n
//+------------------------------------------------------------------+
: n% w. t( } o4 a//| Destructor |
7 C' X' o2 X9 G" J/ h8 Y5 [- [1 @//| Check for initialization, create model |
1 S" A1 N$ o& T( |4 w//+------------------------------------------------------------------+: x2 C0 r! w `; D4 I! I" O- v
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
4 K+ C9 c& m( C% f7 ~( r; l{+ a' b9 L1 W# Z3 z
//--- check symbol, period
/ g- V8 M8 O! M4 v" U$ \if(symbol!=m_symbol || period!=m_period)
' @+ U! L5 e$ Q8 y{) a' l0 Y6 K5 S% q! y8 S
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
3 M |5 R; Y! {" ~! x4 j0 [6 \return(false);1 O* ?4 p; k1 a' Q: G m
}% Q3 q0 |+ O* m7 Z1 p
//--- create a model from static buffer
$ g& G4 r$ ~) X/ `m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);# [9 a8 i; p& {5 c) [' q; E
if(m_handle==INVALID_HANDLE)% b3 s' M- t: o$ f
{
9 [2 @! |7 _" Y$ I. ?Print("OnnxCreateFromBuffer error ",GetLastError());
# p% y2 n; ~- g$ N( o- treturn(false);4 L t0 G7 S' M( Q# d$ I- L! w' C
}. K0 {) T: I! E3 u) V# @$ e8 ]
//--- ok4 L2 f, i5 m/ I' C5 f
return(true);
[1 W3 A. |( B5 ]4 G; B}3 T, {1 e4 r2 X& m* K( D
//+------------------------------------------------------------------+" r6 R/ U5 J6 O3 t) y3 R/ O
m_next_bar=TimeCurrent();
- j7 |9 N# G: G ^2 N6 Dm_next_bar-=m_next_bar%PeriodSeconds(m_period);4 ]. L9 C+ y2 L5 t0 U7 ?# v+ N6 ~/ K
m_next_bar+=PeriodSeconds(m_period);; J, l/ S. l6 Y" N# }
//--- work on new day bar
0 q X5 @0 W9 B& z7 O& h ?return(true);
6 M u( W/ o3 |" A. L4 f- b6 c}
3 a( S2 S- {, ^! u9 B//+------------------------------------------------------------------+
: A: R2 u3 {- C//| virtual stub for PredictPrice (regression model) |
& Q2 r" b% n, R- [//+------------------------------------------------------------------+
1 B2 ]4 D3 c( wvirtual double PredictPrice(void)
: x$ b6 Q3 |+ a{- \ J2 g+ K0 }3 |6 U9 p$ j
return(DBL_MAX);
8 E% L$ d2 d! W) Z# O}
+ d9 m8 t7 o/ ?5 S/ B Y6 U0 Y//+------------------------------------------------------------------+6 Z4 y2 ~( i+ X5 j7 L
//| Predict class (regression -> classification) |
* O8 T$ K: ^& F8 ^' C% s//+------------------------------------------------------------------+% s7 Q) }0 I. U% j' {
virtual int PredictClass(void)
6 b: i N) _2 \& H$ s{
( g3 D- G! |: Q% h! \double predicted_price=PredictPrice();+ T8 L. @* _% `1 R8 _6 o( W$ X
if(predicted_price==DBL_MAX)2 i" E3 a8 k6 a
return(-1);
8 ^. V" K4 L. H% E( s; ?int predicted_class=-1;
' S4 M6 U6 Q% r8 Zdouble last_close=iClose(m_symbol,m_period,1);( x5 t4 }/ h N6 N
//--- classify predicted price movement, E- n! `* i1 o% M# N
double delta=last_close-predicted_price;
7 V$ o! B+ K) Eif(fabs(delta)<=m_class_delta)
) k& [8 S" Y2 _3 ppredicted_class=PRICE_SAME;
: x4 x- h! E5 K( O9 n" H% x3 i* u' ?6 @) Helse
9 v6 u( Q. D& m( B* ?" w& i* ^private:
' I. U8 ]9 Z8 _4 Z! p4 K. lint m_sample_size;
/ L4 C" e9 t* p0 [4 I//+------------------------------------------------------------------+
: w7 m2 K' I: g+ ?5 g# U6 M, ?virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
9 d( n4 h$ f" |% }( ~{9 s( Q/ W( N( X" K7 i* A
//--- check symbol, period, create model
# ~" `6 U1 a/ r3 i {! Fif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))/ |" ?9 U& w, G9 r+ V1 e
{
: b1 c2 Z; w! F, ?3 ?' u- ~Print("model_eurusd_D1_10_class : initialization error");
& L+ G; a/ Y9 }* S) k& h- lreturn(false);
6 i* R4 C/ z6 _; _}/ p+ R" N n* L0 _6 ?! B! y' p" G7 P
//--- since not all sizes defined in the input tensor we must set them explicitly
" f/ |0 |5 X+ A, k2 H( t//--- first index - batch size, second index - series size, third index - number of series (OHLC)
; a" q. g4 j# {2 ?3 ]const long input_shape[] = {1,m_sample_size,4};
7 E' ]5 g8 D# a5 ^; U4 p# ]if(!OnnxSetInputShape(m_handle,0,input_shape))' d3 U7 ]' H8 k4 x
{$ m2 I" j' Q4 t
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
7 {+ D% k/ A" B/ dreturn(false);' P! y+ E0 ]' e4 R2 n0 @. a
}* A" Y/ i- X/ L$ \6 \) m6 w; r, L
//--- since not all sizes defined in the output tensor we must set them explicitly
& f7 m# w, }( s) Y7 Q1 i( D//--- first index - batch size, must match the batch size of the input tensor
) U3 z2 k3 a( e) y//--- second index - number of classes (up, same or down)
* B! D' N/ k+ _) L2 M+ qconst long output_shape[] = {1,3};! d! x7 p0 z& }
if(!OnnxSetOutputShape(m_handle,0,output_shape))
4 A2 y2 [# Y# N& @, s4 M% U{+ f4 D% M$ `' ?' M) D( u3 C1 ^2 Y& p
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
5 t3 a4 J+ M$ Vreturn(false);
7 S3 Q1 I/ o* o6 V4 r, e3 Q4 T; P}$ p# J7 O- C7 N0 {* k
//--- ok, t) \& h2 v7 B& |
return(true);
/ {; ^, _. o# J: ^& o- a% `4 W% w}+ s; _0 ~% \$ Q* X
//+------------------------------------------------------------------+) v# H2 Y" I3 Y( B( N
//| Predict class |
* X9 k) [; J) F0 s9 U# T- u, U3 q//+------------------------------------------------------------------+
, z2 n% c% H2 X g8 Q8 P5 Zvirtual int PredictClass(void)& ~3 Y" R4 k( f5 s _6 Y+ u
{ |