启动交易模型,并构建 EA5 E+ Q+ T* Y- Q- t. n
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。8 M% ?0 ~7 C& S
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。+ Q, I `" F* Y. O2 Q" O. M0 u
以下是制定这些规则的代码。
5 m' I; h& ^' ?; k//--- Indicator ATR(1) with EMA(8) used for the stop level...
0 G2 Z6 ~: m/ J0 \- p. qint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);- m' U: L+ G [' [5 W9 N
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);6 c& W+ E% j) y1 j7 W1 b' i
//--- Define a variable that indicates that we have a deal...
1 C8 [, L" A2 a2 lbool tem_tick = false;( w2 W' z( C2 {8 Z T
//--- An auxiliary variable for opening a position
, J, y0 f0 f" j% n# R. p#include<Trade/Trade.mqh>
! r' I3 ]( W: D" O3 t) P" v#include<Trade/SymbolInfo.mqh>
8 ^. w1 M4 X8 u8 E& b/ @CTrade negocios;" O6 v M( x( j( l& K
CSymbolInfo info;+ M* k! e" @0 x
//--- Define in OnInit() the use of the timer every second
$ {: p# b0 G( |! T//--- and start CTrade
6 h0 u$ C! C' |int OnInit()7 k* l# h$ x! O$ O8 N
{, h" W8 G% `$ h
//--- Set the fill type to keep a pending order
# ~$ q. a% \: _, t7 k//--- until it is fully filled! m+ t- y/ [, K. \9 A
negocios.SetTypeFilling(ORDER_FILLING_RETURN);" Y8 B, r2 E9 e. y8 m8 W+ M
//--- Leave the fixed deviation at it is not used on B3 exchange
, Z8 @7 r- \9 D& Unegocios.SetDeviationInPoints(5);2 @/ V- X' [; d6 t
//--- Define the symbol in CSymbolInfo...
& v2 q# T9 h5 E5 ~info.Name(_Symbol);9 w H! o+ G, j; p* ]0 V
//--- Set the timer...* [ N, e! v( d. L( c7 q4 `' T9 o
EventSetTimer(1);
8 j$ H3 X0 l; j- L//--- Set the base of the random number to have equal tests...' R5 S8 c& z3 `8 {
MathSrand(0xDEAD);! z+ b2 y: l; e; {/ N/ S! J1 s; A
return(INIT_SUCCEEDED);. r& M1 K3 P6 l; t/ \7 }- V0 S
}3 L4 A b: m5 a' ?5 r) w' F* C
//--- Since we set a timer, we need to destroy it in OnDeInit().$ O/ b6 |* y+ G: J0 F3 n+ @
void OnDeinit(const int reason)7 a- {: G# n1 a0 k: p4 j
{
7 a {) E6 h6 \$ [1 C* @; ZEventKillTimer();9 B4 I( H+ D$ V2 j8 ?" d( P. G. b2 p
}
) h5 h V2 ?' j' ]& R! C: B9 }//--- The OnTick function only informs us that we have a new deal, V8 ^7 w$ K/ P: C9 K2 O; c& i3 @! S. Q
void OnTick()
' L1 L% l q, F6 E2 D& H1 Y{7 Q9 [/ O: } k6 z% S+ y
tem_tick = true;
$ m% E, o; z. r. T/ z}
/ m [* g: y3 A G- Z0 [//+------------------------------------------------------------------+9 {- M& k( T+ Z8 H' D
//| Expert Advisor main function |
7 T4 L7 A" c8 }! k//+------------------------------------------------------------------+
$ M* U, M/ f: Mvoid OnTimer()# _5 J8 C7 q5 m& N9 {
{- M! v5 g6 i3 J4 D
MqlRates cotacao[];
$ P: c. `. i ?, h& V; Mreturn ;
" h5 ~) ^5 O# w/ t' J: iif (negocios_autorizados == false) // are we outside the trading window?
3 k3 N( A$ C3 @3 h9 \9 t! vreturn ;
2 R# q' T' P$ _' G4 b6 t//--- We are in the trading window, try to open a new position!
" T, Y' A. J* [0 q' P) n: E- A4 uint sorteio = MathRand();
A; r# D1 ?: ~3 c/ |8 G% L//--- Entry rule 1.1
' p6 N! W3 s) \# U$ D6 q4 v( t: cif(sorteio == 0 || sorteio == 32767)
! M8 U, D& Z+ B7 Ireturn ;: h+ Z# p! u( X1 d5 @; R
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
2 z+ a k( u" S1 x& o5 p7 p{
2 }4 r1 p' ~- i2 S. }: Z6 d: n" v5 Dnegocios.Buy(info.LotsMin(), _Symbol);; Y7 E5 k* F% p7 N% m) b+ H
}& j. S0 L6 n# Y" f1 E. O }1 g. R' \
else // Draw rule 1.3 -- odd number - Sell
! |" c6 M8 Y2 P& g% t9 }* ~2 I{
6 \% ?$ |* d/ L' g9 y: P6 `- Enegocios.Sell(info.LotsMin(), _Symbol);. v* ]. C3 d9 V' E( r. A- k
}5 g; i0 O7 {2 n- |+ j/ `9 F- x
}
k5 |) O/ v6 K7 l//--- Check if we have a new candlestick...1 g8 {1 J% G. P
bool tem_vela_nova(const MqlRates &rate)
8 o/ s }' y2 E. w5 L{$ f; T% d! ] v& r2 s3 `" f
{
8 L$ j; J6 P9 cret = true;; [1 q% V" V+ |; s
close_positions = false;4 g/ H# Z6 t9 H3 ?1 y
}$ G8 X; v; I4 `. C2 ?
else
; {: ?' U M( A! U7 [, {7 u{
$ U& _$ r. l9 P# J+ Lif(mdt.hour == 16), \; s6 @9 S) {
close_positions = (mdt.min >= 30);) Y$ t' M! n8 M0 m; n; q
}
# {) g2 e! U% D) d/ @}/ c( O: T0 K6 W! Y$ R% y" f
return ret;* m5 J* G/ s. D8 o+ q
}
. J6 H# H' E4 n+ @//---& A- e% j6 _' ?/ D) f" I: F$ f- F
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])9 n: j& M( w; c( I$ x
{
% j8 K7 x3 r) u. Q9 `% x4 `% lif(PositionsTotal()) // Is there a position?, T6 x4 v! L; l, T, `8 V
{
; }, c3 n5 ?1 ]) ^' X) S0 s! _8 D" ~double offset[1] = { 0 };$ V9 L& Q) ?# A( W( N
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
+ r q8 f" u/ @: q1 S+ T&& PositionSelect(_Symbol)) // Select the existing position!8 y! q7 a' T* X0 V, R. [9 i# O' d+ ]
{
. J( \/ l6 a4 r6 Z$ E& |) T4 t6 W$ TENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);2 T8 i+ d/ Q! [/ O+ m1 p/ _1 a, {
double SL = PositionGetDouble(POSITION_SL);% `+ a$ ?5 ~& a
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
0 {" \( z1 ~5 F% Y h/ {* ]if(tipo == POSITION_TYPE_BUY)/ a, j7 A* y2 \# n
{' K( G' t5 V+ ]5 l! f" @ I
if (cotacoes[1].high > cotacoes[0].high)% R1 X1 \5 g9 q' u- H$ a4 m
{1 r! d! L j) }* L9 y4 O
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
% g/ Z" N* g7 S6 I S. Oinfo.NormalizePrice(sl);" q) u1 f r: C. i
if (sl > SL)3 l1 P4 Q1 v! |
{% \. R; t! P! B9 [* D
negocios.PositionModify(_Symbol, sl, TP);
: m1 i% B+ y. `}* k1 f% ], {# M5 p# B
}- v8 f" t9 L% l- Y3 v
}
6 n# o) A/ C# e# [else // tipo == POSITION_TYPE_SELL( O$ R8 g, _- c- \: y9 f. f$ w
{) H' P; k) O3 O! ]3 L
if (cotacoes[1].low < cotacoes[0].low)
8 b4 F+ V$ e# H, ^- ]* q{
9 v8 ^, A* x. v8 ~. {2 x: Mreturn true;" F5 d0 C/ I& z
}
+ F$ F7 ~# l& L5 d: W6 p# q5 f// there was no position
: V$ M6 W( W7 u* b: ?" Ureturn false;
- b# Z5 j! {+ }# G+ g: v$ d& ]}4 X4 J, v$ L. r# ` `/ _
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。9 Z! Q6 |8 y) a8 ^" x) g d
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |