1. 我们会用到什么模型呢?
* N3 N! r& S" \在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
! [1 H ~: u( O% P8 Z; \& d我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进 v }. O4 Y: F5 i; w v, h0 H
//| https://www.mql5.com |
- `. P. R; ]/ p& ~//+------------------------------------------------------------------+* v% g8 Y" v4 c
//--- price movement prediction
, t8 _+ O9 j& P8 }#define PRICE_UP 0
$ |8 y; f$ P# {2 _* i#define PRICE_SAME 1
0 G" P9 ^" [) [% j4 ^#define PRICE_DOWN 2+ ?! j( ]3 s, x( J4 e o9 S0 i
//+------------------------------------------------------------------+
& {0 y. f) C. g//| Base class for models based on trained symbol and period |3 h; e& W5 ]/ |8 }* H; |
//+------------------------------------------------------------------+
5 R4 e; O$ a/ i2 q) i3 ~. ?0 t/ D) lclass CModelSymbolPeriod
5 j) `9 Z/ h p! j% I{
, K$ _; Q$ X& w/ c8 i$ w! pprotected:
4 A0 ]! M; b! w* }long m_handle; // created model session handle
% Z+ x8 S5 ]2 D K. h0 v, R( Hstring m_symbol; // symbol of trained data& V" P. |# q9 R' o# L0 G
ENUM_TIMEFRAMES m_period; // timeframe of trained data, u$ ]- e3 z0 Z3 n9 ^
datetime m_next_bar; // time of next bar (we work at bar begin only)/ m, H7 O( d E1 L% K, c4 a B
double m_class_delta; // delta to recognize "price the same" in regression models
' `; y/ E9 T5 [$ j: b3 d# hpublic:
0 v* |$ O. P! i" J//+------------------------------------------------------------------+
6 s5 m$ T% Z0 M% s- ?* {//| Constructor |
7 A/ K$ ]' f9 D3 S8 j+ O9 D//+------------------------------------------------------------------+
" Y* {2 k r$ W8 z6 z( O5 MCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
) M g# B; N- \) {. O5 d{
. n. a, \6 u' E6 Pm_handle=INVALID_HANDLE;$ P" C) D& `# z) i
m_symbol=symbol;8 x- \; c+ E# Q- A( K
m_period=period;3 V' v, p$ t; t) K, V9 O
m_next_bar=0;& j% X( k2 z/ w$ O9 u9 N
m_class_delta=class_delta;! o* _% P) g( F0 w
}$ g- v; Y- i7 X1 w3 L2 _ G
//+------------------------------------------------------------------+
: T- j, r9 ?4 Q; _/ C Z//| Destructor |' b2 c. o- g* ^5 b4 ~# [% w+ `
//| Check for initialization, create model |3 `5 m' e; `1 S4 W9 |. }
//+------------------------------------------------------------------+
8 Q& g, P2 }. u3 B' fbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])# ~3 a: l2 Q( f% n! I
{5 U/ U$ V% B( Y2 f/ p# d4 u3 c
//--- check symbol, period
4 i8 U6 x, g- H. M7 P/ Pif(symbol!=m_symbol || period!=m_period)5 K9 h9 x/ Q( y
{
7 ~1 G( \/ b" K% \PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
$ Y# m& O h$ ireturn(false);6 D0 F7 M" _; A8 s* W7 ]
}
. A1 X% q" w7 N9 ?# r/ ]//--- create a model from static buffer+ D7 D# S9 B' J, f0 u" {
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
: U+ ~; K' l3 n0 U9 T& cif(m_handle==INVALID_HANDLE)7 {$ e- x! k# p1 q
{" l4 l+ \/ X4 r3 N$ {
Print("OnnxCreateFromBuffer error ",GetLastError());
) k5 u4 H( n2 R9 c, W7 `) @return(false);
: f/ _; ]: E; k9 o5 p! }}
1 n) P5 \/ C: z( X) q' H$ o7 w//--- ok
4 w# B& O9 b* G. `; u" Z+ ^return(true);' L$ O; F4 W" N, U
}
. Q/ a! J; w9 J+ P( f//+------------------------------------------------------------------+* Z( f* G+ Z) s4 \- I/ K. s
m_next_bar=TimeCurrent();
1 W/ h8 H3 \% k, z# C6 t2 b, bm_next_bar-=m_next_bar%PeriodSeconds(m_period);% m) A) r9 c5 ^6 o0 x7 S
m_next_bar+=PeriodSeconds(m_period);2 P. G0 {" d: G( m1 D2 X0 e
//--- work on new day bar
/ ]6 [6 N) k' c, d) breturn(true);. B* W3 K. j: k+ a' Z, @9 a
}
" S0 z% @7 m. w# C//+------------------------------------------------------------------+
) p: s$ P) P6 v6 O2 ~//| virtual stub for PredictPrice (regression model) |
, D! ?+ b6 ?1 V//+------------------------------------------------------------------+
- I2 I( \) S8 {: o: w" n4 a _virtual double PredictPrice(void)
: a, \* G8 |9 \8 U8 f8 W( c{
. x5 P: b2 ~. I' ^0 P+ |! Hreturn(DBL_MAX);- p' z z8 A$ ], i7 o" h9 A' Z
}
: s) k& z# N2 J1 T//+------------------------------------------------------------------+
+ u' M! {% R3 R) o//| Predict class (regression -> classification) |
# i# J* b+ u0 L0 h* E4 d/ w//+------------------------------------------------------------------+6 Z- X7 g) }/ L/ H- W
virtual int PredictClass(void)( g/ p9 U+ H8 _7 [/ d1 L
{
7 ]3 W) Q8 y7 v3 c4 G$ Xdouble predicted_price=PredictPrice();
. {$ P5 b3 M1 O1 Pif(predicted_price==DBL_MAX) _0 n0 k) ]* g+ T- O6 `
return(-1);
! c4 L$ X: W- \, u* gint predicted_class=-1;
: @ a/ G* G' x; E% g7 _double last_close=iClose(m_symbol,m_period,1);
* P" M3 W4 r' D( X( d& `9 D. a//--- classify predicted price movement) f9 C% c- n7 T m! v
double delta=last_close-predicted_price;- y) r: T, c6 x1 _$ i
if(fabs(delta)<=m_class_delta) k3 ^( K! ]. w S8 W
predicted_class=PRICE_SAME;6 l* V) k* l5 t3 V" k5 }
else% ~7 p4 c; l, A* H/ H
private:6 j8 ~4 X9 o% q4 d# `. B
int m_sample_size;( ]- M) D9 Y" ~2 X/ ^- e7 L% Y
//+------------------------------------------------------------------+
* |( H6 ^5 x. J. [0 t e- W0 q% vvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period), c- R4 x, ?& ?, C1 u+ \8 ?
{/ I, A G: O; c# |# i- n
//--- check symbol, period, create model$ {* W6 ~* c1 K% I) b/ q
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
# W3 Q; v' F) A( M% o* P{, T7 A/ Q" x. e: k
Print("model_eurusd_D1_10_class : initialization error");
' b; r& f3 d9 {6 V( C- ereturn(false); f3 K' S- Z) k3 B6 @- `
}
5 |5 C* @" d7 {1 Y//--- since not all sizes defined in the input tensor we must set them explicitly
" w8 ^$ T2 n1 N, f i' T//--- first index - batch size, second index - series size, third index - number of series (OHLC)/ {' Q/ T4 _. n3 Q. M
const long input_shape[] = {1,m_sample_size,4};
6 v! U' F! N$ Y: w; y7 X0 zif(!OnnxSetInputShape(m_handle,0,input_shape))
/ ?( R1 s" k. Y# j{$ w5 q! y+ g1 p: ^0 L
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
3 j5 W3 c8 r6 v/ b" rreturn(false);
0 e! ^- G2 S$ S" d% k2 |" p# G}
& k) D! a" b4 ?: h8 X//--- since not all sizes defined in the output tensor we must set them explicitly
]+ t# w* B( V. b: L7 L. P//--- first index - batch size, must match the batch size of the input tensor
# v Q a7 j- l# V: g0 k3 F t! ~! v//--- second index - number of classes (up, same or down)3 K I& J, T/ b- P+ H' n( z5 L
const long output_shape[] = {1,3};
- B$ o/ r3 ?0 f7 b. kif(!OnnxSetOutputShape(m_handle,0,output_shape))
: k7 X4 P8 O0 C8 P- X, G{' G6 l# {# ?( i! X8 i2 o
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());- p$ t6 H. Z8 n# W3 V/ Y
return(false);8 l# a1 z, ]+ h, J2 C5 ?, \
}
( ^' M6 b. |" n7 v% U, A//--- ok$ v) M% k% h8 ~% G- z; d' ~
return(true);
0 A8 _5 q$ X8 [! p! o}& b+ l( @. X( \
//+------------------------------------------------------------------+( Y, H6 _: i8 |( T8 ~9 @( r" f
//| Predict class |
e/ q; A' b* n F* G//+------------------------------------------------------------------+
. U s/ a, `" D* v2 y2 q# e( K) Pvirtual int PredictClass(void), J* G% l& X( L6 k0 R- k) R
{ |