1. 我们会用到什么模型呢?4 u s& ^# b7 S' D0 `# [
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
9 n" r5 `: K) w: I% V" M我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
# l \! P9 ~1 i2 Q* s& b//| https://www.mql5.com |& {+ N4 Y4 N9 p) o% ~ V. i( i
//+------------------------------------------------------------------+
' z2 c W, |- Q1 ]9 R7 |//--- price movement prediction
% I. h8 S* L; D! _1 o#define PRICE_UP 0% ]. }1 T5 e3 T: K/ g# l8 v/ R
#define PRICE_SAME 1
) u9 g. B& e P#define PRICE_DOWN 2, j& U" q& d2 U' E1 s
//+------------------------------------------------------------------+
" Q3 M* b, u0 H: |4 M//| Base class for models based on trained symbol and period |6 R1 Y5 L2 J, a4 k* r
//+------------------------------------------------------------------+; p7 `2 ^8 H/ A8 H3 r7 i
class CModelSymbolPeriod+ p2 [- Q v" i5 t B/ V/ A( L+ O% D
{
2 L) d6 i6 u& G1 rprotected:
) V, o4 q4 h/ n6 Z5 m5 [: jlong m_handle; // created model session handle
8 K2 Z4 e' y# {string m_symbol; // symbol of trained data5 c6 F# ` ~# h6 y9 v& N
ENUM_TIMEFRAMES m_period; // timeframe of trained data
! p4 a- C' v7 r& Adatetime m_next_bar; // time of next bar (we work at bar begin only)- ]) ` _- }+ v, d
double m_class_delta; // delta to recognize "price the same" in regression models
7 y8 e# U% l3 e" G7 w/ xpublic:
; J2 }; Y6 u, ^4 n//+------------------------------------------------------------------+
; W: M* l* B: n. J; U4 G+ T//| Constructor |
& z4 v' ]) \7 H, p//+------------------------------------------------------------------+
6 H9 w! V, K& |. U& iCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)3 c. X" X& c( ?
{
6 ]) r% p7 h- q- u* ^* Ym_handle=INVALID_HANDLE;6 U; V- p: Q: I) r' G0 C
m_symbol=symbol;
% Q! \! q* U( k+ B1 X Cm_period=period;
_- O" u# {8 r; f8 @8 Sm_next_bar=0;
$ i3 \7 D2 `2 h; em_class_delta=class_delta;" {7 Y+ S1 ?7 J9 A
}% s9 x( s; O2 G6 J6 d, `, \; p2 o. T
//+------------------------------------------------------------------+3 f8 s3 B. e$ }& d& ^; p( \) F3 G
//| Destructor |+ K' H' J. Z6 E- F! v
//| Check for initialization, create model |3 L# W; f' r) W% W& P
//+------------------------------------------------------------------+
3 o4 e1 P8 W# H: D# D! ^ e- L$ a1 Mbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[]) }$ J G1 z2 ] W) _) q
{
3 _$ [7 v: Z$ B/ f; _* i- a/ n3 J//--- check symbol, period2 q+ t8 l7 g! ~. T- E
if(symbol!=m_symbol || period!=m_period)
' }: Y2 X0 A6 t) z{8 I2 P" b0 w0 g. e' W5 `4 u
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
; b! m5 ], A( |8 rreturn(false);
; V( u. B" |# R9 A; j7 }}- z( e; x" G0 M( X7 R) ~
//--- create a model from static buffer6 N( D) z* W# h: Z8 K X: p0 p Z
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);: q8 f1 {8 M f$ r( C* j4 y, @. O7 h4 L
if(m_handle==INVALID_HANDLE)
! j* }* Y4 ^) _+ G, M0 n{3 d5 o* K2 R$ U; r0 F% M
Print("OnnxCreateFromBuffer error ",GetLastError());2 [, d$ W8 V4 ]
return(false);# G C- m8 c" }+ J4 @
}/ m3 C6 N, w5 {- l- ?) ]/ i3 {9 H
//--- ok" ]2 T; G( j9 }3 z
return(true);
- P* m5 V5 b) L. k+ N6 N, k0 T* m9 J}
' L) g/ q% b8 @) m- J: t//+------------------------------------------------------------------+( q* t) U7 U: K, l+ w
m_next_bar=TimeCurrent();* |4 @/ l! b7 p0 M* R( p
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
& i' a P; p- Em_next_bar+=PeriodSeconds(m_period);
8 [" B( d6 s+ w7 l# G' l( Q3 X//--- work on new day bar3 e$ X9 O+ I. J
return(true);8 {4 a. `! E" \ _0 H
}
+ W* J7 ]2 A# G0 A//+------------------------------------------------------------------+# V7 a& K; B! M
//| virtual stub for PredictPrice (regression model) |
' k1 @3 k& b8 b//+------------------------------------------------------------------+7 X% J3 E: m# h( i
virtual double PredictPrice(void)4 y$ J4 U4 T/ |* d- C: Y
{. ?$ X" g. D; K* Y
return(DBL_MAX);
r; i# _" T* N1 W}
& W) L' p" o6 L: Y f6 v) [//+------------------------------------------------------------------+6 _( }, a: Q* g" d2 T0 d
//| Predict class (regression -> classification) |4 W: t) V/ q* p/ K( P6 Z A1 l
//+------------------------------------------------------------------+
% p: _# H# n7 q4 o1 z! O/ {, Dvirtual int PredictClass(void)
; D# P: v4 u3 f5 D M9 d* e& f{* N8 }. g, g6 \6 Z5 A
double predicted_price=PredictPrice();8 T" n' Z9 B7 ^' H" X( O- m
if(predicted_price==DBL_MAX)4 r' C! K0 l# r- {) i$ o
return(-1);
2 c/ e3 R+ K6 V0 Z* f! ~int predicted_class=-1;1 w n! g% c6 @: D* [4 A3 x
double last_close=iClose(m_symbol,m_period,1); W& y! g0 W0 Z: o0 C- {
//--- classify predicted price movement
0 R& v+ x- j) Y" D, \double delta=last_close-predicted_price;5 g: ]! P# j/ A9 R/ k
if(fabs(delta)<=m_class_delta)1 v8 h2 Z( ~$ }( x3 `! Q m- e
predicted_class=PRICE_SAME;" U0 G/ {& A& I9 ^' i
else/ q% F; _/ V3 j, V0 M
private:3 r$ V) B5 j- ~+ {9 M
int m_sample_size;
5 a0 Z! m* B/ B& ^- v+ \//+------------------------------------------------------------------+
$ T! K- |0 V( p/ M5 \virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)6 y v g: P' N. [- o) E% J' A9 M4 [( x3 o
{
* j8 I. ]! N6 }+ B& g( r& z# e+ ?0 u//--- check symbol, period, create model$ r" `2 K( h/ } s9 o
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))8 b/ E8 m1 p$ m+ v
{
8 ~! g6 O6 `5 iPrint("model_eurusd_D1_10_class : initialization error");
0 X( `* Y' _4 E9 r7 [- B5 C% e4 kreturn(false);1 k b+ G; T4 |8 k: h" J
}" L; t1 {- u/ H; Y, A) r- b
//--- since not all sizes defined in the input tensor we must set them explicitly
+ ~7 O* _2 \0 h0 I9 s5 Q& r//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 J2 n9 {/ y% H( S" o+ G9 zconst long input_shape[] = {1,m_sample_size,4};4 R" k) {) x+ N% E5 z8 }3 }
if(!OnnxSetInputShape(m_handle,0,input_shape))6 J; f" C( t2 w7 h
{
2 f% L+ q( o2 y! \5 VPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
* z; w4 C; W2 D. V$ kreturn(false);7 J% {" t( A/ ]5 p' p9 Z5 ]1 N
}3 ?4 a! m! a. l H5 j8 F. p5 U% Z
//--- since not all sizes defined in the output tensor we must set them explicitly
/ B% e0 F0 a8 L8 M) b6 {//--- first index - batch size, must match the batch size of the input tensor1 t/ V) j. u+ ^' _/ \, {
//--- second index - number of classes (up, same or down)5 l9 P7 w+ l8 y9 g M/ o- E
const long output_shape[] = {1,3};& P2 S# I$ o% ]$ b
if(!OnnxSetOutputShape(m_handle,0,output_shape))
9 L( y; r, A6 f{
* [' `+ l Q& ]Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
" ^; q0 m! w6 {9 j- g1 ?return(false);* [& T* A% C! d
}: @; X7 L2 L1 n, `6 W# N3 C/ p
//--- ok
V+ Y+ A0 b0 E6 w7 qreturn(true);
* l) u$ P, s& |0 }% Q}
# f0 w- {' y' F) {% U- O7 J% Q//+------------------------------------------------------------------+5 w4 q( c2 R; h, Z( q" @9 Y
//| Predict class |! c/ y1 \# p$ b
//+------------------------------------------------------------------+' ` C) U( O5 [' f8 v& S' o( X
virtual int PredictClass(void)
: G& W: @( E8 R6 T{ |