1. 我们会用到什么模型呢?; h" O b0 U/ E- I
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。; x, t+ ~( p; G ]
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
! G. R! G! I. F3 q1 i5 ~, k//| https://www.mql5.com |
3 k1 h( ]8 A5 q//+------------------------------------------------------------------+ ^/ i# l- n& _: U5 r) P& S
//--- price movement prediction
; W' S! I& @- i5 u9 Q2 U#define PRICE_UP 0
5 i) o: E: _4 F9 M1 K' M4 M#define PRICE_SAME 1* D3 X9 I; F t- ~
#define PRICE_DOWN 2: Y6 K" P3 V. }% `
//+------------------------------------------------------------------+
* u+ e- U, ]( h7 T; E# z//| Base class for models based on trained symbol and period |5 y& n% J+ ^ e: }& L4 j. z
//+------------------------------------------------------------------+
' N& U4 k; W' p9 U! |* iclass CModelSymbolPeriod
" P4 ?& c3 u4 b9 G{
- S+ T. g" F6 V! Rprotected:6 m! z' B) L( S+ O4 R; @, t
long m_handle; // created model session handle
2 I4 R, d- }" E5 j! rstring m_symbol; // symbol of trained data: Y- h, K* W6 z" _/ H3 _$ a
ENUM_TIMEFRAMES m_period; // timeframe of trained data7 Q! J+ l' X) n! |
datetime m_next_bar; // time of next bar (we work at bar begin only)
: N, q F) V* D: G# Sdouble m_class_delta; // delta to recognize "price the same" in regression models- w* B4 f* i R C9 K# M
public:* g% j6 |' `% ^$ Y% A: D" d
//+------------------------------------------------------------------+& `' M2 V! k- ]5 w# _( Q
//| Constructor |
2 [$ V, G, K% ~" o//+------------------------------------------------------------------+
5 H# Q& }' }, f g* }3 U- XCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
/ C/ ^4 C; Q% Z1 E3 S{9 u0 D+ ] v9 D8 G) I; e7 b5 w
m_handle=INVALID_HANDLE;6 _6 [. V9 i" v0 k5 @7 k* e6 _
m_symbol=symbol;' ]& H. Q. `* j8 E$ d
m_period=period;
, Z% r3 _* j( D* n5 x) ?1 w0 am_next_bar=0;8 I b. i. O# n, V" A! n# e
m_class_delta=class_delta;
2 V# Q0 s$ F) a8 x6 Z}
: t5 C" ?' V( k- E+ N//+------------------------------------------------------------------+
2 { ]) z% X0 w: O0 g \6 J9 a8 m! O//| Destructor |" y( {! \+ C6 K6 V3 C! a/ L% B9 s. Y4 h
//| Check for initialization, create model |
+ T8 M) L8 G d& a$ x/ Y//+------------------------------------------------------------------+" S1 M% V$ T$ O
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])7 m2 K( e3 u- N& Z4 w2 f9 T
{2 y! W+ C: R, h, h2 E- ~1 L
//--- check symbol, period
4 K# }) P3 m4 s2 w% a* tif(symbol!=m_symbol || period!=m_period)
, _% f3 e4 y* `* z8 x) C) `0 a* O{* @% K/ H( s+ s4 J2 S+ m% i* j) A
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));. G Q& D9 I8 E6 w, v0 Y
return(false);: M5 X- [0 k, }# ]! P' J C
} k, K a' ~/ m. v
//--- create a model from static buffer
. p/ y" k+ N {) w( @" Lm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);' z9 J9 `, n9 F9 I/ [
if(m_handle==INVALID_HANDLE)# H' z' v/ C% E
{4 ]9 j4 O$ R/ N+ E: f2 G& u
Print("OnnxCreateFromBuffer error ",GetLastError());% w1 Q8 S: \/ A2 y& B* A7 A
return(false);) R6 D: {+ A5 o4 Y/ V! W- Y
}
7 n! _0 I, k t$ d: k7 B# _3 h//--- ok
/ r( y5 ^; p; Z0 g$ areturn(true);
' a8 F6 c9 D+ A* G; `6 ~( r}+ B! A8 N! J; F- D, x: J; X
//+------------------------------------------------------------------+- Y J5 @* x; P
m_next_bar=TimeCurrent();
( o" N, {# \! ]! x2 T- @& ?/ J* P* Wm_next_bar-=m_next_bar%PeriodSeconds(m_period);! I/ e$ X7 }, }) p8 ?5 O `0 h
m_next_bar+=PeriodSeconds(m_period);
0 D; y W. L- s# V//--- work on new day bar+ f* y% V _/ Y. i8 g% D
return(true);
. {0 I Z9 t% g& r7 W}
6 _$ f( u6 j4 C& y# k7 x//+------------------------------------------------------------------+
: b% g$ S H, |! E3 n& E& B5 U//| virtual stub for PredictPrice (regression model) | k1 X7 t1 ~$ }# z- a
//+------------------------------------------------------------------+/ n/ \ j d1 H2 u) v) j& m# B% A+ T
virtual double PredictPrice(void)
" ^+ W" i& p: e$ H/ ` n* [{
4 l# ~3 _+ M/ t' H; x+ `return(DBL_MAX);
0 G# A6 D5 z" A! H2 Z0 s5 S}& ~) Q* T. j( i9 V" e6 I) T8 t7 P/ {
//+------------------------------------------------------------------+
$ v2 o, V- K' E$ f+ g. C4 {2 Z//| Predict class (regression -> classification) |
, H1 I' y& U3 X6 ?, E//+------------------------------------------------------------------+
& c& H. r3 S% S) w1 U9 v) I) Rvirtual int PredictClass(void)
2 ?1 k0 h- B4 N# V* Q4 `{
0 P+ a: o0 _: F' j0 a# Y1 [double predicted_price=PredictPrice();: W; y: v. R# K; F! s3 X
if(predicted_price==DBL_MAX)
: |3 S8 ^1 N! G$ P) y$ ~5 h& D' qreturn(-1);6 N! n! c5 }" u
int predicted_class=-1;
6 `" `9 v* w7 E5 O, G- g" z( [double last_close=iClose(m_symbol,m_period,1);
- M6 N; S* s4 \; g k: s1 Q3 W//--- classify predicted price movement
! ^8 B& V- I3 h/ zdouble delta=last_close-predicted_price;
3 u1 J2 P0 W1 e2 X. L! S) _5 Sif(fabs(delta)<=m_class_delta)5 c* S: [! q* w
predicted_class=PRICE_SAME;8 `; r4 C$ D& L9 ^) y6 B4 n& g
else
, q2 G! }) c+ w' x7 ^2 u' F6 @/ {private:
( E' e+ ]: `! Y; r9 l6 Bint m_sample_size;' K# I$ z; Z% K& f
//+------------------------------------------------------------------+' ^8 h& {; M$ _) A. L
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)' X- o, l3 a4 X j) @5 w% [
{ w5 e! P+ y9 J8 ?0 }
//--- check symbol, period, create model' Y( I5 C# S- z9 p+ J2 ~1 E
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
8 }) e% Z8 X8 ?- g6 d% }{
% O, ^) ?# h) ~5 T9 `Print("model_eurusd_D1_10_class : initialization error");
- Q4 V; t; ~6 Y9 ~% k+ Q7 v0 x. ireturn(false);* V' i# [* L4 P4 Q6 M* \
}
$ K: x# Z6 J$ b! W$ I//--- since not all sizes defined in the input tensor we must set them explicitly
: Y8 J% P7 R7 f2 I: y4 |//--- first index - batch size, second index - series size, third index - number of series (OHLC)7 [8 i! }5 F" r0 W
const long input_shape[] = {1,m_sample_size,4};$ s0 ~- a" t' {
if(!OnnxSetInputShape(m_handle,0,input_shape))
4 ^- i: `3 k7 g! t{1 D C$ d e, r! H6 a @6 {
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());' a1 `5 z: W; q# N
return(false);; X# y i' {7 e+ H2 p; r
}# X4 q# v: c: W: p1 t4 m* y. y/ l; B6 }
//--- since not all sizes defined in the output tensor we must set them explicitly1 U: T5 D0 ~2 n1 R" B' g
//--- first index - batch size, must match the batch size of the input tensor6 K. C% P6 C) {6 _; {( B; A
//--- second index - number of classes (up, same or down)
7 @0 R$ ~3 Z3 j" Q# hconst long output_shape[] = {1,3};
! v; ^" G5 {7 n( dif(!OnnxSetOutputShape(m_handle,0,output_shape))
( A- [ N5 B. F, Z' I{
1 z9 ]/ }" h n9 W9 R# G, NPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());/ r& n; d$ e( l
return(false);" C0 X. @8 U. l& y/ C
}* q0 g* G/ \5 V4 q
//--- ok
+ J A6 N* b) [7 w8 v @* _( ~+ xreturn(true);0 F8 E% r- N7 p9 l
}
' ]/ C& m, y/ F! Z7 x//+------------------------------------------------------------------+* }' _% m3 c0 @7 T
//| Predict class |1 n7 T" F3 p% t( a
//+------------------------------------------------------------------+" [' g# r* F+ V3 W1 p3 z) O
virtual int PredictClass(void)/ G7 `& n5 |2 h6 R3 X
{ |