1. 我们会用到什么模型呢?/ r2 _/ M$ X8 B9 y# k7 M) P- M
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。; U3 l* v" r0 a4 }
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
" K4 c; k( `7 \' d1 N//| https://www.mql5.com |# i1 r9 F# Y z( o( ]* l0 Z
//+------------------------------------------------------------------+- u6 K5 S' J( ]; W& s; b* a
//--- price movement prediction
8 F, \( @/ X- N7 U5 T7 R( s#define PRICE_UP 00 i$ N! t: N5 K" V' z2 m1 Z
#define PRICE_SAME 1# W( `3 R, o% K1 t2 q
#define PRICE_DOWN 2
* [: }2 P% d ]9 x5 U//+------------------------------------------------------------------+8 _- A4 l0 n7 w
//| Base class for models based on trained symbol and period |1 [ {" @9 v/ v
//+------------------------------------------------------------------+
! J9 I6 y* f$ W& Y% Oclass CModelSymbolPeriod
* }9 ^1 `. K/ S{
4 j+ q0 k- \ J; [protected:: _- j* H* u' f
long m_handle; // created model session handle
" { }* C" N% N" g& g' jstring m_symbol; // symbol of trained data5 W' @; f' b& O" O6 I# T! W/ C
ENUM_TIMEFRAMES m_period; // timeframe of trained data
$ Y" `5 b3 z3 v7 ydatetime m_next_bar; // time of next bar (we work at bar begin only)
7 g* m* X/ y9 b8 | d" {2 X' [double m_class_delta; // delta to recognize "price the same" in regression models
3 o3 s$ v7 Z, n7 V* xpublic:
! @8 s% R& ?0 q" B3 {//+------------------------------------------------------------------+9 Y% t8 x% Y% c2 w- q
//| Constructor |2 s- T0 j5 }0 Z
//+------------------------------------------------------------------+
# k& x; ^+ z4 q7 _5 MCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)1 M/ J; Y5 a7 w x, @
{
& @2 G" T! c; b& e8 g( |m_handle=INVALID_HANDLE;- d! i! E4 @$ [4 D) z0 q
m_symbol=symbol;0 ^: R$ ]; @) `8 ^; j- k2 M3 j
m_period=period;
4 t/ C6 s8 S, h' E- Um_next_bar=0;9 W8 C& A+ A4 D6 E/ e/ F
m_class_delta=class_delta;
; _9 r3 L0 w* b/ r& A/ `( y" `}) P+ |) ^ l; C3 n7 j" K4 j0 I
//+------------------------------------------------------------------+
7 ]! j% ~0 p9 p" P8 A//| Destructor |0 {9 l5 `+ s7 s
//| Check for initialization, create model |. C2 D% `0 d! c5 [
//+------------------------------------------------------------------+, g9 \# _/ P3 h( T8 k. c
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])6 l9 ~4 x3 I. I& H. P# X
{6 ?( ~0 a$ M4 `: t% K
//--- check symbol, period7 t0 W$ E/ u4 c f1 Q! o$ `9 O8 R# t
if(symbol!=m_symbol || period!=m_period)
! ?' H7 {' P1 a$ [2 [{
( W5 J4 ~' s9 U, p! }PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
4 v; @( Q2 X: ^3 Ireturn(false);6 t- m) u+ S. i1 {, r
}
5 Z& }7 x) v. j+ m# {% h//--- create a model from static buffer3 s \. k1 r, p M/ @
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);6 m8 Y. a+ \' U& N U
if(m_handle==INVALID_HANDLE)0 |' s% a; V4 `
{
2 y9 `) [- H* N7 U Q. `/ h4 qPrint("OnnxCreateFromBuffer error ",GetLastError());, M* a7 x# ]# W3 T; f7 d
return(false);) L; r" d; U$ W; l: Q1 }* [. n
}7 h4 O) E. |; u F! Q% @+ Z4 }
//--- ok) N# P/ D1 b. f/ b/ p4 k
return(true);
& ^- ^5 q$ ~( G8 ?}
7 e- C1 T* H, }, c/ J0 l//+------------------------------------------------------------------+
0 ~3 S" s! I( b0 a! Vm_next_bar=TimeCurrent();
: @5 n) B- m# T2 K6 u+ f/ x/ y5 tm_next_bar-=m_next_bar%PeriodSeconds(m_period);
0 Y( O. r/ S5 A8 x: J1 Tm_next_bar+=PeriodSeconds(m_period);% x! E7 c# r; P, D0 {
//--- work on new day bar: p% M& \' y' N! }) W/ p
return(true);
2 v. D/ `6 `( Q) y) S* S5 l$ ]}# V7 _ ^. m0 [8 a+ R" i) b/ ^3 |
//+------------------------------------------------------------------+
) {# o0 e& Y, r1 T, ^( ?//| virtual stub for PredictPrice (regression model) |
* n* }) Q8 l% H. K8 y//+------------------------------------------------------------------+/ D6 j) ]8 p& d) G- N1 j
virtual double PredictPrice(void)! b9 B) e% V+ u" \$ L8 v
{* J2 C# `% B! }( _8 o3 Q
return(DBL_MAX);0 a* Z( E7 Q5 M9 s1 _6 E* Y
}6 y9 {; z" b( T5 z& z; S
//+------------------------------------------------------------------+
1 V" n. D2 H e- F0 C5 b//| Predict class (regression -> classification) |
- B$ T* ]- [* J; }1 D//+------------------------------------------------------------------+$ `' G$ d. |) P, W* c
virtual int PredictClass(void)/ [/ T8 l; |4 x# d5 N3 F& o
{: ~8 q, Z @5 @3 o
double predicted_price=PredictPrice();% h1 `8 Z+ S6 i
if(predicted_price==DBL_MAX)
9 r6 x. W- d/ { t7 B [return(-1);3 s. z2 E1 c; L
int predicted_class=-1; N" [* ]9 s0 _- t; a! {
double last_close=iClose(m_symbol,m_period,1);
1 m) {6 j! |8 }2 U! Q0 [$ U//--- classify predicted price movement
# R/ C0 Y; F5 b: j' C, R0 I# h# pdouble delta=last_close-predicted_price; T& j4 ~5 y: {, C0 J
if(fabs(delta)<=m_class_delta)
3 P8 @& ]# S! d: {* Mpredicted_class=PRICE_SAME;
0 A) e; e8 F% w1 telse
8 \6 u( K) C+ t0 M; _- mprivate:/ W m) \5 b2 |8 Z* Q. h9 k) T
int m_sample_size;
" \& J: y0 y* B( s7 x//+------------------------------------------------------------------+
, v1 I# g t- {! \) G. ovirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)1 g3 V: _: D; d, K, l7 ~% T0 y
{6 G% I# m+ s9 I8 W. p
//--- check symbol, period, create model
3 ^+ ?+ s4 ?! x- S; D; k- Tif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))& A& j& ^# M2 z! t$ _6 i- v9 M
{* J, h$ Z' `. |! J
Print("model_eurusd_D1_10_class : initialization error");
I# Q6 J, O! d& H! M0 treturn(false);' X0 E! X' T$ R1 y0 s( A
}
2 [+ l' }2 h% q$ i) l7 M% J//--- since not all sizes defined in the input tensor we must set them explicitly% c3 o) ^1 A5 `+ b% g
//--- first index - batch size, second index - series size, third index - number of series (OHLC)0 {4 A5 I9 A @
const long input_shape[] = {1,m_sample_size,4};
# n p/ ]: G1 b, vif(!OnnxSetInputShape(m_handle,0,input_shape))# a. d5 u# i0 r8 y9 R
{
B' Y% w0 I0 U' {, _5 gPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());5 G$ G% m7 |1 m+ `3 o; Y
return(false);
! w5 \# f9 q0 x. m" Y7 E}# W7 f2 {/ |& B* E# s# v
//--- since not all sizes defined in the output tensor we must set them explicitly" e) `" a& Z( w0 c
//--- first index - batch size, must match the batch size of the input tensor
. R: s F8 B( O8 `; ^) b//--- second index - number of classes (up, same or down). r6 M( Q& v& s3 Z
const long output_shape[] = {1,3};
1 u' T' z3 T* M/ i T/ g: Aif(!OnnxSetOutputShape(m_handle,0,output_shape))
, @% A$ r: v/ F# g. K# O6 l{
3 F8 `7 b* }! l" S' y/ LPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());2 O% D5 j, b8 U1 v- q2 Q. x+ ]
return(false);) h2 a5 j* ]; O1 `& f
}# i. l5 d. n$ P G2 I
//--- ok
2 H9 S3 z( H. P# @7 N! breturn(true);3 s3 T p5 @- e0 M4 \6 _
}1 ~" X$ [* g/ [1 p' P
//+------------------------------------------------------------------+
0 b( m4 n5 p% x2 l5 |5 p4 n9 m$ j//| Predict class |
5 ^3 a4 d% S, J. ^2 c7 o" v//+------------------------------------------------------------------+: A. s, V* R$ m( x) ^
virtual int PredictClass(void)" I1 [# q9 r9 Z6 q
{ |