1. 我们会用到什么模型呢?8 m- {2 {9 ~" Y, G6 A
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
' s+ _! m9 _. X& r9 ^我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进/ i* J* r% C u6 e m8 \2 [
//| https://www.mql5.com |
3 g' L7 r0 I7 J* m4 \0 {3 y, h5 V1 P//+------------------------------------------------------------------+# @; O2 V# A7 b. g
//--- price movement prediction3 f' \; x7 t: ~& U
#define PRICE_UP 00 @8 m1 z7 j: [% U4 H7 y* t
#define PRICE_SAME 11 L, o' B. ~9 k
#define PRICE_DOWN 2
4 K2 ~* w- n3 L9 J' x1 z! P//+------------------------------------------------------------------+. }% y. Y- _3 f% ]7 e1 k
//| Base class for models based on trained symbol and period |
0 D+ X3 p% r" q! p//+------------------------------------------------------------------+) Y& d U# f! p$ ^1 I8 J
class CModelSymbolPeriod
! a D7 [% z) M{
+ P$ e! n7 m5 o7 H* R1 E6 {protected:
" i$ V; u! C0 n2 P7 p1 \& @* }long m_handle; // created model session handle
4 h8 `" c) w8 v$ T8 I. e' Xstring m_symbol; // symbol of trained data
; D+ c9 _7 a- a' iENUM_TIMEFRAMES m_period; // timeframe of trained data: }. z: i7 q/ c/ d3 V, ^
datetime m_next_bar; // time of next bar (we work at bar begin only)
6 c: w% N* |) k! ~3 C' e- Ldouble m_class_delta; // delta to recognize "price the same" in regression models0 T, v6 U/ I8 _6 M5 C
public: ]* P; H3 j/ L) q& g
//+------------------------------------------------------------------+' g' R0 [2 q8 E: v
//| Constructor |
4 i" R+ ^- \9 ], q2 l2 }//+------------------------------------------------------------------+3 [. M) I+ u6 {4 ~
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)# j' E( h( m5 O! b/ ]
{
V X2 I1 m4 G8 w6 em_handle=INVALID_HANDLE;6 A; h) C/ {( A# S
m_symbol=symbol;* N& }5 G# S# }4 o5 B, j
m_period=period;
- v3 ]" H8 c6 \% mm_next_bar=0;
; d: O* R r. {- S) J/ ?; cm_class_delta=class_delta;
/ } j9 N; @5 t W}
! K$ n3 J1 j' r- I5 |4 B//+------------------------------------------------------------------+
2 F0 E2 C9 \, [! ^2 }//| Destructor |* q% D, I* l x q
//| Check for initialization, create model |
0 P7 S2 F: e& ^" s5 b//+------------------------------------------------------------------+) W8 t4 x6 g, }1 d2 ^
bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])9 H. D) C( ~; c, N
{
& q& h+ l% i( R7 d//--- check symbol, period
+ u, V* T( ?, o% G, J# S' vif(symbol!=m_symbol || period!=m_period)9 _2 K2 `0 g/ V/ d
{
! V& |9 Z+ b5 i! P* T. xPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
6 A1 v; G* b$ k# ?7 s$ kreturn(false);
' I ^( P" P- Q}2 G9 c8 ^& f x, E) y' e! z2 I
//--- create a model from static buffer
! t# A$ Z1 v, P- L9 E, k4 Nm_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);$ y8 V5 x" z* D8 [
if(m_handle==INVALID_HANDLE)
9 U! p8 p* e3 W% Y, W& r{
0 y# I' w8 k; y7 S' h" [0 aPrint("OnnxCreateFromBuffer error ",GetLastError());' Q& [4 q* m' j$ W; _* g$ t) v. r5 A
return(false);) P2 M- f' D& d3 w0 {
}
+ i) m; x' F) E4 [- S" J$ I//--- ok) n6 P" `. F. \* v* I( M) Q, u
return(true);
/ ]0 r9 v- Q7 P# L Y* k5 q! ^}
9 M; U$ m) J+ q/ ~9 r2 A' t; w//+------------------------------------------------------------------+
% J7 R6 t" B" F0 Jm_next_bar=TimeCurrent();
9 |* c% W; s6 h) E% Nm_next_bar-=m_next_bar%PeriodSeconds(m_period);- p- ]4 G' b5 l2 Z8 e* x! K
m_next_bar+=PeriodSeconds(m_period);
4 P( c. P4 f0 v# I# @# x( _//--- work on new day bar0 T# r% K, |* C: I0 C) I
return(true);
+ b Y, Z6 F M}
* }, i. _9 Y, g* b v//+------------------------------------------------------------------+4 H! y- J+ D [' u
//| virtual stub for PredictPrice (regression model) |
9 }) F& o+ t7 [' {" X @7 @; R& d- A//+------------------------------------------------------------------+8 l8 ` y, ^9 @# a3 S8 b
virtual double PredictPrice(void)
' z, v/ {1 E3 `2 S( d" Y7 Y& @1 p{
+ G6 C' {& k$ Q$ |) x; \; J% Breturn(DBL_MAX);
. l# a Z& z4 e6 z% U# A; ?}
) ~( S& u, C' u$ R1 h- J//+------------------------------------------------------------------+
0 R8 ?) j6 h# N* u//| Predict class (regression -> classification) |
7 k7 [* @) y4 ]( f' |- @//+------------------------------------------------------------------+' ^) }0 p3 s3 C4 `4 u( o) A
virtual int PredictClass(void)
: _& _* n* o: K. o' h0 _{/ [, Q+ E" H1 w$ \
double predicted_price=PredictPrice();# s v8 T: }6 t# {# ]
if(predicted_price==DBL_MAX)
% q( c3 e- u o$ {8 h: Sreturn(-1);( ~4 ]% ^5 B6 i k1 |
int predicted_class=-1;3 [: K, u8 V) p* ]/ m- Y! {
double last_close=iClose(m_symbol,m_period,1);
2 @. r+ }4 P1 g" d//--- classify predicted price movement
. \9 b8 S4 U! @# f; i$ pdouble delta=last_close-predicted_price;
, U* f$ R5 z# cif(fabs(delta)<=m_class_delta)% ~/ a! ]6 R ~5 ~2 h5 q1 }
predicted_class=PRICE_SAME;+ i& S: v! n: ^+ a. V' [
else7 F* Y! {' u2 ~8 b& M' ^% |/ ]( h& V
private:
7 o3 e1 t& P2 u) Sint m_sample_size;% V' A* \9 [! c( g
//+------------------------------------------------------------------+
9 Q$ \& k, M( g3 o' z J0 i& M0 rvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
$ I7 A8 c# g9 a& H8 ?{/ N; c6 ]5 i# B% |; `+ Y
//--- check symbol, period, create model
7 T9 l' f3 `3 K8 ^. `if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))5 z& }: f& W. b0 I
{
F5 c' v$ ^! u' F: dPrint("model_eurusd_D1_10_class : initialization error");: W) M& C) L2 C/ z# U
return(false);
- f% {; e- B! n' _9 R% V}
; |7 g9 b1 Y0 j9 C, J) |* N//--- since not all sizes defined in the input tensor we must set them explicitly+ N$ e, D7 V$ R3 X. B3 R9 \
//--- first index - batch size, second index - series size, third index - number of series (OHLC)
. L' x0 H6 c2 D+ _5 j% o7 w; Y! vconst long input_shape[] = {1,m_sample_size,4};
" \" d' F* \6 J+ x7 _+ dif(!OnnxSetInputShape(m_handle,0,input_shape)); f# C" f/ ?1 |; g" D$ T
{: P1 F' N5 L8 V' G" e9 c
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());7 p& s4 I1 e1 c, k6 H, u
return(false);+ w- I8 e8 ~' H
}
, b6 I) L9 n7 e- `% L3 g//--- since not all sizes defined in the output tensor we must set them explicitly
3 @3 f0 S4 v0 ?//--- first index - batch size, must match the batch size of the input tensor# Z; h! L/ q' y, g6 X/ T) l
//--- second index - number of classes (up, same or down)
" X/ e. ~8 K5 }* f0 |! Z" Mconst long output_shape[] = {1,3}; V; x; `- o2 n { \" P* ^; g; V
if(!OnnxSetOutputShape(m_handle,0,output_shape))3 r0 Q/ {5 t$ m5 ]7 B, G3 k5 V+ [
{ z' Q. @, c7 K" M8 S% P
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());. ]2 V2 x! z3 N% D# H) R
return(false);7 o2 p' b) X2 S+ g9 [
}
2 X0 L+ D$ l# d//--- ok
T+ z7 \1 x# ?9 Xreturn(true);4 v G0 t4 s/ O: R$ Z
}
4 w2 ~! |* B$ m: s' \# O+ b5 }//+------------------------------------------------------------------+& U" Q4 l1 K7 a
//| Predict class |" n( G& v$ x- @& c8 C4 g) t
//+------------------------------------------------------------------+
% J- f2 K: C" }) I# Wvirtual int PredictClass(void): E* Z! ^0 _& ^ K9 j" }# h
{ |