启动交易模型,并构建 EA
, l1 ^+ {6 ?8 W; }) v在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
/ k+ R% t3 T3 p/ {* |6 P为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
% [6 t* o9 e9 H S/ b2 `5 n' D' O0 V以下是制定这些规则的代码。
- f* R. a+ Z- ~9 `//--- Indicator ATR(1) with EMA(8) used for the stop level...! d, z3 `3 y! I5 Z4 @- G5 M
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);. w1 x9 S! k4 T& A; W
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
+ k3 X0 \$ T0 D" G, q//--- Define a variable that indicates that we have a deal...
i/ z- U& q8 w! J ]bool tem_tick = false;
; }/ p* v$ h* W! n+ x+ o5 h6 a# V m//--- An auxiliary variable for opening a position
' Q+ }2 E, M) p# o% Q* H/ O#include<Trade/Trade.mqh>
y% Q. K" }' Z% {8 }5 D) g#include<Trade/SymbolInfo.mqh>7 ]8 ~) b; }8 s2 Y) z9 b! N
CTrade negocios;
# i- l# U( d9 X: j( w7 P7 \+ XCSymbolInfo info;( U1 ?) w8 J' b+ N+ |' D
//--- Define in OnInit() the use of the timer every second
3 ?, M) z9 g6 l! ~//--- and start CTrade% E) M% l2 b/ ~$ l9 }# I- P
int OnInit()
5 z' h' W- Z, Z! t" f{& |; x) _! I& C3 l" I+ z
//--- Set the fill type to keep a pending order! O1 G2 o! i) |) a
//--- until it is fully filled( V0 ]! M8 N2 {" r& R
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
" b. l1 S* _* r- z//--- Leave the fixed deviation at it is not used on B3 exchange
8 [: e) c0 u8 y6 | pnegocios.SetDeviationInPoints(5);
6 X4 @* o' o6 T5 c) e) R/ h//--- Define the symbol in CSymbolInfo...
' S. ?' x( K z5 uinfo.Name(_Symbol);# U* U/ r- E u `
//--- Set the timer...( @. Z! {1 @2 Y1 a' f
EventSetTimer(1);# C% G- S2 g7 r, [* J
//--- Set the base of the random number to have equal tests...
% Y/ j5 f! Y+ q9 i. o$ oMathSrand(0xDEAD);! r" i) W$ T( `0 F) {
return(INIT_SUCCEEDED);3 S, @+ d0 Q, t) a8 K
}" _) a9 F- c2 `' `+ [4 L6 t
//--- Since we set a timer, we need to destroy it in OnDeInit().: U& I# k1 C( W8 N
void OnDeinit(const int reason)+ V- i" d( ~6 I- g1 o
{
4 q/ I( r2 s3 h6 V8 u) JEventKillTimer();
- g* \5 Z; O3 X! J4 }}+ Y; @; @3 v1 g7 s0 H+ m
//--- The OnTick function only informs us that we have a new deal
5 ~4 j, r; _' J$ P, @0 Lvoid OnTick()
! Z4 h" U) u& R% j) a1 ] ]4 s6 x{& g0 J. j( j6 ^0 W2 n
tem_tick = true;* C# B! r$ | x, f' l
}
+ O- \- J' p! y0 `. ~//+------------------------------------------------------------------++ G; [. b/ G% n6 l+ K
//| Expert Advisor main function |0 e6 B5 c" e7 `
//+------------------------------------------------------------------+
1 a' b1 o( p- r6 uvoid OnTimer()& X! M5 j8 o3 _& f. |7 ^) D" G
{* f4 n: v1 e8 o/ L- v
MqlRates cotacao[];
" p9 R0 Z( n$ o+ Y' v9 q' dreturn ;0 l4 P$ E9 O- R" E
if (negocios_autorizados == false) // are we outside the trading window?
# V% p$ E3 _7 g# Ureturn ;
3 X/ x4 i: N9 {4 O( Z/ X//--- We are in the trading window, try to open a new position!) `9 H1 O8 `3 t8 X4 V
int sorteio = MathRand();
1 T& \% c1 @0 d9 C& T* ?* \//--- Entry rule 1.1- M/ i7 H" ]1 b4 \% N) \2 a! I2 I8 N
if(sorteio == 0 || sorteio == 32767)
/ B$ e( K% y5 a# i o( hreturn ;* `# f1 F7 V; {; ?/ v
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
; s$ e" D: H7 ?! q: }{
4 T) S2 e. [. j& T4 Fnegocios.Buy(info.LotsMin(), _Symbol);/ `5 O+ H. X" g$ u" L% `, T
}
7 @' y" Y4 g$ m2 l4 F8 ]else // Draw rule 1.3 -- odd number - Sell
" C E& i: h9 i. t; \' v7 [{
% b6 } Z/ U( r# D- ~3 J' r; c7 `& T0 pnegocios.Sell(info.LotsMin(), _Symbol);5 {1 `5 n2 @) x' b& p- a% `
}8 R+ a6 D2 l2 v$ k* E
}
, S, a5 \9 \$ G) t! m, h4 R ^7 }//--- Check if we have a new candlestick...
" c( Y0 ~* D1 G- B0 X# ~4 W# ?9 hbool tem_vela_nova(const MqlRates &rate)
1 v4 i. B2 V4 v+ ~" X' \{2 v+ h1 e- Q+ l. j
{$ |& V) |# r% H$ U" r
ret = true;
! @" E8 K0 g! [$ T' @close_positions = false;; p' u6 K% K, k0 V0 M6 k" w
}
- Z, i! E" Z3 b4 Oelse
6 i( T( V3 ]) \9 {; x4 s{
" t/ N/ K" Z7 Uif(mdt.hour == 16)
, N [# c; f# l6 G' V3 w3 nclose_positions = (mdt.min >= 30);
% J' K; K2 X1 I0 X. k/ a}
7 ]3 H( }( j6 c' A+ U& d1 q}5 k2 i; M M4 r2 h' c! J
return ret;# F* z3 L: s5 M( i% S# `
}$ ` D B, A$ m; F9 T1 \# v& T
//---, a, ^+ W; H; n9 m3 U$ h
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
7 a" C2 V# q9 z+ ~5 H# ^+ y{ _" r; J7 e" K1 a- I
if(PositionsTotal()) // Is there a position?: o. X x, K* D3 d$ C- y
{4 ` z/ @& j" I# W
double offset[1] = { 0 };
$ j1 F8 }- a& U: Aif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
5 s8 F- K7 a2 I" I&& PositionSelect(_Symbol)) // Select the existing position!
' |3 V# Y7 z7 T- q. `{$ Y0 u3 u: f Q/ D$ R$ }
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);" o( O. X* r3 D6 t! f
double SL = PositionGetDouble(POSITION_SL);% u& y% J$ h+ Z' p' U9 D& D
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));) `* ?6 N# |3 s8 h
if(tipo == POSITION_TYPE_BUY)
- S: d9 D( F8 T{
L- a- b) t2 V0 O8 ^* Jif (cotacoes[1].high > cotacoes[0].high)
3 W+ ^. E; _' C/ o{
7 X; a+ S4 V& r1 P2 ?4 Odouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
1 U, R$ Q- s+ y3 i& w' Jinfo.NormalizePrice(sl);
7 `. w9 p9 R3 w$ zif (sl > SL)/ r8 S) U" p9 G
{# ?5 g9 i# j. R( l1 Q. y. _4 M2 |
negocios.PositionModify(_Symbol, sl, TP);& Q% H. }: z- c( @& u
}
7 ]0 S: Y }2 g9 ~}
1 U/ T# l( B2 s}1 Y) z7 y1 e. {: G, E1 F; z6 I
else // tipo == POSITION_TYPE_SELL
: o" K: ^# ]3 l6 P{
+ Q' | h" ~. `) _* N2 A! W* U' sif (cotacoes[1].low < cotacoes[0].low)
, X: ~( w" ~1 V( Q1 D8 L5 R{
& H, H* S; g' Y# Q( J" q' y8 zreturn true;' Q+ l. @: H! @7 x+ w% K% M
}5 v( M7 s- p3 t0 [4 p4 G4 D
// there was no position$ Y2 m* ]. K% k6 ?
return false;
4 i8 l- g! n8 b}
/ {( O5 L; h! ?我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。/ e3 b: X5 l, S
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |