1. 我们会用到什么模型呢?9 @) {7 V! W' h) U, a5 `
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
) q' M" V( |$ Z( Y: T$ |+ t我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进. G' ]5 R, t5 E7 v( A( u
//| https://www.mql5.com |
! O/ F* ~6 I" w" c# p//+------------------------------------------------------------------+2 Q; J' s6 X3 W' L5 W# d/ _& j* p
//--- price movement prediction$ N+ M4 l$ H( I( j5 ^
#define PRICE_UP 0' D+ |* G. S; t* h
#define PRICE_SAME 1
# e: | ]9 ^- j7 p: f5 M#define PRICE_DOWN 2
\ Y* M+ F) D, z# ~; H//+------------------------------------------------------------------+4 \& t( |" O7 C% n' `2 u% h
//| Base class for models based on trained symbol and period |
9 _" ]3 y) {2 H//+------------------------------------------------------------------+# c6 A/ P) i# H- b3 |3 L, T! m$ t
class CModelSymbolPeriod
$ t4 d: I' B- n4 e& l{% _* B( @: D1 `! n" e: i& X+ l
protected:$ K) K8 k; p+ o! _2 k0 R. ?4 q
long m_handle; // created model session handle
! a9 P1 @/ N C3 O6 ?4 `3 K3 L; ]string m_symbol; // symbol of trained data
; c( c! o$ ` iENUM_TIMEFRAMES m_period; // timeframe of trained data
6 h- D/ n: I% m1 vdatetime m_next_bar; // time of next bar (we work at bar begin only)
. L7 |0 o! C4 ]+ Tdouble m_class_delta; // delta to recognize "price the same" in regression models& @2 [9 \+ h4 i
public:
* e5 i1 f, |: L) m//+------------------------------------------------------------------+
+ A( E5 I0 O/ A0 z r0 }//| Constructor |
& C; w% h9 |/ u* ?4 a. \//+------------------------------------------------------------------+" z. L! U( l, k
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
d9 \0 K- t" W' L{) J& [: ]* |% T( ^& ~( U7 X) u
m_handle=INVALID_HANDLE;/ |; ~5 U7 @6 W1 o
m_symbol=symbol;
) X$ A# _4 R+ k" r; r2 E2 cm_period=period;( o) p& q& } P- q X4 z P
m_next_bar=0;
/ ~6 w! E+ o4 wm_class_delta=class_delta;3 H$ h5 i" o, ?
}2 W1 F. {/ W" s6 v. W. _
//+------------------------------------------------------------------+
+ c+ [0 U% J3 o% b' b; y+ Z, ~//| Destructor |! R* P" t/ n" J6 o; P* e; F/ K
//| Check for initialization, create model |2 m( e' t6 k: y. O
//+------------------------------------------------------------------+6 I2 |7 B0 o$ s, r
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
" V8 I! Q) G2 Y8 E/ _{! _8 n8 Z3 R" I3 ? \
//--- check symbol, period
8 C$ Q* B% I7 o: b' D o+ [1 b8 `% o5 `if(symbol!=m_symbol || period!=m_period)
, g, R; S4 L+ i4 M0 r- C- ^{9 I- N. n/ E, ]; K. @/ s
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));; u8 q+ s! N- t8 Q
return(false);
4 h# I. n f0 ?- q$ }7 v}
2 X- S6 t$ X$ ~2 V//--- create a model from static buffer
; U- d, o+ o& j( d+ `& ^m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);' D; \5 A+ O8 r$ P
if(m_handle==INVALID_HANDLE)
5 a9 u1 ]9 d& `{3 M+ W! G6 r& W0 ?0 s2 Y) h# g
Print("OnnxCreateFromBuffer error ",GetLastError());% b! b( R" w" k' S7 H5 x
return(false);
6 F/ \6 [9 z+ O' b) a}3 {1 y+ \' B9 D: Q3 N& U
//--- ok2 Y( i: V5 A* P3 O1 E: ~
return(true);
; j; z% M+ r9 S, r/ Y}1 Q m! t3 L" P3 D) S
//+------------------------------------------------------------------+
' G" Z8 I: y7 g; H, f \- fm_next_bar=TimeCurrent();
( L |' l# q1 n L$ V3 f0 pm_next_bar-=m_next_bar%PeriodSeconds(m_period);' I* ?. X$ ^+ P# p% l- D& Y
m_next_bar+=PeriodSeconds(m_period);3 R9 M* O1 Y8 ` W
//--- work on new day bar0 w; J: I# w7 e' j9 l& S9 m
return(true);
# {2 L: G6 `1 s8 M, o}/ I* `6 F* l, _* r% D( Y
//+------------------------------------------------------------------+- e1 n- p* o9 Q/ z0 O2 ^. o
//| virtual stub for PredictPrice (regression model) |! L8 m9 Q8 |, j6 D) k, o
//+------------------------------------------------------------------+
8 n& b7 w9 O% w5 E& Dvirtual double PredictPrice(void)
; G( T; ?, L* z{
2 w, i, a, k0 M, s1 s' xreturn(DBL_MAX);0 {8 e& @ x, `2 W% n. t0 X, Z; u
}" x+ o! y$ L. N4 }' N
//+------------------------------------------------------------------+
+ N+ A5 @% b, a V( l# `& |//| Predict class (regression -> classification) |1 z6 w" r& B/ {4 V
//+------------------------------------------------------------------+$ }6 Z+ y- Z. ~) |
virtual int PredictClass(void)
/ l! C* a! T& u- M{7 m5 j5 U' Z' Q1 {. B
double predicted_price=PredictPrice();
! A3 ?- l7 @& H# ~7 {) W; f- @# Lif(predicted_price==DBL_MAX)
! A% v' i6 m& b9 h2 q' f) I' o6 Vreturn(-1);; C3 \$ f6 _3 ?& ?2 ~
int predicted_class=-1;
3 u7 P. d% v) i. _6 v1 Jdouble last_close=iClose(m_symbol,m_period,1);
' H4 {5 x1 i o7 y- q# \//--- classify predicted price movement4 D6 j$ h0 H# Q3 T: n( N
double delta=last_close-predicted_price;
- @( S8 n* h- U A5 c7 ]! [if(fabs(delta)<=m_class_delta)8 p+ c" _9 k9 c' h- _
predicted_class=PRICE_SAME;# w% S/ d5 D$ S% U
else( d7 C, Z" e" i3 j
private:
2 x2 H; [( A4 p: h9 I( jint m_sample_size;2 L; K. x7 p8 j3 W& k W' S5 |* T
//+------------------------------------------------------------------+
% [4 n7 y- K8 ]4 a, ^) ^virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period), |! I1 a% q( S3 V% `$ H
{& u9 \8 q* B, ]7 B8 n7 {* J
//--- check symbol, period, create model
( e4 M. K$ \, T1 N }0 _# l- pif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))4 I1 T4 f' S% C* x2 K
{
# U! C9 z ]9 n) j: B5 B- [Print("model_eurusd_D1_10_class : initialization error");$ I% z) E6 [, s; Q+ F
return(false);3 s( b ]1 x: {! X( Z
}
. ~/ L' _: Q3 g/ v8 e$ {//--- since not all sizes defined in the input tensor we must set them explicitly
$ \ w8 M8 |0 p# m" a//--- first index - batch size, second index - series size, third index - number of series (OHLC)# O0 p# z6 J5 b0 T& ^0 y. s5 G% v1 g
const long input_shape[] = {1,m_sample_size,4};
) h0 C& J$ q/ u0 n5 Mif(!OnnxSetInputShape(m_handle,0,input_shape))
7 o, Y+ ^9 e* O7 e{
. t0 F! W7 m! nPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
2 d% |$ |0 k% L# n" ?( L1 `. [$ ureturn(false);
# O. V0 j& J5 s' [1 q& B! l, {8 i}
: J' \. t D1 R6 m' t( C( N//--- since not all sizes defined in the output tensor we must set them explicitly* H& U0 }/ ?$ n; r2 S6 L! c. L
//--- first index - batch size, must match the batch size of the input tensor
/ z8 x9 Y/ T, ?6 j# a; H* R//--- second index - number of classes (up, same or down)* F% v' ]! K% n! N; [, f
const long output_shape[] = {1,3};
5 z- }" P. h! K: t0 T4 t" j1 fif(!OnnxSetOutputShape(m_handle,0,output_shape))
, E) K0 G" p5 H+ x! J7 L{5 f! U0 Z0 ]+ w+ V
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());; O) |/ B; B: `. m: y* O
return(false);
/ o$ |# N- v. C- `}
% q* i% }- F# n) r//--- ok { v; f9 P: @' I' W. l2 ^
return(true);
4 u9 \9 P% k( C$ \) T5 d0 b/ ?( c}
8 d% y: W6 c9 R" E$ D//+------------------------------------------------------------------+
5 P1 w! T9 L' p8 }" ~' E//| Predict class |
- _) L, Q0 T$ E6 W+ V' @9 H//+------------------------------------------------------------------+
+ f8 q) G5 }# R* ]virtual int PredictClass(void)5 X% u6 W+ s9 r
{ |