1. 我们会用到什么模型呢?
& A. G1 W( D3 Q1 a2 q9 l在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。, ^, L- ~, h9 S/ _$ b
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
4 T, c6 s# x. h. b% M! _2 v//| https://www.mql5.com |- N3 q- r8 A" D/ s- T
//+------------------------------------------------------------------+
0 D1 F$ O& J! j0 }5 t5 [//--- price movement prediction# w" W4 h. `* \5 |; `$ C
#define PRICE_UP 0
8 n z7 I1 ?3 }* K- ?8 w* C#define PRICE_SAME 1
# G& g- Y4 M. i; m$ A#define PRICE_DOWN 26 y2 j1 y2 |$ U% T1 G6 f* j
//+------------------------------------------------------------------+) F/ y( {& }. o7 t) O" L
//| Base class for models based on trained symbol and period |
4 \3 o3 R l/ E5 v, ]: U//+------------------------------------------------------------------+/ v, ]( u( @8 T1 M8 P
class CModelSymbolPeriod3 {7 H: i8 v- p3 q
{. w0 |0 X5 N/ D& Z9 I5 ]
protected:/ Z2 T/ y! r) w' s/ _& n) |9 H0 t" ~
long m_handle; // created model session handle
9 n3 _" k; y: W5 S1 U! vstring m_symbol; // symbol of trained data' P$ _3 p% `" T6 O5 I" y$ f, h
ENUM_TIMEFRAMES m_period; // timeframe of trained data7 d0 r' q9 P, p8 A6 y! i: E6 F
datetime m_next_bar; // time of next bar (we work at bar begin only)
5 ^2 m9 ?4 D3 }0 D+ [; R* wdouble m_class_delta; // delta to recognize "price the same" in regression models
' w' B/ f" M& F9 Kpublic:. c- n9 f/ h+ M! s! C- ?4 O# \* ?
//+------------------------------------------------------------------+
% z0 O8 F7 d( U" R" j" @. ]% i//| Constructor |
' _" \; @5 S) ^( }& I1 V//+------------------------------------------------------------------+
- v6 R9 i( C- w& H! ? J/ s4 OCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
3 ~9 x9 k% d/ ]# H8 C _{
4 ~& K4 t3 G/ Z* R+ Vm_handle=INVALID_HANDLE;; s) {; F/ e/ B& e% I
m_symbol=symbol;
/ `: h+ m% a% |: v7 I* j5 K" p4 M' ^m_period=period;4 r. Y5 \5 `0 @( f8 j1 x* Y
m_next_bar=0;
) Q, Y5 I! L0 k. b) N+ _m_class_delta=class_delta;# {% o2 ~2 ^. |& W8 z9 G, y
}" m% e" h1 s' _& T2 W/ k1 k7 n
//+------------------------------------------------------------------+$ X5 D6 E" q9 Q& q5 f: W: R. Q
//| Destructor |- j/ p7 |0 S4 P D0 b. _, V" N
//| Check for initialization, create model |- R, L; @" q V% v- n1 ~
//+------------------------------------------------------------------+4 Q+ h/ h* } i8 ^0 y w- M4 x
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
, {# V" q Z6 ]2 F( t7 I{8 f" M8 p: d3 }3 u3 |
//--- check symbol, period( v* T C: y& C4 ~
if(symbol!=m_symbol || period!=m_period)1 l7 Y4 g6 K% A$ H7 a
{- W5 F! f7 A" T, w5 ?( o' {
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));& [7 |! H3 o! E% p0 V! q
return(false);
4 F2 N) k2 n9 l( x5 C3 f6 k- v}+ Z! L9 f- ^: k5 I0 Z% c# V- Y
//--- create a model from static buffer, c) T' W5 C1 w3 G! v: ~
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
0 i2 U P3 i; C- {if(m_handle==INVALID_HANDLE)
% C9 d7 }" S5 \5 y{
r: {+ u9 o( M3 G2 APrint("OnnxCreateFromBuffer error ",GetLastError());
. V' q9 u, v2 S' H9 ireturn(false);$ C, _& a# T2 X
}* z& g, I. L$ U/ n" `1 a* Q5 G1 ~
//--- ok
3 H- v) _8 g) s8 b* Q/ ^- u; ` Kreturn(true);* N. c3 o5 P+ v% C4 C7 s
}! B9 j ^, G. F7 z
//+------------------------------------------------------------------+
1 T/ h6 n/ H$ w# f9 H( W2 Dm_next_bar=TimeCurrent();
4 I5 P- K4 ?% E4 r, e' Im_next_bar-=m_next_bar%PeriodSeconds(m_period);
% q( o) P+ A( l1 a' hm_next_bar+=PeriodSeconds(m_period);; C p; H5 l, _
//--- work on new day bar5 G6 }% O8 K0 G+ t
return(true);& g3 |% h% A; D: E$ t% G3 O
}
6 Q/ y U. C" v9 x0 ]6 W# r7 i//+------------------------------------------------------------------+0 Q9 I1 [+ g- c4 W1 U
//| virtual stub for PredictPrice (regression model) |
# _9 E8 z2 R% { v3 [//+------------------------------------------------------------------+ d6 Y6 G/ k' m$ o* S7 n, y1 S
virtual double PredictPrice(void)
% H7 L# U7 _; W1 _, T+ h{
9 @( _/ x: O3 u9 g8 Preturn(DBL_MAX);! M7 K0 d, Z* E, A) y7 k
}
7 v0 I% l4 Z4 P6 e' N* @9 \, {& N//+------------------------------------------------------------------+' L; R( h" Q4 W% X# n) K& y
//| Predict class (regression -> classification) |
) \" \# N5 S* Y- i/ @+ T. y//+------------------------------------------------------------------+
% y8 S/ K0 n5 R2 A9 {virtual int PredictClass(void)
, f% { n" J1 c- ?! E7 S{
/ i& X L# [- g5 Z* U7 \( Adouble predicted_price=PredictPrice();+ I: R& _! ^9 M# e
if(predicted_price==DBL_MAX)
3 z2 ?, r) c# O8 j* `2 g4 wreturn(-1);
W' |' ?4 A5 @; U9 p, N- Aint predicted_class=-1;( j$ D8 {: q7 g! T4 t: C+ T# `
double last_close=iClose(m_symbol,m_period,1);& V) q5 v6 o+ h/ K- ?
//--- classify predicted price movement
2 j8 u) ^5 |- e* R6 }9 H% jdouble delta=last_close-predicted_price;
8 \* S7 Q7 P) B2 v( Mif(fabs(delta)<=m_class_delta): T( u) d% |5 T; P3 B1 L
predicted_class=PRICE_SAME;+ U' w: T& V- J0 D- y
else9 V) U% a& h2 i: |
private:
/ a8 I) `+ T, p' fint m_sample_size;, _5 b J9 C6 c( [ P1 B
//+------------------------------------------------------------------++ p a, L0 J& i! K( i
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)/ }" A) [* y# d% c
{
+ o0 E1 ~% G1 J2 w5 I% L: @6 A//--- check symbol, period, create model5 f) K3 i& Y! d3 f. D/ _
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))' h9 ?7 s, O# o3 {$ W- b3 p; z
{1 q/ D' t+ |! X. y
Print("model_eurusd_D1_10_class : initialization error");
F7 N4 ~- Z% i" L0 `0 ^/ Mreturn(false);3 A/ _# }5 O0 G
}
& G- U9 C2 F# u9 s5 x! i//--- since not all sizes defined in the input tensor we must set them explicitly3 J* e4 o7 T. O; J c m
//--- first index - batch size, second index - series size, third index - number of series (OHLC)) K7 `7 m0 N4 i% g- W3 c$ N
const long input_shape[] = {1,m_sample_size,4};
$ h: q. r4 |# c/ y. l- C. jif(!OnnxSetInputShape(m_handle,0,input_shape))/ X u7 p9 x/ m% i( ?/ Q
{
# O" ?* W6 f' U& T, NPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
* }( U* r& \) }6 M3 d$ Wreturn(false);4 U4 X. h7 q* H4 Y; x+ B6 H
}
7 h# ]. i% s: y5 R/ I" w. J//--- since not all sizes defined in the output tensor we must set them explicitly
: v' c3 X6 O1 e//--- first index - batch size, must match the batch size of the input tensor! j Y/ r$ h, I. G2 T9 D7 L( c
//--- second index - number of classes (up, same or down)- ?. M$ K3 d7 q7 H/ |
const long output_shape[] = {1,3};- h# h+ L" d& B. e( H* L
if(!OnnxSetOutputShape(m_handle,0,output_shape))
; i4 T- G: M1 C# F2 I{
3 }! O- P' n+ j, p1 G% x* }Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
" I* z; o" K4 t+ x# F$ i! i) t( X `return(false);4 h) v' v& L: B5 d& @3 J" B
}
" Z! X5 `" G' T" i//--- ok
! _. o W o8 p) _4 d9 lreturn(true);
5 ?1 `/ c0 G! P C* d- h3 v" G4 ~* H}
3 }- @: d3 W$ [. N//+------------------------------------------------------------------+
$ d1 Q& ^7 e% S2 d) ~- H$ V5 C. A//| Predict class |
9 I! c U- @$ w' W//+------------------------------------------------------------------+
( K; ^4 e9 [4 e& Dvirtual int PredictClass(void)6 p% Z5 {( _8 ]5 y! a
{ |