1. 我们会用到什么模型呢?; D0 e) v3 W- L- P
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
3 p* [7 W# w" D) i4 {5 m) K我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进; J1 X. X1 c6 ~6 K* M2 ]# h- l0 {( N
//| https://www.mql5.com |% D" ^& H1 S _3 i1 S; F! _
//+------------------------------------------------------------------+
1 X, |$ t( y' K& ~3 }8 u//--- price movement prediction
9 S0 i1 k! w( l( Q4 W- X0 K#define PRICE_UP 0
3 B- }8 W5 M" c3 b) O#define PRICE_SAME 1
6 F- m! d$ J! ]( @#define PRICE_DOWN 2; z* t# Y( H# E
//+------------------------------------------------------------------+
) {0 z; ~) k5 W% y# Z% {9 z; t//| Base class for models based on trained symbol and period |6 \: ]3 V5 ?& |' M k8 p
//+------------------------------------------------------------------+
& H6 K! F# y0 C4 I4 nclass CModelSymbolPeriod5 n+ Y* ?* }' o: j0 h
{1 d, U4 V+ t( G0 y! U7 o: B
protected:( x/ V* w! q# K1 z) ^
long m_handle; // created model session handle
7 X+ N+ [+ A- N1 G7 ostring m_symbol; // symbol of trained data" E; d# h5 X2 h( G8 \. \6 L( {& x
ENUM_TIMEFRAMES m_period; // timeframe of trained data
0 K! I2 H4 {) X n" sdatetime m_next_bar; // time of next bar (we work at bar begin only)
, @+ N& {4 J9 r2 C H- m' Cdouble m_class_delta; // delta to recognize "price the same" in regression models$ B. R9 Z( X) t, b
public:
' N# n0 {; v y. `//+------------------------------------------------------------------+
- B. S$ Q4 i5 S//| Constructor |
8 ^/ C; M1 K" i* F//+------------------------------------------------------------------+
. n- S4 H/ J( D! u3 M8 e" ?& M) H" _8 ACModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
9 u, s# q0 h& q: j7 h{
6 o& N# D, _3 F5 m1 Pm_handle=INVALID_HANDLE;" U" d: q& |* N. ^- J3 p+ r( Y
m_symbol=symbol;
7 f5 Y# {4 N* r: S3 Lm_period=period;
$ [: D f% g+ u! T) y1 y! f- t W% {m_next_bar=0;
# G2 I: x9 a4 `4 Um_class_delta=class_delta;, r, [. q* y1 y, [3 {+ U+ r& E
}# _. ~$ p8 i& t) U' _5 {& g
//+------------------------------------------------------------------+
, U4 [; s5 `1 R5 t( f//| Destructor |
6 u# `* I: N, l8 e- P//| Check for initialization, create model |
. F; h+ z* ?6 [7 r6 ^" d s! ~1 U//+------------------------------------------------------------------+
6 @ `( l0 e! y, dbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])2 D& d7 h4 E- B
{
, s0 h, h) B! x! A# j//--- check symbol, period
' a& H1 ~! z2 e$ ?if(symbol!=m_symbol || period!=m_period)3 m% H0 p9 Z; B! p" ~6 g6 C
{7 G. [/ }+ E( Q& a% @
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));+ }& y: a. S" }8 H- f, ]
return(false);
: |& {; K$ p5 x6 d, l# ~}' X7 S) s, K1 T
//--- create a model from static buffer* \% S- X. A5 t. X# \( B* E
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);, t" x, j, M3 F% J8 C. F$ J* z
if(m_handle==INVALID_HANDLE)
4 I- n3 ^" M' j4 e5 t2 r3 S/ U{- e+ h& u z7 k: r P4 t
Print("OnnxCreateFromBuffer error ",GetLastError());8 b9 ^' ~2 z7 C
return(false);9 U- P# S; O, H5 N( a5 J( w
}9 \' D1 A8 _2 Z; T) Y
//--- ok
+ r2 `. i! Z; r0 ^$ z, a U# N5 W8 ~. Greturn(true);0 a- j1 C( N( F6 f% ^# F
}
* j9 Z I2 |. `: {//+------------------------------------------------------------------+
/ Q9 H8 o$ l6 n; O& ~. pm_next_bar=TimeCurrent();
3 R) ^5 i& q4 @1 ?$ Km_next_bar-=m_next_bar%PeriodSeconds(m_period);
* M# Q& C+ m9 U g3 d" h- o Fm_next_bar+=PeriodSeconds(m_period);6 a8 z& s- u/ V/ ]5 s4 C0 |0 y
//--- work on new day bar0 H7 \4 B) U2 l! T; r4 C
return(true);
$ c7 E8 q5 D9 _. d* I3 Z}
7 d0 b9 I+ P$ I0 F$ C9 l7 y4 i//+------------------------------------------------------------------+
& S6 @, t- t$ Y; j- o- G o8 v6 x//| virtual stub for PredictPrice (regression model) |
9 y) t& o* Y: b- y/ r3 i& p//+------------------------------------------------------------------+
6 ^4 P; J; Y" B1 rvirtual double PredictPrice(void)6 s& }4 Y$ i& ]! s' J
{' V" \1 @% K$ Q6 W$ V3 ^
return(DBL_MAX);
! j& j+ W' q2 q: X}, a R6 u$ j0 t1 N
//+------------------------------------------------------------------+! C5 ~9 F- t8 G- m: a
//| Predict class (regression -> classification) |: l7 v+ t+ v" @, x
//+------------------------------------------------------------------+- l3 p1 u- L! a! W- b' |- e3 E
virtual int PredictClass(void)
6 W M7 e( l& W- U: }{ j9 r5 }1 c% }! P! F+ v
double predicted_price=PredictPrice();
7 L! ^) H$ e8 e) Jif(predicted_price==DBL_MAX)
9 p- l2 \. w; O. @. L. J2 ^! x7 h5 @return(-1);* o4 \& @ Q/ ~: q3 _
int predicted_class=-1;
! P$ B" }! v, T- ?0 d* @9 V6 e0 fdouble last_close=iClose(m_symbol,m_period,1);
$ p( F% S4 j0 O# k: A$ t//--- classify predicted price movement
8 x# L6 X+ l2 S9 w% r2 S4 wdouble delta=last_close-predicted_price;0 Y' a% b7 Q$ Z. N4 {
if(fabs(delta)<=m_class_delta)0 l+ F. [6 U- _; y# R
predicted_class=PRICE_SAME;8 G: ]" a6 @! `: w) A6 \4 S
else
7 d ^! C4 } Xprivate:
5 u& B; J7 W4 Q; q" q+ n7 ~int m_sample_size;
6 O' u4 T! G: g9 b T+ H" ~/ M* x//+------------------------------------------------------------------+, H! g# e) O& y. a& B# h- ?$ W9 l( d
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period); k% G& T$ w7 \4 I2 Z2 }
{
5 L+ S( w9 u4 T9 C0 l$ Z8 w" d//--- check symbol, period, create model- ]8 p% x& ], X& k6 B, N9 c, t3 L
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
* b6 u- g& V- R/ \( y9 Z6 t{" D r# F4 P9 y% Q9 H7 O
Print("model_eurusd_D1_10_class : initialization error");# V9 K% C" x& p; K/ w/ z" T H
return(false);
5 Z3 I& F: \9 D}
0 D" k. k+ ]8 a, {% O; e, h, t//--- since not all sizes defined in the input tensor we must set them explicitly; t5 v0 @0 L4 @% H2 s0 b
//--- first index - batch size, second index - series size, third index - number of series (OHLC)+ _" N2 y% b& S, {( H5 m
const long input_shape[] = {1,m_sample_size,4};
& P1 v" Z9 s8 ^/ [8 R2 _% Sif(!OnnxSetInputShape(m_handle,0,input_shape))( ? t0 @8 U5 {1 h1 D- |
{# V# f0 A( x* K/ ]- l8 {2 E; \
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
; D3 N1 ]1 a; ?, h! C- ?, C& s7 t5 rreturn(false);
' ^( I# J5 D' K) a} z6 q! |+ a, _
//--- since not all sizes defined in the output tensor we must set them explicitly. l7 g: B8 Z% Y; R+ w7 F
//--- first index - batch size, must match the batch size of the input tensor
- ?" l8 H1 g$ S% Z$ Y; l# u//--- second index - number of classes (up, same or down)" s' W, E* Q: y. K7 R- D& K
const long output_shape[] = {1,3};' w* [& e, U( w7 l' p+ A. F
if(!OnnxSetOutputShape(m_handle,0,output_shape))
1 a5 O% R( C$ ^ H# G9 ^{
% v& T/ Y+ l3 e* k# ~, r# k% jPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
$ c) k Y2 d4 o3 wreturn(false);2 n \* { t: Q# y; A2 q3 |# C& Q
}1 x& @" N5 U; t2 a @
//--- ok; s4 M, m: {0 t0 m5 I ?
return(true);0 ^, s9 r3 i8 H3 j
}' q& H# ~7 @2 p. n$ J) c& Q
//+------------------------------------------------------------------+$ C B( ]& p) B! k9 p# A
//| Predict class |- Z. n; Q1 g* c$ o0 F. R9 n" f4 r
//+------------------------------------------------------------------+
& g0 o3 O; T, E0 e$ ^( P4 Lvirtual int PredictClass(void)) e; f) x; o! v# T& }
{ |