1. 我们会用到什么模型呢?0 J% K8 C8 P4 H* D
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。% o4 [+ D9 z- Y
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
5 e3 J6 X- D. x3 n$ C//| https://www.mql5.com |, v; R4 v* A- ^5 @
//+------------------------------------------------------------------+, R7 ~% e7 s4 c6 d8 ~
//--- price movement prediction
: m$ z B: z8 I1 n( k2 t# Y: ]#define PRICE_UP 0- S6 l' i7 S" |! m. [2 A4 J
#define PRICE_SAME 1
& n' E- j0 _. G9 m4 k) [#define PRICE_DOWN 2; R8 K0 o8 g- p* _3 {
//+------------------------------------------------------------------+! X& |- [2 F" a. e* j
//| Base class for models based on trained symbol and period |0 A3 C, I! }, c
//+------------------------------------------------------------------+ v3 C: s! |# ~
class CModelSymbolPeriod$ k+ c7 P' C5 a+ q& m
{
9 |0 o$ [, R6 V7 R; Tprotected:
; [; d3 ?+ ^8 s5 ilong m_handle; // created model session handle. z5 a G N$ q
string m_symbol; // symbol of trained data. B' T' Q& d% ?- t, d* _) H
ENUM_TIMEFRAMES m_period; // timeframe of trained data/ Z, ^9 ?+ B" v2 ?9 Z
datetime m_next_bar; // time of next bar (we work at bar begin only)
. Z# i6 ?) }( o z7 ]* Tdouble m_class_delta; // delta to recognize "price the same" in regression models- \. a" K o7 R0 [) R, r7 a9 c2 W
public:
3 x# k6 O1 R; U- Y7 p//+------------------------------------------------------------------+
9 |5 D4 j% V, d8 _9 Z//| Constructor |
6 T% l% _( f% Y v5 \& b//+------------------------------------------------------------------+0 a% f4 q3 p: C/ G( M+ O
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
: r/ \& H3 G9 ]0 x+ w{
6 ^3 W! y$ F: f& K- am_handle=INVALID_HANDLE;' K6 X# h8 t$ G/ U9 K
m_symbol=symbol; o" |0 U+ n, H
m_period=period;
" w- \1 ^5 O. L7 qm_next_bar=0;
3 A3 ^: p* X5 k. Z6 S2 ~+ Em_class_delta=class_delta;* j _4 \( {) o1 e- ^9 f4 r# j
}
( d5 o" T( D% Y7 x: g//+------------------------------------------------------------------+/ N0 H6 u- m0 A7 k0 S2 F6 ?3 i
//| Destructor |
7 w; |# e0 h2 {, q9 {5 L. C% f//| Check for initialization, create model |
/ I8 c- J, H/ m K//+------------------------------------------------------------------+% u+ s" {1 ^- d# s. [
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])
9 I+ l f+ d/ {$ M3 q6 ?0 J{
6 ~2 I2 F6 E( u( ^ e+ |* u//--- check symbol, period
9 }0 ?+ p2 U3 Q) s1 Oif(symbol!=m_symbol || period!=m_period)
+ v" a% s+ y% I* @: [{ \- o% p6 I5 b! k' J7 F
PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));: u/ t6 O; z& Q. l
return(false);- L3 F1 E+ ^/ [' C) ]
}$ f; ^0 r8 U& [5 P
//--- create a model from static buffer. S0 A; |% n6 m5 h4 ~- |" S
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
0 F+ h a# a( u3 R. [if(m_handle==INVALID_HANDLE)
& m, I9 {0 e4 q/ J6 K8 A& N{
c( ^, g: l$ ]2 ?7 n$ X, f$ v. [7 pPrint("OnnxCreateFromBuffer error ",GetLastError());
( {) Z- c: X1 E0 l* y1 v8 C8 N6 |; ureturn(false);+ v: ?/ I( P& q* Q7 X9 K; o
}8 b3 ~' d9 G; I# b% _1 Q" ^; y" l# Y
//--- ok' X$ t7 c5 t: ^3 _) d7 s
return(true);' G d- v! D& _7 o. R
}9 ~9 b H9 F( h5 O4 Q1 a1 {
//+------------------------------------------------------------------+
% }( ~% v/ ~- i# Xm_next_bar=TimeCurrent();
( t% }* H& [. q; b2 U$ u# |- W0 ^6 im_next_bar-=m_next_bar%PeriodSeconds(m_period);
3 ^6 P3 D; C7 g2 Mm_next_bar+=PeriodSeconds(m_period); N! w" y4 t; ~
//--- work on new day bar
, s& k; g3 y, Yreturn(true);1 i% ~4 ]; r8 [, n( R! ~
}
' D. o7 x H) w$ F- T* L( U$ ]//+------------------------------------------------------------------+0 c: A* @6 k) Z" W. l
//| virtual stub for PredictPrice (regression model) |3 G8 }! R3 B _- k
//+------------------------------------------------------------------+
+ O- E+ ^ O+ i3 \ F$ ?virtual double PredictPrice(void)
; W, g; S% S% X4 @# T{0 r3 K6 I; a5 P/ ]: W+ Y
return(DBL_MAX);
$ V0 D. U z2 J}
9 m% `+ a1 q: o' z0 U//+------------------------------------------------------------------+( p5 g( M8 u& ~% G. ^2 s7 v
//| Predict class (regression -> classification) |
" Y5 B; Z+ E$ [( @//+------------------------------------------------------------------+
; R8 \8 o; V X6 Z% k Mvirtual int PredictClass(void)4 w' \' y1 H: }; y, E7 i
{
3 z. K9 D. l& B% f' h# ~# Fdouble predicted_price=PredictPrice();7 u& ^) g5 P/ q1 [0 r) x, g1 q2 h
if(predicted_price==DBL_MAX)
5 E0 |" C6 {2 v! @8 ?/ U( greturn(-1);7 M4 C# I w8 ?* A
int predicted_class=-1;
% b* q+ z; o# Xdouble last_close=iClose(m_symbol,m_period,1);
7 E/ Y6 N5 B0 Y% H//--- classify predicted price movement
) o" y- M& o+ T- s2 Xdouble delta=last_close-predicted_price;
9 |8 i# Z& u) ]) Yif(fabs(delta)<=m_class_delta)
g! W, @ K% V1 L1 C: [0 I$ b. zpredicted_class=PRICE_SAME;
& u" ?: r$ S1 Felse+ C# Q0 `8 S% Y. o
private:
3 `1 l h q9 W l7 sint m_sample_size;
- Q3 t; C( O) X//+------------------------------------------------------------------+4 V8 Y% T0 G+ S( n% m
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period). [# v# A% S8 T6 e9 o
{8 [4 E& e1 I! o1 Q8 N! T3 N Z4 B% {
//--- check symbol, period, create model
( `: I0 ]7 Y0 a8 j# O0 n2 q5 aif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
`+ V/ V. B! q0 V7 ?. N Y{
: g4 B' V% ]; w2 EPrint("model_eurusd_D1_10_class : initialization error");
* X4 y$ t" @4 g) D, W! N$ Creturn(false);1 x. I7 C- L- h: d, Y0 C
}! t& N# C" R* l8 U1 |! K$ p% s
//--- since not all sizes defined in the input tensor we must set them explicitly4 S; m% \6 n) Z- y) h) @
//--- first index - batch size, second index - series size, third index - number of series (OHLC)0 ]" A% g! O0 @0 a
const long input_shape[] = {1,m_sample_size,4};1 l- _& L% e' M8 J- ]+ g9 N! C4 T* G
if(!OnnxSetInputShape(m_handle,0,input_shape))( C3 h# j2 y6 L3 J- O/ N
{' a3 Y7 w2 `: p# h9 i
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());1 A5 p& e% l6 ]0 h% z
return(false);) X3 D6 l [6 f# i) Y' |
}0 Z) J) C- ?7 h$ ^/ a
//--- since not all sizes defined in the output tensor we must set them explicitly
# c' C9 R: I6 q# g//--- first index - batch size, must match the batch size of the input tensor- K N9 |1 B+ w I
//--- second index - number of classes (up, same or down)
. E0 T- ^% |; W# pconst long output_shape[] = {1,3};
. `5 ~9 m2 ^2 B) V" nif(!OnnxSetOutputShape(m_handle,0,output_shape))
8 U; L5 ~. U' [3 h* f7 b% f{
0 I" Z. d5 S. e+ T' N9 U$ WPrint("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());4 }! U& B" W. \& _0 M
return(false);% l- G2 Z( F4 B0 D# y. u
}
Q5 b, M& o$ K# `* X5 x! E' _//--- ok
; W" [/ ^; R7 e( breturn(true);8 @7 t. }6 a4 M8 J
}8 {$ @* c+ f# f8 m. Q' d6 q7 `/ I
//+------------------------------------------------------------------+
5 Q# Z9 h/ k1 t. ~+ ?//| Predict class |
+ v$ n, R8 i6 h' R//+------------------------------------------------------------------+
3 E1 g5 w4 H7 I @virtual int PredictClass(void)
) G5 g* z3 k3 o H$ Q6 ^{ |