1. 我们会用到什么模型呢?
; d U$ ^. @: @" v. b9 R) {在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
0 @9 A9 T _% |2 Z5 j我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进# N5 i0 P0 h" ]" G5 p; [, y
//| https://www.mql5.com |
+ g2 V' n/ [. N2 g6 ?" ~( Q//+------------------------------------------------------------------+! b- x4 ]+ e! v( W
//--- price movement prediction
4 L9 b" U# d& u4 k% s( W" D#define PRICE_UP 0" a5 d9 |1 g) E7 _8 J
#define PRICE_SAME 1- E2 i6 ]& ?; Y
#define PRICE_DOWN 25 T! ^# a9 L$ ^: {, n2 R
//+------------------------------------------------------------------+8 `* o: r6 B3 t7 ]6 {
//| Base class for models based on trained symbol and period |
! m3 t/ a; r" ?( W% C l//+------------------------------------------------------------------+
8 y0 o9 L. O5 yclass CModelSymbolPeriod
- Y# f6 t5 q }) {7 u# k4 U9 I! \{( R( E* w( S6 G1 I0 d/ g
protected:# H( j" y* I+ w' Z0 S
long m_handle; // created model session handle* g( l r& m+ n( u
string m_symbol; // symbol of trained data7 t' \. O$ j7 [/ \( d% G* N. V+ u
ENUM_TIMEFRAMES m_period; // timeframe of trained data
/ @) x/ O' q- G$ v4 f; r+ edatetime m_next_bar; // time of next bar (we work at bar begin only)" x+ ]" P& O+ Q! G
double m_class_delta; // delta to recognize "price the same" in regression models' W2 V9 V# d6 g) Q" ~
public:# ~% U$ b' t% n, k+ M
//+------------------------------------------------------------------+
- Y B- x* f6 {( p& W//| Constructor |* r8 Q* N+ u. v. k0 D+ V# f$ \# m
//+------------------------------------------------------------------+; j! u( N3 u3 L' u
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
: Z8 C1 k6 m% i" y{
/ g3 g' l+ u( ]4 Q- m$ ym_handle=INVALID_HANDLE;; Z- R5 @0 P$ \% |2 `. \- y: u
m_symbol=symbol;% g: ]( B% l- L- `& Q
m_period=period;
! | O; y9 Q% o3 B1 t) K2 j/ tm_next_bar=0;; g, j7 n( A% m, x. R, `+ y: g
m_class_delta=class_delta;
' t# h4 Q% x" u, o$ E}
- i7 e s* c; @//+------------------------------------------------------------------+2 T9 b# A u% G( w- @* U$ l, }7 B
//| Destructor |) d) U1 @" e# N& Y$ m
//| Check for initialization, create model |! p8 R: p# e A' Y" j
//+------------------------------------------------------------------+
: a! q" k( F& n/ d5 t5 Gbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
: i0 L* n7 N+ x4 N/ u{
2 j& j9 {4 t0 F6 F( E. j) ^//--- check symbol, period& }9 X, Y0 f' e
if(symbol!=m_symbol || period!=m_period)
+ H/ e0 L% p0 K4 K1 l{
" v' v1 A1 W( c" t# C ?PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));( g% p1 k2 f9 C- b3 {
return(false);! P$ O/ }$ j7 ]5 t" E s
}) ?! l3 R9 o& d! k
//--- create a model from static buffer
/ [) c* _! B+ }" s3 km_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);7 i$ H# F+ y# h9 S9 A0 A# R) `
if(m_handle==INVALID_HANDLE)% l7 u- u# l* x+ J) W' I P
{( Z% I% C P* Y) \/ b
Print("OnnxCreateFromBuffer error ",GetLastError());/ @1 C% q! Y( L" o: `- K
return(false);7 v& Q- o x* A: f
}4 z: u m# H* c+ m& U# `
//--- ok) a( {% C( B& S5 b
return(true);
- v5 H* c9 m/ I" `/ C}/ R' U1 L% G3 J4 K
//+------------------------------------------------------------------+* u1 c$ b- i# u1 \/ b
m_next_bar=TimeCurrent();! i9 s/ S) i/ [. q
m_next_bar-=m_next_bar%PeriodSeconds(m_period);, `( K" ?& n. ]; }! H' C5 |+ Y2 P
m_next_bar+=PeriodSeconds(m_period);( o1 z$ r1 D' L
//--- work on new day bar4 z/ l8 X [3 R" s
return(true);
: t: \$ {( ]% r) Z" I9 \}/ i$ R5 f7 t+ m( w3 k. ^( G- K
//+------------------------------------------------------------------+
- E5 D' r8 H3 j//| virtual stub for PredictPrice (regression model) |- u' ], Y) l' W8 o2 S; D; {
//+------------------------------------------------------------------+
& M, N* Q9 l9 U. P) Z) lvirtual double PredictPrice(void)
7 h9 z u/ d7 W8 u1 E/ d) g o# E{- ?. K1 a, P% A" A- G' Q& E
return(DBL_MAX);6 W7 c( H' `8 i' J$ b0 }; ]
}
& Y& h% L9 N* K$ s2 t( ]$ x//+------------------------------------------------------------------+- e/ i' V5 I* Z3 B" e, f
//| Predict class (regression -> classification) |
8 a# J+ N- {0 G) b' ?//+------------------------------------------------------------------+
0 ~ s/ e0 H2 K2 [8 Xvirtual int PredictClass(void)
. Y, O' V$ Q, }0 y8 ]4 N! C6 c{
. I2 {0 }: f) ~) l1 c8 ^double predicted_price=PredictPrice();
% a5 d7 d% `5 F( a8 m) Wif(predicted_price==DBL_MAX)
0 t. q8 i" D% p+ w+ Rreturn(-1);6 v+ ^0 ]! |( m- f
int predicted_class=-1;5 U3 a3 m9 C" J
double last_close=iClose(m_symbol,m_period,1);+ w; L. w+ y' x+ Z$ `7 \ F7 G% J
//--- classify predicted price movement! o. [5 r9 V2 o/ F$ @ m3 E
double delta=last_close-predicted_price;
8 n" i4 ^, v! C0 @9 E+ ]if(fabs(delta)<=m_class_delta)
* G) F/ s3 n2 H4 Npredicted_class=PRICE_SAME;+ E6 u; M2 Z+ \+ _4 |, E9 _$ {/ v& a
else
& i) l1 T7 @$ H+ W; Wprivate:
" e8 c8 e! ]; i( h" Q1 H# P7 Y5 qint m_sample_size;( d4 c9 X( F8 w- D8 C& j
//+------------------------------------------------------------------+* d4 h3 G" n0 `( i/ D+ s
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)/ M* Y1 A3 n3 N" [8 I) v0 W
{. M5 n4 T- _1 a3 T) U1 s. r5 a6 a
//--- check symbol, period, create model8 x2 `. Z* I0 c, I
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))3 }" D$ B2 w) Z. n5 ] [
{& J# C& J9 O5 \; c" T* a& e
Print("model_eurusd_D1_10_class : initialization error");
9 }9 |0 B" |$ R& F* I2 Freturn(false);7 q2 X B- B+ [& c5 u
}
: Y# U2 y$ D: o' Q6 \3 @//--- since not all sizes defined in the input tensor we must set them explicitly
2 l5 d0 ^+ l% V$ s } p4 A) b//--- first index - batch size, second index - series size, third index - number of series (OHLC)
( H) }% n; d, b$ r, W6 H8 Cconst long input_shape[] = {1,m_sample_size,4};3 U6 y! f+ U6 P( @4 l
if(!OnnxSetInputShape(m_handle,0,input_shape))
2 m4 A& c! C% ?6 @; p/ r; C4 t{4 J t" F3 f% s% D4 s
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
. P" \6 C. y) P# Breturn(false);
! J- ?. b; b9 _1 Q5 w8 r}9 W+ Q: U' D2 \. b4 a
//--- since not all sizes defined in the output tensor we must set them explicitly
( _- ^5 Q; K8 o//--- first index - batch size, must match the batch size of the input tensor) Q% H: j( N" [3 i; I& `
//--- second index - number of classes (up, same or down)
7 u. `: z3 c. ^% X3 E' \3 E- ?const long output_shape[] = {1,3};. X0 ^8 B2 R- t7 u( J
if(!OnnxSetOutputShape(m_handle,0,output_shape))
% d# u1 Q% j) C5 S% E# C U{2 F8 {8 A! E+ _% ?
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
8 j; s$ h* C' E0 n& V7 N0 Mreturn(false);0 r [1 \0 }3 k* H4 S% z$ _
}
, b7 C3 R0 d* j6 B//--- ok( s/ f4 r% M" z6 W. g( C
return(true);
( y- R7 p* i8 u5 I! A}
! V( A; h( _9 ~! x, G//+------------------------------------------------------------------+
6 ^/ @1 t8 J1 `7 G//| Predict class |
% t5 F" E; B% M5 ]$ d' \# E; O//+------------------------------------------------------------------+
9 Q. T3 g( B* f. tvirtual int PredictClass(void)) Z- Z7 e+ @4 D4 Q4 r" M! Y8 i0 ?
{ |