1. 我们会用到什么模型呢?
5 k: \3 v5 m7 A在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。$ w; j- B3 K+ I" D9 q" J
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
9 y: r' p# k, X+ q4 i3 r, _; S//| https://www.mql5.com |
1 v8 Q& e8 @; ^5 l//+------------------------------------------------------------------+
' T1 S" o+ v- r/ C//--- price movement prediction
& L# ^5 d7 p" {6 _9 I7 h#define PRICE_UP 0
1 S9 A* y0 {6 t+ H& A) \" {#define PRICE_SAME 1+ }8 Y0 j; p; H4 V+ e
#define PRICE_DOWN 2& @0 e G8 ^* A1 H
//+------------------------------------------------------------------+
, `( w3 N9 \/ S$ ^//| Base class for models based on trained symbol and period |: r e6 j& y% Z4 @# \1 u
//+------------------------------------------------------------------+( ]' a' q" x) B0 o9 c
class CModelSymbolPeriod
7 b- R8 l( M- ^( _1 E. I! O{
2 l+ X# c- Y* c5 U) a3 P7 Pprotected:: W! d6 s: a7 T9 P! l5 L2 U
long m_handle; // created model session handle
" \- v9 w2 r4 r9 X7 t4 r0 ^8 ystring m_symbol; // symbol of trained data3 S' f5 g8 B& w
ENUM_TIMEFRAMES m_period; // timeframe of trained data
. |- c% _' S$ L( [- l) k+ l5 udatetime m_next_bar; // time of next bar (we work at bar begin only)
- K0 j' G) P/ ]& X1 Q. e$ Z. Bdouble m_class_delta; // delta to recognize "price the same" in regression models
/ S, K7 S/ ?' W+ r3 Z. fpublic:$ R0 N f8 s& F
//+------------------------------------------------------------------+8 ]; I ]/ J; _
//| Constructor |% I' l; g/ U, n' ^
//+------------------------------------------------------------------+
- _) T1 R& c. u% P, l1 k3 PCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001), V$ T9 z! M% O& e5 B
{3 u- F+ r& E# x3 Y" u2 D
m_handle=INVALID_HANDLE;) f" Z k( B, {% h! G2 K4 m; M( Q3 Z
m_symbol=symbol;* I2 e$ a6 N" I; y+ q) R; x3 ?
m_period=period;4 \# B* @. t- |# `5 N
m_next_bar=0;3 h! _( X; h0 ~9 p7 F: U
m_class_delta=class_delta;
- P; u* M( l5 C; |* c/ L& W}
0 D1 x% W0 {! I, W6 ~//+------------------------------------------------------------------+2 i8 {8 t+ H/ X" W2 }# \# b
//| Destructor |3 z: [" ?7 M: Z& u5 k$ n
//| Check for initialization, create model |
$ z" e' C) @: M: x! f//+------------------------------------------------------------------+
4 A5 h' |% _# w6 j; r0 e: Nbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
& ]2 i7 U ~ v{
9 b2 _9 n8 P# A//--- check symbol, period
# a5 k/ T5 u9 {# m1 J- N9 F% qif(symbol!=m_symbol || period!=m_period)
1 I% |9 U! F5 e, F4 J* x; b{
3 G+ T( @* j* K. r+ d4 P' }1 e% qPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));% i9 g; s: V, S- P! c. z( ~1 v
return(false);% [. Y- N4 T2 {
}
0 P5 q1 Z7 L5 @0 F7 ?: L//--- create a model from static buffer: u- a5 D1 a$ L% L6 ]
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);2 q% @$ J4 I1 K" W
if(m_handle==INVALID_HANDLE): k% R8 u7 l7 N! O' D1 c4 o
{
L6 B4 r' [* |1 t$ }Print("OnnxCreateFromBuffer error ",GetLastError());, b7 V. T" A& f
return(false);; S7 \0 B7 B/ h. M: L* D3 R
}, K" z& d( Z- Z+ D: x Q9 y
//--- ok8 a$ T% x$ W+ q. Y# k
return(true);
+ Z o1 x$ s" [0 ?' c, _}. K4 g/ n) F% x+ Z, c
//+------------------------------------------------------------------++ E5 W2 ` j7 q5 G; S, v
m_next_bar=TimeCurrent();6 G5 q; A3 i2 e9 a
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
& N; H3 t5 b4 pm_next_bar+=PeriodSeconds(m_period);) o3 ]+ l6 j6 `2 K9 D
//--- work on new day bar
7 @9 N' v) T+ x9 F5 q" u2 Lreturn(true);
* M; O$ u- ?9 @9 `5 O}
' t* P, Z4 r2 Q, c2 h# C//+------------------------------------------------------------------+
) u9 |" T/ q4 `. f: d//| virtual stub for PredictPrice (regression model) |
* K* g2 y9 |! K//+------------------------------------------------------------------+
& D. A' M8 @6 K6 |( Kvirtual double PredictPrice(void)$ C9 a" F# ?* z. `5 a
{
5 O# o, E7 w+ i6 Q% Ireturn(DBL_MAX);
. x# t4 x% F# b7 |! f" h3 Z& s}
% F# y" M, l' D* j+ ~9 i) g& ~2 n//+------------------------------------------------------------------+* l9 s( p& l# I- t' n
//| Predict class (regression -> classification) |
$ L0 c7 V' C3 }- v+ M$ V//+------------------------------------------------------------------+7 }& x. \' T3 { h; J
virtual int PredictClass(void)' M- p$ |0 c" ?! j
{+ K8 d2 w% c6 }' ]7 _3 K( N
double predicted_price=PredictPrice();) D" S1 d i" M' J- U& j4 _8 X" I
if(predicted_price==DBL_MAX); @# t! y1 h3 {% h) `
return(-1);
5 N2 r) a% ~7 F$ {) Y7 Xint predicted_class=-1;4 i# t% Y# h0 f' E
double last_close=iClose(m_symbol,m_period,1);- \) A# ?9 \: F+ O8 N
//--- classify predicted price movement1 g# t, \. F' N( |* W
double delta=last_close-predicted_price;
* b9 N5 ]8 b; V' h4 r) {2 @if(fabs(delta)<=m_class_delta)
* j# K$ v" Q9 Z% w( T7 j$ ` opredicted_class=PRICE_SAME;
$ F7 B4 {0 S0 I3 gelse4 O2 @* _" B# c: e4 a. T
private:0 C; s. ~; b: X0 Y
int m_sample_size;
$ n& Q* n( t- @//+------------------------------------------------------------------+
% M0 U0 a* J2 }3 p& J( r8 _8 N; Q ovirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
X# n7 e" R; T$ x0 P/ q& S{
. T5 S3 b2 F) W, M/ L' b' H! S9 k$ q//--- check symbol, period, create model* D) ~9 L# ^* V# S! l
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class)) L; A; S9 B# P7 H: U
{
2 c l. o1 m2 Z1 SPrint("model_eurusd_D1_10_class : initialization error");! z( I( z) D x
return(false);
; E( G7 ^8 R6 r% y/ Q, S}& y0 A3 ~ @1 c& `2 J5 w, ^, Y
//--- since not all sizes defined in the input tensor we must set them explicitly# E5 ^% x5 Q. K; Q
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
$ `! ] D7 M5 u5 \const long input_shape[] = {1,m_sample_size,4};' q# O7 p& z' E
if(!OnnxSetInputShape(m_handle,0,input_shape))1 [8 y3 D" R( m# o
{) e3 U5 |, V- R+ V
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());. s5 b) h$ }+ Z
return(false);
4 J1 a& K9 ?7 B' Q/ }3 p}
9 T( ~( R+ z5 A/ C' Z# F; i3 P7 F% e; Y//--- since not all sizes defined in the output tensor we must set them explicitly
, C$ {/ M7 b# O. q0 i7 I1 L+ \5 X$ M//--- first index - batch size, must match the batch size of the input tensor
4 R3 |$ X7 K& L, o; [; f//--- second index - number of classes (up, same or down)( t6 Y: W) M1 q- A
const long output_shape[] = {1,3};7 k U+ j @) A& [$ Y
if(!OnnxSetOutputShape(m_handle,0,output_shape))) d: n: J# E4 _) _* |2 j# G! s t
{
6 ~. Z @2 R$ H2 E6 EPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
& K& O6 T6 p# z2 rreturn(false);
1 U( Z0 O- W6 P+ }}
/ \9 ]/ R' \, A6 ]/ }//--- ok! z/ [" X4 H; A# L5 O' B
return(true);
! r8 p* x$ v, J A( E! U4 j}
' G( n/ Y' J# f( C//+------------------------------------------------------------------+
0 v3 C/ P1 t, D4 e1 Z u4 R//| Predict class |1 X9 T; J% v7 x7 X; _- p
//+------------------------------------------------------------------+
0 {7 D5 a$ \$ W% }) E6 V3 P- k5 gvirtual int PredictClass(void)! F# i- _8 [, q! c3 p
{ |