1. 我们会用到什么模型呢?+ e* Q/ D4 L- [0 Z5 \6 k5 e
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。! G7 t, p/ h% @) J" O+ W$ h4 r
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
& `- v( M O0 |& |//| https://www.mql5.com |
1 G# L$ Z. [6 i( }1 L1 N//+------------------------------------------------------------------+. W+ x7 ^7 a2 K* t2 ^ e3 `; O
//--- price movement prediction
* l" P& T# {$ u# {8 z+ A1 s#define PRICE_UP 06 L) C. t1 D% e* t M e8 \4 c
#define PRICE_SAME 1
: v1 @3 @& t# i2 U5 r; V5 g4 U#define PRICE_DOWN 2
3 o' K. q2 [0 V% ~5 c5 T3 T//+------------------------------------------------------------------+* f! @+ I/ j) u( l6 G
//| Base class for models based on trained symbol and period | P1 [; D2 Q- j) I9 \' i# W- E R
//+------------------------------------------------------------------+
+ b5 q- v3 A1 kclass CModelSymbolPeriod0 x+ p1 Y4 M& W
{
/ O. M6 |/ Z& b6 |4 Bprotected:
$ _; M4 q& j+ I) y, Dlong m_handle; // created model session handle" N+ O8 _, k5 f) v. w$ {
string m_symbol; // symbol of trained data
9 y$ l9 r$ A- R9 Q. Q& }% ?ENUM_TIMEFRAMES m_period; // timeframe of trained data
2 {8 {% P7 T: J! j ldatetime m_next_bar; // time of next bar (we work at bar begin only)
/ J% n' q& Y; w4 }+ k+ {double m_class_delta; // delta to recognize "price the same" in regression models/ H h$ T/ @! `" S0 a6 k
public:" c0 H. X: W; o$ b
//+------------------------------------------------------------------+3 E2 q! G @7 ], @6 j
//| Constructor |2 p0 G6 n# Q2 }& C$ ?
//+------------------------------------------------------------------+# o( E7 \3 Q5 C" A/ }. w
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)7 C% v& q/ [; ?- _0 H
{( g9 }) |2 W0 [' i* |
m_handle=INVALID_HANDLE;5 R0 E. a v. W; m0 o3 L3 h
m_symbol=symbol;
% l* U% _' T+ J/ hm_period=period;! e2 j& |4 ~5 N7 Y6 e0 h
m_next_bar=0;4 C1 s4 f3 [6 H# }. X: [$ r
m_class_delta=class_delta;& }- F2 r6 Y& X! k( I: [3 L- Q
}
- z; f- V I }4 h7 P0 z//+------------------------------------------------------------------+
+ w$ z+ U! c7 j: L! \- a; |//| Destructor |
3 k" y5 U: W4 B( | k0 M//| Check for initialization, create model |# o1 }# V- C1 W4 f" ~& s
//+------------------------------------------------------------------+
7 \, z7 |/ j( K, g, Mbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
5 k9 p) b8 T/ N6 h0 G{
4 f4 V( r( I: g% B//--- check symbol, period3 g" b3 w4 V* o/ k/ L. `3 e
if(symbol!=m_symbol || period!=m_period)
! h+ {" s& n$ M2 f{* C6 q. h: R7 E/ ]# S
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));9 j$ }5 H# i8 D0 K
return(false);" G) l% O3 t: h" R5 `8 y7 W+ c/ y m. J
}4 d+ L7 ^1 l) p9 S' a
//--- create a model from static buffer
0 C# }! l# }, h' ]m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);8 d( p) ^ I( L. h- n, e5 R0 {
if(m_handle==INVALID_HANDLE)
* f; J* d) T' \5 w; D{
: j5 t6 Q% f+ u' B2 t% R6 V% \Print("OnnxCreateFromBuffer error ",GetLastError());
% z. B& [" h- }& i4 T4 k8 Rreturn(false);
; K! ^: j3 T/ l7 U; z+ }/ F}
* ^ p! Q/ a4 k7 K& a//--- ok
# Z; z1 R# }4 \. C; c9 Creturn(true);
! P% I* h9 p' v) \# h/ Z. D- d}
% }: ?& g( V9 A+ X8 f% ^- L D9 i//+------------------------------------------------------------------+# B) D; |; V" }% g" [) W$ V
m_next_bar=TimeCurrent();
) E' M' |: `" L" ], w, U- `m_next_bar-=m_next_bar%PeriodSeconds(m_period);3 s' N& s* @% Q9 Y
m_next_bar+=PeriodSeconds(m_period);6 p* W3 M' J2 S7 D# |' S- \
//--- work on new day bar
8 w4 i0 a7 n8 D. _; Ireturn(true);
" {$ a1 ?. a% ?" y+ w}
j- D0 A2 Y) a9 A7 _" Y; q: [//+------------------------------------------------------------------+% b5 q/ [' ~3 ^. E X" G
//| virtual stub for PredictPrice (regression model) |. U0 P! x w8 @) O9 u3 q
//+------------------------------------------------------------------+6 p2 a1 D0 F. P3 p& Y
virtual double PredictPrice(void)
2 ^# F0 ]7 p; E: w; k{
Q( \, { Y# p' A1 u" g) wreturn(DBL_MAX);" w3 x+ }, b5 A+ ]
}
+ p4 c( z* x; V$ q//+------------------------------------------------------------------+
2 T [, J2 k$ p% Q8 u( `$ y' D//| Predict class (regression -> classification) |
+ {4 J- w7 N6 ]4 p//+------------------------------------------------------------------+4 m' j' @; W7 F {
virtual int PredictClass(void)
5 n2 f' n' b% Y. S2 j; M$ r, b: e{0 I7 v6 _- [. M+ Y/ t0 r5 ?
double predicted_price=PredictPrice();( j+ [9 Y0 e1 m! h9 F9 v7 B# i
if(predicted_price==DBL_MAX)8 b' m: \) U* L: N) ]" M
return(-1);- C0 v0 P8 R9 ]7 k) ~/ U) M4 W8 r
int predicted_class=-1;
1 o v! t& j/ _1 f; Ldouble last_close=iClose(m_symbol,m_period,1);
5 u+ N/ f; i& }* T: W//--- classify predicted price movement
. f* f3 `8 L( ?9 G" xdouble delta=last_close-predicted_price;0 ?, P5 C1 D+ M# ^
if(fabs(delta)<=m_class_delta)2 L- l" e8 u7 v2 T
predicted_class=PRICE_SAME;
% N# O7 ? P- I% n" Ielse
! L" V0 {# n/ {. H: g9 lprivate:# _5 F, z7 i6 d: Z/ S+ X) L+ `
int m_sample_size;
% D2 M* ]) ~* b. H' h$ g9 c* c//+------------------------------------------------------------------+
2 n" E" v" _; B* J# pvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
; v7 }9 V6 K H{
% g- P+ Z, O: H N4 C//--- check symbol, period, create model" {4 x" n, L @
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class)): e' B+ T7 S8 M, p4 \: Q1 g
{
$ A1 T, ]: }2 ^Print("model_eurusd_D1_10_class : initialization error");) `7 L' ` W: }8 S* s' M( V/ ^
return(false);
# B' ~, `0 E: f+ N2 O+ c$ r}. h# a8 u# e6 Z8 Y3 I
//--- since not all sizes defined in the input tensor we must set them explicitly) x5 t$ |0 V! g. u6 ]2 Y
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
/ F, R! J! @+ u+ Z- ]const long input_shape[] = {1,m_sample_size,4};' S! ^1 g5 b5 j# x7 r3 u# n U
if(!OnnxSetInputShape(m_handle,0,input_shape))* F2 {& |% J( O8 N: t( Y3 _
{
& ^. ~2 V- \& X" w* C) U0 @" FPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());+ d: a* T5 j( p1 f
return(false);9 k$ Y' }; _3 Y1 ~) B8 j. E
}
$ u1 G6 L1 `3 }" x//--- since not all sizes defined in the output tensor we must set them explicitly( M$ [1 i: P+ V0 Z5 d+ ?
//--- first index - batch size, must match the batch size of the input tensor
0 [3 I) u& V/ ^1 S2 [" u//--- second index - number of classes (up, same or down)' {; \4 | J) J" v- O
const long output_shape[] = {1,3};
3 B+ r& V2 a# v4 q% V. _if(!OnnxSetOutputShape(m_handle,0,output_shape))' x `9 o' { S! l' o
{
' V6 @: p# j! `Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());2 q: _ R5 X$ j, f6 Q- J- Q
return(false);9 ?: O4 \1 Y+ x O7 ]! V
}
+ C9 A; C4 h" @" c# P7 K+ \//--- ok
# D3 L8 B) `7 |" d8 w; f) lreturn(true);' m# _# N+ D [& Z! s
}
! X! |2 C4 B& o//+------------------------------------------------------------------+! M6 K9 F2 N0 L2 L, |8 {
//| Predict class |
; p" F* G. S& c. n, C {//+------------------------------------------------------------------+! v/ n" b0 B) ~; z5 {- v
virtual int PredictClass(void)
- `7 _0 ~! S' H1 h{ |