启动交易模型,并构建 EA
! l3 o; |! C# s, A/ \ j; [( c) D在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。; }/ b" m, I: y+ g# i
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
( z6 U5 \$ q* Z/ t以下是制定这些规则的代码。
, Y! W: F' }0 o" q% f& s+ ~4 F# [6 S//--- Indicator ATR(1) with EMA(8) used for the stop level...
- e% _+ c" r9 P. d5 Yint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
: n% p. j" [, F: H( E" _' `int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);' d5 G' H5 s7 \, `
//--- Define a variable that indicates that we have a deal...( ?8 g: M; \$ t' Y3 b* s! p
bool tem_tick = false;
" [- E4 m# [# K# m7 q; s3 _' P//--- An auxiliary variable for opening a position) A% x& |6 G$ ~2 v
#include<Trade/Trade.mqh>, J: B" v6 f3 h0 O4 V# ~
#include<Trade/SymbolInfo.mqh>
! j1 Z& d, c% b0 X& U* ] ~# LCTrade negocios;+ [( A. s4 K: R; C* S
CSymbolInfo info;
) U8 h0 _5 e8 P% A( e6 x//--- Define in OnInit() the use of the timer every second
) v3 W/ c* l- E6 W7 `3 [9 x//--- and start CTrade3 `( }1 J- F5 N6 V" ?4 I
int OnInit()
# p1 z/ b* L D+ y I{
6 F( B1 R q% p//--- Set the fill type to keep a pending order, i4 g. y; C; Z# R5 w Z1 E2 K
//--- until it is fully filled5 M7 j9 ^0 f- ~7 M
negocios.SetTypeFilling(ORDER_FILLING_RETURN);1 k" p) I' b7 m3 d& H( Z. t
//--- Leave the fixed deviation at it is not used on B3 exchange
: ~. {2 E/ ]+ y$ T9 ~) qnegocios.SetDeviationInPoints(5);
$ q: a' p' W6 {% B) \//--- Define the symbol in CSymbolInfo...
7 U/ D& }7 ~$ hinfo.Name(_Symbol);
$ R$ b$ h% l& @8 S1 T$ R, \//--- Set the timer...
: Z* X, q a! FEventSetTimer(1);
7 Y0 r2 K* O! o& ~& W//--- Set the base of the random number to have equal tests...+ {# P, h: H. {: s% J
MathSrand(0xDEAD);/ B7 ?) k* v, ~: R7 N2 @
return(INIT_SUCCEEDED);9 P& K0 ?9 z2 G% N
}
8 w8 B" {; p6 k3 v3 \//--- Since we set a timer, we need to destroy it in OnDeInit().
1 B( y: S. ^0 z ~6 mvoid OnDeinit(const int reason)6 O% {6 ?, |+ M2 r% H, X! r
{1 w" U& u% K) W( Z+ B
EventKillTimer();6 h6 |5 s; Y$ c1 b/ d" H
}* V9 L+ ~ a5 B8 o, t. C3 P
//--- The OnTick function only informs us that we have a new deal
7 m9 M# N% N y5 ]4 dvoid OnTick()
% z- C. y4 J5 k/ d{- \& ?- ]1 e( }8 N8 R5 }6 T0 L
tem_tick = true;
. s5 Q8 f# x: X2 c}
: ?' x! F2 S2 O+ y1 U& O//+------------------------------------------------------------------+
; \7 t5 T0 V( \2 f8 Y# P//| Expert Advisor main function |
9 `5 K; w' ]/ ~$ ^//+------------------------------------------------------------------+! y) U- j" n2 w& w) c+ l2 i G B+ g4 B
void OnTimer()
: i/ \2 h; s5 i9 v5 D0 k{
9 `3 n# p6 L9 NMqlRates cotacao[];! W! y# l* l* E0 U
return ;
[+ D- _7 Y4 H* Iif (negocios_autorizados == false) // are we outside the trading window?. h& m5 R, u ^( E% ?
return ;! i+ W% r4 Y( W q: V
//--- We are in the trading window, try to open a new position!
# Y Q$ ?7 O2 ~6 }( z) e* Iint sorteio = MathRand();
5 \. r/ {9 \, ~. [# R//--- Entry rule 1.1
9 i- T `' a0 Fif(sorteio == 0 || sorteio == 32767)
3 t- R) @% P" vreturn ;
% W$ J. I4 X) A( ~5 b1 s8 Gif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy7 S& m7 x, y/ D! Y
{. n: I3 j" w1 m Y& M7 @5 q1 p
negocios.Buy(info.LotsMin(), _Symbol);% E# s! r' `6 D1 T( I$ ~) L0 t% ^
}: L, o* q& X- Z$ a k% h2 N8 w
else // Draw rule 1.3 -- odd number - Sell; a( c* @- d9 R' W1 s; P
{
+ s$ `- V$ @3 U8 d4 F: A4 _; R# @negocios.Sell(info.LotsMin(), _Symbol);5 {0 S/ b6 d1 V2 ^) z& O+ |
}( V& o* h. E# ~) A' ~4 E
}* p3 s+ `: G( `- k7 ?1 j
//--- Check if we have a new candlestick...9 h' w4 }7 V2 z( k' |. m
bool tem_vela_nova(const MqlRates &rate)' ^6 m5 R- s3 i) j+ n" w
{
, T) N7 B7 z5 {6 i- `* p8 \4 }{
9 }# l, e8 E6 cret = true;
) y2 _4 `; E+ @, ^0 }9 y2 uclose_positions = false;
& F0 l4 B& q; W% |}7 B9 ], Z% b8 z( h/ m4 V
else, {1 T$ I" O! {$ n4 [
{
$ B9 |. \/ s, \/ Jif(mdt.hour == 16)
/ P- c# t$ {/ G; D- p1 Nclose_positions = (mdt.min >= 30);& b7 z/ E4 C9 A. `2 b! ?6 v
}; h$ g, N2 l- R- Q) n4 F/ o# @& K
}6 t1 C7 j \+ h7 b( ~2 p/ p$ k
return ret;
. E6 F/ n8 Y- W6 @}# T) o. u" v0 E4 Z
//---& ?; P- k, V; Q7 [
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 G& W* O7 T7 P" g, B/ k3 E/ [6 z1 O{
% t) k E) N5 c$ K" w5 B& q3 t( Pif(PositionsTotal()) // Is there a position? L! \3 Y* W$ C+ M$ P: S4 M5 x& x
{
2 R, l$ K. {( Zdouble offset[1] = { 0 };
- \9 V( f) ?; ~* wif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
+ U9 ~9 I; @ ~&& PositionSelect(_Symbol)) // Select the existing position!8 D; h: N) C9 N6 C0 Q$ [ L L0 h
{" [ S9 O+ j. [0 F$ S! q
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
/ g/ Q! Y- ]/ T% fdouble SL = PositionGetDouble(POSITION_SL);
# N. L$ W# _9 W7 @ c6 l6 u7 d; vdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
$ w" z7 B( ]; Rif(tipo == POSITION_TYPE_BUY)
- F: E( V. F y! o{( _# l; {3 D& x( T! t: `
if (cotacoes[1].high > cotacoes[0].high)
5 M6 c, a! K& p5 y{ J* L f) n2 f2 N2 q$ P1 A
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
9 W! X9 Z9 k6 J' T+ c# G# ]info.NormalizePrice(sl);0 G3 ^, _; k, E3 m T6 W! z
if (sl > SL)
% F' y7 m; I# n{
Z2 l/ a& _, P: Z T! M' Qnegocios.PositionModify(_Symbol, sl, TP);5 c' L; y& R, D
}- r a1 U' v) x, u2 F9 L! Y8 h* y
}% C& P. Q2 T7 Y$ ]9 |
}3 g: I6 m$ q8 @% D8 n* Y1 L
else // tipo == POSITION_TYPE_SELL$ a0 ]/ n8 V0 H. @) f: B- m
{% K( Q- r8 N' v; [" M
if (cotacoes[1].low < cotacoes[0].low)
6 C( C# w2 v& t/ U! O; z, A{
8 }5 @. X# ^, x/ [# ]- @6 Xreturn true;" i$ ?5 {7 O, G: H s4 V
}
2 E5 S* ?# E2 W* v% X" _2 h( ]. Q// there was no position6 o3 `9 y9 J1 a, l3 D
return false;) z% f" l R( h+ ~, \
}7 P& r! Q, j6 k/ N0 ]
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
' z2 o, {; \ ^到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |