1. 我们会用到什么模型呢?" p& T4 b! `( f7 z: R( r8 H
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。1 X9 m' i9 Y& A9 u" P2 [
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
1 Z+ e& ?9 |7 Q( T s( x//| https://www.mql5.com |" K9 i* g. A) l. I3 c. S
//+------------------------------------------------------------------+4 p1 j+ S. B2 x3 h( L
//--- price movement prediction6 s- N" Y0 `8 U$ H. U4 H. N
#define PRICE_UP 0$ t7 Z- U' ^- W7 n! L! N1 N2 p
#define PRICE_SAME 1
. s/ J( I- V0 s8 C#define PRICE_DOWN 2
7 z: z, b6 F+ S: A3 M7 r* d) x//+------------------------------------------------------------------+
4 z* G2 i: Z1 W ?- V7 x//| Base class for models based on trained symbol and period |
/ i$ [0 X8 Q: U+ L7 o0 u//+------------------------------------------------------------------+& \( ~' k6 r3 D. m9 a
class CModelSymbolPeriod
+ r6 G9 X1 D; S5 R$ W& l' Z{
8 b5 [7 g6 d* @% r# Lprotected:1 @: y% ^7 g' k# c
long m_handle; // created model session handle+ q( G" }( {1 I
string m_symbol; // symbol of trained data9 p# x6 y! Q* W: b' u
ENUM_TIMEFRAMES m_period; // timeframe of trained data
' m( x/ T9 K' ^8 udatetime m_next_bar; // time of next bar (we work at bar begin only): i% @9 g1 n5 b! x# Z/ R
double m_class_delta; // delta to recognize "price the same" in regression models
: q$ X" z4 m% i& b/ S: P( i1 G/ vpublic:
1 ?# U6 Q- w4 A* j//+------------------------------------------------------------------+6 o& c3 B' _9 {+ Q: a
//| Constructor |
) j* q. a. O' Z2 H9 v$ t# C//+------------------------------------------------------------------+
# a9 c. Q0 t5 m8 T9 o" RCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)0 z A, b8 M# s
{
1 N0 \3 _ u& E. jm_handle=INVALID_HANDLE;$ G: g$ P6 B @5 o+ s* h! _3 y3 u
m_symbol=symbol;* p, _: f+ m% E, v
m_period=period;3 F8 V) M$ ?4 G$ f$ ]) @& j
m_next_bar=0;# ?" g2 n- I+ ]: H1 P* O; `
m_class_delta=class_delta;
- ?7 [2 X/ S. k/ p) g9 F}
% S' I6 N4 t' l. K c! t G//+------------------------------------------------------------------+
8 Y/ B2 [" [9 \: ~//| Destructor |
4 G7 [) K7 ]/ N/ Y) `+ M7 U0 m//| Check for initialization, create model |
. z6 t8 P4 r- q7 J/ ~$ ^//+------------------------------------------------------------------+- [8 d& c# X" x: b! B+ Y3 m; Q
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])8 _8 S% I, F2 r2 p8 B" x
{2 ~! c# I: H1 r9 q5 ^
//--- check symbol, period" k: z/ y5 R b; J6 \5 ^( I/ o
if(symbol!=m_symbol || period!=m_period)8 z; V' t9 x! f+ D3 i$ Z
{
" w- B$ M# n6 \3 q' W* GPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));9 x. V" U0 {0 W
return(false);2 ]. E$ L; Y( S3 }
}" y) t- S4 z. J7 n( |
//--- create a model from static buffer
; U5 K4 y- f0 s; _* @/ m2 h3 E5 jm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);1 |! U! [, R5 _# \/ Z6 J
if(m_handle==INVALID_HANDLE)! r0 C: {: N# [" x0 P7 g2 z: i6 \
{
0 @8 Y( D3 }4 p. sPrint("OnnxCreateFromBuffer error ",GetLastError());% }8 K0 a$ _0 r/ ?, C* A( X
return(false);2 Q; I8 g( ?; ^. o$ `1 n
}* x- ?% q6 E2 e& a5 Z
//--- ok: e# j+ T( d3 N, J2 A
return(true);% a; L3 }$ F1 t4 i4 J1 c( F9 s- H8 @
}
8 T- |4 z& e) ], M4 A0 O6 @//+------------------------------------------------------------------+7 v ^' t, h$ b
m_next_bar=TimeCurrent();
$ V1 X1 z+ V; q# m& Y9 b) w3 w0 D2 O' t( Xm_next_bar-=m_next_bar%PeriodSeconds(m_period);2 C: Q1 Q& l# y: W
m_next_bar+=PeriodSeconds(m_period);7 X6 [( M: `, M
//--- work on new day bar8 {0 T6 M0 v1 B5 v
return(true);
1 a* u: q) H+ X# ?: ], u}/ @; Z" q8 @; Q
//+------------------------------------------------------------------+) F* R* h$ e6 R8 x/ I3 Z( {2 v8 [
//| virtual stub for PredictPrice (regression model) |
# O/ K7 c1 D& _& c//+------------------------------------------------------------------+- t6 q9 W! A' r* o% v- v4 y3 Y
virtual double PredictPrice(void)
% q% ]+ e. p" O8 `. o{- V& B7 H, r: w8 M
return(DBL_MAX);
" N+ l0 o% b% o% V8 G: ]} c. o" {3 ^7 j5 Y
//+------------------------------------------------------------------+- @$ p8 Q6 n' D5 e7 u' n% r6 p8 o
//| Predict class (regression -> classification) |
- o8 L2 H0 a+ R& z1 j//+------------------------------------------------------------------+% I* H5 g' Q; y
virtual int PredictClass(void)
6 P. y, r' w2 s N9 B, E{; p2 p ]% E3 p1 {! e
double predicted_price=PredictPrice();
2 M5 A4 p y, t* S5 gif(predicted_price==DBL_MAX); U7 f9 ? K: B, v! H
return(-1);, w, u" h& E( I W, G- e
int predicted_class=-1;! c' }9 S- e2 b
double last_close=iClose(m_symbol,m_period,1);5 L: _2 U0 n$ q# c0 }2 @9 g
//--- classify predicted price movement
/ m0 V+ R) {$ Zdouble delta=last_close-predicted_price;
9 r4 z8 G) y. X5 `if(fabs(delta)<=m_class_delta)( }9 }# E$ L7 d f4 d% V
predicted_class=PRICE_SAME;- P4 P. A0 B; ]" |5 i
else6 l7 [( J9 R/ u. ^
private:
! C2 k4 [9 @- M. H* w, A- Iint m_sample_size;
' Q* W$ Z; p6 N6 Z, S3 u//+------------------------------------------------------------------+7 P3 N7 C( k- G) ]6 f5 M, K/ ]7 |
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period); q) [* Z# X \6 X
{
; S# p8 l: [6 ~' s7 D! M3 K* c+ g//--- check symbol, period, create model
% ^4 q# e0 T; K9 u; Gif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
- Y9 a n' F% B1 r k; `- Z# I4 [{
, c" s/ n( F8 L Y' x0 s$ e- _. _Print("model_eurusd_D1_10_class : initialization error");( u# q; a; ~) g% h% d+ h: W
return(false);( G4 `+ V# R' B n1 F
}
0 u% P3 w! }* I4 a) I//--- since not all sizes defined in the input tensor we must set them explicitly
, e# q1 N9 j; O6 _//--- first index - batch size, second index - series size, third index - number of series (OHLC)
8 D8 R/ T' o& H% kconst long input_shape[] = {1,m_sample_size,4};
/ \. C0 f/ J# Rif(!OnnxSetInputShape(m_handle,0,input_shape))( K1 A# q6 ?0 ?+ M* O5 l% f* w
{# x! u0 k4 A2 R; {
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());
# `8 C2 w2 z1 d( A+ `return(false);
5 d8 t U: \ a( g" Q} p7 f/ G& o4 j! e0 J& \# a3 s; ^. X
//--- since not all sizes defined in the output tensor we must set them explicitly
% Q/ z9 Y3 x) P r$ o+ Y//--- first index - batch size, must match the batch size of the input tensor$ ?% @- E# t( c) z4 l( P
//--- second index - number of classes (up, same or down)
! u, K' J2 k8 r$ }# |, r/ W2 {const long output_shape[] = {1,3};( p% ]+ q/ c2 z) X. A8 V' H, x
if(!OnnxSetOutputShape(m_handle,0,output_shape))/ f; s# X/ h; r; k u8 u/ | o
{" h1 M* _& F8 M2 h
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());* {& S3 g3 Y6 D& p9 [
return(false);; V' N7 U. [9 W7 r; \( ]/ i
}; N8 `6 \. l3 D) S- L
//--- ok! n v# j) ~2 e& X' v2 p/ W( ?) A( T! ]
return(true);
" I, `6 u2 x. O x/ W3 N3 p; B}
" p: {6 y: x3 m$ u- I$ v//+------------------------------------------------------------------+
5 M$ F% |; @' V0 r% V; o//| Predict class |7 V5 ~8 @ {% x
//+------------------------------------------------------------------+$ ?( W: x" c5 \# v; t8 T; q
virtual int PredictClass(void)% G7 o8 F" b, `& _
{ |