启动交易模型,并构建 EA5 W/ D! P+ \% O' T6 f
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
3 G2 Y8 X: t4 S1 s$ \为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
. I# d5 V7 Z' F6 u+ E0 S5 X* ~* O4 O以下是制定这些规则的代码。
' E n: ~1 ~0 T5 p0 _7 Z X//--- Indicator ATR(1) with EMA(8) used for the stop level...
9 J! Q3 H- @/ uint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);, V0 S8 @- [5 u) s0 S3 w/ {/ i
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr); h+ e6 H# V- { z; ?: I. q
//--- Define a variable that indicates that we have a deal...
4 ^" F7 I( `: B0 e5 D( x8 w4 Sbool tem_tick = false;* O: g' q7 ?, C$ R& G$ A3 [) b
//--- An auxiliary variable for opening a position( }5 ]/ K; {7 G$ T4 ]' `& {7 x2 X7 b" }- R
#include<Trade/Trade.mqh>: z1 F% U& m( v, P6 L+ ?% {6 y
#include<Trade/SymbolInfo.mqh>
9 j' a7 S# p! c5 g, \ D. vCTrade negocios;
8 l# b/ n' D! m2 k M! J& w: q0 j8 SCSymbolInfo info;
Y9 f7 \9 ?' W4 j4 q- E- f//--- Define in OnInit() the use of the timer every second$ d7 q! K0 t ?; x5 d
//--- and start CTrade
/ K9 H/ U8 ?$ i, z/ Uint OnInit()' H2 \* m+ V7 K0 e0 R3 z
{2 q ~3 [' Q( {' i
//--- Set the fill type to keep a pending order; K8 R% r* N" ]6 @7 Q
//--- until it is fully filled
$ _; o! O' |0 m' z# N8 X/ k, [negocios.SetTypeFilling(ORDER_FILLING_RETURN);$ ?$ t% a+ M' [. w5 v' y6 a
//--- Leave the fixed deviation at it is not used on B3 exchange
! Y6 c6 M8 t* }/ G1 |9 N( dnegocios.SetDeviationInPoints(5);
9 M9 i% Y6 @1 p/ X- f' A( M1 O//--- Define the symbol in CSymbolInfo...8 U; q' o1 ]+ w" T5 Q% w G6 G; D- P
info.Name(_Symbol);
4 L7 C E6 c6 u7 B1 Q* I//--- Set the timer...# L; o; T3 C% s
EventSetTimer(1);" t; p0 U0 b9 {! G" ?4 }
//--- Set the base of the random number to have equal tests...) B* t6 O+ M+ c5 F
MathSrand(0xDEAD);( A7 |( A# V l' z( q
return(INIT_SUCCEEDED);
+ L z2 T' E5 t}3 O( L- K, g( J7 a, J
//--- Since we set a timer, we need to destroy it in OnDeInit().
- y# C+ w U4 y/ [3 Pvoid OnDeinit(const int reason)4 |8 m: F; b, T( t0 L
{( m; N/ W2 S0 Z. N7 ~* M
EventKillTimer();; Q# Y. |) ]9 W
}
" ~# s: b) I! t3 V, I+ C Q//--- The OnTick function only informs us that we have a new deal" D/ z% \: @) ?" f- G3 z0 G, {
void OnTick()
3 S8 ]1 G5 G& \0 v{- z( m) [1 ?/ Q' s
tem_tick = true;
# r! p3 F% X7 a- \+ L5 w+ Y5 s' F}
6 V. E, k4 y; M//+------------------------------------------------------------------+
- f4 a5 q5 V7 Z* Q' b. B) l/ ?//| Expert Advisor main function |- d6 @1 O* j$ Q, M9 k
//+------------------------------------------------------------------+
7 \" }/ y" L4 a0 Ovoid OnTimer()+ j' }0 b3 t+ O3 x6 d5 A7 ]
{
2 I2 l" W$ t( h2 YMqlRates cotacao[];
1 E+ G7 T5 }& X; ~. S% xreturn ;- @8 {5 U5 q3 u. C* l
if (negocios_autorizados == false) // are we outside the trading window?
: q, n! ^- @% {3 Ureturn ;
0 X6 a) u6 W [1 j$ p9 {, _//--- We are in the trading window, try to open a new position!; n1 ~/ x/ R. }, x
int sorteio = MathRand();
' T1 x/ K3 p- T//--- Entry rule 1.1
- {, p6 c2 |" ]if(sorteio == 0 || sorteio == 32767), S8 d4 O: X" `6 q/ V
return ;9 v' d; V0 L/ k9 G
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
2 B% H" @6 S1 R. e- S$ P) V{- v4 g% J0 h# {* A3 A" S1 |: }
negocios.Buy(info.LotsMin(), _Symbol);
( \2 a5 ?' K# v! D! R}
0 ~7 I; H: ~+ z) L2 }3 n2 Z+ oelse // Draw rule 1.3 -- odd number - Sell' a' a6 G2 e2 R3 a
{5 T, b# y$ ?7 Y, A. l! j" @
negocios.Sell(info.LotsMin(), _Symbol);
0 O. V1 X% \ J0 d}! C" i% S0 Q' X c% Y* n; j
}7 |0 D( _/ j! c* i
//--- Check if we have a new candlestick...
2 R- a( \3 d2 Z7 Y. U$ @% D* abool tem_vela_nova(const MqlRates &rate)
. X/ s- z5 [8 ]5 C9 _ N{( W f; r$ ?) M
{
1 x: t- N& ` oret = true;) r8 s. P4 x; O( j7 q- _
close_positions = false;3 W, U8 u- [7 ~6 P3 F, E" I2 f
}
( o6 j4 z* V6 W7 i) W& C. welse
' J1 W. ^# q: D) l! {" Z& b2 g' _& Y8 e{
% b0 D9 Y) w9 P6 Y8 p; tif(mdt.hour == 16)
9 Y0 ?9 M: ~& Z8 m8 Xclose_positions = (mdt.min >= 30);# L$ D& o7 ~6 W. o
}9 b( r/ A& |- [9 E' D
}, D" g2 j+ ~, ~
return ret;8 d6 h7 a) t- p8 I6 D
}
6 I+ K* N' v5 R, p//---
- d' O/ c5 m5 P1 b. C: Pbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])1 D% F# _& M A2 A# ?$ ? `' y$ o& k
{
; h# }& c' D) iif(PositionsTotal()) // Is there a position?4 a' y; c1 ^$ w9 G2 P2 b
{
& `, `7 U7 Z: a) S8 Bdouble offset[1] = { 0 };4 s3 [: C$ t7 B0 E' e# U
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
" T$ R+ N; Y8 @0 P, \&& PositionSelect(_Symbol)) // Select the existing position!. w( h7 c+ S5 j! t
{( \" h' ?+ Z ^" d" j1 G0 l
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
. h" @! r% ?2 s' `double SL = PositionGetDouble(POSITION_SL);2 u" b* b0 \/ n' ^# _, Y# y
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
, G1 O* @4 o( ~# S# }. Yif(tipo == POSITION_TYPE_BUY)
% S N |5 s, j% W- F- i( L; R+ H' k5 P{
% H$ P5 E" X# n5 S8 Rif (cotacoes[1].high > cotacoes[0].high)0 V) Q, i5 U1 }# Q
{
( h7 J o% s5 M2 \/ Ndouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
+ ^5 e; p3 i6 H& ninfo.NormalizePrice(sl);
) @% G; S2 b5 T! B `) eif (sl > SL)
8 I4 V% t$ V2 E{' R: S; E) q4 b9 p; t, F: N
negocios.PositionModify(_Symbol, sl, TP);2 c8 m4 f7 H/ n1 G
} Y& f2 _1 O, P ^) p
}
1 m# `; x+ y- K0 k' L M}9 l. u, `" Q$ g
else // tipo == POSITION_TYPE_SELL
& F3 c: j6 s2 Q& e{( S7 d1 J N( G& K
if (cotacoes[1].low < cotacoes[0].low)/ `$ w ]% }! ]
{' [3 Q( c: k7 ^8 J- s$ H; Y
return true;
! ^+ _' d; {1 {- w}
0 u" [: {0 R/ h! R+ u// there was no position
2 n N' u! ?) Qreturn false;% I1 U9 a. z5 W* ~
}( @0 h3 \5 }5 l6 j# E6 o
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。( O7 u) d5 r4 y9 ?; J: A
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |