启动交易模型,并构建 EA% p h9 E$ I7 h* S N- a
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
. g+ ]7 y3 u5 \ W6 ?为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
0 q! R: h* h& J" t; z' {4 m+ v以下是制定这些规则的代码。
' b( }% v2 Q1 E/ @//--- Indicator ATR(1) with EMA(8) used for the stop level...
, p5 ?, D. W4 m' |) vint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
5 a3 X/ t [3 C' a* K4 M! s9 x; iint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);8 n6 ?' a; X6 O2 U& I0 L. c; O
//--- Define a variable that indicates that we have a deal...
$ |- s4 |1 ^7 n# ^bool tem_tick = false;2 ^" e; [% w6 K4 |
//--- An auxiliary variable for opening a position
. D2 m E& R& p/ n4 ^( d8 f#include<Trade/Trade.mqh>
4 b. a" E2 O" o9 x9 Z( \' O#include<Trade/SymbolInfo.mqh>
& s$ {% f) N% U) A- M" GCTrade negocios;. p) u: u2 p( t' d, m8 T
CSymbolInfo info;4 V# ]( ~2 D, S& P+ R: t
//--- Define in OnInit() the use of the timer every second
+ w5 `3 R! Z9 A. Q" @2 g//--- and start CTrade
4 J- w8 ]$ ?) O9 Nint OnInit()
" ~% {% V4 A- B$ l3 | `! p{5 @* { M0 K$ ~* @" S- l
//--- Set the fill type to keep a pending order
! P# C# a$ W" \! J//--- until it is fully filled
# m+ G+ g4 I* B8 X6 w0 Rnegocios.SetTypeFilling(ORDER_FILLING_RETURN); F9 M2 A0 H, x- H8 f( {$ ?; q0 K
//--- Leave the fixed deviation at it is not used on B3 exchange6 ]) V. Z- j$ g" I8 O/ D
negocios.SetDeviationInPoints(5);
# e1 w# U$ q7 d//--- Define the symbol in CSymbolInfo...* r" w1 V' }+ s
info.Name(_Symbol);* p7 y' x) X4 p! a: ^% u4 O* b. T
//--- Set the timer...
: L8 ^: s$ Y) J2 NEventSetTimer(1);
! y9 s0 Y7 F8 e//--- Set the base of the random number to have equal tests... N# ?; e5 c4 |9 G& b" V$ d! a6 G; K
MathSrand(0xDEAD);5 a5 ], A9 w( G- q+ V
return(INIT_SUCCEEDED);
+ Y; N4 E; `7 w! f* `# q}
$ \! Z8 X- B8 ^( o8 D4 Z//--- Since we set a timer, we need to destroy it in OnDeInit().2 w. ?" n" } r8 w
void OnDeinit(const int reason): k+ J1 R6 H3 P, O) e. r, \" ]
{6 J- w' ~4 h5 _; `
EventKillTimer();
0 v0 C+ V" D# }) r( n! q/ b+ w}
1 T( K7 k9 m6 s% l//--- The OnTick function only informs us that we have a new deal
0 Q4 ?0 E9 K- U' rvoid OnTick()
# @: b1 o9 ]* K: o! T L{& v2 V% j) z3 V) p
tem_tick = true;+ ]7 A( R$ T: E
}
0 g& k3 _. i' \1 @' B ^" P/ Y//+------------------------------------------------------------------+
1 ^( e1 G; C" B3 V \% v) T//| Expert Advisor main function |
* \' x! S" n2 c! j! ~//+------------------------------------------------------------------+
( n* R" \& o9 n6 ^, Z* I! Rvoid OnTimer()
9 y" e) H2 j, H{
& }# B( W$ Q- O c: s3 G+ b1 o! RMqlRates cotacao[];- V* J8 ]' W) m( W
return ;4 _2 M" {" O7 `/ n5 m: E! }, k6 @
if (negocios_autorizados == false) // are we outside the trading window?; T) H0 e3 F. R% A5 y7 X$ A) B' {
return ;
4 b4 m8 D# j5 K9 g//--- We are in the trading window, try to open a new position!/ U3 l- A3 b% @! f- q. Q
int sorteio = MathRand();
5 F" Y% E7 K" B3 ?. y8 h//--- Entry rule 1.10 w9 C, \+ j6 r0 `- O
if(sorteio == 0 || sorteio == 32767)) R# H* L1 F [5 ], ^( N
return ;
) \$ r% I' |3 O/ xif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy& g( Z- a5 \5 Z' Z Q, Q6 Q7 [/ f
{5 `: y: l* ?% c: Q
negocios.Buy(info.LotsMin(), _Symbol);
7 z, |, W& \ b}! w$ t, |) X' T4 r0 a) w) p
else // Draw rule 1.3 -- odd number - Sell2 b1 Y" | k8 w. F* i
{
8 E' [( J4 a2 ?8 h. n; g- }1 x2 ~( Ynegocios.Sell(info.LotsMin(), _Symbol);% k) d$ A8 P1 ]( ]1 u1 F+ C
}
0 {+ I, ]9 p( e5 ~}3 N; u8 _: O' l- N, N4 A
//--- Check if we have a new candlestick...+ W/ G+ @9 f0 O) C9 z" U; y0 x9 G# e
bool tem_vela_nova(const MqlRates &rate)+ ^. i @3 ^, W$ ?) l1 c0 J! I& L
{2 `4 Y# Q: P( h2 e
{7 Q2 @( T$ Y, t% R8 K
ret = true;& b& E0 S: Z* C9 N5 @
close_positions = false;, Q8 T6 b) J, @+ h) V3 S
}
& W+ \4 H9 M; e4 d" k/ F; H! oelse: ^0 \( P8 K( I* V5 @
{
$ I% k6 m. m- R4 K! _' J3 tif(mdt.hour == 16)5 a- W* K! _: M% k! C: M4 W
close_positions = (mdt.min >= 30);2 g0 w, K5 ~/ `" U' f' ~- n
}
3 X( k( Q4 J/ N9 s}
1 Z+ P# u- k& m2 m/ @8 F( Dreturn ret;+ \$ {4 H7 T/ m" I' {! {
}, ^! w7 ~% s$ ^3 b/ i- F
//---. _5 I/ w! y: f7 C' d$ E+ l
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
. \; M3 g3 D. q$ {1 O{
6 q& v4 b9 c& g/ N6 T& a+ }if(PositionsTotal()) // Is there a position?2 H$ O# ]' P' ?6 n: O! \ A( |
{' y: G; R4 U2 I* a
double offset[1] = { 0 };& s! Q* }/ e' y) h' E
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
" Q( y0 U" u0 a6 E( g7 o&& PositionSelect(_Symbol)) // Select the existing position!
5 X& {! h/ a" c' H+ `" r3 b, `{ Y9 Y; U) N2 _$ b0 {
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
: A; P2 l0 j% @3 o6 A) p/ f1 Pdouble SL = PositionGetDouble(POSITION_SL);" p+ d2 x# G: |+ P0 t. E8 K
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
6 X4 C+ {1 b/ U% Gif(tipo == POSITION_TYPE_BUY)
7 F, B: B+ {3 M) f! {5 S) f4 _7 B{# T2 I" f: l1 M! g8 W
if (cotacoes[1].high > cotacoes[0].high)
% j. ^/ P2 @5 z7 z {# V# ]{
/ q" C' x; R) D7 ? Pdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
4 V7 m$ A* m! A5 N5 minfo.NormalizePrice(sl);5 I' \! _* u- ?5 m# V9 w' X i7 Y1 Y
if (sl > SL)
, \8 t) g9 l# x, I! l. }: @{, e* n! h' y: k- F, `" r Z7 E! K
negocios.PositionModify(_Symbol, sl, TP);, N9 s5 f3 D$ `8 ~' ~5 p$ {
}, t( u# W: l. g0 Y+ L
}3 S o. L {$ b, x1 _, k
}; S l ^" |3 m2 E0 }
else // tipo == POSITION_TYPE_SELL
4 M. J7 D8 }- p- U9 O& q{
& q% y, q# r9 fif (cotacoes[1].low < cotacoes[0].low): R9 g/ u7 a7 a! ?- C, B. W
{( |/ G+ ~' F1 Q+ {+ T. W. o
return true;. j, ]0 ]0 T( I
}
0 G. y& ~. h3 I* ~- N// there was no position) w( o: y3 C* k J; _) P
return false;& D( i; a n$ T3 x) [+ C
}
/ @- O; K, v- o0 G我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
6 l" ?4 B1 a' Y- k5 T. y到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |