启动交易模型,并构建 EA7 t. ]1 `- i' a2 M
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。: a" j! M' }. P5 _3 ~. F
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
& }) T' A3 s4 `/ A( b% o. d以下是制定这些规则的代码。" \' C [* ^, ]& h1 j
//--- Indicator ATR(1) with EMA(8) used for the stop level...
2 V% |% }' E9 t+ O4 n) `, xint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
% ] }5 I, I* B6 h* ?1 S3 Dint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
- U. U5 L# y" X- X$ `# n//--- Define a variable that indicates that we have a deal...) w7 b0 P# b+ Q) w& C9 ?) Y
bool tem_tick = false;% `( ~# n' `4 b( w
//--- An auxiliary variable for opening a position
4 y3 W5 x, ~: |5 }( r#include<Trade/Trade.mqh> q7 Q# d: n! r4 t7 M7 P2 u* q2 t) e7 x
#include<Trade/SymbolInfo.mqh>
" C' |/ s( o! k, CCTrade negocios;
T$ Z; f3 w, U' TCSymbolInfo info;/ ], x! h( U1 L- x9 P ?4 G: m7 H9 A
//--- Define in OnInit() the use of the timer every second6 G6 [0 K* `3 \
//--- and start CTrade4 i( i: @$ z7 t8 S6 J2 Z6 t
int OnInit()
$ l- u6 N9 T% S& C( q' O% T- B& ^ Q{5 ?" Y) u. \/ N8 c7 h; b* M% p- C
//--- Set the fill type to keep a pending order
# O: L) K' q7 o# j) i+ |- ?//--- until it is fully filled
9 Z! Y# Z' D" V; T2 H( Wnegocios.SetTypeFilling(ORDER_FILLING_RETURN);% R6 _9 A6 f# b7 L" u% w9 U4 W, X
//--- Leave the fixed deviation at it is not used on B3 exchange
% f4 l' ]7 q0 V/ A9 nnegocios.SetDeviationInPoints(5);2 \' x3 m( r. Y1 z5 [7 H4 t$ i
//--- Define the symbol in CSymbolInfo...
+ F. d, O- }/ d, p/ j% B" Zinfo.Name(_Symbol);$ P: V' s3 E3 A6 d4 j3 D
//--- Set the timer...
/ H: T9 t2 j' i- ]6 o' B" IEventSetTimer(1);
: R& ]7 f+ L6 Z. f( i' B# G! ^7 {//--- Set the base of the random number to have equal tests...( U6 e' \. J! j9 b3 \# d
MathSrand(0xDEAD);1 _) e& V; h4 Y
return(INIT_SUCCEEDED);
6 n/ o7 E% l; D s2 f; p/ X}
' _$ Q# T3 x! I+ f& F/ `+ y u//--- Since we set a timer, we need to destroy it in OnDeInit().
# |5 S5 _5 T' Cvoid OnDeinit(const int reason)
+ {/ e& }- n& q6 |% Z& \9 G{
0 _; h1 |, e. s B/ g0 r% X' JEventKillTimer();
8 B, g6 B# a4 {" K4 A( A1 s* y2 ^}' w0 B5 |: r2 X% C7 ^
//--- The OnTick function only informs us that we have a new deal
9 o- |$ q) G0 v: qvoid OnTick()
) _: @3 b- N: h; U{1 Y! C, I3 T- X
tem_tick = true;
" y9 S1 y0 y; J% I6 t0 i}
# S" D. ]# ]% T8 j//+------------------------------------------------------------------+% l6 Y/ o& x' z' I1 F
//| Expert Advisor main function |
3 V n5 O/ I# C0 j, m% l9 b$ L//+------------------------------------------------------------------+
. r- \* E: \ G& Q; V7 }8 uvoid OnTimer()( p) a* Q' o1 z R
{ S. u1 J1 u* v8 b+ n# N9 c5 e
MqlRates cotacao[];8 O" g3 }* r# C9 q) Y. u2 P
return ;
9 I6 r) u2 ]6 i, P+ fif (negocios_autorizados == false) // are we outside the trading window?) o5 Q- Q) W, k! h- }* n
return ;$ w/ ?# P b& R/ _/ v- K
//--- We are in the trading window, try to open a new position!
" t% b" X) [+ L7 rint sorteio = MathRand();7 G9 o3 [8 D# h' |. O' j& v D1 ^
//--- Entry rule 1.1
2 J0 e/ P, D5 m9 ?if(sorteio == 0 || sorteio == 32767)
% L" Z- y( Y; L! Z# Areturn ;+ I( y& r; u$ h. x6 y
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
! v$ M3 y# \6 Y2 O+ V9 _{& o8 T# h' s$ k) D. m7 C% N" U8 a
negocios.Buy(info.LotsMin(), _Symbol);2 s, x* q3 f' u, b G- a) k
}
" E. w; q; J. xelse // Draw rule 1.3 -- odd number - Sell, ^4 Z3 m L( o( |
{
. f5 a d1 \: M, w& F6 I) L+ {2 |negocios.Sell(info.LotsMin(), _Symbol);
: S# y8 N1 ?5 ~$ U3 {8 V n# Y}/ h3 Q% ^* \: e+ D* Q
}5 H' W1 a5 w0 c5 y
//--- Check if we have a new candlestick...1 L, {3 m1 q6 A6 N) \
bool tem_vela_nova(const MqlRates &rate)
! F* a* A, n+ p" }# S( ^4 b{
# k7 a! e9 ]/ O- H{8 Q& j8 s ~8 t& W% I) p
ret = true;- p5 m! ]% B L" w( P8 F
close_positions = false;
0 {$ o! P2 m, S5 c2 o}+ O; n4 U0 h+ a2 y- u/ ^
else% ~0 L0 y1 E1 H7 F2 {( B
{
: K3 s0 ]$ Z$ @4 K3 bif(mdt.hour == 16), j6 m; y# p* h! t: h6 `4 \
close_positions = (mdt.min >= 30);
! i! s0 e7 s/ a/ C4 N4 Z9 L( Z}
# O/ W7 ^. T( G! I2 p+ C( q- v I2 K}* y! y2 x! o. V' M, Q3 u' }4 J
return ret;
?# B0 u3 Y* r}* f; n0 b+ n& i2 k2 J
//---$ g1 L. C f( J q& c7 o9 a
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
" k0 r: r* ^8 y5 G{
1 ^. b6 @! _: C( b1 i2 rif(PositionsTotal()) // Is there a position?
$ @$ c E) C6 L3 {, n, {! M{
+ Q2 Z$ a* a2 k5 p& adouble offset[1] = { 0 };
0 u8 U; B1 f$ J7 A% w# Xif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
4 ?0 w+ q7 Q7 {&& PositionSelect(_Symbol)) // Select the existing position!
" h# f0 q: s( h0 I! K) }* Z0 }' I8 v{
1 l; _' q8 a7 d* ]1 CENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);; m% u% G5 G3 g6 L; h
double SL = PositionGetDouble(POSITION_SL);5 y' C, C5 q; {* T: u6 w7 Q I" q
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
% k2 ^; u# ?# L) w0 l' j1 j$ O, o+ Tif(tipo == POSITION_TYPE_BUY)
- T5 r# L; X* G. P{
; {! m/ E% m6 e/ a3 A' D6 l; B: Kif (cotacoes[1].high > cotacoes[0].high)
2 b6 p) ^, k; ^) ]: r. I5 ]{
8 F L' l" U# xdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
- j+ B2 k$ T* Xinfo.NormalizePrice(sl);' v: @" e8 M' r4 s, t
if (sl > SL)
$ a" e' \( v/ \" Q: T. N{1 `9 _/ o: u. R) P4 t7 V
negocios.PositionModify(_Symbol, sl, TP);
7 M* _" B2 T6 t7 U$ T) m}
- Z* j1 m1 H( e# w}7 X1 j: i$ |' v
}8 [5 n' U- L, t+ `0 |. X
else // tipo == POSITION_TYPE_SELL/ m- ]; m4 s0 R. H, o
{2 s3 [9 e) N- O4 C/ q
if (cotacoes[1].low < cotacoes[0].low)2 C. G. f4 I* x0 `4 H3 D
{6 C8 Q0 y/ z, o/ G
return true;
' K0 K2 p# E# L% C0 G$ P}
?% o& d' g, o// there was no position
' t2 X1 ~& Z, r' b5 ^4 hreturn false;
7 e" a3 L* Y. J}
; p4 `; m3 ?7 X+ C, Q- D8 ]6 B! @我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。6 \8 J$ Q2 ]% E# [# G7 n
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |