1. 我们会用到什么模型呢?7 q3 e7 U7 v5 }
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
+ v$ E6 C+ |$ F% L( e+ r我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
1 P$ K" U3 }3 F7 m" z( }//| https://www.mql5.com |6 n* f8 N, @7 e5 V2 N$ [! O1 n# e
//+------------------------------------------------------------------+
3 \9 U4 k( p A/ v9 @6 @" {//--- price movement prediction
3 h9 M# h) h8 a4 e! W: w5 a e#define PRICE_UP 0- ^3 x1 P0 ?$ R7 X
#define PRICE_SAME 1
5 a* j8 E7 o7 p#define PRICE_DOWN 24 {" a2 e4 ?4 a. E
//+------------------------------------------------------------------+
3 q# g. P) F/ }$ H//| Base class for models based on trained symbol and period |' i* ?. ^; v4 \- i) q
//+------------------------------------------------------------------+
- Z0 s0 C$ [8 F7 l8 [$ V- iclass CModelSymbolPeriod
; E7 a8 j7 f2 @- F{
" K% @6 j4 @8 z, Q5 E. d5 @; \1 d& _protected:! U+ {; e" V8 H, O- m
long m_handle; // created model session handle. p9 I9 A1 a3 [" a! m" r- C
string m_symbol; // symbol of trained data
( U" m6 P( X. e4 QENUM_TIMEFRAMES m_period; // timeframe of trained data. A5 F$ f, l( F3 e
datetime m_next_bar; // time of next bar (we work at bar begin only)" X5 ^- \9 k+ U6 r
double m_class_delta; // delta to recognize "price the same" in regression models
% _. h+ Y" |6 A8 y+ x5 bpublic:
/ y3 ~% ~; ^. l" V//+------------------------------------------------------------------+; U- x2 `( y) ?0 J+ g
//| Constructor |2 ?+ a4 J0 j: T6 ^
//+------------------------------------------------------------------+* ^' d j$ f- c+ m1 |
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)7 T$ `. a- v) A" k8 j! `
{
$ h: K% B. c$ Z) r3 V/ um_handle=INVALID_HANDLE;
- p8 C. z0 c9 J4 xm_symbol=symbol;& i% R- B; N0 M* i
m_period=period;; |( M; F/ J% C# A
m_next_bar=0;5 t! X& `# H6 v
m_class_delta=class_delta;
2 g, {( n1 e. L}
0 l$ ~: i+ |4 H$ d0 ^0 g( x//+------------------------------------------------------------------+
4 E7 d. g$ z5 V% e4 z5 [ B5 K. V//| Destructor |; f2 H9 u, f* K4 Q
//| Check for initialization, create model |
( G# V; w6 h" y; T, v; p//+------------------------------------------------------------------+
; l1 U2 E2 j1 _" kbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
# N, ~+ {! b3 l1 ^, h! ]7 X3 |{
+ E- Q$ b$ t! G" \1 d1 K//--- check symbol, period; t' r! j% j/ X! y
if(symbol!=m_symbol || period!=m_period); C4 {* e* g: i2 [! Q
{
0 Z" k3 O9 }# A8 x* u8 _PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));( Y0 U1 T/ D& s0 ?- J
return(false);
6 k9 T1 A/ m) P' d}' X* m, i6 F; [; E2 q. N
//--- create a model from static buffer5 w w' ?- W# v! ^* {) C, ~+ Y
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);; z4 y- M- X7 X' a
if(m_handle==INVALID_HANDLE)
7 I5 P* u1 D8 u$ E% B6 s4 h ]{0 C& J& ]; L( A/ l' C3 j. @
Print("OnnxCreateFromBuffer error ",GetLastError());
% Z, [1 p9 x0 m6 b8 J" O; }3 }return(false);" v" P0 y# N3 }% ^, m
}/ V/ {, U3 W, Y; `
//--- ok* G2 }5 \$ p3 A" n/ ~
return(true);8 Z# v8 m' y" b/ F8 a
}
9 a8 t$ S- @6 l# k+ c//+------------------------------------------------------------------+
& B! R, g$ ~1 Nm_next_bar=TimeCurrent();
" c9 W9 O, J9 |$ b( gm_next_bar-=m_next_bar%PeriodSeconds(m_period);
. O4 M3 d# W1 b) t; y. }m_next_bar+=PeriodSeconds(m_period);) m) E Y: N- x4 i3 E
//--- work on new day bar
! x1 h% G0 N' \ `: q% C( P0 ]return(true);3 I! Q+ T" @8 n. ~' \) N- Z
}: y& r' Q; W0 H5 w$ N
//+------------------------------------------------------------------+; C0 P, Q+ ]9 [
//| virtual stub for PredictPrice (regression model) |8 S/ n. g5 H3 g/ `. x
//+------------------------------------------------------------------+ r4 f: E; S M/ e: e* z
virtual double PredictPrice(void)* ~& P4 a ]0 S9 i _
{
0 d/ y& F1 l- Q, l# ?3 s4 \, jreturn(DBL_MAX);
- _0 j9 ]" C! K( S}8 k& G& L4 I- P* D; ^
//+------------------------------------------------------------------+
* G4 l$ t* P6 M& ^//| Predict class (regression -> classification) |( t6 k0 H4 \9 g
//+------------------------------------------------------------------+" o# z5 b+ Q$ M/ L: f
virtual int PredictClass(void)
9 ~" k! \4 f1 ~; v) c{3 L- l0 ?, _/ p7 q; _6 S P C" k
double predicted_price=PredictPrice();
& f5 B! }1 S- Z$ g }8 tif(predicted_price==DBL_MAX), Z1 I; o- Z1 J) c9 {% p9 r
return(-1);
$ N2 A! ~0 `% d" q Qint predicted_class=-1;1 J _; i2 t: v- @
double last_close=iClose(m_symbol,m_period,1);+ ~; m7 b) V" A' M$ {) R# p8 ]2 n
//--- classify predicted price movement
G# `- S" \" J; mdouble delta=last_close-predicted_price;
( j. J; h: W# c6 s( ^if(fabs(delta)<=m_class_delta)
9 C* Y: J: _& ~. l- M3 r" d/ npredicted_class=PRICE_SAME;* `+ T0 F# K' N: w2 {2 r0 i
else
, w9 j7 b5 h) m1 I+ a: c$ m' K1 C# Rprivate:" O' b+ T# Q5 i/ k
int m_sample_size;3 X5 L, y; C3 l/ {5 V2 c1 @
//+------------------------------------------------------------------+
! z6 s' B% @; z) U t1 N( ovirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)# [1 v0 m2 P8 ~4 p; c0 a2 p3 L( x
{8 a8 N9 J$ f6 N+ `
//--- check symbol, period, create model
1 J$ }. w p9 I1 t, h$ s/ l4 ~if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
; J" X2 o4 z7 I) O$ k7 \+ R; B2 Z{
Z8 n* H k0 L4 R. E: HPrint("model_eurusd_D1_10_class : initialization error");% N( C5 B5 V* Y
return(false);$ K" ]( y0 c7 E4 o3 \& q: A
}
6 Y: m2 x9 ^- s2 e5 U# D# f2 }//--- since not all sizes defined in the input tensor we must set them explicitly6 L, s9 @; y" E" p2 G
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
2 q" [# Y3 Y; V$ O9 Q& E$ e/ d2 fconst long input_shape[] = {1,m_sample_size,4};
7 B& K& d- {% V( \" [3 ^8 c; tif(!OnnxSetInputShape(m_handle,0,input_shape))
' R9 i# j: ]+ i) \: `& _" r0 s, M{7 G/ M( @( _3 l- _) ?
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
}9 B% T" P- G9 Jreturn(false);
$ f/ V/ K. U X: s6 {+ G) ?}. @0 o$ ~1 X1 h$ E) j) e _
//--- since not all sizes defined in the output tensor we must set them explicitly! i6 G1 x/ s& N* ]2 ^4 q+ ^
//--- first index - batch size, must match the batch size of the input tensor
% n0 D" u* F2 H, ] |& R//--- second index - number of classes (up, same or down), _) _5 U& v, q0 v% K8 c1 V0 W
const long output_shape[] = {1,3};0 N8 e1 ^* V# Q+ f7 ^( D( ^
if(!OnnxSetOutputShape(m_handle,0,output_shape))) c' O7 [5 t1 A5 s+ @4 O
{* F6 u3 S) J0 A# o8 c% O0 C( q
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());0 v% W1 t+ [' T6 `; n5 p! ~3 I
return(false);! ]5 k. k* ]8 h) k$ Y5 t
}; h& _. G" z- M* c8 u4 c
//--- ok
) |3 w1 I% t x% R- ureturn(true);0 g+ E, m; T1 l5 W1 e
}5 f! k& M' c# b% d9 X! a2 q
//+------------------------------------------------------------------+3 b- o) e8 J3 y2 y. @
//| Predict class |9 x2 Y5 {% E9 C4 m
//+------------------------------------------------------------------+) j0 x- ?- C% ?* d
virtual int PredictClass(void)
" {; b9 N1 G& g! F5 P6 I- S{ |