1. 我们会用到什么模型呢?
$ G9 a+ a `! @' Y3 @在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
; H6 F% z2 s, r ^# ~8 ]我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进5 A, z, Y& v- D/ Z$ ~6 ?
//| https://www.mql5.com |
4 ]! k1 I: k' T y0 E0 v4 s//+------------------------------------------------------------------++ M4 D9 Z7 c j5 S- w5 z
//--- price movement prediction
4 P ~' i% c1 `1 w/ F2 d#define PRICE_UP 07 X$ O( O( K. O, z
#define PRICE_SAME 15 |3 u! S% w$ I; T. `( Y
#define PRICE_DOWN 27 n7 R6 d5 S, l. y. }
//+------------------------------------------------------------------+: x/ {! y F5 \7 e4 D' D! Y
//| Base class for models based on trained symbol and period |
( [' x2 z, B' \$ ?3 h2 r//+------------------------------------------------------------------+4 u8 k: s" {+ b* M% U. ^, U+ A$ z
class CModelSymbolPeriod
$ d2 ~* o7 f1 q) I1 G3 |, T( y{/ C2 h1 }0 o$ q$ N5 {7 d
protected:$ [& h0 V% c' W. ~
long m_handle; // created model session handle
4 F6 z& P6 Q5 estring m_symbol; // symbol of trained data. @4 S+ \; ^' V! F" B
ENUM_TIMEFRAMES m_period; // timeframe of trained data
6 O9 j) F- Q4 t1 d* `' _datetime m_next_bar; // time of next bar (we work at bar begin only)
' F- h' E( }6 }0 o! ]0 s) ^9 wdouble m_class_delta; // delta to recognize "price the same" in regression models6 ?$ m7 |9 i* t8 K9 x% l
public:. D% K) L$ K. {
//+------------------------------------------------------------------+
7 p1 l: U6 q% @) T% V/ j//| Constructor |
5 _8 d2 W0 t6 D7 H//+------------------------------------------------------------------+! c7 _8 ?# `* e# W% O4 R" v) F& ^ E
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001); o; y( w/ O" q' |
{( Y+ [- H# F ?2 A& m R& m" S
m_handle=INVALID_HANDLE;% k' R* m; G6 x
m_symbol=symbol;' z5 w6 V: s2 w2 a8 V- Y
m_period=period;( |# [9 ~$ O) O1 V0 d
m_next_bar=0;2 m& t9 d& T4 Y. J- K1 D4 A- p
m_class_delta=class_delta;
% y) [9 z" J# {: V}
2 m, u" b7 Y. h% F2 V//+------------------------------------------------------------------+
3 U4 S ]3 B, X! h7 P1 t//| Destructor |1 C7 Z) R4 W5 H. v4 W# @" o9 {1 ]
//| Check for initialization, create model |- N6 X6 |5 w2 `$ F& ?
//+------------------------------------------------------------------+
" a+ L6 s7 n% @& z8 h" dbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[]); Y8 i" Q. B9 ]+ N8 n' c" R
{
3 {/ ~5 _4 z9 n7 ?' R# h//--- check symbol, period
$ B+ R1 P) \ [0 p: T! i- d! hif(symbol!=m_symbol || period!=m_period)/ W/ U) h' R6 d, J
{
6 s8 ^' r: [% l6 x2 V0 [PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
5 Z8 X3 |& z- Q Z. V O( }return(false);
! _, ? n: W( k. G9 V}
4 h2 y1 \; ^6 H5 f6 B% s//--- create a model from static buffer
6 ^; z) E1 W: i( ~. Rm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
. T" m3 j y5 O" Bif(m_handle==INVALID_HANDLE)# {9 n5 l, ^3 J) Y$ f4 `* i' u- _
{
0 z, J" Y% @- S& l3 EPrint("OnnxCreateFromBuffer error ",GetLastError());1 k. r/ d% `4 B/ H
return(false);
/ b+ W0 w6 Q; U# Z0 H}
# J# j+ L# l5 }, [; r) h6 s//--- ok
E) R0 s$ ]( a$ i2 K& s4 `* vreturn(true);7 {! M1 I( ` }' X3 n* K' e, A$ h; H
}! o. J7 [6 G, f# u, T
//+------------------------------------------------------------------+: I O+ p, i( S+ v+ }$ p6 ]
m_next_bar=TimeCurrent();
( r6 e, l( t3 g# Jm_next_bar-=m_next_bar%PeriodSeconds(m_period);+ E% V; Z% v4 \/ v, u; S2 m% i1 Y6 N
m_next_bar+=PeriodSeconds(m_period);; j9 F& C, t/ N3 E( B# @
//--- work on new day bar7 z) v* V7 ~1 A# x8 l5 B
return(true);, {( d- l+ l+ M0 |
}
, y0 t* c% j4 `) |& a8 Q. D! r//+------------------------------------------------------------------+
p; H0 j( {% L$ `) f* v: Q//| virtual stub for PredictPrice (regression model) |
' e9 x& i) L/ I1 d( z1 }. V//+------------------------------------------------------------------+
3 b9 Y6 t( f! f+ L+ |% W. f& Rvirtual double PredictPrice(void)* p( d! [$ }: C( Y, P& }
{" P+ Y B2 Z# C) ?/ c5 |
return(DBL_MAX);3 d a5 I6 |! \' U4 d6 [
}2 J% y: b* x0 l! N3 I& T0 x# y6 Y
//+------------------------------------------------------------------+
- q/ H, B D* S3 g' o! ]& Q//| Predict class (regression -> classification) |" ]! Z8 i9 o5 O/ h5 x& s
//+------------------------------------------------------------------+& ]) R/ i# j$ B; Z# T+ ?8 {: z/ ~
virtual int PredictClass(void)
. Q3 n+ R5 k7 p. T{
2 g) P& N% N7 G4 G! J1 [) P. g3 ydouble predicted_price=PredictPrice();' v9 s1 ~7 H+ R" x# z; i
if(predicted_price==DBL_MAX); p$ L# C! O. |( g
return(-1);2 a: P% E, U3 y, c, o1 z3 B
int predicted_class=-1;
! x$ y9 J7 P# S6 W0 o* qdouble last_close=iClose(m_symbol,m_period,1);
+ ?: ~# @! _9 w. c//--- classify predicted price movement% J N1 e w. B( w) V( d- F
double delta=last_close-predicted_price;& ~( s) h' g! R! }; A
if(fabs(delta)<=m_class_delta)
% R6 _6 K1 o( S! K) @7 Fpredicted_class=PRICE_SAME;5 |# x2 M/ Q- A) @* D/ Y
else
; g& M6 e7 x) ^; xprivate:
+ w- l ?: V; J( i! J. Y: uint m_sample_size;
5 E# H$ a, H, C& L//+------------------------------------------------------------------+: [1 B( l, x# U
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)! }5 ~) `' {! Z) ?' _; w
{
4 q8 Z r% [3 [3 x6 U2 L3 e; N) }//--- check symbol, period, create model3 U# y, Z' u4 k- P4 q
if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
/ P2 U" Q' @/ m* ^{
& J( ^% W! l: v! xPrint("model_eurusd_D1_10_class : initialization error");+ p# t: e' a1 K" R
return(false);
- x6 U o8 {+ q. m9 c C}
9 }' R) r5 R' H9 n//--- since not all sizes defined in the input tensor we must set them explicitly
% u& r6 c# x S- k- M3 l//--- first index - batch size, second index - series size, third index - number of series (OHLC)
: L- X* E$ q, G2 n, c3 Hconst long input_shape[] = {1,m_sample_size,4};$ e6 M% O0 k( K' ^0 }' c0 O
if(!OnnxSetInputShape(m_handle,0,input_shape))
7 y, K; I( m3 t# |$ s6 }0 E{
+ Y) r n, J( l( r, `* n' S3 B& ?0 v/ oPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError()); M7 ?, b: [/ a4 Q% C( ]+ R' [2 D
return(false);
% A# z( c: c' a7 F7 _}
- S& D" a" _- k7 t5 M//--- since not all sizes defined in the output tensor we must set them explicitly7 T3 B4 Y( ~# y9 o8 C' {
//--- first index - batch size, must match the batch size of the input tensor* b( t1 e# M# D) S* k; u! ]
//--- second index - number of classes (up, same or down)9 c z$ }. J8 Q
const long output_shape[] = {1,3};: T0 J% p0 q1 n2 D- v, p) M
if(!OnnxSetOutputShape(m_handle,0,output_shape))- u3 Q/ R1 p' T: a, S
{% u! J* _- v, E/ s( _ n% a1 e
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
0 b D/ z5 A* g+ t' i( K9 Z. K* kreturn(false);
" q& C. ]' P! d}9 M8 }) B6 M2 h& e5 e2 g. b
//--- ok8 A& Q5 D1 e* ?( [! L! q, o' s
return(true);
2 S9 G; n) a$ W7 D* u6 q2 b}
( Y8 f* D: D4 A" f+ {//+------------------------------------------------------------------+# L' s' x$ X- C8 G' q$ r* U: ^/ e
//| Predict class |
% _3 }( i1 @ ]$ Y, y1 H0 ^//+------------------------------------------------------------------+
7 g) l" T% {; }* `6 |) L, j1 Fvirtual int PredictClass(void)
7 e# |- m7 F7 W" ^1 n o2 z{ |