1. 我们会用到什么模型呢?
. L$ _# |% U* {8 I& g7 }; I在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。5 {7 U/ P6 T% P9 O( i5 H" e& ~
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进3 o8 o& {# E+ q) G: G
//| https://www.mql5.com |
( T% w2 Q9 a7 Y//+------------------------------------------------------------------+
+ g% _& i7 L5 P$ A//--- price movement prediction
8 ?( T& n. U% h. R5 ]- Z% G#define PRICE_UP 0
* v3 d3 p' {) Q3 _#define PRICE_SAME 1
3 k D1 m9 P2 D" {#define PRICE_DOWN 22 s: p. }+ b; _& o7 A Z" t
//+------------------------------------------------------------------+
9 y; m/ m; V7 Q1 h5 p. j j//| Base class for models based on trained symbol and period |- f! ^) [2 e4 D$ I. R. s
//+------------------------------------------------------------------+
1 Z$ ?3 e5 |6 ~$ d) S. zclass CModelSymbolPeriod+ j+ o; z8 c& `. S& p
{
$ c$ R4 Y1 U5 b0 Cprotected:( U7 \9 K i/ \* v E
long m_handle; // created model session handle! F7 k$ T& Y/ u: s7 L; J2 Y; l
string m_symbol; // symbol of trained data' F( B& e9 k! r( n
ENUM_TIMEFRAMES m_period; // timeframe of trained data1 v0 s( I' W7 R8 k9 t8 o6 ?
datetime m_next_bar; // time of next bar (we work at bar begin only)
( Y/ L3 j! l5 n' G& zdouble m_class_delta; // delta to recognize "price the same" in regression models
( L, n2 T8 j7 u% d# p* a4 `public:8 u# p! Y1 g& B4 p* J" e
//+------------------------------------------------------------------+
: V+ z) I3 y+ K6 H" z) [: ?5 Y//| Constructor |
& _! T+ M( e& d( R" L# }9 P//+------------------------------------------------------------------+, q" t Z) ]3 p0 R. [7 ^* J
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
3 k7 C2 H5 w3 G0 {: u6 Y{$ u$ B E: I6 e. D$ e) w! `; Y( p3 l
m_handle=INVALID_HANDLE;
: k* ?* W/ f- [. R2 X2 q. X; I' Zm_symbol=symbol;
1 _# A0 q# P1 z* Wm_period=period;
+ m3 i0 r( T* k. ~( V- y& E* Rm_next_bar=0;
J( y+ i. l: f( Q' ^! Fm_class_delta=class_delta;
/ K, Y. x0 n) F* D1 H}
5 `3 z/ @2 R! J6 r/ ~& Y; h* m/ d0 x//+------------------------------------------------------------------+: g& t7 D% u1 B$ J
//| Destructor |
8 S3 K2 _1 }& [! r/ o% ?# a& f2 [//| Check for initialization, create model |3 s1 P! ^* r/ w9 T8 Y9 t; I/ i# b$ b' D
//+------------------------------------------------------------------+
% d, \! p e, X$ A2 i8 ibool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])/ a0 `% ?# u2 O0 f" [9 n
{: @# t% S" Z) ]& J
//--- check symbol, period8 \/ r# W5 s, f0 O) W9 z
if(symbol!=m_symbol || period!=m_period)7 n0 V3 R3 i+ i
{
) F- e! d+ W: N( f( IPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));) e2 w1 T3 |, k5 \- d
return(false);& D. ~" h2 t( Z( P& p8 z
}; w, i' V5 q/ o' b
//--- create a model from static buffer
& V, ]& \7 _3 \4 Tm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);. F) L$ ?! ~7 N" A, c6 P) C# m4 y
if(m_handle==INVALID_HANDLE)8 \. f( `- f- }! H' T; y
{: m4 x- O2 l8 K; g- B% T
Print("OnnxCreateFromBuffer error ",GetLastError());) Q8 O- @+ R5 t& D& `3 K( i+ j" i. t
return(false);
' o/ V0 ?0 E4 n- [4 T# v}- h1 x9 {9 u" r0 S5 {" M
//--- ok/ P5 q: n) L/ h8 C- M: Z) E
return(true);% t# w4 @; h8 c
}+ G" y# B6 m# z R
//+------------------------------------------------------------------+! j$ j. ?& K: ?% w
m_next_bar=TimeCurrent();# E" I& s. p3 c$ |& _- b
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
7 H$ {, V- b$ bm_next_bar+=PeriodSeconds(m_period);
6 [) i$ C+ H" S: O- g' ^6 `//--- work on new day bar3 q' Q! P, e( ] y7 I9 s
return(true);( ^& t7 V2 K( V$ ?. k
}: F9 ^+ i8 \! R
//+------------------------------------------------------------------+5 U8 z( Z j) j" J. g) A- d3 ^! A
//| virtual stub for PredictPrice (regression model) |
3 a7 z2 Q6 {3 U0 K" H+ U6 g, s//+------------------------------------------------------------------+3 o# X7 k" F* B* S0 n
virtual double PredictPrice(void) {- D, U& [% O |
{ ] f9 J" L1 Q! j7 ^
return(DBL_MAX);
4 P$ r. t; O( `1 L}: n( E" l% P0 D3 U
//+------------------------------------------------------------------+4 ]% X- G( ^0 s& c7 U
//| Predict class (regression -> classification) |' e: D) N8 u, h2 I) _( o
//+------------------------------------------------------------------+
7 T+ X5 Y5 w6 M2 r* [virtual int PredictClass(void)
( l; U, M( s8 k3 s0 |% r( ?/ k{6 R5 O0 ?& f% s' |' j/ \
double predicted_price=PredictPrice();1 t( A) f/ R- y& `4 l" D3 ~
if(predicted_price==DBL_MAX)
8 a. ~) t1 V' r3 Areturn(-1);
1 V; J* p n( O. ?int predicted_class=-1;- v% @9 W3 d* c/ I2 @
double last_close=iClose(m_symbol,m_period,1);$ h4 J; e2 { b0 W. y
//--- classify predicted price movement
2 ]5 y# {2 y# I3 v( m$ H* @; i) s+ edouble delta=last_close-predicted_price;
8 g. d6 f8 A5 U5 k. A. V, D9 n' wif(fabs(delta)<=m_class_delta)
' ?& L! G' u6 J" K) Cpredicted_class=PRICE_SAME;- h, d2 B* y( G B
else6 h( U$ K+ G- f3 r& {/ `2 M
private:
4 l6 B' a7 `( }0 B+ Dint m_sample_size;
9 j; t/ w1 Y2 K//+------------------------------------------------------------------+
: |% C8 A9 ]4 m/ fvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)5 `+ \1 c( U0 D( [: \) F6 ^# S1 `
{
: k3 y' W% V1 B) {8 n* ~1 j: M//--- check symbol, period, create model" E2 H o( ~1 q1 q* x
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))7 ^% N5 `( Q; ~% ~3 N/ ^' @
{
* g, p( ~* i/ o7 \$ JPrint("model_eurusd_D1_10_class : initialization error");
6 D9 w+ \* M7 e: sreturn(false);, w; e: r7 J- R; \% |9 W1 {
}& z. i2 q& W1 N" W
//--- since not all sizes defined in the input tensor we must set them explicitly) f" n: j. j3 _! z5 l% N
//--- first index - batch size, second index - series size, third index - number of series (OHLC)8 E: O; B) k6 R2 L& p3 H3 p$ G- a
const long input_shape[] = {1,m_sample_size,4};
% C1 N% Q d) W e U$ u- f3 hif(!OnnxSetInputShape(m_handle,0,input_shape))+ ?2 I5 C- m2 f/ e
{4 J1 _) T, I! @) [8 Z
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());! ?2 B1 `/ v0 A& o/ y
return(false);
- u5 C2 F& d$ I: K4 }6 |6 H- B}# `+ w; m' s5 c* K) W D/ \1 G1 a$ s$ O
//--- since not all sizes defined in the output tensor we must set them explicitly0 [* D1 T/ K% ?& t
//--- first index - batch size, must match the batch size of the input tensor
# Z0 w7 x0 t3 r1 L# g4 F/ W. r2 |//--- second index - number of classes (up, same or down)
4 u) u& \) S/ C$ p* G* qconst long output_shape[] = {1,3};0 p( S1 e E' h6 x# B! s7 J
if(!OnnxSetOutputShape(m_handle,0,output_shape))
9 ]9 u! g/ x' Q# a, d" f{) i" a* [/ g% d6 z1 P$ `
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());3 w/ W0 Q1 c! y8 l: v% f
return(false);. t- Z n" g8 G$ b: e' t( F, k- n) b& a
}
0 w3 ^* H0 D( ~& _9 o//--- ok& G, A& @5 d) z6 }7 k: h6 ?* ]
return(true);
' ^3 H; @3 U! v) \6 n}7 M d* e2 h, |! b; Y
//+------------------------------------------------------------------+5 I: ]6 R, x) {/ ?
//| Predict class |
. g" |3 ^2 ?. X* {2 F. F b//+------------------------------------------------------------------+
f/ T2 B) }2 Kvirtual int PredictClass(void)( }9 M+ N5 J, Y! o3 p
{ |