1. 我们会用到什么模型呢?
0 `% N3 Y0 f' ` @4 m6 j7 o% T% X% |在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
; a" ~ l) ]! h& P3 r我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进8 C6 _+ L6 ^) P) t0 q
//| https://www.mql5.com |
/ @& M* x0 @$ N1 S/ l/ S4 E3 ]//+------------------------------------------------------------------+
- w) O9 \. Z' m3 \8 m# s3 x//--- price movement prediction
( V, a1 \/ p2 j' e#define PRICE_UP 0' h9 s3 p2 D+ Y. c) h
#define PRICE_SAME 1) F& C0 K! K% ?" ~, c1 y! ?
#define PRICE_DOWN 22 L% `+ Y _3 S# j1 G; t
//+------------------------------------------------------------------+
2 |% J4 z) I, L* _6 k//| Base class for models based on trained symbol and period |
1 O$ T/ K, M J0 k, D. I! D% [//+------------------------------------------------------------------+0 {# u: w; }0 c( z
class CModelSymbolPeriod
5 v& z. V' X/ `! J9 C{
# b' I6 B, [* X( F/ sprotected:! _8 r5 o/ J5 g b2 f
long m_handle; // created model session handle
: r3 {/ N% E( S7 I# tstring m_symbol; // symbol of trained data( C+ y3 M( A8 W" h* w7 c
ENUM_TIMEFRAMES m_period; // timeframe of trained data8 g" d6 e& [" {/ F x( S8 V
datetime m_next_bar; // time of next bar (we work at bar begin only)
. n! t8 g1 G% }+ _8 r8 ]9 hdouble m_class_delta; // delta to recognize "price the same" in regression models% [) f" d$ L5 P& W) G
public:
7 x+ F, |) n9 l8 G//+------------------------------------------------------------------+
9 q* q5 s! b* j( o1 |5 c//| Constructor |
, s A& T+ t* @6 o9 ]# |//+------------------------------------------------------------------++ P, m! `8 W3 B# B# W
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001), W; v7 R$ f# A% l" U2 H% l( a
{
4 G' b% P" {" f5 K. lm_handle=INVALID_HANDLE;/ z; q9 W7 D$ X0 N) h# h9 b+ k( r# y
m_symbol=symbol;) a0 o0 Z% o$ {* e8 g( o
m_period=period;
! [) h* c& z8 o* d. ?# zm_next_bar=0;
% y' t9 n8 g4 [8 b% Q1 [/ f; Y& Ym_class_delta=class_delta;$ c, Z( I$ U Y8 z, O' [/ d
}) S0 [- c: y% z' a
//+------------------------------------------------------------------+
, M3 k& t; d) n//| Destructor |
1 H; w5 y5 l# C1 c/ f$ d$ L8 c4 @" a* g//| Check for initialization, create model |8 X3 Q: v( P B$ o
//+------------------------------------------------------------------+
+ {) D8 k: @. G; [( w- @bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
[# B7 w9 p4 | J4 d& o{1 O6 H' p5 a: f5 T0 F4 e! t1 p
//--- check symbol, period5 M# S, H' J5 S& q9 \& \ Y+ x
if(symbol!=m_symbol || period!=m_period)
% N B; ?4 ~; G$ E$ ~8 c8 v, R{
# B# Z- B7 T# d1 P7 Z* SPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));0 ?, C% {8 j ?
return(false);4 ?3 d, C% h7 j. Z3 j" c
}
% f& C7 S/ e/ A4 n6 r//--- create a model from static buffer
! x5 o {1 F+ x# F: S1 D2 um_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
5 Q0 q. }- C% rif(m_handle==INVALID_HANDLE)
. j6 K( P- l, o2 q3 x" @8 a{- \- G& F+ u' J- I* r3 i
Print("OnnxCreateFromBuffer error ",GetLastError());" r* o; q3 }! L, ?- b
return(false);7 p4 B& ]) ^1 ?
}/ |: Y% u* b5 r }, T4 `' F
//--- ok+ K9 B8 b7 u2 e
return(true);: _ v. B* t+ k* w" x
}' X( P: S% U) L( R
//+------------------------------------------------------------------+, G5 |( d: S* B' l7 y
m_next_bar=TimeCurrent();( c: F% q! X6 y) N2 Z0 ~) O
m_next_bar-=m_next_bar%PeriodSeconds(m_period);) N% p/ q! z+ C8 p# `
m_next_bar+=PeriodSeconds(m_period);0 J2 |' G: a; Q- L3 A8 u
//--- work on new day bar
! q/ s8 Q' {, g2 A9 Z; {' b9 `6 Mreturn(true);4 _; `/ C, P4 P; ]: Y" _$ t5 T
}
7 g0 b1 t5 ?9 T$ e3 t7 |//+------------------------------------------------------------------+
# j; {8 `; R. s2 N2 Y//| virtual stub for PredictPrice (regression model) |
/ A4 J" A A' y2 h+ X//+------------------------------------------------------------------+
1 K$ r) _+ n3 R5 P, v# dvirtual double PredictPrice(void)
( w6 P$ d9 q3 L2 Z* S{7 V& i' O: @ P' u& ^
return(DBL_MAX);
3 j6 n+ z) z/ k2 k3 J0 D6 ^/ i}
, v& D# `! c* I* a3 |' B0 ~ Z//+------------------------------------------------------------------++ ~: H5 U0 u# Q/ j7 a8 s4 Z
//| Predict class (regression -> classification) |
# f |3 |4 x) ^$ M1 ^# {//+------------------------------------------------------------------+$ w* J8 u6 W* P; l' l' M
virtual int PredictClass(void)& f& Z- u2 X0 e( k& Y0 Q7 k
{! B% Y; ^! p7 T5 g) `/ v4 D
double predicted_price=PredictPrice();
) D, m# {" U* k1 _( }1 Fif(predicted_price==DBL_MAX)$ L; M) ^1 n1 F) E, D0 k. Z$ D
return(-1);/ N& d' ]+ n6 p \8 w
int predicted_class=-1;9 v4 C& S0 [5 |% }4 X6 o& W
double last_close=iClose(m_symbol,m_period,1);, q( H8 e+ D2 Z
//--- classify predicted price movement/ ?6 G+ a" @* C0 f" C" N
double delta=last_close-predicted_price;
# D# M, @$ b& }, }" m3 ?* uif(fabs(delta)<=m_class_delta)
* i: W6 ?) [/ lpredicted_class=PRICE_SAME;
% A5 W4 u) m* g$ x; p; p' ^7 R6 N y+ [0 gelse
& G. t8 y0 Y4 L2 f( I9 tprivate:
& n K" p" t: H' P4 qint m_sample_size;
5 ~ m4 o; B" b" d8 r m) C//+------------------------------------------------------------------+
$ e" k- x- n4 Y' Hvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)# e+ _- }8 H# J; v9 U5 T
{0 e/ v9 ^! `+ M6 f/ T# @: j! h
//--- check symbol, period, create model
/ J! S, p' x, b0 lif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class)) y9 C0 X1 h# a/ Q+ P
{' w8 m+ [3 {, m) U g4 @1 t4 Z
Print("model_eurusd_D1_10_class : initialization error");
) t4 I: P7 R) oreturn(false);
' a& y3 Z2 W# _. ]+ |) Y6 s$ `}
3 O# k% j; C+ s4 I7 r8 k//--- since not all sizes defined in the input tensor we must set them explicitly
; x) X. [+ f5 |) b//--- first index - batch size, second index - series size, third index - number of series (OHLC)
# C3 D0 m2 I7 i! n) P/ q; Yconst long input_shape[] = {1,m_sample_size,4};
, a7 P1 v6 E4 S8 q9 w2 bif(!OnnxSetInputShape(m_handle,0,input_shape))6 R6 p/ [; }6 W( U0 l* w) i/ P
{. r9 l' n, e( b2 w4 ]( P. W! b
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
, P1 N9 B u1 P& J I" Mreturn(false);* w* J4 G: l& n* B. ?5 ~ r1 ^
}
8 @6 P2 v) {; G5 k* I//--- since not all sizes defined in the output tensor we must set them explicitly) q e# I: \% {, b& ]& d# l7 d
//--- first index - batch size, must match the batch size of the input tensor2 o5 M% m7 L, f- @& @
//--- second index - number of classes (up, same or down)! a4 [! k/ X2 {1 Y4 u1 g
const long output_shape[] = {1,3};
# M' U5 N* B* {( b8 v9 V1 Aif(!OnnxSetOutputShape(m_handle,0,output_shape))
/ y( b d; t0 w- l{
) i/ t4 W& D, ~# r3 kPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
4 v2 q: F. g- v4 t* ?return(false);
0 D. `. B3 T2 C$ x8 [1 {/ g}
. k, P; ^. @, C9 I; s4 Q1 D2 V# {) [//--- ok `# @& y. q- z
return(true);
2 _' m0 x( v: R; g9 c8 l}
% s$ d1 L2 p4 P( Y" v//+------------------------------------------------------------------+* c+ ^9 [! x* I) | T1 ~! ^
//| Predict class |
9 Q4 s6 q1 ~! A$ |1 W* y//+------------------------------------------------------------------+
& m! r3 q1 Y* @virtual int PredictClass(void)( E% p: U* ~6 s8 M$ W
{ |