1. 我们会用到什么模型呢?
1 N/ r+ a. z- b! H/ _8 o- N! p在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。+ S6 _) p+ G$ U7 m, w' |
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
9 \1 L9 u) ?) _+ R* I//| https://www.mql5.com |3 X x( G+ W0 f4 f% n; c9 `' t: M8 }
//+------------------------------------------------------------------+
, G, A3 P4 Q- J+ }* i+ ?- Z ?6 L//--- price movement prediction
, v f' X$ e7 }6 s* P#define PRICE_UP 0
~/ N% X7 A, o( R6 t4 C( K2 x#define PRICE_SAME 1
4 S: |6 j" A! x) V2 w$ b3 @7 Z#define PRICE_DOWN 2' H6 m* u) l; n: j
//+------------------------------------------------------------------+
) V* N& k1 ^+ O- d- O f: D//| Base class for models based on trained symbol and period |" \' q5 M! _) B( o
//+------------------------------------------------------------------+
; P' a% L p( B4 ~1 ~class CModelSymbolPeriod% g7 b% Y9 j4 z: _- y9 Z. d
{' ~# v! G' F7 q( J2 b" r7 e
protected:
% y, l0 g, N/ `7 h' Z' R6 Along m_handle; // created model session handle7 z2 D+ x; l$ n/ ` }* L
string m_symbol; // symbol of trained data
( t3 x5 q0 N) K( X/ O. {ENUM_TIMEFRAMES m_period; // timeframe of trained data
0 O. u. Q% ?- @/ X9 V( Wdatetime m_next_bar; // time of next bar (we work at bar begin only)) B, W6 b: r/ Y( Y F
double m_class_delta; // delta to recognize "price the same" in regression models e; Q7 T6 @) D) y
public:' m* ?" n" d, W% X
//+------------------------------------------------------------------+( Q; f) i3 Q9 l& u I7 A( N; m
//| Constructor |) |+ n7 U* K- Z- W: S
//+------------------------------------------------------------------+
5 M. w6 R% @/ B. w, rCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
( e, O: L/ ?, L' f{
* y! V# ~/ [9 D# J$ \m_handle=INVALID_HANDLE;
; S# `3 d& n/ m0 W, T5 X/ G" {& zm_symbol=symbol;
! [; I' {9 @9 v7 `; {m_period=period;, O/ F5 O! e5 m' q
m_next_bar=0;3 p [ |5 t* ]" I( X: }
m_class_delta=class_delta;
: u5 K9 Y( L2 R}
; v; z% \2 W1 p0 i5 S- M, |1 @0 ]//+------------------------------------------------------------------+ |9 j& Z- Y2 C( n! {: Z
//| Destructor |
" ]' F' `# }% M+ q7 V* e& M: ?8 @//| Check for initialization, create model |
! Q( W J# ]& c- X, E) X5 T//+------------------------------------------------------------------+
. q: O* I" j+ x- h3 E6 Pbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])* R3 `7 {2 [' ?7 _
{
3 v: m. B: P( A& ^ i8 N//--- check symbol, period
$ c" X* [2 s8 s i1 Q" w5 U# gif(symbol!=m_symbol || period!=m_period)& d% K) r. q' w3 I; `2 K6 D1 b' k
{
& f4 i& C' j \0 F4 y" X/ q; ^PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
5 p2 L. i/ c4 u U- W. L4 y/ |return(false);
& @7 H5 n& n& m* ^}
. N: L* v: z; [2 }. q) S h0 k//--- create a model from static buffer3 K/ d2 a! A9 x( R
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);, V, ~0 W l8 {7 v# ~8 c4 ^
if(m_handle==INVALID_HANDLE)- _) F+ H8 a5 {. B
{+ x3 x& V# S) z
Print("OnnxCreateFromBuffer error ",GetLastError());
! a) V1 N) K' b* a I/ dreturn(false);
' w8 I6 U- j6 E) s}
4 r5 K" }" J- ?" u' V//--- ok$ p. X3 V6 @3 O2 H9 b8 O
return(true);8 H7 B8 e# m6 W2 R8 D* e# w+ Q8 T$ S* i
}8 o. T$ u. G: Z( u% S# E- N( r! _8 M2 @
//+------------------------------------------------------------------+8 L! c$ p( k; b' o
m_next_bar=TimeCurrent();; v* ^+ V: ?/ w5 y9 B( K7 U
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
$ v3 K+ S1 a% d" T lm_next_bar+=PeriodSeconds(m_period);
6 N* j$ u3 u! T' ~; ^/ J//--- work on new day bar
1 m$ P. x7 g+ {return(true);# U/ R& J3 H* a) d2 a0 M" ^" p
}! [' R- k( I& G9 A4 W5 `
//+------------------------------------------------------------------+
/ a+ D8 {1 W8 V: w# @/ L' H//| virtual stub for PredictPrice (regression model) |/ E& u$ \/ U6 Y! ^7 D- q F+ B; R
//+------------------------------------------------------------------+
3 E: C. W+ y3 W l0 Wvirtual double PredictPrice(void)% e$ j g' h* ^/ P5 i! v
{
; w0 g& y# G6 f& `6 n) U: greturn(DBL_MAX);
$ {% u' w( I& i8 C j}
: P9 v# M& k/ Q9 u& v0 s+ [( q//+------------------------------------------------------------------+* b9 P0 q8 l: f$ ^
//| Predict class (regression -> classification) |
7 R& m, N; Y% k//+------------------------------------------------------------------+0 T+ }$ W' N! Z0 q! h5 {/ d0 C# B
virtual int PredictClass(void)
/ \5 x$ E% H) g( X7 Q/ G{9 |- `7 A! F. | F4 t5 a5 _. l; A
double predicted_price=PredictPrice();8 S4 {. F: K# Y5 Y) {" \
if(predicted_price==DBL_MAX)
* q, ?( O5 |! V9 K, T) ]return(-1);
) x, ^: f9 s7 u9 u- i7 `7 R3 |int predicted_class=-1;
0 u: e2 o2 h1 E+ Q+ K, Hdouble last_close=iClose(m_symbol,m_period,1);
1 {! W, Q& }9 ^7 H& V, O) T//--- classify predicted price movement
7 h( u) d. o) E4 T5 Z# Y$ Ddouble delta=last_close-predicted_price;5 w9 ]/ Z. q7 T6 Z; }1 W& ~
if(fabs(delta)<=m_class_delta)
# f6 \4 H3 b3 ]: ]predicted_class=PRICE_SAME;
0 X' P( j' o: |+ aelse M* N' q$ ]% D
private:
8 a- h$ q, }1 |/ h0 rint m_sample_size;
7 r6 c( P7 q5 N7 h& `//+------------------------------------------------------------------+
1 g+ v @7 ~- J5 J6 C6 nvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)0 @0 w5 X3 [- Z, T# F: U: s6 z- `
{' J. j( R) i0 C+ i {% [' j
//--- check symbol, period, create model
. v; W4 |9 H. q) D$ t( ?if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
& x& y" L. R+ {{
/ T( L: K2 Q) q0 h6 PPrint("model_eurusd_D1_10_class : initialization error");) a. q, J# d- j( H, _8 j
return(false);
2 E0 R, d; m/ j3 E3 D- S}
4 P# t3 N4 A+ L. C9 h/ D& D9 A& n) T- L//--- since not all sizes defined in the input tensor we must set them explicitly7 D- O @$ I7 Y* |/ @% I
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
4 y: m! i' I* _, `const long input_shape[] = {1,m_sample_size,4};& l* l# ^/ L; D0 G# ^
if(!OnnxSetInputShape(m_handle,0,input_shape)); u7 r8 `5 {5 c! g" U0 {3 ^& |' w1 k
{; Q e" P4 p& V4 K* \& U6 D% x
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
/ P6 @1 b4 p- D, E5 A% ?! Kreturn(false);
1 A) {3 b% T5 d/ g$ g; z, k}
% F- F5 l, k# q* L' h9 M2 L: S2 t//--- since not all sizes defined in the output tensor we must set them explicitly! U O# }) S( m! L z
//--- first index - batch size, must match the batch size of the input tensor
, ]4 F9 f5 y: `//--- second index - number of classes (up, same or down)2 l7 c! o2 u6 u! j/ _8 |
const long output_shape[] = {1,3};
* v+ m( q, g! @# o; c& Z' Z+ yif(!OnnxSetOutputShape(m_handle,0,output_shape))
3 [ U) C; \3 i1 @1 M{; h. }3 ~" `4 d
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
+ U% Z# W( e ?5 U1 m( r* S; yreturn(false);0 S g+ |' S, K. o, _
}
5 A8 H% L& w5 p, @//--- ok" J1 L$ @; P) ]# P3 X
return(true);
5 z& r5 P9 i9 J# c! o, B}! J% C: I7 U1 s8 H4 O# P6 c
//+------------------------------------------------------------------+5 s- u& m' w* `% S+ c6 ^
//| Predict class |' w& n4 x, _2 J9 R9 {
//+------------------------------------------------------------------+
2 Q) y5 [5 p# ?' `9 svirtual int PredictClass(void)
) d" P9 j9 K& ]% [5 ?{ |