1. 我们会用到什么模型呢?( o6 _6 X8 s) O4 ~% B! X# h
在之前的投票分类器中,我们用到了一个分类模型和一个回归模型。 在回归模型中,我们在用于计算分类时,用预测价格替代预测价格走势(下跌、上涨、不变)。 然而,在这种情况下,我们不能依据分类得到概率分布,而对于所谓的“软投票”这样是不允许的。! o! t* _8 _ T0 x
我们已准备了 3 个分类模型。 在“如何在 MQL5 中集成 ONNX 模型的示例”一文中已用到两个模型。 第一个模型(回归)被转换为分类模型。 基于 10 个 OHLC 价格序列进行了培训。 第二个模型是分类模型。 基于 63 个收盘价序列进
% b" T' x7 F# o; l9 F, n//| https://www.mql5.com |
; Z' a3 E8 r5 q* J5 y) `% \: U//+------------------------------------------------------------------++ C2 b# p! \* x' d* D z: w* _
//--- price movement prediction. R+ Z8 A. [& D- O
#define PRICE_UP 0
0 w( E( X1 R6 P: G9 f#define PRICE_SAME 1
: `8 g( `' r0 V5 _7 J3 e* R3 v#define PRICE_DOWN 2
* W( b j( m; m( E//+------------------------------------------------------------------+
- l8 N* i; y% m//| Base class for models based on trained symbol and period |, d, L( M- D" Z e. X3 W
//+------------------------------------------------------------------+
E5 w0 p X9 B* ]) x: [( I! ?/ N; \class CModelSymbolPeriod: F, R2 e# ]$ i7 V2 i: ?
{
+ B7 B5 k t) xprotected:
$ f9 u4 b9 O# m, }" ylong m_handle; // created model session handle
4 T2 L/ J. F& f6 W% e7 Dstring m_symbol; // symbol of trained data
6 u3 z/ \! o& e; a2 t& aENUM_TIMEFRAMES m_period; // timeframe of trained data
. S; x, m) R4 Q8 \/ D; v3 O* Gdatetime m_next_bar; // time of next bar (we work at bar begin only)
. `; @- z3 J# h0 H8 s3 n) B& Ydouble m_class_delta; // delta to recognize "price the same" in regression models1 @4 F* X3 n7 f5 s3 H
public:
/ }/ T# @2 s! l//+------------------------------------------------------------------+
% Q) K' g) L2 X' Y1 Y7 E9 q _ c//| Constructor |% O( T$ M+ n1 }# w, E! | K8 N
//+------------------------------------------------------------------+- @! ]" l3 s7 u( ]" k; a: x. a" J
CModelSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period,const double class_delta=0.0001)
1 Z* [! N) M9 N9 W: j7 [& r{
9 o0 R5 ?% L+ V- O, S; Bm_handle=INVALID_HANDLE;) k/ N/ f& k: p8 I1 U. R; Z( J
m_symbol=symbol;
* F* Q* A- Z3 Z8 Im_period=period;! T" P r' s# Y9 e* g/ ^1 k
m_next_bar=0;1 k- [7 @; T! z2 h2 h0 f6 \
m_class_delta=class_delta;
4 u7 c0 t& m) {( J( W8 ]! p9 V}
1 r4 O' O( t o5 L4 e//+------------------------------------------------------------------+1 F/ R- a2 i% w0 y- p3 P, g
//| Destructor |
2 l7 `6 S: U: Q( I) @//| Check for initialization, create model |6 F! ]6 W) ^% k# d
//+------------------------------------------------------------------+
0 K z3 W3 F$ d9 b; j- N+ }bool CheckInit(const string symbol,const ENUM_TIMEFRAMES period,const uchar& model[])6 b6 ]# D9 U7 @
{
8 A% v# S: w! e//--- check symbol, period
* v$ z0 }, h8 U# n' P. iif(symbol!=m_symbol || period!=m_period)! F, }8 D d! Q' h4 d+ s% z
{
3 L+ Y1 x1 U' }2 p6 M' PPrintFormat("Model must work with %s,%s",m_symbol,EnumToString(m_period));
. r' D. l- q; Kreturn(false);
& a3 t+ Z1 }2 b' o}
- |' ~" m P* o5 d& c1 ?% C//--- create a model from static buffer4 S# w/ Q' @" x
m_handle=OnnxCreateFromBuffer(model,ONNX_DEFAULT);
) C4 d: q* X9 j4 x# Pif(m_handle==INVALID_HANDLE)( _7 D4 R$ B3 r- _
{
9 N* j1 o0 w8 G6 V; R) D. _Print("OnnxCreateFromBuffer error ",GetLastError());! }% r# h% K$ n
return(false);9 I9 e+ [" L& ?% m3 v8 }- Y7 H
}
( f5 [6 `; f! k& D' I5 V//--- ok
0 H+ k0 D" c4 _return(true);: @8 ~& W1 f, m
}0 ?4 S. r, D4 Y3 \
//+------------------------------------------------------------------+6 ]% e& S' s+ i4 v% f! P
m_next_bar=TimeCurrent();) l# V9 F6 C; @+ \5 w! e
m_next_bar-=m_next_bar%PeriodSeconds(m_period);! k) q! v. T9 b$ k3 f
m_next_bar+=PeriodSeconds(m_period);
3 [( \% z7 @4 G. A9 w//--- work on new day bar! W7 a) \* [' o1 F$ U$ `
return(true);
3 T# |/ k- Q& m}: q1 a: R4 W: }8 Y
//+------------------------------------------------------------------+
8 r' P; y9 _$ w//| virtual stub for PredictPrice (regression model) |
/ I3 i0 R8 ~( C U8 p//+------------------------------------------------------------------+
' n1 {" F" M3 X. Z* Dvirtual double PredictPrice(void)4 \( Y7 ^2 E1 d' B; G% E
{
. R( ~) y8 G2 u6 o( y* ~, J& Rreturn(DBL_MAX);/ T! K4 G" l8 X2 Z2 b% Y/ O6 |
}
* R6 a9 l( N6 F- {0 g' R//+------------------------------------------------------------------+
: c1 F g- a7 H) g' ~/ V4 x//| Predict class (regression -> classification) |
! W3 b6 I! K% g% U; k//+------------------------------------------------------------------+
" `. D; `2 G) X" j1 ]2 _virtual int PredictClass(void)
1 g& Y4 E( z5 @! X( {/ ~+ D1 ~% a{- z/ k. y4 R8 g& c! e* }
double predicted_price=PredictPrice();
$ e$ E) s( X4 [9 \# N8 y$ Xif(predicted_price==DBL_MAX)
. A" a( |7 ? \0 |. |/ `: f* t freturn(-1);
* J! k7 ^' A9 s. b$ | O/ lint predicted_class=-1;
3 o6 Y9 S8 ]) k( Y) x3 xdouble last_close=iClose(m_symbol,m_period,1);
% _' t5 r z' V//--- classify predicted price movement/ c" U$ K: b& y6 q6 }) a
double delta=last_close-predicted_price;
0 H8 X2 |& M0 k. W u4 U! Sif(fabs(delta)<=m_class_delta)3 F$ F+ Q+ W6 y/ {
predicted_class=PRICE_SAME;
9 ?1 K0 a# [9 Melse
1 y0 J9 P' S, ^3 _# c8 Mprivate:
. \) {( {6 e! Y5 d1 P, |9 T( e% aint m_sample_size;
6 g0 P( C* E) I+ `; f# i V//+------------------------------------------------------------------+' a! _3 G" N- |, t1 m% z
virtual bool Init(const string symbol, const ENUM_TIMEFRAMES period)1 O, }" {# C9 j6 Y7 `7 D0 V1 g
{
+ j, Y, y+ a( U: P) K9 ~$ j+ g//--- check symbol, period, create model
p. I( h0 f+ y. ^# lif(!CModelSymbolPeriod::CheckInit(symbol,period,model_eurusd_D1_10_class))* q5 _6 O$ ~3 E2 R
{& S0 i) j$ A' U) f& h! f4 b/ b1 l& x
Print("model_eurusd_D1_10_class : initialization error");* Y; K/ Q" Q% Y1 v2 [. v1 S3 Y3 g# W
return(false);
+ o7 k+ F; D8 f; Q}
7 F& [9 {' j! u& \$ P, i: v//--- since not all sizes defined in the input tensor we must set them explicitly
8 V, H5 t% r2 }$ n! ]//--- first index - batch size, second index - series size, third index - number of series (OHLC): v: |& z7 q+ u& B2 g5 h
const long input_shape[] = {1,m_sample_size,4};
C2 A- ` ~3 i9 V! D, Tif(!OnnxSetInputShape(m_handle,0,input_shape))
7 S, L3 a: n7 c) Z{" g& I% C$ t0 m4 k5 V
Print("model_eurusd_D1_10_class : OnnxSetInputShape error ",GetLastError());8 r/ E- }7 z% Y% K( u
return(false);; m5 T: Y- w8 N4 {
}
; ~! X" }3 _! L& m% y) |//--- since not all sizes defined in the output tensor we must set them explicitly
, C- ~. W& z5 D: ~; ]//--- first index - batch size, must match the batch size of the input tensor
( ]5 A+ n _: W+ X- A$ K! A) l//--- second index - number of classes (up, same or down)! ^$ `! r1 C* T$ w, ~2 G5 `
const long output_shape[] = {1,3};0 D9 R8 g1 V" f. b" n" D- p
if(!OnnxSetOutputShape(m_handle,0,output_shape))( x- c5 B) c" ]& F7 f
{( `- d6 p' l; `7 @5 W/ u2 J! x& x
Print("model_eurusd_D1_10_class : OnnxSetOutputShape error ",GetLastError());
3 R% C" Q' K- z- O U- ^; m8 F: Jreturn(false);
8 n/ Q* l- h* r. a}1 s: q) M0 k; D, V$ F
//--- ok% N# m" ?1 _! e$ d0 F7 y/ P% A
return(true);
$ A- D5 O0 G0 K! ~+ R: `( ?}
* y" }, }: t# h( B& V6 X//+------------------------------------------------------------------+- D- N$ [/ H/ `" [9 U7 o; z }
//| Predict class |
5 \( K8 ~ n( o6 Y+ I/ |//+------------------------------------------------------------------+
8 X; ^0 m" v; }* ^2 ^virtual int PredictClass(void)
8 E8 e' [; B# q d9 j{ |