1. 我们会用到什么模型呢?5 a+ p" u1 i6 l! e8 Z' p: x$ _
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
; X5 Q, l- F m+ m9 I |我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进8 x4 N+ u! U3 M' T
//| https://www.mql5.com |4 n& Q) Y9 b8 ?, J- y
//+------------------------------------------------------------------+
/ M9 z$ ^# A1 u5 O+ O. |4 |//--- price movement prediction& |/ z7 ~8 Y& q5 c
#define PRICE_UP 01 I1 y$ a5 V! q; `7 S
#define PRICE_SAME 15 n+ W- r( j9 n$ @* \) z
#define PRICE_DOWN 2
& g5 S# j4 G2 h* w4 j//+------------------------------------------------------------------+
( o2 Q' j. x9 l! ?3 U//| Base class for models based on trained symbol and period |4 m( ]8 S8 l9 @0 E* Q, _: P+ X2 g+ c
//+------------------------------------------------------------------+1 t6 |) c E6 o' g+ M) d4 z
class CModelSymbolPeriod
* \- ~2 p4 Q( Y& Z2 B{
- ?3 M4 Z9 [' sprotected:' v1 D" V% J n; g7 g' F+ l$ A
long m_handle; // created model session handle
9 h+ H* B9 F( ^% M4 n: ^string m_symbol; // symbol of trained data
8 u# ^2 X+ D9 AENUM_TIMEFRAMES m_period; // timeframe of trained data
- W) J k/ D6 s4 i! p* zdatetime m_next_bar; // time of next bar (we work at bar begin only)
; y3 e6 g$ @( e% Xdouble m_class_delta; // delta to recognize "price the same" in regression models
& Q' x" Z5 S1 Npublic:8 h J6 q' @5 g/ L' z6 N/ a
//+------------------------------------------------------------------+
+ r0 G9 h; q; H, `* F7 z, _ Y//| Constructor |
9 Y: |. {) k [3 h, s2 P( L//+------------------------------------------------------------------+1 c+ L3 N+ H# m( M: g" `
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)1 _" |2 ? z7 V) r+ M" |/ [3 x1 V- J
{
& |: d% D0 B7 L* p: m0 H1 dm_handle=INVALID_HANDLE;
* M0 O4 m' ^* h$ Am_symbol=symbol;
. s$ g- V/ a& r" K) o; i# ]m_period=period;" o% x4 `/ k' k9 K) V8 o
m_next_bar=0;" T. n! n3 g" N8 h
m_class_delta=class_delta;
: O/ A9 A3 O6 r- y}
/ o# \8 r, K- ]6 I* a//+------------------------------------------------------------------+
: N( }+ t; M; v: j4 ~//| Destructor |
" ]# X- F; Y2 [, g" @* _//| Check for initialization, create model |
+ I8 Z+ |' o' a8 p% a//+------------------------------------------------------------------+
; l5 v& ~7 N. Cbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])6 K9 ?# j. r5 n7 X* N" O
{
" S( M9 l# J% Y8 s- @! ~//--- check symbol, period
9 t1 W+ W0 z( d8 O. j/ C8 R' gif(symbol!=m_symbol || period!=m_period)
/ D. A6 a3 q9 {, w, ~. W{
3 E, y. }; u6 a0 iPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));" J3 E9 a& c- q1 S. m
return(false);' F- L6 V0 d" d2 ^7 L
}
& p. N/ g3 m- g" f8 \8 a//--- create a model from static buffer
3 z8 X( P1 f- m" L7 d$ @8 }m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);8 }0 z& i: x8 e( r4 R3 X* @
if(m_handle==INVALID_HANDLE)( f. m( j' ?% x2 m5 ]& v0 w
{) Q. S# N: p) C" X' {
Print("OnnxCreateFromBuffer error ",GetLastError());
1 |0 q k, Z/ @( \, xreturn(false);" k3 F9 G% h2 u9 x) ?2 |$ U p
}
2 j& _ Q+ l0 `- E& W( p2 _8 L//--- ok
0 U d+ Y2 t6 r5 y5 R0 }. vreturn(true);
* ^* Q) f* `' v& Z/ n3 I$ J}& m8 ]# `4 O6 O
//+------------------------------------------------------------------+: g7 G) X. [# f$ z2 n5 z3 Q% ~; I
m_next_bar=TimeCurrent();
& \$ N9 J; u) G5 S: am_next_bar-=m_next_bar%PeriodSeconds(m_period);9 Y1 O+ i5 |3 h$ P% w, O; v
m_next_bar+=PeriodSeconds(m_period); E: K) ]4 d' `
//--- work on new day bar2 m4 [' K1 J+ O5 F2 Q
return(true);8 U; [4 b' M/ s0 b8 T$ \/ v
}/ Q5 J3 v: v$ u
//+------------------------------------------------------------------+
- X) n6 Q( c0 `5 R) J5 `//| virtual stub for PredictPrice (regression model) |
1 x6 P6 v l; H/ [& D' p; W$ ?//+------------------------------------------------------------------+
7 D% O# F; x+ z( f6 {4 ^8 Rvirtual double PredictPrice(void)& V/ C6 P7 i% Q* p1 s8 Q+ L9 _) Q8 D
{
9 G. h8 G( N0 W5 T, t' P2 X0 B6 }return(DBL_MAX);8 g U, J9 F( B; ^1 {9 J
}
T& P3 k/ [, d. ?9 ~4 ?8 i: h0 A//+------------------------------------------------------------------+
6 D/ c$ q+ Z {//| Predict class (regression -> classification) |
: q: e1 h2 ^) B, T4 }3 r//+------------------------------------------------------------------+) \& [, C! L0 ]2 l4 {* W
virtual int PredictClass(void)
" ^/ ~/ j( m4 o- A/ z/ p# c3 V2 w{/ _' \6 F, w, s( p8 t- c w
double predicted_price=PredictPrice();4 u, @2 T- W }) F" d
if(predicted_price==DBL_MAX)* K# |8 j' u+ k# X, @
return(-1);7 I4 W z7 k+ m/ o6 E+ A
int predicted_class=-1;8 ^) g7 ]7 e4 p4 [
double last_close=iClose(m_symbol,m_period,1);
# L( v, M% m3 t C//--- classify predicted price movement
) ]/ x1 B" C9 K9 p ^3 q) R% Hdouble delta=last_close-predicted_price;
3 f/ Z p% Y, dif(fabs(delta)<=m_class_delta)* h6 s$ S: c1 v# h1 \& |
predicted_class=PRICE_SAME;
' w8 @5 r/ Q0 h: S0 m. I* g, Pelse" r/ X" {7 [+ j& h/ Q3 n
private:
1 a0 I. w& ?( `6 Z6 [& rint m_sample_size;
1 U; M9 E# P: g1 x u i# A//+------------------------------------------------------------------+
3 S% F* z1 `' h+ A$ x9 h' {* \8 E. O8 {virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
3 o$ u5 ^+ ]2 g1 o{
4 G0 j5 D5 N( }0 R V//--- check symbol, period, create model- K; I c E0 V H
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))4 }/ C8 _. p1 c, `/ X, d9 ^
{
% Z5 u9 f4 p3 Q) MPrint("model_eurusd_D1_10_class : initialization error");
3 s- X" z/ a+ j* g& H& u/ V9 lreturn(false);, e1 i; a+ c R" M# r5 }- A
}
/ H; Y7 R# e% Z3 x8 ]) r//--- since not all sizes defined in the input tensor we must set them explicitly
3 Q; R) }- X4 N2 e4 y" z O3 M; I//--- first index - batch size, second index - series size, third index - number of series (OHLC)
6 C6 z' K( k" wconst long input_shape[] = {1,m_sample_size,4};
2 J5 q7 ]7 B8 v* |7 pif(!OnnxSetInputShape(m_handle,0,input_shape))
( x" ^8 P3 q0 N8 l3 ]{* Y6 B- y0 m. [
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());0 i+ B2 O2 L% s* R* T3 H+ @% x
return(false);
3 o; V" Y1 U% e" D$ R" f6 o}, r3 N6 W$ { n U
//--- since not all sizes defined in the output tensor we must set them explicitly
( X# U3 W# k6 K1 @$ Q4 f//--- first index - batch size, must match the batch size of the input tensor
; E3 o/ v5 z3 h- P4 C//--- second index - number of classes (up, same or down)
! {9 v+ T# K+ w' S+ {( y- S0 ]+ U, E# Xconst long output_shape[] = {1,3};
, {9 I& }' G3 R8 j0 m5 Gif(!OnnxSetOutputShape(m_handle,0,output_shape))
2 s4 ]7 Z/ }0 ^% A1 F% u{; {" c# g; ~0 [5 w* m) T( o8 ~
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
0 k" {! x! Z! H4 D$ oreturn(false);6 p* z' ^, a7 T. ]" ~% E7 `, {
}
$ ]+ P/ I- Q4 k( ?: [) y' X/ \* b8 \//--- ok
1 X. f; p3 ]2 R+ ^/ treturn(true);* w( `/ J8 m! \( O
}$ w) u$ m3 Y$ t3 S% ^ M* z+ f
//+------------------------------------------------------------------+
4 b- ~ ]/ p1 z' h' P% e//| Predict class |* X# R/ y: U+ [, d+ j2 f [
//+------------------------------------------------------------------+5 a- _4 t( R; U2 p1 o1 F: [# z) ]
virtual int PredictClass(void)
# y: V! a: G2 k1 P{ |