1. 我们会用到什么模型呢?$ c9 {& n) M/ E: R3 O( m
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。( I. i4 `& H ~. N8 @
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进7 J# n3 m/ |% }6 z* A1 c2 Q
//| https://www.mql5.com |
% U; @$ b( W, b6 Y0 E//+------------------------------------------------------------------+
9 D% S: T( ?/ e! N# k//--- price movement prediction
5 v3 J1 h% W, R4 E/ h#define PRICE_UP 0
* B+ X( }( n! h5 o1 h9 M#define PRICE_SAME 1
4 X; \# R! X3 L; I+ i#define PRICE_DOWN 2
& J) x( @$ k+ v! w, [//+------------------------------------------------------------------+
8 @. f7 O t5 D- t2 S4 i; A- t//| Base class for models based on trained symbol and period |4 Y( n0 R e9 e
//+------------------------------------------------------------------+
6 q2 e9 ^, t9 u* V( D# Kclass CModelSymbolPeriod! g3 g9 Q" N6 g4 q% S7 K3 {
{
6 n) t4 W1 i, k, @( Q k0 R, Eprotected:4 u0 G% o2 \9 c- S) t u3 d
long m_handle; // created model session handle
/ J' E! h# E8 |" C+ `" Kstring m_symbol; // symbol of trained data
0 f9 g$ Q. M! RENUM_TIMEFRAMES m_period; // timeframe of trained data
# u: [! T2 g' i- N) ]+ tdatetime m_next_bar; // time of next bar (we work at bar begin only)
# {! e g4 F; c0 g! _double m_class_delta; // delta to recognize "price the same" in regression models H, P7 r1 a) q. t
public:. I7 \) b I. Y V! ?$ b$ N
//+------------------------------------------------------------------+
# }0 e6 C% |' m: M B* |$ Y+ m9 d//| Constructor |% C% w+ {' l3 `* M& ^
//+------------------------------------------------------------------+& ?1 u# w9 Z$ A- Z. e% C
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
8 y( S5 d2 n& n% c; Z' h{9 @$ N) W9 }% z6 D" P' v* D
m_handle=INVALID_HANDLE;# v) P* V# l k D
m_symbol=symbol;- L" X& J5 E) t( B0 f' a6 S
m_period=period;" w' K# X( s0 P+ N' v. {% o0 i
m_next_bar=0;! ]6 t# d! \# i# Q" `9 i
m_class_delta=class_delta;
) v- n4 D/ U+ L! g, Q# y$ z}1 z6 }7 ~5 ~$ t8 u$ ~
//+------------------------------------------------------------------+
- i# e% s: d, ~6 x p) m9 i2 r//| Destructor | u+ l3 e1 g& J$ J$ T
//| Check for initialization, create model |5 l* Y% a4 |, T( m2 K
//+------------------------------------------------------------------+
! ]4 J2 U0 L" s- ~, {# S( {bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
5 I* ]9 V0 L' K1 d{
5 Q! L a/ @6 B( x/ Q//--- check symbol, period
! Q* P' u* z9 D( u# {if(symbol!=m_symbol || period!=m_period)
* d) v. f$ `' [( Y0 u6 {{; y- E$ [; k& C, w! b& L5 j
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
3 b( ], h3 f$ e) B0 L1 Y) Ereturn(false);8 V+ h* c* M/ ~7 c3 b, y) Z
}" K3 M' y8 v) w4 \; S- s- E6 v
//--- create a model from static buffer- ?& q) k% ^! S9 p. ]9 e
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);' ~% v! y3 G7 c1 s
if(m_handle==INVALID_HANDLE)
: \6 S/ X: L) E8 v{/ U$ o9 y" ] p6 v
Print("OnnxCreateFromBuffer error ",GetLastError());
`' m5 r4 }, i4 m7 D& ^8 ~+ C" [/ ureturn(false);
, B. M. p3 E( y6 U1 A( ~1 s}
/ }0 M6 M, A' `1 { z& r) Y2 }//--- ok
5 w7 m; G4 |/ F: a8 yreturn(true);
4 a; t* O; S/ K) \* }}
( }- @$ ^0 z i, j//+------------------------------------------------------------------+
* O1 ]. x1 P& ~; p9 j6 P0 {3 l/ k7 `7 T0 }m_next_bar=TimeCurrent();6 p8 o& N( z0 Q5 C
m_next_bar-=m_next_bar%PeriodSeconds(m_period);# S% B! j) T0 u: ^' k/ _1 I7 f6 o
m_next_bar+=PeriodSeconds(m_period);
, X: l' _( t+ l1 t0 x8 d q//--- work on new day bar0 b2 N) B' X; A, h1 i0 S# e! z
return(true);5 w2 ?& e: V$ K# w: Y2 I" Y! W
}7 P% P2 Z7 o" \, v) ~
//+------------------------------------------------------------------+
6 I+ v2 ?( ~2 ^8 J//| virtual stub for PredictPrice (regression model) |
7 `' r1 |3 {& I//+------------------------------------------------------------------+( \0 J$ H) C1 h& q# G6 J" O
virtual double PredictPrice(void)2 m: F, {) m; E- Y, l# r
{- \' N9 b: y& o6 U
return(DBL_MAX);, P I" a y, |* V0 t; G( ~
}
& G( ?6 `3 ]) S6 d o9 ^//+------------------------------------------------------------------+
+ j5 J# p) L; i* p& r! Y4 f( @//| Predict class (regression -> classification) |- m8 H# T; M: z g, @* @7 ]: m
//+------------------------------------------------------------------+
* X' Q' b* j/ U5 i8 i* g( p3 Ivirtual int PredictClass(void)
) C+ a9 o) w k" }; P{6 V' P% O L# o, H. O! S1 v; h+ y
double predicted_price=PredictPrice();
" V1 F6 }6 r5 e5 I' Zif(predicted_price==DBL_MAX)
2 x9 x# E1 V: Y% u& o' breturn(-1);
( ?5 w7 s; F; M9 {9 B, Lint predicted_class=-1;) C4 K5 ?, f! R" _* {! z
double last_close=iClose(m_symbol,m_period,1);
9 Q* l" _: Z0 u1 x7 G& F: o1 q% |7 i//--- classify predicted price movement1 @/ ~( ]% W) k4 h- X8 J# K
double delta=last_close-predicted_price;3 Q) b/ l* @8 a% {# v0 l
if(fabs(delta)<=m_class_delta)
7 z4 X3 w. e9 `+ U( {: k1 cpredicted_class=PRICE_SAME;" ^6 O2 R' x' C9 p# P2 u( P
else% y4 B ?2 c7 q8 _
private:
3 R1 u5 p( ^+ ]. R/ u rint m_sample_size;0 O9 ~) _& g+ l3 |
//+------------------------------------------------------------------+
, Q7 S# g5 h6 i4 `0 ovirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
+ r2 @+ U( X0 F{
/ G& b. L2 n+ }0 O R, W//--- check symbol, period, create model% r9 U+ T% M* ^0 E1 H) r2 [% N* x
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))/ ~2 z) b+ e M% G& N
{6 i$ D1 v- @, Q1 m2 l" M3 X
Print("model_eurusd_D1_10_class : initialization error");
/ i0 E) ?, x) {return(false);5 A* g* ~5 \9 A5 m. ~ E; \# h- I
}
2 E# O5 ^' m, o: y, J% |, C1 e//--- since not all sizes defined in the input tensor we must set them explicitly- z6 F8 c/ Z& T& A( f
//--- first index - batch size, second index - series size, third index - number of series (OHLC)# V" ~, K1 c# F! F2 C
const long input_shape[] = {1,m_sample_size,4};- a1 v' r; q3 G2 s8 H, r) w( V
if(!OnnxSetInputShape(m_handle,0,input_shape))2 P( G2 ?- \8 s3 C9 F
{
0 a4 |3 `9 R. iPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());6 {& k: f1 T5 ~- m0 P, h
return(false);& l$ T0 z9 ~3 g e+ y# H e
}* j0 ^5 W3 u8 @) k5 O6 l. H: j! B
//--- since not all sizes defined in the output tensor we must set them explicitly
; K8 H1 q( p$ r9 l+ U//--- first index - batch size, must match the batch size of the input tensor! e2 \4 ] x: g$ x2 h; c( n/ [: w
//--- second index - number of classes (up, same or down)
' T- b' N& y5 B- T, t% Aconst long output_shape[] = {1,3};9 h" G8 {& g0 Z; Z
if(!OnnxSetOutputShape(m_handle,0,output_shape))
' G3 P5 U- O4 U1 O2 g" A" ]{$ }4 J: i0 J2 ]2 v! v6 H2 e
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
' m1 [( E% e( K$ O, Q, Y2 Oreturn(false);: k+ I M D( ^
}
: Y0 |3 `5 P$ m- V//--- ok' K+ c& c5 A+ i0 I$ l
return(true);6 ]8 D' z8 ]* u/ m6 S/ U; g. b
}
' n8 T. W6 h, s) }. |//+------------------------------------------------------------------+/ U$ a" ]) j: u6 `) [/ j8 X
//| Predict class |
! y m$ f* [2 ~" `% G//+------------------------------------------------------------------+
& F: F7 ^8 x( N/ Z6 L) qvirtual int PredictClass(void)
9 g, l1 r# ^/ K$ {. p{ |