1. 我们会用到什么模型呢?
5 _1 t+ c7 \2 L x4 ]1 m在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。6 t& K# p9 d; M% t2 M
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进; F/ s" v( G7 i; z
//| https://www.mql5.com |1 ?) B$ u* R' O+ r, `
//+------------------------------------------------------------------+ `! a, [/ r- p: t& r* ^+ I U/ C
//--- price movement prediction8 H% ]* X- S3 m+ k
#define PRICE_UP 0
1 @$ d5 @1 n) V. x0 h#define PRICE_SAME 1
! b1 c5 K9 k' T9 ?" f) |#define PRICE_DOWN 22 h0 G) z4 R& T6 J2 o4 M7 C
//+------------------------------------------------------------------+' R4 B" r! K! u( Z) Q) M5 C
//| Base class for models based on trained symbol and period |$ r) V( a! y9 T' O- `0 ?
//+------------------------------------------------------------------+7 k1 w* `0 g5 ?* D9 d& T( I
class CModelSymbolPeriod9 O3 b& M$ i7 d0 E3 ~* H% u# [
{
+ @2 o* G3 t3 R7 J! Mprotected:7 |9 s% H! U! e5 w ^
long m_handle; // created model session handle# T& n- l0 o0 q( B' D$ r* U
string m_symbol; // symbol of trained data) }- Y: k5 d( {! S, T
ENUM_TIMEFRAMES m_period; // timeframe of trained data
5 e/ T+ G# h N/ ^8 Hdatetime m_next_bar; // time of next bar (we work at bar begin only) K; a0 p, C" Q) Y4 I& H
double m_class_delta; // delta to recognize "price the same" in regression models
! c# L+ Z# r$ E& a; g- F' m# Npublic:+ ]" q$ E5 N- h1 @& e" t! w
//+------------------------------------------------------------------+
' T) t+ |& r; X3 T" a//| Constructor |! t3 o4 z5 h- c, h& e: r" k% ^8 u
//+------------------------------------------------------------------+
) p3 |) ]4 G( v- g! jCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)6 K' C- E" a4 T8 \2 ^
{! `! ~# q1 {6 L+ W: s
m_handle=INVALID_HANDLE;" K+ X" M. s) h! y; n- k
m_symbol=symbol;: G6 m d$ U9 Q) j% E
m_period=period;9 }! D8 O/ d, x3 o, W6 {" Q( g" ^
m_next_bar=0;0 W/ ]+ A* i9 y
m_class_delta=class_delta;4 N) I o+ x9 m' k; K
}: W% l8 [- a$ Q5 i; \2 a
//+------------------------------------------------------------------+# b( Y% g. p$ Z* I2 _' P5 [# [9 |
//| Destructor |
' G% k# c& E" u4 [//| Check for initialization, create model |
$ h- N, q. ]+ h7 T//+------------------------------------------------------------------+
& R$ Y1 i5 m' Sbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
1 P( a4 |+ l) q, U; ~6 A1 G{
( I1 N6 [* q' u& P1 G! A# l//--- check symbol, period$ ?8 l, A6 N! w) O
if(symbol!=m_symbol || period!=m_period)! _3 _5 C! y1 {! T/ e3 i
{
9 Q6 K% R1 L0 F( J v0 qPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));7 t0 e. X, p) f. j
return(false);
& C4 C# u: ?9 ~/ F3 A}
0 A& b; `* }; ^+ @& i//--- create a model from static buffer1 c: A4 ^5 `# O& n
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);3 v, [: W; k0 ^
if(m_handle==INVALID_HANDLE)9 ^4 p3 K3 f0 p6 F9 e
{
5 m3 Y% \' H* bPrint("OnnxCreateFromBuffer error ",GetLastError());1 g3 S- I0 \2 ^4 ~
return(false);8 `7 N% p7 y4 E2 V
}
+ a( ~$ A# @1 }- Y2 O2 R//--- ok
7 ]! f. B) v, a. @ k4 F T! j! xreturn(true);
( N& c1 o. i, C, _( w}/ L s; W' T( d7 x) `
//+------------------------------------------------------------------+- b' _8 n# I6 Q8 `$ A
m_next_bar=TimeCurrent();
- \( \% c. L+ ]' g! }m_next_bar-=m_next_bar%PeriodSeconds(m_period);; x# d# v: f; F' M5 ~
m_next_bar+=PeriodSeconds(m_period);
) m2 T2 M2 r. }, @: @9 w# f//--- work on new day bar- a3 d1 F- e s0 q' m
return(true);4 E, R/ q C4 ^3 @1 ^( p
}* C0 }6 x( h/ a2 ]7 n9 I4 O4 t+ @3 G
//+------------------------------------------------------------------+2 S4 W0 K, N9 E: j4 t* Z+ t" S* t
//| virtual stub for PredictPrice (regression model) |
% U0 k. [- H3 E//+------------------------------------------------------------------+5 k5 v% Y1 q* ~ h) m
virtual double PredictPrice(void)
$ c) F" s$ m1 o9 C# `* J X{% O, x" p* A7 ^
return(DBL_MAX);% Z; E" a8 n% b
}2 k( |- X& v+ i; a; h. D+ X
//+------------------------------------------------------------------+: @+ T. F( l! V) ~; E
//| Predict class (regression -> classification) |2 `% T) u: J( o a4 |, o+ O
//+------------------------------------------------------------------+
5 N/ V4 q1 P8 ]- Y" f* x( Hvirtual int PredictClass(void)
1 W; m+ c0 g ?& k. N{
# g- l' a1 O! [- ?4 pdouble predicted_price=PredictPrice();& |- ]& b @5 z; W1 b9 l
if(predicted_price==DBL_MAX)$ m/ F& P8 D& ?! I0 P
return(-1);4 ]. i2 F9 _" \# F/ a- W
int predicted_class=-1;
6 m. y) z h# |double last_close=iClose(m_symbol,m_period,1);
+ b! G6 Z% \8 Z//--- classify predicted price movement
# ^ G" F" f( R6 q, vdouble delta=last_close-predicted_price;* `- K' B/ p6 l7 G1 p. X
if(fabs(delta)<=m_class_delta)
: Y4 q3 L( H% W/ ~7 s; o" ]predicted_class=PRICE_SAME;& ~2 R3 @/ O% a' _" R
else
! {( i' T, D- aprivate:3 Y1 S0 ?" ]/ {% x0 f5 F
int m_sample_size;& v4 d8 k3 t, @: a
//+------------------------------------------------------------------+
- d6 R$ k( k; g' b0 nvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
! Y; |3 x% a' B* {& P% t{
( Y! F" z2 m \; d4 Y6 @0 t4 L//--- check symbol, period, create model
, X& E3 U6 b& zif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))$ h: ~9 A7 H# a$ i7 ~/ J4 R
{) \: j5 S, ]* Z& b3 Y1 u
Print("model_eurusd_D1_10_class : initialization error");; n8 m# n% [- S8 j3 N
return(false);, ^. R* J, o D7 Y3 `
}2 A9 p1 ^2 q, P- V
//--- since not all sizes defined in the input tensor we must set them explicitly% v- ]3 Y- {- a6 x
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
0 L' r, T: }- \- X" nconst long input_shape[] = {1,m_sample_size,4};
+ Z" M5 S# n. _- Dif(!OnnxSetInputShape(m_handle,0,input_shape))( E5 c: L$ X E: O( ?+ ?
{
4 n8 ~, E8 t8 o: u6 t* ^Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());, F6 X5 q7 `9 \: L
return(false);
. y, B3 a7 B- Z2 }" g9 p5 j}& X4 j2 p' u) O% t3 I
//--- since not all sizes defined in the output tensor we must set them explicitly J) V" E/ x% \, k
//--- first index - batch size, must match the batch size of the input tensor& u4 t1 _* {1 g8 D3 ]% `: d+ e1 Q
//--- second index - number of classes (up, same or down)6 }; A P0 J* h6 @6 ~
const long output_shape[] = {1,3};# i0 i( j9 m$ x. m
if(!OnnxSetOutputShape(m_handle,0,output_shape))% q0 K) z' h5 T# i0 f1 r6 q1 [
{" p/ w! J6 c9 b0 C4 Y$ |
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());" ~/ m* A$ y6 M9 U
return(false); n; Z6 Q1 o( ]0 D* [
}
7 _ x! F; w h6 a& \/ U//--- ok
/ L+ P/ u+ k) }return(true);# h0 s# x6 m$ @" r0 b
}9 F0 J& y2 Q! @: ~: o6 d7 b2 P
//+------------------------------------------------------------------+0 x- }! {0 A4 v0 a
//| Predict class |* e0 Y+ C/ P4 }* o' {1 @
//+------------------------------------------------------------------+
' S8 \5 I/ q6 L. |$ }& Rvirtual int PredictClass(void)
# ] Q4 m% E9 Z' o, q{ |