1. 我们会用到什么模型呢?! b* F% R# {' M; @: E) x' x
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
& G; X- I- n% X l# ~5 D0 g* N( z- c我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进% V+ ` k; F: Z& l1 o* U8 @
//| https://www.mql5.com |
7 b3 B9 l% e: R; R/ O* p% q//+------------------------------------------------------------------+
0 V" C# N" L( L& j//--- price movement prediction
" w# [' [" `$ J" a% w#define PRICE_UP 0
) J. O* C+ M3 A8 X#define PRICE_SAME 1
c0 o5 v+ i& n; y$ g0 X#define PRICE_DOWN 2! x% `$ R& q$ S
//+------------------------------------------------------------------+( [5 F+ E+ o9 b2 G1 R- t: J
//| Base class for models based on trained symbol and period |
* a% G3 D3 k+ o//+------------------------------------------------------------------+: ^% Q- F. `* O, ~
class CModelSymbolPeriod0 ~- S6 g% _& V
{
/ E! T9 ]: H* D% Iprotected:
1 s! J* C8 J' X% H% Z: b) qlong m_handle; // created model session handle
t- E7 G- [* M& C4 `8 Tstring m_symbol; // symbol of trained data
) j; ? `- Y2 o) ~/ V. @ENUM_TIMEFRAMES m_period; // timeframe of trained data
% l) B4 y7 ]& j2 I- U. x+ Qdatetime m_next_bar; // time of next bar (we work at bar begin only) g7 X! g a6 }, S4 ~
double m_class_delta; // delta to recognize "price the same" in regression models
7 Y* ~. ^ L) N- ]3 `& T# m! |public:, s3 c% J/ Q; q \+ i& v
//+------------------------------------------------------------------+
x! a5 y; g. P& u% k, B4 j4 _! A$ y: t//| Constructor |( u) o+ I4 H4 S
//+------------------------------------------------------------------+
: e+ I+ b: K: SCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
/ T; {; v2 Z3 ?' [+ t1 g9 e. m{; V' [7 P( x& E( L
m_handle=INVALID_HANDLE;* q5 K0 J) }( e8 A
m_symbol=symbol;
4 k% K$ J7 U& mm_period=period;
% O3 [9 z- Z4 u; D+ Wm_next_bar=0;9 T' N# l. S* Y# L( I
m_class_delta=class_delta;
, Q6 |* p; n, L7 i" ~5 F/ E0 Q}
! V3 ?/ [1 k: r! C% e//+------------------------------------------------------------------+
! W, |2 v3 u0 g( m4 x8 {//| Destructor |5 w# V* P i4 f$ Q1 R! w
//| Check for initialization, create model |
: r; u" x/ H; ?" `( b9 P% ?- {5 u+ C//+------------------------------------------------------------------+
$ k B( `2 r( ?- O8 abool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
- b5 h! M& @# P) o5 ~" @- q{ V$ B/ A. ?- Z1 t# x9 h# [! u
//--- check symbol, period
: l: D. h+ _! H0 z1 Eif(symbol!=m_symbol || period!=m_period)
0 k- U* ~$ l1 R \+ G{
2 l9 [6 w- k. O9 N8 W+ l- [5 q& APrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
6 `( `; z7 b$ Y! f: ]; P% D; z# Oreturn(false);3 v7 J* p# T& {+ B4 Q, l$ B* z
}+ {* v9 t9 c! U `
//--- create a model from static buffer- S F! q; N2 p8 H$ D6 M, n" z
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
' n. [6 K- n1 rif(m_handle==INVALID_HANDLE), v# u+ x2 {6 w2 W8 n
{; f: c: x, O% T0 S% A; w
Print("OnnxCreateFromBuffer error ",GetLastError());
$ g! [% J3 k; x: ^( Ireturn(false);
2 u/ Y$ G+ A# P7 J( d5 m}
# e/ n. {+ P4 v" V//--- ok+ n3 y+ B$ L0 w& s3 d
return(true);
|, G0 w$ o0 h}
% o' j/ x3 c; Z, q5 e//+------------------------------------------------------------------+
! o8 U8 h2 b, |- tm_next_bar=TimeCurrent();
4 A3 c& [$ {4 M9 e* fm_next_bar-=m_next_bar%PeriodSeconds(m_period);
( `( K5 H' e$ Q& d* G+ z Sm_next_bar+=PeriodSeconds(m_period);) }5 }& V; S1 T ]
//--- work on new day bar
5 G) L0 Y5 A2 I: l; I; B" M3 s8 n: kreturn(true);& N4 m6 U$ o+ m7 Q# w, E4 t1 R
}
6 l+ I" R) K, K1 _//+------------------------------------------------------------------+
3 T+ z s0 Z, {) D//| virtual stub for PredictPrice (regression model) |- V9 F8 C# B" w9 C0 g+ ^
//+------------------------------------------------------------------++ D u+ {0 s2 K2 ^
virtual double PredictPrice(void)7 { [) Y) ^8 h) ~- U
{. `" D; E$ P" y9 z* f5 O2 a
return(DBL_MAX);( Z" X; [4 ^3 L2 ?4 F/ _ \
}
2 d, O6 K# A$ h2 F/ U* }( R& Y//+------------------------------------------------------------------+
5 H9 x& m5 J- E//| Predict class (regression -> classification) |; L- j4 S8 I7 s. Y; k% s( Z1 x- `
//+------------------------------------------------------------------+/ W& l# }( k( K w; u2 U! L
virtual int PredictClass(void)
0 z! A+ |. A/ p% n( a9 h{9 `# V6 d- a |% T3 h7 e
double predicted_price=PredictPrice();
/ D7 ]' |* Y: `$ Y- |if(predicted_price==DBL_MAX)
! {8 ^% f0 Z, Sreturn(-1);) B, U6 E$ E2 o: i
int predicted_class=-1;
# `! z( A7 e3 M) Bdouble last_close=iClose(m_symbol,m_period,1);: S3 q5 m% c9 Y3 n7 l( y( R
//--- classify predicted price movement
9 s4 W7 k3 h. K! S8 T- H( R6 ndouble delta=last_close-predicted_price;6 k! \# P! `# I, F. {8 }; K
if(fabs(delta)<=m_class_delta)
1 \# Y1 V' u+ w; S; ?# Npredicted_class=PRICE_SAME;
& z+ n) _( K* velse9 o6 a$ g" I; M p1 ~
private:
: N4 }8 U; |/ `- Lint m_sample_size;
; z# C% f, Q6 {//+------------------------------------------------------------------+$ I' v' C W9 U( I% x
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)( H5 O$ v) X- _
{
2 h& @/ X3 ]4 k" q0 d2 `" U//--- check symbol, period, create model
4 a6 p1 P4 R+ Z, x2 Aif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
, E u- W" Z% h' [{5 u" u7 e+ y' B% b) s
Print("model_eurusd_D1_10_class : initialization error");
" k: d. S+ G2 }6 `7 A, kreturn(false);7 g( g& m. R/ n! a
}
9 u( ~; O: a6 C* f! r" M2 O& Q//--- since not all sizes defined in the input tensor we must set them explicitly
$ Q4 J1 H' {% {//--- first index - batch size, second index - series size, third index - number of series (OHLC), J% w4 ~+ [/ S/ I% r+ }5 n
const long input_shape[] = {1,m_sample_size,4};
8 U' l# x1 ~6 iif(!OnnxSetInputShape(m_handle,0,input_shape))
& [! \* T! T! r% \# H{3 U p" Q6 W3 O% ^4 L$ x4 {0 z
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());) _9 j# E: P L8 b4 b1 A8 G9 O8 B
return(false);" h& ~# h- G! I( a. G* O
}# ~' { Z/ y9 E2 S# X5 S
//--- since not all sizes defined in the output tensor we must set them explicitly
. E! X4 ^# r) W+ m//--- first index - batch size, must match the batch size of the input tensor+ G: J/ A' [& f
//--- second index - number of classes (up, same or down)7 \" X' z. d) w$ u4 E! v* e/ B
const long output_shape[] = {1,3};
1 ?# T2 T5 S- T" ~+ }+ i- I4 t4 {if(!OnnxSetOutputShape(m_handle,0,output_shape))
4 w3 k; x4 ]! B1 O* ?{: y& A/ b6 w* B+ z; `! n
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
6 p% V* T8 r3 R7 u8 V$ p& T! Ereturn(false);) f* U0 z1 C% A# L
}/ v4 g! e! _6 g+ u# z4 @& H
//--- ok' S& a: w. x/ s4 `, y
return(true);
( T9 k+ x6 t% _8 B2 q}
- j' d5 S, i% t# d& ~# i//+------------------------------------------------------------------+
9 b# K. [8 v8 [! m. ]' i* g//| Predict class |$ R6 B2 @$ j) z' i9 a/ Z* J
//+------------------------------------------------------------------+
! ?, N) x* D2 O" ]. m% _) Rvirtual int PredictClass(void)/ {; i6 Q' Z8 q5 Y
{ |