1. 我们会用到什么模型呢?
" k: k) L+ N& z' I9 K1 p5 M在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。# a& s. X6 V$ Y: N
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进& G' h3 {: c7 M, T
//| https://www.mql5.com |- v Z/ u4 R4 R+ v
//+------------------------------------------------------------------+
& o0 I. K2 W. o3 K9 O! c4 d//--- price movement prediction
3 o! R" W8 _' k8 [9 G#define PRICE_UP 0! h* i5 ]; B6 w" [1 S3 k8 a7 g7 R7 l
#define PRICE_SAME 16 T$ \) v+ @$ ]! K _
#define PRICE_DOWN 2
% l: b) _7 h0 v% t//+------------------------------------------------------------------+
. Z, C% w6 Z' ~( {) e) ~( K3 Q//| Base class for models based on trained symbol and period |) j( q7 L9 q( q5 [
//+------------------------------------------------------------------+0 a% f( z' c, ?1 G
class CModelSymbolPeriod
# G m6 g% Y; e' C) O0 c2 ?{ Q% U* R8 K: q3 b* }
protected:* F" s4 o- \9 |# @7 N X
long m_handle; // created model session handle
2 x" `3 q$ ^3 e: |4 mstring m_symbol; // symbol of trained data
9 J; W0 d/ `9 G4 r) O: U: K# M5 U" eENUM_TIMEFRAMES m_period; // timeframe of trained data
2 c; M, x+ I4 T. Ldatetime m_next_bar; // time of next bar (we work at bar begin only)$ y6 T! R) x; i3 G
double m_class_delta; // delta to recognize "price the same" in regression models- X2 R, q! @4 i, V0 |7 Y
public:6 M; B( u: U Z
//+------------------------------------------------------------------+' D7 g9 ~2 e9 n# u R
//| Constructor |
& y: ~5 n8 I( D/ f) o' U//+------------------------------------------------------------------+: z2 {7 {9 c7 g1 ?# ?
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001), P. J& v% x7 e0 L' V0 P% _* k* v
{
# ^) d Z/ L/ U& Q' Q( ym_handle=INVALID_HANDLE;" N2 a" p; c* h3 V% N: e
m_symbol=symbol; K$ d0 p; \- ~, U/ S
m_period=period; l, X0 S4 [/ v0 _; f
m_next_bar=0;
2 C8 a Z4 o, ~' G/ X- D5 {m_class_delta=class_delta;
! n3 G8 l2 m- R1 U, \}
" e: K8 y$ C6 c( y//+------------------------------------------------------------------+
- t% u8 v( T4 l, o0 T9 t4 _//| Destructor |
0 @4 V8 j* e7 F& S" m! u//| Check for initialization, create model |
3 l' e1 `5 s' ]1 |//+------------------------------------------------------------------+
2 }" v e4 p# g. }! w# c/ ]( pbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])9 h* }5 j/ M8 ~. b2 W# A
{+ v" {. H6 W( {' |/ j4 r
//--- check symbol, period3 ~5 O& D# g/ k1 h p3 ^
if(symbol!=m_symbol || period!=m_period)* C$ I% {" p) j1 g' s
{
8 ^8 N8 d: `. k+ Z% w% CPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
5 E B* ^7 F: _- Y8 ~# o1 freturn(false);
+ \: C3 G: @. ^}! j, e8 U8 s6 M" R% g
//--- create a model from static buffer
9 B4 u: v' ]& \m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);/ m! z2 ^3 I* j" h3 d. @8 p V
if(m_handle==INVALID_HANDLE)+ N# R y( O! F% D
{, h( W& R5 O+ R. u0 H6 d
Print("OnnxCreateFromBuffer error ",GetLastError());0 W1 M2 S5 `; z
return(false);. W' d% h/ w0 G: J* M! L I7 x% ~) v
}
q- D/ @8 @. d, @//--- ok
+ n+ F7 p' v1 t; t9 y: Kreturn(true);- \2 C m; z; F5 w9 B
}1 P$ n; L5 ^" W9 H
//+------------------------------------------------------------------+4 R3 b0 o" j6 t# W5 G& a
m_next_bar=TimeCurrent();
" b1 O% x/ a5 U( h6 o; @4 Zm_next_bar-=m_next_bar%PeriodSeconds(m_period);) ~4 M+ [0 ?. c$ `5 v9 b$ o* p2 Z
m_next_bar+=PeriodSeconds(m_period);
l; w! @6 V3 r% p//--- work on new day bar. E/ g) X' z8 J
return(true);
5 k: I9 `9 w. H}1 @- a* T' K, J6 v2 m
//+------------------------------------------------------------------+
! e& C% l5 i" X- ]7 y1 k//| virtual stub for PredictPrice (regression model) |
0 |1 S% r% }5 z9 K4 @//+------------------------------------------------------------------+2 R/ r7 v) O1 H5 e
virtual double PredictPrice(void)2 ~. V* H; B# R4 I' }
{1 O+ e) A8 y: y- V I
return(DBL_MAX);! G# f: R7 e5 m4 n/ l( n2 k/ s4 q
}. v; F8 w; e( L9 _5 q ?* Q
//+------------------------------------------------------------------+2 V! w* k: Y% p/ D" P+ {/ L) J
//| Predict class (regression -> classification) |
- o- C1 H. K# f5 V//+------------------------------------------------------------------+0 ]+ W i6 p' g
virtual int PredictClass(void)
: B; @, L0 U f; J( t7 E{
, J; C- k7 ]; }3 P; U" i5 g0 ]% u+ i) Sdouble predicted_price=PredictPrice();$ F9 l- X' s2 w
if(predicted_price==DBL_MAX)2 n+ [: _2 z- [/ E
return(-1);; t3 H: g$ T. r7 _0 v: ]
int predicted_class=-1;5 @* [1 \$ _+ y0 X) K3 Q0 E! x* x) A
double last_close=iClose(m_symbol,m_period,1);& F3 F7 Q: Q0 e% V
//--- classify predicted price movement, N H; `5 e2 u# _
double delta=last_close-predicted_price;- m: Q" ]4 J! L9 G$ z% E$ ?- v* r, ~2 i
if(fabs(delta)<=m_class_delta)
* z' ]; ~: j& u( K3 A$ ]& ppredicted_class=PRICE_SAME;2 P) \; |$ U! m3 E" v" J
else
( D j* L) y; h Z% W) m* sprivate:: {% u4 x/ \6 {# U7 p7 A! e. T( l: m
int m_sample_size;
3 U7 D2 z& P$ u% `" E//+------------------------------------------------------------------+6 E- c( Q/ S/ O- N8 M
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
$ X1 \$ d% J# M{
2 X6 v2 a8 |8 a @3 j8 {//--- check symbol, period, create model
; C1 C3 X4 x9 W* U# M, Wif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
8 W2 {2 ~- S6 ^! ?9 D* p{
( J }; C) q! x6 }8 Z, l i7 SPrint("model_eurusd_D1_10_class : initialization error");2 Y; t) o/ a; w/ o/ ~0 k# H
return(false);
- u k# o! n1 R6 b& P1 c3 Q5 o}# _$ I z, y- R
//--- since not all sizes defined in the input tensor we must set them explicitly
9 \2 ?( F* u$ c! Q4 k1 @: z//--- first index - batch size, second index - series size, third index - number of series (OHLC)' J2 L. _5 P! p: @! z
const long input_shape[] = {1,m_sample_size,4};
/ r4 j @; p/ |1 n2 z4 tif(!OnnxSetInputShape(m_handle,0,input_shape))" i& u5 s- e& t" ]3 T6 d
{! W7 c3 W' |/ q2 q8 ~9 D# ]: ?
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());) O+ h3 J& Y F+ {2 g
return(false);
: h# z+ @3 O% j0 j0 s+ p$ ?+ u8 z}: q2 _ q( `3 C
//--- since not all sizes defined in the output tensor we must set them explicitly
" l9 ~4 Z) X3 P6 G/ b//--- first index - batch size, must match the batch size of the input tensor3 P2 [3 d3 |2 W
//--- second index - number of classes (up, same or down), I0 z" L9 A M9 v, K* i8 v! N
const long output_shape[] = {1,3};
" K7 s- P. \3 Y2 T, X6 Cif(!OnnxSetOutputShape(m_handle,0,output_shape))
4 V3 k7 k. L# w{
2 }/ \5 t. K; q9 O- O0 PPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
4 Z% j. V9 I! G5 freturn(false);
9 @+ R( L% p: z5 l( s' \}* e! I2 d3 y' A+ K
//--- ok6 p/ r& ~2 y0 @: f' q- P h
return(true);7 |2 x* f4 g" i4 P
}
3 ~* X [# f& `//+------------------------------------------------------------------+5 O% {6 }# C" C
//| Predict class |
; l7 Z3 x% n7 O2 o//+------------------------------------------------------------------+- m: k: h! W, \8 u- w3 u5 u
virtual int PredictClass(void)5 a& S& W$ Q8 U; t
{ |