1. 我们会用到什么模型呢? Y; N8 j" [, \9 C6 a9 K0 W
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。; c+ P% y2 W8 H7 B. V, o1 \) j8 ~
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进) A9 i$ i( Z0 N8 }
//| https://www.mql5.com |
/ z% I2 \& x9 N, c9 ~//+------------------------------------------------------------------+
" K/ t' m: x& \0 R: F4 l//--- price movement prediction" ^* h6 X) K+ R0 D* T+ b6 ?; u; a. A w
#define PRICE_UP 0
, a' E! A- a5 Q4 y( J: \6 |#define PRICE_SAME 13 c' ], L0 k, }) O4 Q
#define PRICE_DOWN 27 u0 `# J0 z' @$ ]3 s5 E% }6 x
//+------------------------------------------------------------------+/ l; g% h* ?4 B$ x6 d
//| Base class for models based on trained symbol and period |4 \; x& l. o8 x# N% y; [
//+------------------------------------------------------------------+: c$ }6 Z5 E w! C/ v
class CModelSymbolPeriod8 w6 O3 z8 R S4 P
{
& [$ K$ F( F1 k0 C5 o1 Q& b2 wprotected:
5 ?4 f6 v; {, l" c% Olong m_handle; // created model session handle
& X/ I3 Z0 q/ w; A Ostring m_symbol; // symbol of trained data
& X; q& } K( J0 R% @/ LENUM_TIMEFRAMES m_period; // timeframe of trained data) z, P! Y# V& m& c& u3 Y' O: C B& W
datetime m_next_bar; // time of next bar (we work at bar begin only)
& @' i$ `4 W4 o! i. g; i* x, G& mdouble m_class_delta; // delta to recognize "price the same" in regression models
1 [9 N+ ?, @$ q6 C& L8 [- K, kpublic:& [5 |, t! `" ^& k* k8 n9 M$ u9 f) W
//+------------------------------------------------------------------+% s( C* f2 x& B4 G7 Y
//| Constructor |
5 y$ x/ i4 E& z# n4 j//+------------------------------------------------------------------+0 q( d/ R# w/ |( h8 w4 N. {) i
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)' e# p! S0 s2 o
{
: x0 `" y9 _: j& X6 ym_handle=INVALID_HANDLE;) _! |2 ~* o6 K: X0 K4 M
m_symbol=symbol;. X# C3 r x+ o2 Q5 \! o
m_period=period;
) g, s9 [$ R% E) ^m_next_bar=0;! l7 q$ z2 C3 o& P$ @$ X2 A# F
m_class_delta=class_delta;
0 j( D0 v# e+ ^9 d0 P6 E}
3 @1 A+ |5 g/ i4 g/ k5 ?//+------------------------------------------------------------------+
) h% q* P) h! g5 p- U' v- r" X* d//| Destructor |
2 g- Y1 R6 k' B5 K3 ^//| Check for initialization, create model |
0 r$ y: m& a* j: Q2 m//+------------------------------------------------------------------+1 W' y3 A8 h6 S
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
4 h$ T0 y( ? p8 m{
# z3 R- O) t6 F9 m2 ?- g- B& C5 L+ d//--- check symbol, period
& D! h$ R% Y$ H" Aif(symbol!=m_symbol || period!=m_period)1 r8 r4 j7 A) p5 n/ |& d0 h
{
N8 b5 e7 @$ R3 Z: N7 fPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
* u1 v: [8 s, q9 c' z: C U& mreturn(false);* L" N1 N# r% {7 u% h
}
- M1 P0 E ~" D; V5 S# j& L//--- create a model from static buffer0 U+ b( r9 [1 T# d3 N" e* i' M
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);" H! h/ v% I$ U/ Y5 u
if(m_handle==INVALID_HANDLE)
3 i2 ]; w0 ~1 D% I# x) R{
& y0 K; _) X& aPrint("OnnxCreateFromBuffer error ",GetLastError());' `1 a8 I' K& }: k& F: U' O
return(false);
' t. C1 P/ a; F}
) B: s( O" ]* `9 G( {6 n+ @ M- B//--- ok
- u1 X6 F* z% k# z' d; Greturn(true);
X, B7 _% d, b/ ?3 ]0 T: y/ a}! J% c, N( h0 d( M c
//+------------------------------------------------------------------+2 V' V; T4 g# v' t9 G% E# G. x
m_next_bar=TimeCurrent();, u+ g2 B, U, i. F
m_next_bar-=m_next_bar%PeriodSeconds(m_period);; X4 Y& ?$ r# m, ]6 V7 z* f
m_next_bar+=PeriodSeconds(m_period);
1 Z! W6 J# B E5 L" I; e7 f//--- work on new day bar4 A7 |% w. W6 G) S1 h; O# ~) f
return(true);6 O* f; L" }8 A0 ?, E
}
( r- _+ j R! N$ o7 A//+------------------------------------------------------------------+' ~1 C$ W5 F# ] ^6 q! _+ c8 ^
//| virtual stub for PredictPrice (regression model) |
: o0 Z& p2 W. i( b1 o3 _' C//+------------------------------------------------------------------+
* P( h& E4 U4 {' N& B% J) lvirtual double PredictPrice(void)
3 l5 F9 @) v: L0 O: p{
3 t5 ?( x( b$ `4 X/ d( preturn(DBL_MAX);+ V8 K0 F5 e# a+ Q' b/ R$ s
}
9 B$ {# D3 C/ r M/ T1 i; e! V//+------------------------------------------------------------------+
' L! F3 i$ Z: y, f& y" }//| Predict class (regression -> classification) |* k. H9 x6 s$ I+ f0 y9 [( }1 ?
//+------------------------------------------------------------------+
! L4 s! n1 W0 h# E! y4 v/ Lvirtual int PredictClass(void)5 F7 K" q4 C% [! w1 P
{5 ]1 L4 P8 k# s" S
double predicted_price=PredictPrice();0 }5 d5 h, |# l1 S) o" Z" J
if(predicted_price==DBL_MAX)" X. C7 {0 `1 J) u) O- ]+ ?4 x7 |) i. A
return(-1);5 b$ I1 w' I1 }+ _3 p5 z& G. {
int predicted_class=-1;& T$ c7 |+ t. ^; F
double last_close=iClose(m_symbol,m_period,1);
6 F# r! O8 P2 D; |! c//--- classify predicted price movement
8 d4 J6 M' a6 ldouble delta=last_close-predicted_price;3 i' i h9 p; V2 o
if(fabs(delta)<=m_class_delta)
0 c9 Q- e6 f9 k3 Q# Q" {4 @* Lpredicted_class=PRICE_SAME;
# S; ]7 H! U! U& ]; ~% _else* n0 T. @" Q( c
private:
/ E6 m* q% H7 i0 Q/ T/ g' s* `int m_sample_size;
- v" A% {2 e U3 Q, }) f//+------------------------------------------------------------------+
! G1 j5 j+ |5 i) J- c4 E# R: _virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)( F3 w) b, X! ^+ ?! B) K
{! P% P4 @$ E* t4 h
//--- check symbol, period, create model
+ a. q$ C" I# d( d' pif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))% M/ D2 |% n0 C: V% ?7 o& J& I
{
& `0 ]" e0 e5 E7 a: P$ Z |Print("model_eurusd_D1_10_class : initialization error");5 a V- {) @; g( G$ q3 W* w
return(false);
5 Q% {* g+ A$ z2 T! U' b, p) B}; j" N+ F( H( W- c1 ]2 _6 B5 n
//--- since not all sizes defined in the input tensor we must set them explicitly
. [' s, i+ |( }3 t//--- first index - batch size, second index - series size, third index - number of series (OHLC)
; g. U _7 K! H5 T7 @( f3 m$ ?const long input_shape[] = {1,m_sample_size,4};
# F. y. n5 _+ O) e+ D% tif(!OnnxSetInputShape(m_handle,0,input_shape))
# G3 r& } o# g- k# D{
9 {, H0 Z0 e# v7 mPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
( V" e* X6 [* G0 H+ v0 E* D4 Ereturn(false);
- \) @6 D7 o8 V' d- A}
s7 Z# p, V% h- q P4 k//--- since not all sizes defined in the output tensor we must set them explicitly
5 Y! _) k. q3 w* b//--- first index - batch size, must match the batch size of the input tensor
' b! \/ `# Y5 e; b6 u4 _//--- second index - number of classes (up, same or down)9 ]; |! A) k+ `' B( o7 v
const long output_shape[] = {1,3};4 i0 r! }- F# E/ u
if(!OnnxSetOutputShape(m_handle,0,output_shape))* ^6 A+ S0 e" I4 R; I- X
{5 R! H$ `9 U {+ o3 w9 }, G3 s
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
" o7 l/ D& K7 V5 L% Dreturn(false);
. r2 h5 h! E7 B- s' a}
" m. x& S. q0 U- d$ `//--- ok
# ^: }: ?4 K; ~" S, Q% Lreturn(true);- z+ i" H' b7 X2 C
}4 F- a' W2 }2 o9 l
//+------------------------------------------------------------------+* V9 X, `5 N b: e& A; W
//| Predict class |5 H6 s6 E" ]" a& V
//+------------------------------------------------------------------+% t& r) ?: ]1 P2 y# l2 I L
virtual int PredictClass(void)6 @0 i' x, A; [! v* B4 H
{ |