1. 我们会用到什么模型呢?
0 A7 ?/ C/ Z! t; k5 ]8 h R在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
) I p7 q3 y# X6 N4 p3 M6 y我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
4 z" {1 Z. H1 K//| https://www.mql5.com |
' R; L( [- `! O; A; s2 Y3 E# U q" y//+------------------------------------------------------------------+
+ P* Q. i1 z7 D$ k; s& n//--- price movement prediction, g; b, o+ f# Z i6 ]+ \
#define PRICE_UP 0
, S% r, m6 A! v) v. N#define PRICE_SAME 1' ], a: U7 \6 _8 ]
#define PRICE_DOWN 2
$ b" Z, v+ u5 _, I/ S: ~4 W5 g//+------------------------------------------------------------------+0 q4 t+ c3 R8 q# L. I* u
//| Base class for models based on trained symbol and period |
^6 T/ O4 |# [" g* C- f* a//+------------------------------------------------------------------+ _; N+ `6 r6 }
class CModelSymbolPeriod
8 d$ z" ]) d- Q2 M# _{" k- {8 U. B, }
protected:; \6 m, o5 v8 t% @4 c- X! f
long m_handle; // created model session handle
1 y; E k3 x5 E' z9 \string m_symbol; // symbol of trained data
& W9 `/ s0 f& D9 C: K3 f0 BENUM_TIMEFRAMES m_period; // timeframe of trained data
. V) M) Z) u" h: `; n+ C Ddatetime m_next_bar; // time of next bar (we work at bar begin only)
9 B* _3 L T/ K4 K7 B4 I6 X( z- [double m_class_delta; // delta to recognize "price the same" in regression models8 b2 J" F1 k# P' i
public:! t k0 x: b) L
//+------------------------------------------------------------------+3 {# @/ v- i: Q, g$ q$ @" P
//| Constructor |
; ?- E; d4 L# V3 i k6 M$ G$ I2 {//+------------------------------------------------------------------+
6 B7 R# Z8 x5 pCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)0 U4 p7 K0 H/ T( U5 t
{
; e; ^6 K5 d" U& Wm_handle=INVALID_HANDLE;
. k( a' ?; |1 w1 {0 c0 R( Um_symbol=symbol;; E5 x% L( h- t* p( {
m_period=period;1 ^: X" R/ n" H8 T& Q' h7 `
m_next_bar=0;1 h3 {" g, \& j8 b5 D
m_class_delta=class_delta;/ z" v" _3 C6 m
}1 `8 B- c) u, O6 L& r# J3 F
//+------------------------------------------------------------------+$ x" c* \$ Z/ S. H- f4 H# E
//| Destructor |
+ Y) Z0 \3 I! W0 S4 h0 w& W' R. ~//| Check for initialization, create model |% F' n' ~* C r ~" `
//+------------------------------------------------------------------+
/ t1 G. Q* f8 v2 Q; z# s5 ?# f9 \bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
6 k8 {( f% T: S+ d5 \{, e8 k9 f. \! y! n
//--- check symbol, period
9 _/ e' @. ?! E l# z( f, zif(symbol!=m_symbol || period!=m_period)
! F n$ j4 l. E* w" E{# _" R) T5 q7 y1 ~- P* I
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));' B5 k3 [5 n- Q- y
return(false);
, B1 a3 x; W' s9 T3 V( a. m}
5 e( \* w1 \1 F! A8 [; }//--- create a model from static buffer( |& m( Z5 A8 E; b- R) U `
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
3 ~5 y; c% Z% G/ E h: Fif(m_handle==INVALID_HANDLE)
9 A! \) v3 z& V6 Z/ o, M{4 p) Z w3 ~7 u* f8 x2 g
Print("OnnxCreateFromBuffer error ",GetLastError());
; i3 J) Q, u1 q2 `4 [return(false);# X5 J# I( h+ ~* {
}+ h) ^2 u" j( p8 g2 o3 T; D/ l
//--- ok
/ d' R) ], O# D) b4 g2 ureturn(true);' ^1 m8 m* |5 o+ i! J
}" X( T7 T1 A9 [
//+------------------------------------------------------------------+
. j# J! K- e# R3 y' Qm_next_bar=TimeCurrent();
, Z. \5 @& c5 W* h& W* q N3 Om_next_bar-=m_next_bar%PeriodSeconds(m_period);
5 L2 d6 Q1 x+ _0 ] Zm_next_bar+=PeriodSeconds(m_period);
0 J# c7 Z ?5 G1 P! A//--- work on new day bar5 {& ^% X8 C+ U$ H/ m5 C% ~
return(true);
( b. ?6 P4 [3 Q: A/ D}
( k- h3 M, Q! V! @7 t//+------------------------------------------------------------------+$ P4 `- ~: k, {! s; [6 K2 a3 ^
//| virtual stub for PredictPrice (regression model) |) p) L9 e' l/ a* V" _
//+------------------------------------------------------------------+
8 Q3 G- p% l: c! k! Z1 lvirtual double PredictPrice(void)
# F" Z$ h9 b/ D) q* m5 x{1 T' j' ~/ y1 K9 X, M# Y
return(DBL_MAX);
+ _& z7 x" n# X4 ^( b9 D# n9 q}; f G4 ~0 a# h# O1 Z' b
//+------------------------------------------------------------------+
- m) Q( N, x( n' h//| Predict class (regression -> classification) |/ h6 @5 N9 x" Q0 Q, c# w9 e2 K/ W
//+------------------------------------------------------------------+4 {8 l* v; ?; f2 |
virtual int PredictClass(void)
% e; C5 _8 U% c1 {{
% v0 q" O8 n0 J% ^double predicted_price=PredictPrice();3 F) H7 M& d! T" X
if(predicted_price==DBL_MAX). B2 ^+ w! c8 v/ A& r
return(-1);6 E. x1 }7 y; }) B1 L( y
int predicted_class=-1;" W$ S0 z- b( ^. g
double last_close=iClose(m_symbol,m_period,1);' D$ G0 Q5 u6 i: X5 J! x- }
//--- classify predicted price movement) H* D3 ~- x0 w0 U: y! @8 U1 [
double delta=last_close-predicted_price;
3 d9 O4 @. @9 }0 }if(fabs(delta)<=m_class_delta)
0 B* b. f, T" wpredicted_class=PRICE_SAME;% [! y4 D) ~8 a
else, ]* | M' B& o, Z# v
private:! q0 Y, v+ y0 R6 y7 Q: ?4 @) l
int m_sample_size;% D1 L, J" G! \- G/ ~
//+------------------------------------------------------------------+
* t' q7 B; n$ A- ^& cvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)0 Q1 a4 T+ S% P; A* G# z
{* @& b* ^* _ ~% C+ u7 a
//--- check symbol, period, create model. s% E, I+ I4 F0 c' {
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
6 h% H W7 q9 u' V0 ], `{& J( `, |; M+ ~7 w' ~0 I; R
Print("model_eurusd_D1_10_class : initialization error");
) c$ P8 e( T0 F3 w1 W- F" U' `return(false);
' t Z4 e$ n, Y7 u# }}
& N# n+ M* t+ I- n) c4 C//--- since not all sizes defined in the input tensor we must set them explicitly
. W7 a* U' `6 I& I& S% p: J8 G//--- first index - batch size, second index - series size, third index - number of series (OHLC)
. e+ Q2 Z' G& v: R3 c) fconst long input_shape[] = {1,m_sample_size,4};
& E O& I+ I- o: q' Jif(!OnnxSetInputShape(m_handle,0,input_shape))
. m: o( x% t% c2 ~" i{4 f% m) J2 o0 z! j
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());" v% `* E) C8 I
return(false);
4 q' b6 S0 F% C( i7 V/ J ]* w}
9 b/ p, |* n/ E8 w//--- since not all sizes defined in the output tensor we must set them explicitly: I9 g1 o# D1 W+ C: c
//--- first index - batch size, must match the batch size of the input tensor. d0 e6 ?1 @2 l7 ^4 ]
//--- second index - number of classes (up, same or down)
! Q( b9 {" |% U* ` d) w" nconst long output_shape[] = {1,3};; {6 o' m- p, Z# o
if(!OnnxSetOutputShape(m_handle,0,output_shape))& b9 O; _$ l6 F9 |0 U( f
{0 D# ~* x5 X& r# Y# y
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
$ H- X7 n3 k7 O) U/ Q2 Greturn(false);
9 I5 u4 O& p0 \. O}
0 t! q0 }, n! R) U* A& P//--- ok
( _* s" N- i2 Kreturn(true);
/ k9 G- v4 n; W: }}
7 ]+ u& V4 f, g8 }8 I- z( }//+------------------------------------------------------------------+. s6 y% D' E- R) m' k
//| Predict class |3 W9 N8 f% {& q8 n4 N; R1 K- b
//+------------------------------------------------------------------+
$ ~3 j+ q7 V0 M( n: pvirtual int PredictClass(void)
9 M7 i6 j* ~& h{ |