1. 我们会用到什么模型呢?1 K ^2 q! {5 I0 ~9 c2 m A5 ]# \
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。
- u* N; g1 ~% a8 q' G6 l我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
1 j! z a8 w9 j//| https://www.mql5.com |+ D, m: F9 x' G% ~: E) x
//+------------------------------------------------------------------+
( l1 a& v2 S C6 ~* V$ Z//--- price movement prediction
' i! B8 f0 d. d6 ^5 [ c6 g#define PRICE_UP 0/ X: H( ^' h! R3 z' z: }
#define PRICE_SAME 15 X, Q" D1 E* `4 ~1 ^
#define PRICE_DOWN 2
$ ]: c% _' u' |) y2 L" U2 J: {//+------------------------------------------------------------------+
, N' C8 ?! g& t! I1 N//| Base class for models based on trained symbol and period |/ c! J1 `" \, h% x- U" F1 O
//+------------------------------------------------------------------+
8 N; k5 E3 ^. N9 C0 r d$ X8 lclass CModelSymbolPeriod
0 g) y* |& B+ [: n{. ^1 T+ p d! Q; ~, q# `
protected:
; j6 ^) |% E! H& u( a& o# Vlong m_handle; // created model session handle
5 @5 b! m8 L u6 L9 u6 Nstring m_symbol; // symbol of trained data0 c! I8 t( t) f/ U$ v
ENUM_TIMEFRAMES m_period; // timeframe of trained data' b: d5 X9 H8 T0 z
datetime m_next_bar; // time of next bar (we work at bar begin only)2 p2 o W4 V' f4 |0 w m1 @/ T
double m_class_delta; // delta to recognize "price the same" in regression models! u! V: O7 [6 t+ m" G( Y0 ^
public:
6 y1 b4 t8 A% |, N$ E//+------------------------------------------------------------------+$ U7 t/ J7 E; N8 `" n. Q. {
//| Constructor |
% o% v* k: w; r! {! v5 W//+------------------------------------------------------------------+
9 t3 T$ u1 _4 vCModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
- R$ f0 c3 n* X a' t$ O. ]{
' N0 W& Z4 \2 V$ u' L' u/ r% hm_handle=INVALID_HANDLE;. m3 \5 k( I1 K W* U; ]
m_symbol=symbol;" T1 _* Y6 T9 P: {/ I
m_period=period;
( r4 X$ ~) M" x( w5 ^m_next_bar=0;: n8 t9 c6 [- @1 T; N4 k. x
m_class_delta=class_delta;6 ?3 ~& ?% Z d# W( O
}% u* g1 `4 k/ u& r1 E8 L9 n
//+------------------------------------------------------------------+# I+ j8 W. l) m+ n% h1 J& m' L
//| Destructor |5 F9 v4 J' Q2 x4 l7 {2 D2 G% T
//| Check for initialization, create model |; F( ]& c. }, c% m) L
//+------------------------------------------------------------------+
# [5 p( j: K7 L( B) b9 D z. Xbool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])! r9 {9 f4 _% t9 P
{
% g$ i# x; K& z0 @) t8 p//--- check symbol, period
" W9 z! J) p4 W1 |& K8 H& Uif(symbol!=m_symbol || period!=m_period)# v2 B ~" `5 g- Q W2 S
{
5 N8 Y7 _: U) H; |PrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
3 l( \, o, Z6 n2 z e+ z: ~, kreturn(false);
6 _' m, }+ s3 B0 x+ x; B}
7 `6 Q$ @( O& _3 F4 H4 I//--- create a model from static buffer3 h% ^+ E$ V' F- |' @' m
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);" e) \7 K2 ]6 _+ a7 Q9 y7 W
if(m_handle==INVALID_HANDLE)
$ d& {& J$ ~# n8 S c7 u9 f{1 x: p: {& N# w0 K p6 ^+ G" C
Print("OnnxCreateFromBuffer error ",GetLastError());
. x* `3 ]7 z6 Kreturn(false);! W" i, _9 E w- ]8 D+ y
}
8 L3 X# _8 h/ ^# q//--- ok
5 Z' s+ F6 Q/ e2 ?return(true);0 L& t. p, N" P% T1 O. [$ \" ]5 q
}* E. d% [$ }- t" ]
//+------------------------------------------------------------------++ F- x' x$ h$ a! } i" t$ V6 @
m_next_bar=TimeCurrent();0 a l* k5 _: j. m) h
m_next_bar-=m_next_bar%PeriodSeconds(m_period);
?4 p7 K$ B7 u+ X& rm_next_bar+=PeriodSeconds(m_period);% y: J% h9 u, p( ?/ g- ?
//--- work on new day bar
# d% h) l: }# S9 E1 Q9 Q; ]! Areturn(true);% |& R) U# p, S" z& ^3 |( {( L5 d
}1 _: u4 m P: [% w2 Z
//+------------------------------------------------------------------+1 d6 B" q- h' Y5 N6 g$ a% f) G# y
//| virtual stub for PredictPrice (regression model) |
' r# k2 t' @7 Z( G//+------------------------------------------------------------------+! Y" `9 Q% {5 o
virtual double PredictPrice(void)9 I0 y$ {# G: `7 g
{
6 E8 \0 |! X6 t4 B8 `' h7 c; _return(DBL_MAX);
- R7 u2 ~+ ~' S; F, V% ]! `/ A9 g}! W. M2 P9 R& h- ~! F( c! s& c! @
//+------------------------------------------------------------------+9 u* f% D0 P. g/ q
//| Predict class (regression -> classification) |- p! ]+ d4 V" l
//+------------------------------------------------------------------+: ?# n8 u3 S' S$ R
virtual int PredictClass(void)& N9 N5 `- t. S4 D F
{/ G* I- V# V! o2 X* `$ Q! |: a
double predicted_price=PredictPrice();
7 c4 M: h7 @3 `if(predicted_price==DBL_MAX)
' s+ Y; a' e* G( Z4 b2 q6 p- Treturn(-1);
8 g3 Y, d5 d% S7 u# B, qint predicted_class=-1;
( G3 x; @# B6 T1 Y4 udouble last_close=iClose(m_symbol,m_period,1);
# F# Y1 Y# @; u% b' F$ I//--- classify predicted price movement
/ b+ L. m9 R/ ?- T) m% }double delta=last_close-predicted_price;
) E p; Q* t2 i5 Cif(fabs(delta)<=m_class_delta)
_4 v. c% g+ o' e$ v4 y4 t4 N/ p' Hpredicted_class=PRICE_SAME;6 X B* s8 c. j' |' y3 h2 n
else$ r+ u6 v+ z' _, r% u2 a6 ~5 t
private:
, A, \! ^9 \3 v. Gint m_sample_size;
9 P' X( S ]+ [* K//+------------------------------------------------------------------+
$ o2 y" j! Z& p4 d7 lvirtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)
! O6 M0 E" p/ h{: w9 q) f: r3 E- F
//--- check symbol, period, create model
2 {9 z' U7 g9 k; N9 ?if(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))
$ f* C- Q6 [1 E& A% |4 B{2 _: ~/ I& B* E) H6 \) y
Print("model_eurusd_D1_10_class : initialization error");, I2 i* |; }5 t$ ^& r% L) K
return(false);
) h+ ^2 q6 d' x7 P2 M: D}
0 I, N/ y1 T" N7 ?3 Q5 w: l# v( h//--- since not all sizes defined in the input tensor we must set them explicitly: V1 L& O- _# v5 O, Q5 P
//--- first index - batch size, second index - series size, third index - number of series (OHLC)3 m$ a0 u$ c: R. n. U+ i
const long input_shape[] = {1,m_sample_size,4};
# A$ r8 q6 A" W1 P6 ^% ^/ b1 eif(!OnnxSetInputShape(m_handle,0,input_shape))
" C, E9 c9 x6 P6 o7 C7 l# i' K; D. a{
! _7 c, C- O! q: PPrint("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError()); N5 y. w5 O2 x1 O* y3 t. ~
return(false);% ?3 \% ] h5 r$ {8 o+ S! E
}* I: t& R3 h$ k* @
//--- since not all sizes defined in the output tensor we must set them explicitly+ ^4 w1 C* w' X5 [& }
//--- first index - batch size, must match the batch size of the input tensor p, O7 j7 l4 U! b/ r
//--- second index - number of classes (up, same or down)
` \3 O, D3 Fconst long output_shape[] = {1,3};
7 M, n7 j4 S& Hif(!OnnxSetOutputShape(m_handle,0,output_shape))- X5 D; H$ e# ]. D" V
{ L0 a3 v5 ?( Z8 \
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());( g! y8 p7 ^4 l9 H
return(false);
5 q- M( M4 c4 ]$ u# x+ |/ f}
4 ~5 Q+ U5 y4 C' u5 d* m//--- ok+ P( o* b' A/ r1 J' q
return(true);$ a/ i8 ?/ K: m2 `
}
" C: w# ]* }& ~4 ]4 p1 n4 Y7 L//+------------------------------------------------------------------+
/ _) @$ Q8 i3 P+ N) @7 o" S//| Predict class |2 w: Z d8 T/ z Q! c7 K' |
//+------------------------------------------------------------------+
# E ]3 l3 o1 @9 h0 ^' Bvirtual int PredictClass(void)
, A) i/ q+ @# H" P4 g0 O' L9 e' [{ |