1. 我们会用到什么模型呢?
) Z X% [ J# Z1 V5 e* D% f% s& ^在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。1 q! X1 \: g/ s% _! i( i
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
- e- t; S, G+ K//| https://www.mql5.com |
1 {: O7 V* u8 E) i* T0 M" E5 D//+------------------------------------------------------------------+
4 Z* ?; K+ c. S. ~% N' E1 k//--- price movement prediction3 R3 w8 o: t7 }5 d
#define PRICE_UP 00 ^+ i7 B6 a, W7 X
#define PRICE_SAME 19 Q) }7 n4 r; G
#define PRICE_DOWN 20 k7 e- p& H- W$ y( i6 ~
//+------------------------------------------------------------------+
- k6 [$ ]1 {4 C$ a: N9 C; k& h//| Base class for models based on trained symbol and period |
% Y( i& A$ A! y: j! w6 P//+------------------------------------------------------------------+
J7 ?7 ?5 R' x$ x$ P1 w! U% l4 _class CModelSymbolPeriod, S$ O/ `) `! N6 X+ u0 p" M
{ e \: w _3 ~4 Q8 b! V( l
protected:
- B7 M, p3 M" |# k4 s) s4 klong m_handle; // created model session handle
1 L. E/ s3 Y0 G; nstring m_symbol; // symbol of trained data
. \; ^! z& g8 R/ M" mENUM_TIMEFRAMES m_period; // timeframe of trained data
4 R( O7 S/ d3 Y/ odatetime m_next_bar; // time of next bar (we work at bar begin only)
# H- F% `, ~! Pdouble m_class_delta; // delta to recognize "price the same" in regression models5 P9 x' k; J C7 ^! ^1 {
public:
! B! d& C6 l4 b) h6 u6 y m3 i//+------------------------------------------------------------------+
% l7 r8 ]; N7 I//| Constructor |
4 k$ p* {: J9 ^* @- }1 t# K//+------------------------------------------------------------------+, ^) I, b+ C3 A2 T
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
5 A6 z4 b" x9 l) a" L) g{
8 w+ v7 f7 j: h! [9 L, s) h3 C/ im_handle=INVALID_HANDLE;
2 j/ F8 }" {9 Y* H/ wm_symbol=symbol;
" Y$ W4 J9 M3 c1 dm_period=period;- L! c2 y0 {) a0 j9 M' @
m_next_bar=0; k! I" b b7 }5 k. |+ C F3 Y
m_class_delta=class_delta;8 l6 q- h5 ^8 F$ H
}2 P$ s9 Y9 x& x2 n# k: _# X
//+------------------------------------------------------------------+
$ F( W0 u( F$ |0 C//| Destructor |' { S4 y8 [! f" S% C4 t
//| Check for initialization, create model |
; i" T6 l3 {6 P# R. Q3 o: i8 y' G, n//+------------------------------------------------------------------+; {- e( X1 F0 u. l8 W
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])8 l. l0 d; _& R1 A0 e; R! ^; t
{
: Q) A8 z* \ X2 M0 P; [. v//--- check symbol, period
3 F. v* H% z7 ?if(symbol!=m_symbol || period!=m_period)
3 X: [. u1 f) i- l1 h- w) A{
2 A' P, D8 O4 q8 z+ y5 C0 nPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));! U* y; [6 S1 b6 k5 K5 Q% O' r
return(false);
* S( ?6 g" f9 Y}( X) n: v: _& b! F
//--- create a model from static buffer
# w5 Y1 ~# g2 y- x& Um_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);8 W: ], Y6 `* a
if(m_handle==INVALID_HANDLE)5 [3 J# e( B C& F2 b* C6 F+ o q
{ w0 R4 t2 u: Y
Print("OnnxCreateFromBuffer error ",GetLastError());
$ t6 N: I+ Q! J. Z$ ]! x. nreturn(false);
) s+ v, I1 l! f}
! x5 i, t- ?2 j//--- ok& ~% K! G8 \1 g, q& W
return(true);" O* s e# `5 v9 Z$ i4 D3 w
}
, P( r/ B1 c3 C( f5 i( Z5 l) ?//+------------------------------------------------------------------+
1 O6 K: D: J7 {m_next_bar=TimeCurrent(); F) b% |6 @0 G) a, Z- t, M
m_next_bar-=m_next_bar%PeriodSeconds(m_period);& @1 W% r2 j! \5 C
m_next_bar+=PeriodSeconds(m_period);* s! `& {6 L6 I& l
//--- work on new day bar3 Z& N& q9 {0 Y) ^, k* ~# n& ~: M
return(true);
* H) F$ c; @0 K% F4 @; {}, W& s, i1 [5 C2 b( Z+ ~
//+------------------------------------------------------------------+
' {: @! B0 Q @' d4 k9 A0 m2 R//| virtual stub for PredictPrice (regression model) |3 t: W, I! g$ I8 z8 Z' n
//+------------------------------------------------------------------+9 v+ B% r) i$ u3 F: c
virtual double PredictPrice(void)9 D$ n* w/ N% g/ \7 ~
{% A4 E6 o" C+ _6 T
return(DBL_MAX);
7 d! G% T" w2 W6 J! w# y" j' S}: G/ y @5 y L3 z7 u
//+------------------------------------------------------------------+* } ^3 x' ?/ G+ [ I$ w2 [7 _. ~
//| Predict class (regression -> classification) |/ f3 E! l3 R/ N5 w7 l' t2 I0 N4 v9 \+ M
//+------------------------------------------------------------------+( _$ {$ X- \7 p5 ]& k1 E
virtual int PredictClass(void)9 p% J: t0 Z4 P- @
{
) {) M: I7 t, k8 p# g( T/ Adouble predicted_price=PredictPrice();/ |# k* [4 Q" _5 m1 R7 g1 k
if(predicted_price==DBL_MAX)- O1 _6 f! b3 w- z% \& v8 I4 J
return(-1);
; \8 Y8 t; h8 Vint predicted_class=-1;
2 r. Q* ?+ J& U; Ldouble last_close=iClose(m_symbol,m_period,1);
4 W& d" s0 n9 B: r//--- classify predicted price movement
1 | ]7 I% `4 |, ]double delta=last_close-predicted_price; H0 T- R: |1 x- T
if(fabs(delta)<=m_class_delta)
$ N! Y' n8 W4 dpredicted_class=PRICE_SAME;
: a; F7 Y. ~ }7 pelse, I' t D) l' n$ `# q
private:5 q8 \+ d/ p9 _ \( p9 Y/ P; ^' k$ |
int m_sample_size;) }- n' y: K2 ^
//+------------------------------------------------------------------+
6 Z. c+ w- Y8 X( O- c' h* Svirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
; }) C. d4 S6 `6 Z8 x{- q0 h' Z- u: C1 v
//--- check symbol, period, create model5 h$ J4 |) w! N1 U$ Q' \
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class)), g2 [' B, s, a& y! L, F
{
! s2 t7 F4 g( a( f9 p' `2 x8 nPrint("model_eurusd_D1_10_class : initialization error");: C( M0 O! t( j/ i: j
return(false);! ]% s& Q, a( \9 m! ~: y+ x
}$ v. C& E7 \) K) f0 @) l1 |
//--- since not all sizes defined in the input tensor we must set them explicitly
: I) R J! `9 w//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 O$ U2 J& \9 j- Wconst long input_shape[] = {1,m_sample_size,4};- ~* W0 Q6 ^& U
if(!OnnxSetInputShape(m_handle,0,input_shape))
# q5 s6 B2 W4 C) H& j: }{$ B0 b7 N2 h/ v( i: L
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());/ m$ d) A- w: ]3 h5 B( e
return(false);: a( J9 f/ F, i1 G) o/ {
}
& {! t: C k/ K/ r. y6 Y6 l//--- since not all sizes defined in the output tensor we must set them explicitly2 W' D/ Z4 e" h
//--- first index - batch size, must match the batch size of the input tensor9 A# G4 O' ?; T8 g) ~9 w$ Q
//--- second index - number of classes (up, same or down)
9 P* v9 L+ p, N. a' d. Uconst long output_shape[] = {1,3};
: K7 U# |* X) tif(!OnnxSetOutputShape(m_handle,0,output_shape))
( p8 s2 |; C& }* D{9 w1 j1 z& r6 i2 ~! w. k; `
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
" ~- i0 x* F! G! I/ b) lreturn(false);
( u9 x: b* a6 t( L9 a}2 ?1 r$ o+ z' ~2 u; r
//--- ok7 B: ?! d. r* O
return(true);' w: z9 S& c" ~1 D9 z8 |8 \
}
" a, }$ P$ b3 _/ O `: D r6 g//+------------------------------------------------------------------+
, ]8 `$ m9 |" ?* s0 ?& f//| Predict class |% L6 d) O: J" s7 N% s+ ~- Z0 [
//+------------------------------------------------------------------+
5 u0 X' j$ Q {9 Z. pvirtual int PredictClass(void): ^' S8 H6 |& I3 w. N! c2 m
{ |