1. 我们会用到什么模型呢?
+ r$ |% T; m" A4 J在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
; R) D/ N3 `# [* |我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
T* q: a# @) O- |( b7 A4 u& M; I//| https://www.mql5.com |
2 H& {$ O4 o: C5 q7 u0 i9 I( d$ t" L//+------------------------------------------------------------------++ R; L8 T j' r9 J
//--- price movement prediction
# D3 B3 V0 N/ ]) N% D1 Z0 t/ ]2 [; a8 g#define PRICE_UP 0
, l/ W* _% T. l7 F3 W- Z2 x- B#define PRICE_SAME 1
5 |6 y- r7 W% M6 O2 l#define PRICE_DOWN 2& x0 B) ^* b ]
//+------------------------------------------------------------------+6 o+ z. W, D/ U* G
//| Base class for models based on trained symbol and period |
! ^8 P+ t! s5 r% A0 r6 W1 o: @//+------------------------------------------------------------------+. x. q, T* ~6 @% g" ]5 i" [% I
class CModelSymbolPeriod( G8 i4 s% h6 m* ]7 p
{2 m8 F+ j( A8 [! ]6 L- V; @
protected:$ g/ g, a1 q: w# T# u
long m_handle; // created model session handle- ~' R; }3 Q5 G' v8 g+ J7 z
string m_symbol; // symbol of trained data1 F9 p1 X' j9 O$ U& z, }
ENUM_TIMEFRAMES m_period; // timeframe of trained data
# `2 ^+ V! I8 C. o- s1 qdatetime m_next_bar; // time of next bar (we work at bar begin only)
# d$ @1 w3 u. z7 d. qdouble m_class_delta; // delta to recognize "price the same" in regression models" M. p, B( w1 f
public:
5 W$ E' r: B3 |8 M( H9 U//+------------------------------------------------------------------+, u9 m7 q1 U" W
//| Constructor |
" x0 [# M3 b' s G/ d//+------------------------------------------------------------------+) s) P$ S- A: b3 }3 V2 ?
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001); q+ T& p1 x0 {$ X% v
{) W3 }4 D0 [+ g! ~# x" C" W
m_handle=INVALID_HANDLE;
7 ]7 n, u. c4 B/ xm_symbol=symbol;
+ \. P9 r1 R! O* R5 Lm_period=period;
+ q; J8 ]# d9 N2 S( Q' B' z+ Im_next_bar=0;
M+ p0 S D9 Ym_class_delta=class_delta;
% N& n' W2 D- N7 d}
6 `: G2 h, d. i/ s* L//+------------------------------------------------------------------+* v3 Y* m! W8 ]& q) Z
//| Destructor |
$ \; L/ t' e" g b/ J$ v//| Check for initialization, create model |
9 N0 c" n: r( `6 t7 {1 ~4 J4 y//+------------------------------------------------------------------+
7 K6 ]" y/ }3 S* t" j; qbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
/ ^; b0 G$ i$ \0 _{
! B K, l, q3 F" ?; j//--- check symbol, period9 T" [ j \/ |+ F8 V) u
if(symbol!=m_symbol || period!=m_period)
) d4 b J% x$ B1 v" r k4 C5 l6 C' }7 p{! n. `- A1 M& {# G9 B) T
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
- q2 r9 W$ m, X" W' ^) yreturn(false);# B, M. n5 ? n# H( e* [2 p
}
4 M3 _. T( d0 g0 H//--- create a model from static buffer) \) z2 e# v' Q. a$ _
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
7 F0 O1 D4 |# ] S, P4 n; v3 T5 V8 {if(m_handle==INVALID_HANDLE)
4 N, _: y. s+ Z$ k1 H3 y{. }9 m0 S! m' x4 u! J0 J
Print("OnnxCreateFromBuffer error ",GetLastError());
2 K0 Z. B: W7 B4 Q+ m4 wreturn(false);; V/ l( }& D# ^1 W2 W. H m t
}! P6 B: x" Y- {- \2 G
//--- ok! k. Q/ c+ i8 i* G
return(true);; p. E( _5 p# |& H3 p
}
1 P: B3 K6 l7 X% w8 a3 ?/ H; t' o//+------------------------------------------------------------------+( ` S. l$ l3 J. D' W2 T% i
m_next_bar=TimeCurrent();! ?- `# q7 a; G' k' J$ m8 d# }, r
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
- a3 S& F8 e6 a' zm_next_bar+=PeriodSeconds(m_period);4 o/ o9 F$ ]' K- ?
//--- work on new day bar9 j% D7 u8 j8 G- ^
return(true);
2 F% Z$ `% w% v4 v1 y}& V, R7 ]2 |4 N& ^5 _
//+------------------------------------------------------------------+7 B5 G& [1 s+ r* V
//| virtual stub for PredictPrice (regression model) |
5 M) ?# |$ B: p4 i# I% ~//+------------------------------------------------------------------+
R( m0 C4 l4 v" A: ^3 \1 D1 l0 ]1 ovirtual double PredictPrice(void)
/ Q1 O& @8 _# Y [{
; u$ |# R# i$ R* \- m8 X7 f% ~3 Kreturn(DBL_MAX);' ~! e! e2 r1 T( c
}" K5 D2 O# G3 O& ?* C& H- |3 Y' I+ F
//+------------------------------------------------------------------+
' X8 i+ h' J5 }//| Predict class (regression -> classification) |
T. P* T7 {" z. C8 `' X- x% [! Y//+------------------------------------------------------------------+' U, G) ~3 {2 ]: c* Y8 G) {# ]- H$ F
virtual int PredictClass(void)9 T+ |& k9 u0 R5 M# u7 _
{& D W# P5 o# F" _3 h, f/ j2 J
double predicted_price=PredictPrice();
+ y( ^4 a+ [" E6 [' Aif(predicted_price==DBL_MAX)2 v( H) j; j6 ^/ ^0 |
return(-1);9 f, d- u' l( f% _6 ?
int predicted_class=-1;
6 y8 R5 k L/ i6 {; q. ndouble last_close=iClose(m_symbol,m_period,1);( v$ N2 H3 O( e5 C( I- G5 m: r; _
//--- classify predicted price movement
& O6 D7 u0 E9 _4 M6 v* Bdouble delta=last_close-predicted_price;* T; K$ p4 m3 k, v9 ?& `
if(fabs(delta)<=m_class_delta)
3 [8 B- c8 |7 o! A5 m8 i, n! P) opredicted_class=PRICE_SAME;7 X/ ]; Z7 v! b3 z
else
* ]/ L; a* F" g% x: j$ gprivate:: I5 p0 M. O) G; J
int m_sample_size;3 d* I# I7 ^) ]( Q7 w) }
//+------------------------------------------------------------------+
2 A+ B7 a' P+ R5 r3 r2 q6 f$ _virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period): v+ U: i' s% _; S' Z
{6 v$ d9 Z' k4 }0 u3 l# K
//--- check symbol, period, create model' Z6 h `" a: m
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
: z' S6 ]$ T( i& J3 X+ o{
- B1 l4 N1 ]2 x) G8 ^Print("model_eurusd_D1_10_class : initialization error");
' ^2 a) x- E/ U1 W# g* P2 ireturn(false);, p" {& q8 K, P% H
}+ v- c9 y; g& F! Q9 @! T
//--- since not all sizes defined in the input tensor we must set them explicitly
- `' f( ?" D# c/ R6 |9 ]8 }//--- first index - batch size, second index - series size, third index - number of series (OHLC)
1 g1 E" o9 G" p S% xconst long input_shape[] = {1,m_sample_size,4};
0 p8 p1 K. L, b& ~6 a M1 r6 E" _if(!OnnxSetInputShape(m_handle,0,input_shape))( i4 L( O8 m7 {- C6 x7 ^; T8 G
{, c; S* Z: Y' }
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
" p n$ F! y3 @return(false);6 u% b8 w' o8 J. }! [
}" q- w; ^9 C& N0 Q
//--- since not all sizes defined in the output tensor we must set them explicitly
/ q n; b& r" j" ^; F5 a//--- first index - batch size, must match the batch size of the input tensor; ^$ `/ L# `4 C: D
//--- second index - number of classes (up, same or down)5 t$ d+ r2 o/ y1 n7 N
const long output_shape[] = {1,3};: L# Q% X" h$ a+ S
if(!OnnxSetOutputShape(m_handle,0,output_shape))
) L( `+ a( ~, Q! A{) R1 O1 q x. ~- J( h
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
! h* A" L8 F7 ireturn(false);$ O& K9 s6 V0 m9 h6 L: V
}
* w H) a M0 |! `, e+ u4 f//--- ok
/ G: x8 l& I3 Z; Y" C2 K9 Jreturn(true);9 m, C9 q+ B) ]$ e4 [) g
}% V$ a1 i5 T( n0 k! {& J
//+------------------------------------------------------------------+
' U4 R; _' z( i F/ e//| Predict class |
1 b+ x; T% L) c+ L R I//+------------------------------------------------------------------+
& Y" b" v; B+ v+ c* `virtual int PredictClass(void)
0 o. K W% `( c0 V6 R; A+ \2 X: _% j{ |