1. 我们会用到什么模型呢?
1 R. ]2 r0 x- s4 B. p" s在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。9 f$ V r9 o9 v3 j/ v$ ] e7 u/ z
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
+ b$ f8 M9 ~- {9 R1 V5 D$ o//| https://www.mql5.com |4 l6 o6 j, |% p6 R
//+------------------------------------------------------------------+9 F- @0 V3 S u* s
//--- price movement prediction- }9 Y7 _2 M6 [8 a# q, B/ n
#define PRICE_UP 0+ q- L* z9 o, y
#define PRICE_SAME 15 {+ z) N% D; \- g: ~
#define PRICE_DOWN 2
. `% R3 r6 o$ y/ z5 a4 k! F//+------------------------------------------------------------------+
) x' S" y6 I( p5 t& E- {6 G4 ?) T//| Base class for models based on trained symbol and period |3 @) c3 b- o: P. \7 k* W- |
//+------------------------------------------------------------------+$ V& Z4 S3 Y- o0 ~. H) T- m# s5 w
class CModelSymbolPeriod
& R& ?* q9 d! f: T( G4 b4 ~( P+ L$ X{
. K9 ]) K. e7 [( }protected:2 @; D6 {# s6 }/ m* \3 A$ t& l
long m_handle; // created model session handle6 F- l5 U5 ^% P, L& U
string m_symbol; // symbol of trained data
+ m7 l6 C" Q' g6 B( F0 {ENUM_TIMEFRAMES m_period; // timeframe of trained data
, X" m' E' o3 M4 zdatetime m_next_bar; // time of next bar (we work at bar begin only)
" E* G" ~$ k8 C8 b) K( D1 V' T7 Kdouble m_class_delta; // delta to recognize "price the same" in regression models
4 u/ T; P( v" ^public:
`6 B5 O( G1 `+ a$ M+ _: q//+------------------------------------------------------------------+
. H+ i9 J8 M' w0 P0 u8 M; B//| Constructor |/ d8 A# H9 M! V) x9 `3 `) ~% _
//+------------------------------------------------------------------+$ M% Q$ i9 X8 c6 A( G, v
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
# v( q: Y* V! F" ~{& F4 {+ _1 s4 T7 T# K- F
m_handle=INVALID_HANDLE;
, S. `' m0 G9 j% d- qm_symbol=symbol;
6 ~' L1 d/ {1 Rm_period=period;4 X. h' D* A5 n0 M/ y. o9 ^
m_next_bar=0;
9 v# }' U0 H2 O5 b( qm_class_delta=class_delta;9 R1 P/ B* u2 R6 P
}& y- c* w; R% G$ F4 L) y
//+------------------------------------------------------------------+* q$ u) c( X+ n! d
//| Destructor |' l/ J u; h& z5 N0 r) t' m
//| Check for initialization, create model |
7 s- ^- `. s0 O q- ?+ o//+------------------------------------------------------------------+
! A' x- h6 q! Z8 w; U& ~1 Tbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
6 d+ `5 s- o+ z0 A" B+ _{$ U+ {, @) Y& u
//--- check symbol, period8 Z5 ~/ V B8 p' r c* |
if(symbol!=m_symbol || period!=m_period)
, d Q' d1 Y0 y1 l' e{ [: y1 ]* M8 z+ h
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
4 D/ H% d# R7 P9 V4 kreturn(false);$ \% Q: }* [* } g5 R
}( e3 w) _' B9 j# a
//--- create a model from static buffer
4 f+ p6 Z" u9 a' Ym_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
2 y3 Q) N- _0 J+ i4 }$ _if(m_handle==INVALID_HANDLE)# K f) s- u" y* E. Y
{! b( @/ V* g2 \' t2 n
Print("OnnxCreateFromBuffer error ",GetLastError());
# F% q0 C% [# i1 wreturn(false);+ N$ A0 i: R+ O
}9 N( a5 e5 _: p! X
//--- ok
! M7 R+ `. `$ N1 ureturn(true);$ I+ G9 i- A/ e) u0 B
}! x/ t9 l7 I0 A J$ @; p
//+------------------------------------------------------------------+6 q) F3 f' I- z
m_next_bar=TimeCurrent();* U }) ]. { E3 G7 O& Y9 H
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
$ K4 y. h/ w' J1 V l1 qm_next_bar+=PeriodSeconds(m_period);
4 \$ y7 C7 z9 U9 [//--- work on new day bar2 P% m/ \0 B8 n, _! q1 F: B
return(true);! c+ \" o% q* a1 z. k t" t
}
4 N- o: ^! `, y//+------------------------------------------------------------------+
! p: J- @5 I/ ?- a) A8 b//| virtual stub for PredictPrice (regression model) |
/ V0 B: N* M" Z& }% Q! L//+------------------------------------------------------------------+! t: C4 l+ }" r0 f# Q& v7 t
virtual double PredictPrice(void), B3 S7 ^2 m1 J! Y$ q0 u
{
/ ]3 `4 }; f& A+ sreturn(DBL_MAX);
+ f6 P$ G, a/ r4 a) G7 d# T}
& ?. z# y8 V3 H( c+ \( \3 [* p//+------------------------------------------------------------------+4 N2 O5 e$ M1 x; J3 d0 V( q
//| Predict class (regression -> classification) |
7 D) W( _4 P; n//+------------------------------------------------------------------+
2 ]4 q' s& w( \6 W9 Dvirtual int PredictClass(void)) ~8 q1 E/ {0 r y3 w' J$ ^. O
{+ v9 a& x/ a' w' n9 d
double predicted_price=PredictPrice();
S% U& _3 B# K% i6 ~if(predicted_price==DBL_MAX)
5 u, C- i4 t% t4 s e+ ?return(-1);
# U/ ~/ W2 C% |) tint predicted_class=-1;
; x8 d' I- z8 c& W) sdouble last_close=iClose(m_symbol,m_period,1);% y# m- P$ n$ V- e# y
//--- classify predicted price movement" o8 H. j7 `; {
double delta=last_close-predicted_price;
) T; J ^9 E! K% G- |* B5 fif(fabs(delta)<=m_class_delta)
6 k* J% L5 h9 q- G( q. O; Apredicted_class=PRICE_SAME;
, k+ L/ Y M& J' Jelse
" ]0 i3 O/ L1 }- p9 hprivate:
( ]. C# p. i+ n5 D% l2 Y% ? A1 p* L, G Nint m_sample_size;2 M4 f2 t, j2 |
//+------------------------------------------------------------------+
3 q$ E) p! r d) ?% O6 T' rvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)4 e2 B5 `0 T ^; t |/ G
{
8 T+ F' r K* v. R8 Q% P0 n" W//--- check symbol, period, create model
; Z- _3 g/ n) L% z, [if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))+ V3 |4 v- e& U+ V* K7 w% h6 q
{
8 B1 t' Y; P2 S/ }; I; hPrint("model_eurusd_D1_10_class : initialization error");
" v- s7 p' S: U1 v. v, j! k9 V& B! ireturn(false);
+ Z# L) y% ~0 T C J4 q}* ~ Y3 m. E- N6 B% r8 S
//--- since not all sizes defined in the input tensor we must set them explicitly8 k$ K; A: a8 u4 u2 [& r- [
//--- first index - batch size, second index - series size, third index - number of series (OHLC)0 k* |( q+ z" b! K; w& x
const long input_shape[] = {1,m_sample_size,4};
. V c6 x# c- B4 x; _. }6 }4 S J/ @+ n6 cif(!OnnxSetInputShape(m_handle,0,input_shape))
e9 d9 J* p3 j2 l) H$ E7 F, m{8 e/ I" z) r% m5 B' w
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
: @& {/ o. W0 }3 ?1 Kreturn(false);
7 m) p8 Q0 j: v5 x# l n* p}% |* t9 |. d; R) M; m0 t( t6 X) G+ M
//--- since not all sizes defined in the output tensor we must set them explicitly2 z+ {5 c6 z/ e- O3 D
//--- first index - batch size, must match the batch size of the input tensor
* T3 V- `; z; H, c" K) ^! u* n- P//--- second index - number of classes (up, same or down)
8 ^* _4 E* s& S) D' A+ Y- |0 [const long output_shape[] = {1,3};* s3 o F* W) e
if(!OnnxSetOutputShape(m_handle,0,output_shape))$ Q4 q! k. j3 r
{
3 u. d! X; I0 K% C2 ^Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
( t! l" P- S+ j$ k" H$ Z/ {return(false);- q B7 z! J7 B9 t
} F, W- b' t# C% Q
//--- ok
, B7 m& a. p3 \) Freturn(true);: e; v$ x v8 p2 @
}
% ^; ?' [6 l- d6 j0 [//+------------------------------------------------------------------+7 m/ X( ~( _& s% A; D, L& f
//| Predict class |
/ B5 P4 y7 V6 V6 T//+------------------------------------------------------------------+
! h3 }5 k# y! ?9 |virtual int PredictClass(void)4 ^8 e2 ]; w& A* |. Y/ V+ H
{ |