1. 我们会用到什么模型呢?7 n% J. L* {' Y: N# J G! C4 B
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。0 t( |( v: O. B1 x: K. T
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进! v: {3 V' ^8 P6 O" x9 E- j* T
//| https://www.mql5.com |
" Q8 j* ]/ J% p3 r//+------------------------------------------------------------------++ }6 V1 s) _8 @/ n/ Z9 m
//--- price movement prediction
. Y- B9 R- L6 p#define PRICE_UP 06 [& N8 N% Q" O9 e0 z5 B0 ~
#define PRICE_SAME 1( [! o" q/ m; l0 Y$ |: t
#define PRICE_DOWN 2
+ J: T" f6 W& n: G# O/ }* ^//+------------------------------------------------------------------+) O- `! r: E+ _9 g0 f
//| Base class for models based on trained symbol and period |
6 k! T) e! Z6 S3 O i4 n//+------------------------------------------------------------------+: z2 _- F0 ]9 ^% y' R i/ `
class CModelSymbolPeriod
1 f) t/ N, v/ E0 z{
; E0 a. B2 @5 S% Z D: [protected:
# m n7 }, j2 {! s2 e/ F4 Blong m_handle; // created model session handle' d* Z, E# p: C) N) a0 O. W
string m_symbol; // symbol of trained data
' n/ D* ?% Z& a* s- N; FENUM_TIMEFRAMES m_period; // timeframe of trained data& V" ^/ h4 A/ K( N! [1 p
datetime m_next_bar; // time of next bar (we work at bar begin only)5 _$ e% }$ j; q$ J
double m_class_delta; // delta to recognize "price the same" in regression models4 ], G( v {* `: I0 D* h# D3 N
public:: H1 `3 d% a1 w+ L6 p% D# c
//+------------------------------------------------------------------+
" _$ _% Q9 n2 Y- l3 ^//| Constructor |
\5 w# B$ n$ V3 f" V: E& f4 D//+------------------------------------------------------------------+
7 W3 h ^# \! W( L# m% S- S. \CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)" U$ C! i8 g) c
{. l* {& X1 L* z; B! ]' K' f
m_handle=INVALID_HANDLE;7 I/ I [0 e# c; D; `4 a
m_symbol=symbol;
1 F3 [4 u6 Y) n' Jm_period=period;1 U# H8 B( s& o) L
m_next_bar=0;
$ p& K; q& J0 Z! D C2 D. T+ f, Wm_class_delta=class_delta;
: r; O, \0 r4 @& E; F/ I}, F* J2 y" t" e/ x% J+ n9 a
//+------------------------------------------------------------------+
' Z3 ^' C; u% L9 e/ z+ p. H7 Y//| Destructor |6 M& G `3 N4 l& c- u T
//| Check for initialization, create model |% {: r. }. f W1 T0 a" H8 A
//+------------------------------------------------------------------+
0 U' T/ M* n# p2 f) n0 w8 }5 |, ~. abool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
9 U! U, F1 R7 m m{
( g7 V2 u! v3 S% [# {" K% N//--- check symbol, period
( s6 g e z8 h2 c* I5 x- ~if(symbol!=m_symbol || period!=m_period)7 `# D5 D2 l. k V* D
{1 [. h5 @0 z: l0 e
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
5 y% I2 `: Q, |: U% @: E9 ?8 J9 Lreturn(false);
% ~1 f& M$ }# F/ B8 p}+ w. {1 ^; c) @0 f' B
//--- create a model from static buffer- u5 G9 O0 e% |% _: ?$ Y
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
6 l/ o2 d- `* N2 Q( f6 Nif(m_handle==INVALID_HANDLE): Q# R- u, s0 v& y
{: H- L# n) `7 p# Q. j/ D' j
Print("OnnxCreateFromBuffer error ",GetLastError());
9 y1 A/ r, J- [return(false);) Q% L$ X4 e% t8 c% E
}
$ |) i1 X8 Q& ?//--- ok2 h% f8 ?4 h+ W/ n/ V* f
return(true);
$ N2 W0 j: h8 {: [+ {( {4 p! s}/ p3 n9 \& w) [. c- W* `( r
//+------------------------------------------------------------------+
/ R* q( S% ]# c$ A( u2 xm_next_bar=TimeCurrent();
$ ]& g7 J% B! Hm_next_bar-=m_next_bar%PeriodSeconds(m_period);
7 j: p. p' {: b" l' w& D: _+ um_next_bar+=PeriodSeconds(m_period);
5 A. F c8 x7 Z) K" r6 k* \# D" V( a//--- work on new day bar
8 _; [ _7 P, Z5 u- `/ Z& treturn(true); [& W- l+ V9 s( z) ?0 N. v( Z
}
# M& H* b1 ]8 m' c//+------------------------------------------------------------------+
% B9 R, J6 Z- h//| virtual stub for PredictPrice (regression model) | ^3 o& }# m' b; B
//+------------------------------------------------------------------+
7 E3 N3 c. p' h) Z, B; zvirtual double PredictPrice(void)
0 v7 y9 K& ?, l9 V* R4 V{
7 J. J5 w# c2 Z; preturn(DBL_MAX);) y% _6 i+ Y, v. K
}7 [ A6 F* N8 n g$ S
//+------------------------------------------------------------------+) C$ o) N- V/ L4 Z% T% B# N
//| Predict class (regression -> classification) |
' \$ L. |) s: ^/ K w8 T//+------------------------------------------------------------------+0 r x! V+ e* _( t, W
virtual int PredictClass(void)% n4 c0 o3 B8 d* _- |1 _2 F+ @
{
) C- f) \( G' x0 d; K% P7 Odouble predicted_price=PredictPrice();
1 n. Q1 \' m {4 hif(predicted_price==DBL_MAX)
2 `) ], J+ e- H8 c& f# q0 rreturn(-1);: |: n9 M0 N& R; h* g
int predicted_class=-1;
f1 u- Q* Z; I! Z7 V* P, Bdouble last_close=iClose(m_symbol,m_period,1);' f& t- L- Y# p( w: P. K9 @5 x q
//--- classify predicted price movement) Q1 x: o! ^$ N2 b' a) f
double delta=last_close-predicted_price;
4 p, ]' @' d* G- }6 b7 R9 Yif(fabs(delta)<=m_class_delta)- C5 b& x c6 @# A0 j$ Y/ X
predicted_class=PRICE_SAME;$ Q+ k( B9 B+ V. ~6 q: _
else
. d& W3 _/ @) K+ K1 Fprivate: f' _. \3 u4 E- l# q
int m_sample_size;
f! L3 L( A, n//+------------------------------------------------------------------+8 R/ \) T* V# k; T# _" a
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
4 i6 q. A7 y9 P& e; Z% D{4 ]$ X9 x4 Y; t4 Z0 {( D/ ]
//--- check symbol, period, create model8 N% J6 @6 I) n" B
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))6 M, u" R3 A) K3 u4 o) T! j. B" B
{: [0 W; d; x( r: e: d' z
Print("model_eurusd_D1_10_class : initialization error");
- r3 o A$ h4 Y1 treturn(false);
5 k/ b( |1 D6 a} M1 D! S# K7 O/ p* _! q1 s1 C, L
//--- since not all sizes defined in the input tensor we must set them explicitly: ~* l# Y0 d S+ h: T3 q. k
//--- first index - batch size, second index - series size, third index - number of series (OHLC)% e- b( S4 N5 l- b7 b# j
const long input_shape[] = {1,m_sample_size,4};
% ?$ Y9 c- O& j8 P8 v& kif(!OnnxSetInputShape(m_handle,0,input_shape))
3 E) w3 ?, @, p& n6 N* g{. ~4 x: m2 m/ D3 S
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
+ \7 ^+ Z7 |9 r% Ereturn(false);8 b7 T% N* \( O
}
) j9 C$ A; g- k5 B! I( \) J: K//--- since not all sizes defined in the output tensor we must set them explicitly+ d" J$ G' c( a; f
//--- first index - batch size, must match the batch size of the input tensor
, l: Q7 G( \7 @! N1 W% b3 x: F, k; [//--- second index - number of classes (up, same or down)
/ s. }1 I& n- L- B0 | h8 iconst long output_shape[] = {1,3};
5 ?4 ~! X4 i, X. q8 w: {if(!OnnxSetOutputShape(m_handle,0,output_shape))
0 S+ Q7 B. c& J{ ?; Z* A" B/ G i5 S) t
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
, H$ }) z @$ L$ Y1 V! f. j/ }return(false);& C# r% O9 _4 J# c3 ]8 u( ?# W
}
1 h9 D s4 u9 \: B. ?//--- ok
* G7 e, D/ m; Q3 G9 R( Z, Z# preturn(true);, ]4 o8 h" ^! ]
}
( |+ z5 i# D* k0 `% J: k//+------------------------------------------------------------------+) z8 k. I: [( x0 ^, ^6 v" `+ U$ J
//| Predict class | k, e( ^, P: S9 |0 t4 C! q
//+------------------------------------------------------------------+6 K9 j; x! D: t8 H
virtual int PredictClass(void)
2 O0 ^3 N# N' {6 w/ w7 r5 |{ |