1. 我们会用到什么模型呢?
R; G, p x. ?在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
. [* g- Y" M% p" l/ Q, w4 M$ \我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进, n) H) n* A/ `7 w8 c: W! B& f6 Y
//| https://www.mql5.com |
! Q' N& @4 Q3 P# O5 m) \//+------------------------------------------------------------------+, Q: A0 s5 x* B
//--- price movement prediction
7 U( O$ R& f2 q$ W#define PRICE_UP 09 W, K! o a* M3 R4 |
#define PRICE_SAME 1
1 E" `4 }( l& E4 S) t% r#define PRICE_DOWN 2
~4 B! X% C6 }3 q2 j5 w//+------------------------------------------------------------------+
- ~: R8 x1 L$ o7 J' j+ M5 O//| Base class for models based on trained symbol and period |: f5 T+ O* N: J# Y0 P$ p# Q
//+------------------------------------------------------------------+8 f1 W) `: f9 j' D
class CModelSymbolPeriod; P4 M6 \% S" e# I
{8 }" p: _( H, q+ [0 L% X
protected:
6 k( ?( X7 r2 g( H+ X- ]. {long m_handle; // created model session handle$ ]. R4 h: O# }% B5 w
string m_symbol; // symbol of trained data8 V) T/ B; ?2 @ `5 ~
ENUM_TIMEFRAMES m_period; // timeframe of trained data
9 K9 s6 G6 J/ ?4 K( ^; ]datetime m_next_bar; // time of next bar (we work at bar begin only)
* I+ J" U" Y) M4 Y6 j: vdouble m_class_delta; // delta to recognize "price the same" in regression models
# r+ X# O2 E' n( I9 r. p0 {public:
8 A3 L& I# ]6 ]- }//+------------------------------------------------------------------+$ a8 _& S! s x/ x/ l0 j3 C
//| Constructor | U4 H' a: X1 {' ]9 }
//+------------------------------------------------------------------+
- `7 v" ~! I' s2 j" O1 _% N# I: F$ }' sCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)6 r r) H o; B. k
{& f8 N0 H& a) ]
m_handle=INVALID_HANDLE;9 E8 p: N. H' P6 n3 _4 O5 t
m_symbol=symbol;
g3 |+ J! U: Vm_period=period;
7 ?/ \; O' a- u' t) k* Pm_next_bar=0;
2 K4 \0 K* C9 @/ U* xm_class_delta=class_delta;7 `2 l) D' q8 L+ {
}
# c; u% b2 P0 A/ E//+------------------------------------------------------------------+' K7 |; x# Q8 |
//| Destructor |# u0 l1 u& p9 R" M0 F4 Y" B
//| Check for initialization, create model |2 h+ Q& v: p" S* v! W
//+------------------------------------------------------------------+
1 O( c8 [( V6 Y5 Kbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
G9 \; o. Z: r4 w{
5 T: b. j, { K5 F' ]9 h1 o/ e//--- check symbol, period! `& }. s$ D) N0 V m- a4 j
if(symbol!=m_symbol || period!=m_period)2 W! ^( M1 T4 m* `! a0 Y4 e) l
{' {* I. Y8 L) _
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
; B( U; X7 G( Breturn(false);
% M9 x0 |% C+ |6 t3 B' m5 e}
) E* y3 ^. ?$ ~, B//--- create a model from static buffer
' b+ h, B& o5 e8 q! H4 e/ Am_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);& N) t6 B o7 |5 H6 u7 X, W
if(m_handle==INVALID_HANDLE)' ^/ {+ u' _/ c) \
{6 S8 X: c s" }( i# S2 x5 ]6 c( ?+ S
Print("OnnxCreateFromBuffer error ",GetLastError());# S$ B# M( N( H6 g1 n: |7 `
return(false);
0 S( Y! v- w* R) |}
6 l- {9 j+ P5 Z' S5 @# O; m3 A//--- ok* S; _8 d4 ~$ X6 O: X
return(true);0 F) S. O" V6 b, P* F( m: N3 y
}
" x. F/ V- K6 G5 p5 M+ B3 X//+------------------------------------------------------------------+
$ b% w* {& X+ F" ^0 j% N* C, Dm_next_bar=TimeCurrent();
' R& n9 r5 \% rm_next_bar-=m_next_bar%PeriodSeconds(m_period);
. |& ~! E+ Y6 q% }. b! Bm_next_bar+=PeriodSeconds(m_period);
6 X& {* ] |( `( h* m- o//--- work on new day bar
/ ~9 G7 P( y# J& P' D; o5 p4 Mreturn(true);4 f: o9 ]$ C. h$ p" r; w
}
/ _$ R# V* d. B% b2 Y7 `) f//+------------------------------------------------------------------+
7 N- e! _) X1 G* a5 h& O0 d2 X//| virtual stub for PredictPrice (regression model) |' ^9 l6 Z. x. i: ^* m
//+------------------------------------------------------------------+' [9 P, [1 W+ g. c+ x2 F/ x
virtual double PredictPrice(void)
7 D1 Q; D4 k; Y8 f' s. @% b{
# |$ }# q: p) O" h! [5 q* K# areturn(DBL_MAX);
2 E1 E, ~* p k* J} j, r: O( M& V- D
//+------------------------------------------------------------------+8 P8 T6 h2 {6 k- G0 V6 X6 y
//| Predict class (regression -> classification) |
' @' J/ v8 \% a. x4 s) n//+------------------------------------------------------------------+7 ]/ s* a( L6 m1 i: u& D
virtual int PredictClass(void)
5 d9 Q% P: P; H- ]{& f. f9 O* ?+ A2 f
double predicted_price=PredictPrice();1 b+ H6 v" p+ U+ [, {
if(predicted_price==DBL_MAX)6 Z1 ~2 l$ N% e) @! u6 }3 o# [6 _
return(-1);& ?- X2 W9 p$ J9 A" ?
int predicted_class=-1;9 h4 N( Q, E, v) ?! i; o; S# G
double last_close=iClose(m_symbol,m_period,1);8 ]( v1 p" w( X, i! y& M l
//--- classify predicted price movement
" |( J1 ~+ _0 r9 n. s) Cdouble delta=last_close-predicted_price;4 v! k+ f. ~. p" r
if(fabs(delta)<=m_class_delta)
* x( G7 U4 v! Z6 p2 W0 apredicted_class=PRICE_SAME;
$ F, N% I( x- l3 @8 Welse8 X' P& I; I, }& v: Q+ L/ z; U
private:2 k' ~0 o+ C( `# N/ {
int m_sample_size;
) f; K( \7 {- Y//+------------------------------------------------------------------+
; T7 ?0 }$ A: ~- e& o* J% Evirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
& V& X+ e! j1 [1 w( j# B{
7 `6 L9 m3 b8 `: a8 c" J//--- check symbol, period, create model
7 {0 `/ f! e# R- b9 e) gif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
) n ^. E- c, f, n{
& q& Y; A% P) M1 ~ M6 x m0 R7 w% ZPrint("model_eurusd_D1_10_class : initialization error");8 b& ]9 Y4 B4 \2 @0 U
return(false);
& {+ K2 l `& `- Z; j}( l* |. G9 s5 _1 O0 {1 O& a a
//--- since not all sizes defined in the input tensor we must set them explicitly X: @) n- p( l& L
//--- first index - batch size, second index - series size, third index - number of series (OHLC); ] Z1 {1 c$ }- H7 ~3 T
const long input_shape[] = {1,m_sample_size,4};; H# [: V5 k1 }# z+ m( {1 D( Y
if(!OnnxSetInputShape(m_handle,0,input_shape))
; `$ \0 l @$ k C{+ F4 \% b9 ^& ] ^/ {8 e% z
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
* o9 O. R% F, Q, F5 b0 ureturn(false);* K9 ~/ g0 A& I2 j
}/ Y8 F/ P9 b2 R& g+ c7 ]8 h# `/ ~
//--- since not all sizes defined in the output tensor we must set them explicitly% @% @3 e" W7 D& z6 y
//--- first index - batch size, must match the batch size of the input tensor, Y: ^: j' r- k& Y& Z
//--- second index - number of classes (up, same or down)2 Q& G2 h" l6 |+ I, X7 C
const long output_shape[] = {1,3};
* I j( q/ H- \- {if(!OnnxSetOutputShape(m_handle,0,output_shape))
4 A, Y. a: e. N; T{
' r* W9 c2 G# Q6 @' p& iPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());# h; e: Y a7 ~' X% {$ P$ g
return(false);9 [# J4 q* x3 x8 b _
}) S: Z+ E3 P" g9 k# c; p5 ]. |2 q
//--- ok
4 P" {# T4 |: D0 Jreturn(true);
: w" |3 Q+ _" E4 l5 F}
" S4 r8 |$ F5 a//+------------------------------------------------------------------+
% ]9 G$ b" Y5 z: S2 h+ u) r//| Predict class |
* j9 A: ^1 u# Q7 z% W: n$ d6 e4 d7 r//+------------------------------------------------------------------+
0 O, O' w& b! nvirtual int PredictClass(void)! x1 q' @4 W z
{ |