1. 我们会用到什么模型呢?' Q+ _7 u x/ e7 |
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。9 ?1 i( x5 j/ h
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进' U- ^+ E o h1 e, q" S( p
//| https://www.mql5.com |
7 I, k# ^2 g/ @ f2 `, r7 H* I//+------------------------------------------------------------------+: }. g3 v" j/ x6 e8 K
//--- price movement prediction
$ Z/ V2 L# ~! u& |7 q2 ~#define PRICE_UP 0( I7 s+ D% z1 S7 h# Y7 h' F
#define PRICE_SAME 1
3 f) h$ D. j1 v+ V+ }5 n9 l#define PRICE_DOWN 2( j: r6 p. _' b$ J1 p: f/ @
//+------------------------------------------------------------------+: l7 B8 W( c* A8 n0 S7 J, @
//| Base class for models based on trained symbol and period |
1 C) m' w- H: v4 F+ q2 y, i//+------------------------------------------------------------------+
; K' q% Q: u9 C8 P; ?7 Hclass CModelSymbolPeriod C# ~8 ]) F+ z# h
{, E# ]6 S e) V0 ~2 ^+ k
protected:
6 V, w/ a) @4 M- Q- Elong m_handle; // created model session handle
0 b& Y# |0 F7 c: J4 `string m_symbol; // symbol of trained data
& u4 @3 m- d3 j8 M) MENUM_TIMEFRAMES m_period; // timeframe of trained data
& X( t1 F& u$ g! S" @datetime m_next_bar; // time of next bar (we work at bar begin only)
. r* q J7 ?. Xdouble m_class_delta; // delta to recognize "price the same" in regression models
: q% f; S- b/ bpublic:8 P' Z: }/ _5 q7 R
//+------------------------------------------------------------------+- \! r% D( I0 N% J" a% w! q7 Z
//| Constructor |5 [1 Y* ]* \6 N# T& _, Q2 C ~+ h
//+------------------------------------------------------------------+
" x5 I R5 Q/ h, U. U: ?% s# zCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
V8 A8 n3 |' {+ V/ D; u{
( A+ v" k. Y% Q, d0 l2 nm_handle=INVALID_HANDLE;
/ _& L2 K# {* [m_symbol=symbol;
# P. Z. ?) i% J* mm_period=period;1 [: r( U' v- C8 C% E; S& h' r/ x
m_next_bar=0;
4 R+ m+ I% ?' e; u1 fm_class_delta=class_delta;8 \% S9 D$ c: n* H) b
}
. ?' ]* `6 n0 [& |, E! q//+------------------------------------------------------------------+
. R6 I, ?( S# ~6 w W: z3 ^//| Destructor |
8 a# p* B- M g" c# }//| Check for initialization, create model |1 f8 l V( u6 J; ]
//+------------------------------------------------------------------+# G( l4 s- g1 H1 I
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])) } G a0 r* [! J1 R! C
{9 A. l2 z: m; F( U
//--- check symbol, period9 g& W; W7 v7 ~# {1 [& ?
if(symbol!=m_symbol || period!=m_period)3 f7 {. U, @: ?( O1 @* b) z. j
{2 R' g* C1 o4 G; g
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
* }6 N+ I$ \4 K' @return(false);0 r; o* W' r1 ]6 n7 P, C
}
0 Q0 M2 c) k. Z% V( M//--- create a model from static buffer
: a) @* B5 u8 d; c5 Hm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);; C3 y! r. G* y- t& @7 g7 C4 R
if(m_handle==INVALID_HANDLE)
7 y3 _* X7 h$ j8 n7 h{! Y) O+ }& H/ i* \
Print("OnnxCreateFromBuffer error ",GetLastError());
. F4 h! j2 z. vreturn(false);
# O( C/ S t$ t- E- A2 p6 d4 H}: p0 W- f( x4 g$ X
//--- ok
4 z7 A0 ?1 J" a0 w2 \: C; ^return(true); p. ?$ C2 l9 k& p
}) K. _% c8 b( b( v) m0 x
//+------------------------------------------------------------------+" ?. e" o. V0 h3 j4 f0 S4 o
m_next_bar=TimeCurrent();/ I3 r: z) C A3 O* G& N% i
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
. g, W9 n! x9 E- p* fm_next_bar+=PeriodSeconds(m_period);
: [# l# u) G* k M5 x//--- work on new day bar6 x7 Z* x- Q* q6 z% G
return(true);; O1 |# _2 p" F( @( S- ?' u
}
- W% _4 R3 }" q; Q//+------------------------------------------------------------------+, {" d4 |' t. m$ t$ I8 S% X; ]$ O
//| virtual stub for PredictPrice (regression model) |+ A, [$ r, N; I) q; T$ {
//+------------------------------------------------------------------+
O( L; R( c. p% K+ Ivirtual double PredictPrice(void)
" ]0 m4 L8 s3 `{. m) a1 n6 Y0 v9 B( `
return(DBL_MAX);
0 \1 t* I( y- x* t6 c [+ G}
9 L/ H8 C; [5 [ ~1 l% O+ G# t//+------------------------------------------------------------------+
% e0 D6 ] Q: c' _//| Predict class (regression -> classification) |' `$ G1 Y/ E5 A" |8 {! |, c
//+------------------------------------------------------------------+; Z& c; m0 E9 w2 y# \. a
virtual int PredictClass(void)
9 J N6 W' }0 ~ \+ }+ z{
6 G* S& [/ l% h" Xdouble predicted_price=PredictPrice();, ]6 Y) Y( }& \
if(predicted_price==DBL_MAX)
7 a+ {9 e1 v) H' @3 Qreturn(-1);* E" }+ C0 Q6 I8 `6 G' p% j& n, P
int predicted_class=-1;5 l" B5 S8 V9 z) b5 B3 i
double last_close=iClose(m_symbol,m_period,1);6 x4 N, f7 Q/ ?& c/ u
//--- classify predicted price movement2 p+ H+ K B2 f, G! G) Y& G
double delta=last_close-predicted_price;4 K4 H# b% G; j7 S1 p
if(fabs(delta)<=m_class_delta)" p: g( W8 t) d: }/ @
predicted_class=PRICE_SAME;
8 t) i4 T. G" {; o Z( y/ Kelse; v. f5 M! q: e; } e. ?$ b
private:5 L0 b( [/ c' }; S, n; r
int m_sample_size;2 g3 s7 e C# [1 k f
//+------------------------------------------------------------------+
2 q0 f! l! x1 I& J p! Y( r" Nvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
, {8 o8 E* a. {1 y{
0 Y) b j1 T( \& a# L//--- check symbol, period, create model
: s+ y# ]/ u% q6 ^0 ]% \/ Bif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
$ W" _5 f! Q5 S0 o! B, j/ X{% T- ^7 M5 H( I, W& F
Print("model_eurusd_D1_10_class : initialization error");& n( c" G& S+ [' L9 `
return(false);/ V# J5 }; E5 ]/ }" W
}
. _4 X4 g4 ^& v7 p6 c5 n% v9 j//--- since not all sizes defined in the input tensor we must set them explicitly4 T, `0 n+ e! G1 ^
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
% z9 v( v' B$ R* {const long input_shape[] = {1,m_sample_size,4};
$ t, `" E1 D; m0 Mif(!OnnxSetInputShape(m_handle,0,input_shape))+ @3 F' J( v, v+ a9 f! [
{
8 a9 `. U& b, `# I' zPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
j% T" ]4 c. hreturn(false);4 W, i. c# ?, L5 j( ~0 P, J
}7 @$ {; U9 `$ s1 f- P/ E3 @
//--- since not all sizes defined in the output tensor we must set them explicitly( B% Z4 m& i* o% S
//--- first index - batch size, must match the batch size of the input tensor
3 M6 y* u j5 ]0 \" E( c' ]4 f! ?//--- second index - number of classes (up, same or down)
* P8 _ O' a4 D6 ~3 I0 y9 pconst long output_shape[] = {1,3};
! u, u" f- K. T1 o) tif(!OnnxSetOutputShape(m_handle,0,output_shape))
$ ^3 |3 x# O4 p) d{* M% a$ `$ Q% s3 F
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
2 I( C( p# {( |" [7 h3 ~1 u: a$ Dreturn(false);2 i- E( C; u! M/ p4 f9 W) _
}
2 l8 M" a. h$ [//--- ok) ^; L( H+ P0 B+ ~% c
return(true);
: j7 Y( k/ L8 Q+ {; R}! d7 l# p- [2 M
//+------------------------------------------------------------------+
; I3 \5 g( `8 D' z' _//| Predict class |
# v8 u1 `6 ?* C! E' r+ S//+------------------------------------------------------------------+
( Q5 M' r1 X7 R) a6 k( Q9 Yvirtual int PredictClass(void)
. z, L) Q1 _' c% h/ ? _{ |