1. 我们会用到什么模型呢?; P0 f# X" y/ ^$ L5 [
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。$ c$ H L2 M4 z: c
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
% L- p+ @6 ]: H9 Q//| https://www.mql5.com |& ~3 `$ y: B3 A; W4 @
//+------------------------------------------------------------------+5 h7 k8 v! ?$ i& {: a9 O
//--- price movement prediction9 {& r% W0 G3 t6 t) N: \
#define PRICE_UP 0% @# b6 t9 D: t1 p+ V
#define PRICE_SAME 1
/ X Y# `# G- U$ |/ M#define PRICE_DOWN 29 q. c9 A6 |6 A$ X0 }; `: H$ _
//+------------------------------------------------------------------+& N) x6 Z9 B6 b" O; C. c
//| Base class for models based on trained symbol and period |
5 W! ~+ \; [! ?% A! J//+------------------------------------------------------------------+& K% r% _, f9 Y/ `# y& u5 P" S
class CModelSymbolPeriod! D, e9 t8 W0 e3 z# h, E
{% T) W$ `; v. i. R, @3 F9 t5 i% V
protected:: @0 ]2 o) y" q1 i/ W
long m_handle; // created model session handle
1 |# ]! L# N) e6 D9 lstring m_symbol; // symbol of trained data( H; @) W+ v: C- M! p; N! o
ENUM_TIMEFRAMES m_period; // timeframe of trained data
' f& Y% G5 O) a( qdatetime m_next_bar; // time of next bar (we work at bar begin only)
' h" G( l# Y/ {. [/ P% @: F0 Mdouble m_class_delta; // delta to recognize "price the same" in regression models9 c8 \ J" M) n7 n S5 I% |: n
public:
% y5 T, q) d5 h( Z4 v//+------------------------------------------------------------------+
, a1 q0 g. \$ B- l( h0 O# ^//| Constructor |% X0 Y9 P+ y1 T* e! `
//+------------------------------------------------------------------+8 m- A' r4 l7 `
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001). v. `1 K( L2 T0 Y" V
{$ c( n& ?$ X8 S1 J' K6 z: R
m_handle=INVALID_HANDLE;2 |. [/ N7 v+ r. S. H( R; w$ \4 N; N
m_symbol=symbol;
% \9 @# e. }2 sm_period=period;; d' Y% b7 v( {. d4 L' Q& ?
m_next_bar=0;
1 @2 J$ Z# `' Wm_class_delta=class_delta;; s5 G* b3 W# M" u& M
}4 v2 f3 u" Y# X$ W
//+------------------------------------------------------------------+2 I+ v8 w b* S, g1 k
//| Destructor |
+ `* K7 H7 Z/ ^ C3 ^4 k//| Check for initialization, create model | Y8 U1 P% v6 j. h
//+------------------------------------------------------------------+& ?8 e' P* g; v7 Q
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
% g0 ]- I, Z4 l: t, V% B* c$ O{
, j2 I: e' F1 o' O7 w//--- check symbol, period _, P* k4 Z/ K
if(symbol!=m_symbol || period!=m_period)# ]6 u! r. e' T
{% ]% w8 Z& e8 R8 I# L2 Y+ t3 p
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
3 F+ j3 r/ X* _5 Rreturn(false);
1 }7 l. {. }* Q' }}
. o; X$ T4 ?5 f g/ P, u//--- create a model from static buffer
& ^4 H( K3 }2 z2 X( Z" a3 m5 C im_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
( P0 t" j4 A8 {8 C4 wif(m_handle==INVALID_HANDLE)
3 E" P4 U. R# A{) N6 f: ?- x" r. a; C
Print("OnnxCreateFromBuffer error ",GetLastError());1 ?' j* L/ R m6 `+ F
return(false);
0 \( K, u9 G. q4 V _& y}4 R# `- @# L* t+ t' H' g5 F$ j
//--- ok
/ g z/ h6 m5 a" r) r0 x: Dreturn(true);
- D' z6 w; l8 o2 s& Y}
3 K8 Y3 ]$ {( v/ T! l, s( P% w7 s1 A//+------------------------------------------------------------------+
n9 s2 {1 W, j/ Pm_next_bar=TimeCurrent();5 ?/ ~( D) H* |+ `$ b7 D, ]
m_next_bar-=m_next_bar%PeriodSeconds(m_period);. H: }. N( j+ `( s: |
m_next_bar+=PeriodSeconds(m_period);# k/ @6 b' f: l
//--- work on new day bar
+ L: O; n- |% N) F/ Dreturn(true);3 _% m# |! Q ?) F1 J. I
}9 a) K0 R( r: f# J& ~
//+------------------------------------------------------------------+
$ S+ [& x. \/ T/ r//| virtual stub for PredictPrice (regression model) |
& r l# z4 t9 H/ L+ ~* p//+------------------------------------------------------------------+
3 y# U, g8 {% Cvirtual double PredictPrice(void)! i4 r6 y4 h8 v
{
, C5 Y) Y+ Q8 U9 _, k3 E3 n4 }return(DBL_MAX);
. r/ j' J1 A# B5 ^( C}+ U |( ~/ m( @9 N+ Y
//+------------------------------------------------------------------+8 j! _. f; d) o) v8 E9 P; S& O$ ~; y
//| Predict class (regression -> classification) |
/ H- x+ K# e# c" m$ {/ ?//+------------------------------------------------------------------+
8 C3 X) d+ }$ Y9 ~virtual int PredictClass(void)
* o% d. d. ]: x; Z; l# I{
3 i" \- `/ v. F. K2 sdouble predicted_price=PredictPrice();/ {; F6 D9 t. A, F5 h3 g
if(predicted_price==DBL_MAX)
4 `: j0 x) c. y. C) l2 Z" ereturn(-1);& [2 F% M7 N: h3 Z7 j: D8 Q
int predicted_class=-1;
' U- p+ C: V8 F* W* M" i/ p. Pdouble last_close=iClose(m_symbol,m_period,1);
0 r! O2 Z$ Q! j9 U8 H//--- classify predicted price movement$ M. O# h+ `- b. e, r" L" p
double delta=last_close-predicted_price; h0 x! X+ w* ]& E$ r
if(fabs(delta)<=m_class_delta)
% I3 P' R8 ]* j9 K2 ?, Ppredicted_class=PRICE_SAME;
3 T F( }, S2 xelse
" s6 L/ ^7 g |4 X8 Bprivate:. V: s S' l- g: y* \% [
int m_sample_size;+ g! I7 R4 @$ O! W
//+------------------------------------------------------------------+" @( k! M0 B4 w! r, i1 f4 N
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)$ x5 q$ ~6 E7 | Z5 q/ |
{' P( z, ]' g9 @5 ~3 B
//--- check symbol, period, create model
9 u5 f0 y* X. a7 _9 V) nif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
- \7 g) s5 X0 ?$ U- f2 D{9 b( b4 Q' M8 h" u+ F
Print("model_eurusd_D1_10_class : initialization error");2 l! f0 E% `# d2 p" ], P l
return(false);
( f, d: W$ a$ s9 D4 E}
5 v7 ]- d" v9 q5 E6 K//--- since not all sizes defined in the input tensor we must set them explicitly
4 C, I/ a* o* m0 n//--- first index - batch size, second index - series size, third index - number of series (OHLC)2 m5 x ~# w g4 L5 j" n
const long input_shape[] = {1,m_sample_size,4};
- l* R5 }# L) S8 Cif(!OnnxSetInputShape(m_handle,0,input_shape)); {0 i. [. E" K" G- Z
{) v* }& q* Y9 T* c( u
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());( }& h* [8 O ~3 y4 J
return(false);) p7 S, @. M/ e9 n7 W5 _ s
}
! p7 D! r4 x1 A) B//--- since not all sizes defined in the output tensor we must set them explicitly
. X" @) y3 K! [, \//--- first index - batch size, must match the batch size of the input tensor
- p5 n: r' t" K8 f//--- second index - number of classes (up, same or down)$ D7 K& m7 c! n2 J/ v3 u# J
const long output_shape[] = {1,3};* _# I/ D$ T- Y/ o: B
if(!OnnxSetOutputShape(m_handle,0,output_shape)); C; @$ q3 W% d ?! u |
{
k& T5 ^8 q; ?+ MPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
6 h$ A, p' ^% H2 W) `' E3 creturn(false);5 o) N+ [" I" s. T
}
3 U# ~+ [8 y5 U: C" O//--- ok
9 u5 t' p/ u& z9 x8 [! x+ o$ e0 xreturn(true);
: r* l& P3 V, G4 S}
7 x! m4 x; b' U' ]4 }//+------------------------------------------------------------------+
) U3 J! Q0 v' K. i' O C//| Predict class |, }8 U0 T. p( Z
//+------------------------------------------------------------------+
3 u& I( a" ^! O! Y9 q- _2 ~virtual int PredictClass(void)
" O: e. j2 o, V- k# q{ |