1. 我们会用到什么模型呢?% W# f2 G7 F* [
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
9 N1 [+ X7 ]* T3 P, W! g7 j我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
* ~5 v w; n! r, h+ Z% v//| https://www.mql5.com |
9 L) o* `; W i* ^7 R7 n) r Z: u//+------------------------------------------------------------------+
8 ~+ ]/ H3 P( D: m7 m# h4 f//--- price movement prediction- O9 j1 Q+ U9 S# X
#define PRICE_UP 0
! y- D7 B/ P0 H4 g* E8 v#define PRICE_SAME 1 b% E, E/ L4 S( b! P9 g: f W5 j
#define PRICE_DOWN 2
, y( q) {! f$ W7 E//+------------------------------------------------------------------+
& s9 ]# \( D# k; c, [* F) w//| Base class for models based on trained symbol and period |: u" g7 _& [" e( y E. Q" Y
//+------------------------------------------------------------------+
" s: J) h& p( x! } {2 T6 b. ]class CModelSymbolPeriod
+ K) ?) C% H+ ^) Q{
1 {: [( @* ?2 p, n: t5 A/ T+ kprotected:
8 a0 h3 L! n. g3 w- t9 xlong m_handle; // created model session handle$ z+ q# L/ E/ T) A/ h- E2 P9 m3 P
string m_symbol; // symbol of trained data
5 s! D7 q* s, Y9 k! s. w! EENUM_TIMEFRAMES m_period; // timeframe of trained data+ Q2 c. d# u! j# a" D8 l; O
datetime m_next_bar; // time of next bar (we work at bar begin only)/ k! |4 T" y' d5 N; k# O- q2 Q
double m_class_delta; // delta to recognize "price the same" in regression models3 R; E6 r8 \! E9 u+ s8 L$ R5 Z
public:
8 e1 M [; h9 T0 N, x9 L//+------------------------------------------------------------------+
7 v% x" B8 \) y3 T/ J, L//| Constructor |7 g0 m' X9 v+ H# w1 V7 T
//+------------------------------------------------------------------+ q) `# E/ N3 g# O' C; e
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
- a& ?/ l+ ~' I' t, l h. o{
0 H% ?/ s R% E7 i8 ?m_handle=INVALID_HANDLE;! {, e6 Z$ @, s6 V7 w" X
m_symbol=symbol;
9 p& n8 d1 {1 b7 W4 ^( Z; }! ~m_period=period;
# A) t! L* x8 v( ~7 l4 pm_next_bar=0;
$ W- Q, P; J/ L# Qm_class_delta=class_delta;
( J2 z' {, E* v& X/ X6 ^}" w1 a/ s3 W' m- {' ~9 D# ?% x
//+------------------------------------------------------------------+. i8 I4 Q0 Z! E% M5 S& M
//| Destructor |
2 Q# C2 ?5 T# H+ W5 ]//| Check for initialization, create model |5 w/ A( c% D# g* H4 _
//+------------------------------------------------------------------+% _# V9 ?% F$ d
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])& ^8 y' ^: m% q- @: j+ }* u& ?: x
{) c+ V1 z i! k& b
//--- check symbol, period5 y2 t# t& K% ]" O! i
if(symbol!=m_symbol || period!=m_period)
) M3 F; ^( o6 r{. w% n* P1 l) T8 ^/ Y& \+ ^8 q
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));6 F4 W0 H8 q4 S
return(false);
( R$ S* x+ l/ q; Z1 Q5 R/ }}
" U3 X7 T8 P2 a& c8 D//--- create a model from static buffer% D `# |7 T8 y' z5 ]9 M; N
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
$ y, u! h \; x& n6 q0 y! m5 uif(m_handle==INVALID_HANDLE)
" L3 n! ^1 I; M$ B/ [4 n( A4 N/ R{# S) p& e9 ^1 G
Print("OnnxCreateFromBuffer error ",GetLastError());
- C) m% X$ r' v0 Greturn(false);( _: N' Q9 X! z% N
}
! b _0 Y4 e+ z3 d. A0 I//--- ok! ~( u* c* h$ s5 ?/ J- J/ J
return(true);. n$ l" u3 R: O
}
0 T. e0 k: v9 c//+------------------------------------------------------------------+. r! K) p7 a, D* p" D
m_next_bar=TimeCurrent();
* \0 m, u7 V( q9 c7 A$ bm_next_bar-=m_next_bar%PeriodSeconds(m_period);, o N/ U3 ^9 R% B; H8 }
m_next_bar+=PeriodSeconds(m_period);$ w. F [% V8 t2 ^& z( a
//--- work on new day bar
! s( c2 N) ~0 Mreturn(true);
' a' Q) K6 K+ `; ~) k}
& J$ r% Z# Y k( ^//+------------------------------------------------------------------+
6 h+ {+ ]3 i5 P) Q; c//| virtual stub for PredictPrice (regression model) |
. @8 S9 P0 V& R//+------------------------------------------------------------------+4 y$ X- X, n! ^! h2 J
virtual double PredictPrice(void)
1 l1 m; M/ }6 c2 {{
, m9 t; r1 k3 k% b3 creturn(DBL_MAX);
) t9 @" ^: r+ u& l5 F7 ?4 h}4 }1 Y( o3 s8 _8 k& `3 K
//+------------------------------------------------------------------+/ E4 _) t9 R& y( k
//| Predict class (regression -> classification) |
5 A* ]4 ~3 U6 x) z2 u% ^//+------------------------------------------------------------------+
( g1 m& w; E% Gvirtual int PredictClass(void)
: M8 e4 K( m; R! M{" j. Z0 U# |; i* A: g" A
double predicted_price=PredictPrice();6 F z k2 f2 n7 @
if(predicted_price==DBL_MAX)
* u. z# g5 L; W8 X5 W# V; _& Treturn(-1);
a3 Z. Y! y* V4 d( rint predicted_class=-1;
: H! C2 x0 X8 P" m. M+ J, [2 u9 Qdouble last_close=iClose(m_symbol,m_period,1);
5 [5 O; q5 M+ f3 H//--- classify predicted price movement( i, w) R+ m& }: h# _6 Q6 J/ k
double delta=last_close-predicted_price;8 b! ]. ?* q7 p. @
if(fabs(delta)<=m_class_delta)5 C7 h1 d7 B; X( R5 V9 s+ m+ ]
predicted_class=PRICE_SAME;
# A0 d8 S9 ~6 g' W1 Gelse
- q6 z# g; y0 f$ E6 V: |! n& W+ Rprivate:& ?* ~9 C( d; j; V! I
int m_sample_size;
K8 \' J, l) H( q* @9 e//+------------------------------------------------------------------+
" ]& |/ R# p% A( }0 lvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)& T0 O0 F0 ? K* }: C$ {: M
{- p" D0 S0 X+ t. l0 k% j1 ^
//--- check symbol, period, create model4 L) h6 p# B5 v- }* H" i
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))9 g1 ?& m" }( d0 v+ P
{. D4 u8 t; l. v* T9 [+ r/ [* I
Print("model_eurusd_D1_10_class : initialization error");
6 Z6 b, E! v% I+ o6 E8 {2 ]return(false);& [8 }" [2 g5 q$ k" W( E- o
}
p5 x5 U7 O) F//--- since not all sizes defined in the input tensor we must set them explicitly
' B, H" V$ ~' r/ l; W, x7 i//--- first index - batch size, second index - series size, third index - number of series (OHLC)
1 f0 g7 v4 H/ f$ n) n% {/ Y1 rconst long input_shape[] = {1,m_sample_size,4};
0 P# m6 P" u' k/ [9 x* X- aif(!OnnxSetInputShape(m_handle,0,input_shape))
' X' x5 @- n& I$ G{
# j2 O5 ]+ F4 ]! ?- Q; V% j! `. mPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
0 k$ m K0 c9 H% [! oreturn(false);1 h0 J6 g, D/ f- v& K
}7 J3 t- a$ x! C4 g( Y H
//--- since not all sizes defined in the output tensor we must set them explicitly
+ `: B6 K' x) ~0 B* u//--- first index - batch size, must match the batch size of the input tensor9 ]1 ~' g1 m3 z8 H4 O
//--- second index - number of classes (up, same or down)$ t6 _; a) z% s* C3 V. C% A
const long output_shape[] = {1,3};; |* k& n# s- a9 f
if(!OnnxSetOutputShape(m_handle,0,output_shape))$ B: S B( \; R w
{
u# u7 E$ s# _: }+ RPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());* a+ @2 t' A4 r7 F+ V! x l
return(false);0 S. C3 B# E- I: S7 m
}8 ?( @# {7 `+ K. l% l$ T1 D
//--- ok
" y8 u# _1 M7 \, g5 w; u! Sreturn(true); ~3 ~. y& g. [- \
}
8 x9 J/ k* M" h! i8 M//+------------------------------------------------------------------+' G8 S8 y1 t; R; K* e+ f: \* H
//| Predict class |
) p/ k, @* X& O9 w( _! C) ^//+------------------------------------------------------------------+
1 Q" n0 j+ r6 K9 }4 }2 C/ Zvirtual int PredictClass(void)
7 S( Z1 R6 z, J$ R/ M! p. Z+ y: L- k{ |