启动交易模型,并构建 EA
' f$ x: I+ I9 g ?/ r' m' M$ G) f" `在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。. R) c$ C. j" i5 N1 u/ Z
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。8 K% n' s5 [( i$ u/ j: s& {, E
以下是制定这些规则的代码。+ b2 H0 X0 J# ?" c3 e1 y
//--- Indicator ATR(1) with EMA(8) used for the stop level...
3 _' F$ H9 i8 d" L( T( G% u! tint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);' l7 m6 A4 u( B$ P9 d& o' v, S
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);/ H$ x$ N0 F# W
//--- Define a variable that indicates that we have a deal...
X3 }+ A% }5 }. {+ Gbool tem_tick = false;
U; @2 ~: p$ a. V7 \& X- K//--- An auxiliary variable for opening a position
# w( Z6 g/ u7 G. ?6 ?#include<Trade/Trade.mqh>
0 Q% T9 P2 [( [3 f: e+ M#include<Trade/SymbolInfo.mqh>. j% a' T+ b' E2 N* Q
CTrade negocios;
* m- J8 n# t7 f6 QCSymbolInfo info;
; O0 x' J3 J1 q% U( g//--- Define in OnInit() the use of the timer every second2 [" R* f G+ z+ C
//--- and start CTrade
/ u7 y* }5 h+ S. a' X7 W0 gint OnInit()
7 t9 v+ Y9 E( k& z1 m{
* a; e; y/ T4 T2 \6 Q4 |, i//--- Set the fill type to keep a pending order; d, t# u- M0 ~/ p0 j7 w, W @" e1 W
//--- until it is fully filled8 i" x/ s- U3 S: r
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
6 t: {) f# {# }& s//--- Leave the fixed deviation at it is not used on B3 exchange
: c& {% B: X# ~9 }4 C" W5 Tnegocios.SetDeviationInPoints(5);1 z/ E2 \! ?( b3 T, _
//--- Define the symbol in CSymbolInfo...
* ^# u' E, g1 b8 j1 z# kinfo.Name(_Symbol);4 r* v+ b1 y `. o5 ?
//--- Set the timer...
& C. J' {/ P. o4 z9 ~EventSetTimer(1);
9 F0 v' V9 G9 X4 ~; U: I//--- Set the base of the random number to have equal tests...
# D- F/ w0 L* m" R0 C9 @# O8 oMathSrand(0xDEAD);8 R, g$ M) I1 M' |% L) {3 s
return(INIT_SUCCEEDED);
4 }, ^' M" h+ w# V: M- z}4 E6 c1 w* b; b3 W) B0 o
//--- Since we set a timer, we need to destroy it in OnDeInit().4 Y$ q( @1 U8 a7 D4 x1 a; _
void OnDeinit(const int reason)
$ p/ V5 c$ e' ^( J{( q9 p- U( B7 I
EventKillTimer();
, g! v2 h8 B+ C9 X0 Q+ _) c( h' Y}; X8 H! {; Q& ~7 u5 t b
//--- The OnTick function only informs us that we have a new deal
( K" W- B, ?" i* Rvoid OnTick()0 @/ d! R! B; I# ?. f5 Q5 c: l
{
1 ?+ h4 w' u R$ stem_tick = true;1 I$ Y* N, B6 J
}+ t& q: B9 O# E% I
//+------------------------------------------------------------------+/ S2 x/ ?/ z( e# F
//| Expert Advisor main function |, P$ O* G: B1 W! x
//+------------------------------------------------------------------+1 `. X7 G3 |( x0 q* R
void OnTimer()
: t5 Y- S# V, o( [! r% r{
: K. l+ g, h) DMqlRates cotacao[];
% g3 c2 k2 K1 X& v- yreturn ;
' k$ ^0 N/ ^; d; s8 ?; H7 N& xif (negocios_autorizados == false) // are we outside the trading window?
4 c5 i, p' D3 y( v, \! sreturn ;
: O! ^0 M. x- O//--- We are in the trading window, try to open a new position!
( L& V% S( q+ Y I7 v7 ^1 {( Oint sorteio = MathRand();
) F. g2 \2 r% t' i- v) I//--- Entry rule 1.1
& x! f' n* i1 S1 y8 T3 Iif(sorteio == 0 || sorteio == 32767)3 Z9 [8 T% @ A
return ;' |# W0 b x/ h
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
7 ~1 c p6 R. l{
! g" E" _1 x0 d' ynegocios.Buy(info.LotsMin(), _Symbol);9 x# m" w0 b. J- i) }
}
4 w2 h7 {) p0 l* R) N3 relse // Draw rule 1.3 -- odd number - Sell
" @/ a9 R4 x, S6 T; v/ j{
5 n4 K0 c+ [; F' _) W" d- Xnegocios.Sell(info.LotsMin(), _Symbol);2 p0 l: \1 L) o+ C1 h3 U
}
: C. U* ^+ ^. g. q0 [0 [* S& Q}
' K5 q9 ^* k" l% A6 n//--- Check if we have a new candlestick...
3 t1 p7 |. B1 L& @bool tem_vela_nova(const MqlRates &rate)
; p9 Q) I) m- h {0 z{
( |3 f3 \! g% t5 t{
3 O% i/ v( T5 w8 uret = true;
* B) p, f! N2 w7 G$ ]( Uclose_positions = false;* I8 F) }$ x( _9 y3 F
}
H1 R1 J& v$ G' telse5 e5 x: A5 _1 L' C6 I
{" O8 b3 I0 _! J0 U
if(mdt.hour == 16) y; R; I, x4 m5 A7 f5 o; V8 x/ ^
close_positions = (mdt.min >= 30);
2 N/ `. D$ z( Q, v# @}6 @0 q( P4 Y& f' W
}& _+ [( y+ v( i* y" K( M
return ret;
: ^ e8 T! Y- \* ?- K}
& b9 C* E0 _+ L( s/ @/ m//---) E9 T u% Y$ k, O* l2 f( f
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])1 W' e5 [: V- ]1 n" |5 o/ D& }$ H, Y
{
; m5 ]* o A, D" ]0 G& Wif(PositionsTotal()) // Is there a position?
$ ~2 E) D# ]# F6 w* k{# w) [# B8 V' T- I2 ]. T3 B
double offset[1] = { 0 };
. p7 b3 T9 a/ O8 \" C$ o8 i: L7 S, a/ jif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
4 r6 R. k/ A8 \) W, m&& PositionSelect(_Symbol)) // Select the existing position!
$ F6 V$ e' ^) l; }7 a3 R- q7 v* p4 O{* } C+ @, D4 K `7 E
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
% J: j6 V# [; hdouble SL = PositionGetDouble(POSITION_SL);
3 q2 P5 g: J0 b- J. Xdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));/ x# u9 P2 z- V
if(tipo == POSITION_TYPE_BUY). n7 L" B& \- u% D$ B
{+ E9 S' a; K$ p$ k# d4 N$ [& v
if (cotacoes[1].high > cotacoes[0].high)
! {( Q1 n" ^' V6 u6 [( g7 j! d9 |7 P{/ m0 @* w! ?" I- a8 I: J {7 g4 `
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
$ ]2 Q4 X( X" z& p' A; ~$ [) ^: ^info.NormalizePrice(sl);
/ c8 q9 \# _; Lif (sl > SL)5 V" P' x6 i# T6 d9 d; v
{
+ o* R# n7 G& t& f2 H7 Z4 @negocios.PositionModify(_Symbol, sl, TP);' q: w$ b; Y7 |. B: u9 h. x
}
4 g/ w9 _- g: ?- T: e" w1 _9 M}
# T5 c# J3 T, u1 _8 i/ M}# p) y& \5 l( x$ a( E) p! i. l. h
else // tipo == POSITION_TYPE_SELL( m$ s8 N8 k+ P( h0 k
{5 _# W( x. S$ \6 k$ A7 E
if (cotacoes[1].low < cotacoes[0].low)
) j: e( Q8 D. M$ ?" h$ `{
5 ~1 L) }& V% ^4 b) w- B% l" V& Wreturn true;
0 o4 s. ]7 [9 |3 ]9 ~( |* }} q A V9 H" J' Q' c& _
// there was no position; l7 h5 | C% o. H: U# X6 w7 k& Y
return false;6 _9 ~$ V& Y" |) V! F) L1 x
}
U# | N* V* g, ]我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
# z) X+ v& T5 [& w& k5 _到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |