启动交易模型,并构建 EA
. m( w0 m7 W& U% z在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
: q( `+ y O) h为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
5 ]* l% L# b# m- o% K以下是制定这些规则的代码。6 j/ T2 v. r4 o1 z* C
//--- Indicator ATR(1) with EMA(8) used for the stop level...
" [. B0 d& P* _. x) eint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
+ e/ @# p+ `+ X' Jint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
+ m, o! s6 V/ W" h" R//--- Define a variable that indicates that we have a deal...
: y: @8 P3 l* g4 Rbool tem_tick = false;+ f1 Q0 n4 |9 P; ?/ h
//--- An auxiliary variable for opening a position! [( y' D# l' ^* t
#include<Trade/Trade.mqh>
/ ~1 D* M6 ~' Z- N/ u6 [#include<Trade/SymbolInfo.mqh>
( R9 ]: k! Z8 r* F$ p6 ACTrade negocios;: o# Q8 Z m7 I5 z# m
CSymbolInfo info;
# n9 N/ e7 i1 s//--- Define in OnInit() the use of the timer every second
3 N' o% y2 w* B8 f+ V//--- and start CTrade! C( a, e- T* Q4 B" i
int OnInit()
; Z% P9 M4 N( V6 r( A' w" B{; P3 | R% w' a. c7 I
//--- Set the fill type to keep a pending order0 r" h; D. g: v3 [" ?6 ?
//--- until it is fully filled
4 w' |6 s& U8 J2 b% s) \& {negocios.SetTypeFilling(ORDER_FILLING_RETURN);5 W3 L, u. ?% D" H5 j8 L6 u# o5 C$ s+ q
//--- Leave the fixed deviation at it is not used on B3 exchange- Z$ H1 E* Z5 \7 O/ a9 C
negocios.SetDeviationInPoints(5);, ^9 u9 n/ i" ~+ \
//--- Define the symbol in CSymbolInfo...
7 M3 N3 C. M4 m. ?info.Name(_Symbol);) `* _, J- ]' G$ A+ |3 e1 E' S2 _
//--- Set the timer...
2 G& Y- `; t! w# g, jEventSetTimer(1);
) Y3 S. r+ C1 e: W4 e: z3 D, l# \* }//--- Set the base of the random number to have equal tests...
0 d; ^" [, M* Z1 \1 rMathSrand(0xDEAD);4 i$ G; W0 n a2 o1 d9 X
return(INIT_SUCCEEDED);
, l7 s$ t: Y0 W6 t}
: I1 Y# y: x# w& z; L. S9 ]//--- Since we set a timer, we need to destroy it in OnDeInit().
" b) m9 z9 c0 _. U3 x, I. ], xvoid OnDeinit(const int reason)7 ]! u. X- y* l8 \: E
{
7 C. c- \; Z* n3 B- Z$ |- A eEventKillTimer();3 c4 ]7 v' X# F$ V6 {5 d+ j
}% b: B- T; F, A, a6 g- s
//--- The OnTick function only informs us that we have a new deal" [; o: ~3 v2 p0 [3 ?4 l" ~5 S5 h
void OnTick()
& g' R9 D; A# y( i" S{
$ L* G- j: z; ]; |& s( {tem_tick = true;
1 i4 }4 ~7 t: h3 Z}/ ~3 v5 m+ O0 U! ]1 R
//+------------------------------------------------------------------+
! j6 t8 c/ {. H/ | H//| Expert Advisor main function |: v; l, O: X1 s/ z, ^0 C& @
//+------------------------------------------------------------------+' v* u" `$ K& F0 y; u' h
void OnTimer()
: p- N& O, J/ Z$ A: \{
) f8 e% C4 |0 P0 o7 D. j; @3 oMqlRates cotacao[];) n$ U+ q% s# p3 p0 j% j: \
return ;
! M! V9 h5 w9 Z( ^' G5 W: Uif (negocios_autorizados == false) // are we outside the trading window?
8 Y+ E8 L5 G4 D+ \return ;9 l% D9 U' C$ g! \
//--- We are in the trading window, try to open a new position!3 R% f2 N+ }! n# @# L
int sorteio = MathRand();# T% @; i D% F* u' f! Y
//--- Entry rule 1.1
1 l3 R( D' B8 A2 Hif(sorteio == 0 || sorteio == 32767)
2 t9 Y) r) W* sreturn ;
6 ]( I1 X* Z l$ xif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy! A$ L: Q9 n3 C/ a
{ H! P( s/ Q' t: H
negocios.Buy(info.LotsMin(), _Symbol);8 i) j1 f* p7 ~9 o- u) ]& f- e2 |
}1 K4 ]( e, T! Y' D) G0 S
else // Draw rule 1.3 -- odd number - Sell
9 s0 P7 q2 a$ g- A5 U& L' k, R{
0 @, T% t' y9 v/ y6 gnegocios.Sell(info.LotsMin(), _Symbol);
$ Z2 H+ t+ L, |! h0 H- ^}4 `: |* E+ ]" z
}- i {( u7 p6 U, j
//--- Check if we have a new candlestick...
9 x. j- g, M6 E' g/ j4 Kbool tem_vela_nova(const MqlRates &rate)
$ d% J9 s3 Y# j( G3 y5 i{3 N& b/ x) ^) h8 H; @3 c9 _3 C
{
& t; b# s; f$ Yret = true;
4 E# R0 L% D1 N6 H3 J2 i& Yclose_positions = false;7 @7 u- y& h8 D' n; T2 U/ n
}( K# Y8 z- w6 c7 |
else; u' U, G2 Y! {! A3 C5 B; j j( c
{0 ^! l' d' G6 J' j+ B3 g3 Q; [
if(mdt.hour == 16)) z$ o" F; {6 H. D6 B
close_positions = (mdt.min >= 30);6 k, _# Q0 _9 |; U! y
}
: a0 F m5 J- z% j" ?8 G. f}
4 C* J1 U9 ~0 c* \+ Z: y( t6 Lreturn ret;. T5 V, k# @0 B+ t
}
$ I; f6 Y% j: ?, F. X//---
* J" q* I2 b( c) D Pbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
5 Y& _8 }1 |3 p7 S{! A ~+ D' ^3 c |& }5 n( a2 `- m
if(PositionsTotal()) // Is there a position?
1 V0 ^, q; E1 _# l# M" C" k2 o{0 `7 H+ G% K; d" Q$ P
double offset[1] = { 0 };
/ y; C' O' S1 ^2 \6 J, Iif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
$ \: a. M# n0 R&& PositionSelect(_Symbol)) // Select the existing position!. i: N* l' R/ S. C5 m9 u
{. o9 `6 }$ }% l5 D; c' b1 K
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
; |6 h6 n9 S* B* g9 N% ^9 `& c0 `double SL = PositionGetDouble(POSITION_SL);
/ L+ R+ f' m+ U2 E" ddouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));6 }- N/ T! `# ?- ~1 ]
if(tipo == POSITION_TYPE_BUY)* T5 h. \8 O* N3 D/ u8 E6 E
{7 A0 b; \$ k8 e, d$ ]' Y" z
if (cotacoes[1].high > cotacoes[0].high)+ {2 _) v( X1 G& |5 r" H6 S
{
) N0 e5 D7 V0 [! R. Z* m1 `double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
; o* q3 e q1 K% Xinfo.NormalizePrice(sl);8 D! Z! _8 B/ E: X1 f$ K
if (sl > SL)
% g; T8 {1 M4 L& E$ I5 Y! H h{
3 C' U. D/ p1 D1 P# A2 G! mnegocios.PositionModify(_Symbol, sl, TP);
6 `9 i- z0 g' W; f}5 e9 k3 k; n0 I" s7 f
}
, S6 |) ? T, t( i- H0 C7 Q/ B}
, X+ X; I7 k6 m5 s% helse // tipo == POSITION_TYPE_SELL: ?$ @0 y# s( X$ h+ r$ `
{' k8 p( t2 s9 j
if (cotacoes[1].low < cotacoes[0].low)
; K) o0 a$ a2 x8 X" {: F/ B! y* a{
3 o/ Z* b5 q+ u7 [4 \% T& Ureturn true;# H/ C6 O; S2 w9 G( }" g
}7 u% ~; ?4 k) d# S
// there was no position4 C# H- T& j8 j- d- {9 U w |( @& @
return false;
' Y' r. n- r& y, a+ S}
7 H# K) Y; {' @" e9 r+ X我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。9 n5 s) y& g/ E9 L
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |