1. 我们会用到什么模型呢? o+ R9 G+ ^9 F+ ^+ V
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。& ?- l1 A: T3 V9 R
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
, g5 Y) {' U- @% Q//| https://www.mql5.com |2 T$ Y3 D0 R) y4 V0 F) a3 A% H& f
//+------------------------------------------------------------------+
" X/ L; V$ Y7 z% I' r/ l//--- price movement prediction
( {9 x! k( P: a# j0 S9 K#define PRICE_UP 0/ [( Q: ^5 Y& }0 E' x" l
#define PRICE_SAME 1
6 I" h2 s4 J% O9 S#define PRICE_DOWN 2( G: b, @! Z( I9 }% c
//+------------------------------------------------------------------+) j' t' u) @6 R0 L: }
//| Base class for models based on trained symbol and period |6 b. Y5 k" j* a# }6 M% n0 u i0 w
//+------------------------------------------------------------------+' Y/ z7 D- M* H. i
class CModelSymbolPeriod2 ]; W9 w. ^5 U3 x% \, L
{
9 Y7 m" p; l% \8 d8 v, |5 ?protected:. u9 v" H# I) B. K
long m_handle; // created model session handle8 I: h7 I6 Y8 U' r0 s* {' M
string m_symbol; // symbol of trained data0 A5 Y& p F. T# H
ENUM_TIMEFRAMES m_period; // timeframe of trained data2 c: y1 f) c, I* F
datetime m_next_bar; // time of next bar (we work at bar begin only)0 _! y7 X3 x6 a4 M. \
double m_class_delta; // delta to recognize "price the same" in regression models! J' t1 [0 _9 M) B' n
public:
) O0 s% [5 ]) ~$ i* L* {//+------------------------------------------------------------------+6 }' _9 p) X% f, b* l% U9 t/ h
//| Constructor |
) s- g7 d* `8 U5 [; c- m8 y//+------------------------------------------------------------------+
6 W- d' D9 Y" SCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
1 e5 y# w7 K9 Y% Y{
( |* q% Y: i1 [$ lm_handle=INVALID_HANDLE;$ g3 E, E' x- ]
m_symbol=symbol;
5 R0 Q. Q0 c' i: `7 `8 j) lm_period=period;: K( \7 ? v$ j" \
m_next_bar=0;
. Q) I) ?! V; p+ C2 `5 ]. Vm_class_delta=class_delta;
/ ~0 N! ]4 S; b7 v0 W9 B}* [+ n0 U$ v" q5 X$ k
//+------------------------------------------------------------------+
3 R5 ?* W! x4 g//| Destructor |
# U1 G% v _, c0 [4 X//| Check for initialization, create model |
4 |! c& s8 B5 h% B6 w* Z" K* Y//+------------------------------------------------------------------+- c a3 W: n+ D5 I) o
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])& {$ a7 T4 d8 H) L/ u L. X% k
{
; |# J: j. b2 U+ T, B//--- check symbol, period6 H( n% {: {0 x' _
if(symbol!=m_symbol || period!=m_period), Q& T4 Q2 u/ Q9 n, W( s
{
0 ]8 s: O7 Z4 t6 s* UPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));. B6 ]" X! ?( {' c# w2 W) Q" i
return(false);1 [; I- l) A# F4 V V- E, y
}
- D: O1 Y# E4 m6 T- T* C//--- create a model from static buffer6 Q Y# H* @1 O8 ^5 r' |0 y
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
* i ?& g! u/ L6 r. eif(m_handle==INVALID_HANDLE)
; U+ j/ q8 {+ a. D- l{/ E1 z2 }! B+ [
Print("OnnxCreateFromBuffer error ",GetLastError());0 r# U% }" a, F# ~
return(false);
5 F, }2 p! T# H/ ?7 C}9 \9 r# N. y5 o) M" u) [& M/ y
//--- ok
! U1 a9 Q2 o1 l8 ereturn(true);- v$ @5 x0 H4 ~/ g, h
}$ c p |! m3 }8 R7 T% R3 J# E
//+------------------------------------------------------------------+5 D' z5 q$ ^3 {' h. h& H
m_next_bar=TimeCurrent();
8 c8 r' k- l/ \, ?+ l& y; l. bm_next_bar-=m_next_bar%PeriodSeconds(m_period);
$ S' G2 H! ]; ?2 fm_next_bar+=PeriodSeconds(m_period);
! `1 v. u# U- l% L* d/ C- C( l//--- work on new day bar/ {" y4 F- J8 p5 q. }
return(true);
7 j v6 d2 h. H8 R' d% N}
8 I1 W+ J4 V# ~' Z4 J/ J* X: ?: Y//+------------------------------------------------------------------+" z, L7 d, S" K! Q0 ^
//| virtual stub for PredictPrice (regression model) |
; m3 I# o* z2 {! U$ c g- e//+------------------------------------------------------------------+/ q) w d8 t& @7 u% A c4 m
virtual double PredictPrice(void)
4 A7 B" v9 f1 N& I! s$ z1 M) C$ _{
) p" Q; u/ l( \" {1 i S* t% f: `7 dreturn(DBL_MAX);0 F2 q) _5 u1 N6 @- s2 \5 O8 U" D
}- S1 N, G( y* f% F: z: p
//+------------------------------------------------------------------+
- e6 w: e- N3 {//| Predict class (regression -> classification) |
4 c5 ]2 |+ q5 k. R+ \//+------------------------------------------------------------------+8 {! M& I& C H2 A4 l y
virtual int PredictClass(void)7 @( R& x* Q0 A; U! k
{# }( u$ r" b1 U/ K" ?' H' o; r( B
double predicted_price=PredictPrice();
; X# J1 e" {8 |0 bif(predicted_price==DBL_MAX)
1 Q; \$ U6 d2 e% d7 Rreturn(-1);
- n3 R' {, H. e$ G- s" K8 Uint predicted_class=-1;; }7 R4 `$ D/ e& N [/ N: Z
double last_close=iClose(m_symbol,m_period,1);# {1 U6 h( b$ o* g
//--- classify predicted price movement
: a" R5 V" f7 T& bdouble delta=last_close-predicted_price;8 @. ~3 z+ u) i0 W9 ], Z% b w
if(fabs(delta)<=m_class_delta)
6 I. f/ A2 c% i3 v& C8 T* Wpredicted_class=PRICE_SAME;. r/ O9 X5 B0 \- Q6 |3 q$ N3 N. i
else! ~# E& }/ {6 K; H: \% n9 i
private:' |( K: V6 U! v9 I% g
int m_sample_size;. n: g7 \5 ~# L- M7 P
//+------------------------------------------------------------------+
2 X( P4 v7 o6 V% r, xvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)' u! m$ R( `7 ~3 C
{) ^, L/ \6 q+ b% u9 \- i. X% Q6 h# R
//--- check symbol, period, create model
6 ]5 s N" ?9 V+ eif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
3 K$ w* d' Z/ S) H# p- O* P* Z{
/ q; s7 ^0 d) D% \0 @Print("model_eurusd_D1_10_class : initialization error");/ A3 e$ n4 u. J8 m" P; V
return(false);0 {7 b5 s& O8 _7 D; ?7 N
}9 p9 v; `' c0 G& `0 N
//--- since not all sizes defined in the input tensor we must set them explicitly. d& L2 P ^# g6 O$ H: Q6 u) k( W5 m
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
3 d- I8 F) O* e" Rconst long input_shape[] = {1,m_sample_size,4};
3 t) b- S% w* {* f% }" h) t8 M6 ~if(!OnnxSetInputShape(m_handle,0,input_shape))0 P5 D0 r" C1 _% j
{5 s( J: |, I- C" R5 H7 y: {
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());' t! [3 h4 j3 e U" j4 z& v9 a# t
return(false);+ Z8 _0 o5 w, K8 b
}
& ?4 A& D8 h$ v& n. i//--- since not all sizes defined in the output tensor we must set them explicitly* a9 a l' Y) w* b
//--- first index - batch size, must match the batch size of the input tensor0 v5 g; M! v$ ]2 m/ L3 Q8 D
//--- second index - number of classes (up, same or down)8 t8 |' Q$ S8 P6 N* V
const long output_shape[] = {1,3};
- \% h% n* s2 F+ Mif(!OnnxSetOutputShape(m_handle,0,output_shape)) m6 H' k. {2 Z3 {
{
+ [4 t2 X8 g" O. UPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
7 O( O4 O8 X+ p; b/ C# x1 w' freturn(false);
, {) @- f6 M6 {}3 V7 N. V% a& b& e% a
//--- ok. U9 g$ u7 G1 j) j
return(true);
/ P1 ?% a/ s8 z$ f% x% v}5 d# _6 _; S: \7 R4 w
//+------------------------------------------------------------------+
C1 m3 k$ ]2 v. b//| Predict class |9 X9 w% ?5 t# Q4 R
//+------------------------------------------------------------------+( r. V% w. _% _% |; l
virtual int PredictClass(void)
2 i$ x( _) F9 U; G{ |