启动交易模型,并构建 EA
% S8 c: n/ B! `0 e8 l9 o在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。9 w p/ _: Y$ X2 ]( s
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。1 k2 n& l& @5 @# j
以下是制定这些规则的代码。8 Y/ E$ P6 F3 c# Q0 u1 u1 g
//--- Indicator ATR(1) with EMA(8) used for the stop level...* E. c) ]: z) E4 i
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);- B0 C. X1 G W. @. T9 m$ }$ n6 Y
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
7 R F8 I5 N3 j, \0 Z) b$ S2 T! }//--- Define a variable that indicates that we have a deal...
% O, E# q j' @bool tem_tick = false;' E& X( d$ Q% r: U4 ?" Z+ S) q; J v
//--- An auxiliary variable for opening a position
5 }) ?6 g0 E4 M5 q; u6 U0 n#include<Trade/Trade.mqh>
O; @2 _. B- g) |4 s) X. z2 e% r1 R, ^#include<Trade/SymbolInfo.mqh>8 M8 |$ p( J/ K
CTrade negocios;
( L6 o8 Y! C! R; v8 T! aCSymbolInfo info;, d5 ]4 Z" M S, C. e! }! w& u* ?
//--- Define in OnInit() the use of the timer every second5 X3 {* B- y5 h w6 I
//--- and start CTrade' S4 K) Y3 e9 {/ C$ W; @1 m. W
int OnInit()7 \1 X. i- u+ q R& C% s5 a7 X+ S- y1 m
{ W# `, D' ~% I1 J
//--- Set the fill type to keep a pending order
. l- M, P/ Y; { S0 y% {/ U( A8 g ^//--- until it is fully filled
8 h8 j9 s# z- K3 w+ Onegocios.SetTypeFilling(ORDER_FILLING_RETURN);
5 D! |; @* s# K" d) I- u6 v- L//--- Leave the fixed deviation at it is not used on B3 exchange
& l, B: e; P* L- n+ Znegocios.SetDeviationInPoints(5);
1 Y) \/ `& {$ a' z//--- Define the symbol in CSymbolInfo...
5 ~6 R; ?& g8 P* binfo.Name(_Symbol);4 P( y6 L5 ?1 g O- L
//--- Set the timer...
0 F4 r0 o6 t- ~+ `8 |EventSetTimer(1);0 P. T. z p7 j1 G# J, t7 z3 o
//--- Set the base of the random number to have equal tests...
" I& z6 Q. q3 M B" }$ H: T" N3 kMathSrand(0xDEAD);
: L- w) ~( g0 k; P+ m) E' D0 Z, lreturn(INIT_SUCCEEDED);% c5 } {. G' M, }
} i- h7 X9 ]; A% l+ z& [, y X
//--- Since we set a timer, we need to destroy it in OnDeInit().' G+ p# q7 W$ _) B- f, L+ e
void OnDeinit(const int reason)
7 p" B4 ^2 E# T! G, Z0 n% [{
! y( M# }6 O8 i# g0 }3 {EventKillTimer();
/ m* i7 B- _1 E5 r6 x}
: W9 k& r& V2 z' K4 o//--- The OnTick function only informs us that we have a new deal
& Z! I: K( T4 J8 c7 l% p1 cvoid OnTick()8 Y. z) ^: p- R
{
1 c/ b3 e0 R: b- Stem_tick = true;, V) b0 U" A( m& h8 [6 @
}
8 b+ O4 x8 Y/ F% b3 t5 D0 J//+------------------------------------------------------------------+
' i2 H- j; Z' K//| Expert Advisor main function |+ @0 i. E: u+ P% \. P' J
//+------------------------------------------------------------------+
2 R4 I' y( ~7 D9 Hvoid OnTimer()
+ L3 q; i7 a6 z, s{" n3 J/ W& ^6 b- y: a
MqlRates cotacao[];
: Q5 t' i, j4 U5 g6 ?, v$ Qreturn ;. @) d% D3 A4 z& }1 B. H5 T q
if (negocios_autorizados == false) // are we outside the trading window?6 @& K$ b) M5 F8 Q3 x
return ;
5 B' j9 j7 t! X) M1 C4 w//--- We are in the trading window, try to open a new position!, q/ @# K* ^' l( _) P7 m
int sorteio = MathRand();
" v6 b: F! K' C9 P7 y( K) g//--- Entry rule 1.1+ ]9 M$ V0 g, c% ^& I
if(sorteio == 0 || sorteio == 32767), K, H1 W! r$ A1 U) L9 @% P
return ;+ K8 x- l$ w) x1 n* ?
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy. a: i0 t1 n; ^1 F' S* H, {! h
{6 K( `4 q6 ~: r) z7 v$ ?8 e
negocios.Buy(info.LotsMin(), _Symbol);. w# p2 g, W% `* d& i) u; U6 @0 x4 F
}# |& G0 H1 t! J9 Q0 ]
else // Draw rule 1.3 -- odd number - Sell
6 S* d* Y7 n2 h8 ?3 e' z6 Z* }{/ w# J$ D# a2 O% z2 @
negocios.Sell(info.LotsMin(), _Symbol);3 ?1 p/ k$ `. b. U- p9 U
}
- f! F G- \: ~9 Y3 ^}
: j- R4 S( F1 l2 Z, f//--- Check if we have a new candlestick...
' H* ?# r" l9 W: f! k3 {& W9 Pbool tem_vela_nova(const MqlRates &rate)5 E# v) I1 r' |" M
{/ `- n9 ?0 Q5 W+ V- b- n7 A! H$ z
{" X2 A/ g5 G' I8 J! w5 k9 A4 q% H
ret = true;4 ]* c3 F, C9 s e( y
close_positions = false;% J* F1 N! k# P* i$ r
}
2 U: P5 K! u1 z1 Y* x! x( m3 xelse
2 a& ~8 S. v I( f+ W+ ?& M{. p6 t& d2 Z7 b! M0 x6 S/ T7 g4 B
if(mdt.hour == 16)/ Z$ h& B( D5 ]8 ?/ I" E
close_positions = (mdt.min >= 30);
" T: d/ p! u; c0 `9 Q+ h6 Q1 _+ H}! V1 K+ M+ l7 v3 q
}
B9 x2 R" i3 {3 Treturn ret;, R6 J) L6 g: ?9 g
}- d: C4 z3 H! x+ T9 c) A9 U' x" P D
//---6 [7 k0 m+ w8 \0 j
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])$ R0 E' a, f1 [& Y; a9 m
{' T0 }4 c. l% C7 R/ O" G/ o h
if(PositionsTotal()) // Is there a position?; m& B/ t, l- c8 P8 K, R" g
{
( ^& I! C% c: A3 J% r7 X! Cdouble offset[1] = { 0 };1 s; a) B( j- j5 t( y
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?: @ W! K0 _- {5 F' K. ?
&& PositionSelect(_Symbol)) // Select the existing position!5 k- G; W, B' J- a
{
" m: s7 i+ f& nENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);0 i" s% L8 ^! A% Y) M: H# L6 R
double SL = PositionGetDouble(POSITION_SL);# H/ n ?' N4 x$ m. Q
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
8 u3 P+ W, M# U& Wif(tipo == POSITION_TYPE_BUY)- A1 e9 Q, o# I
{
3 f! `; f) ^ W* \; R0 X5 `if (cotacoes[1].high > cotacoes[0].high)
# Y7 {& Q, P# z) ^+ B- ^5 g3 n{/ Q& x: s! S% y" i/ s- e2 q4 p# @6 @3 S
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];3 N: |! a4 P T' t, ]
info.NormalizePrice(sl);
3 _; R/ u9 N( d7 P6 U( k+ B0 _" Nif (sl > SL)* x2 z; \$ [# N
{
& V2 K% w& Z* H7 fnegocios.PositionModify(_Symbol, sl, TP);& ~1 C" W7 I7 n1 ^- F% X6 w7 F
} P3 A. g/ l4 {. e4 K1 g
}9 Y7 c. J# Q5 _9 T) n4 P! X8 f6 k& H8 C
}& e; q9 j3 m) n: d% O
else // tipo == POSITION_TYPE_SELL/ i( }( ~; E8 n/ ?" O8 J$ W2 g
{
, @* N U' a& e3 ^/ {if (cotacoes[1].low < cotacoes[0].low)
+ }9 Q2 l- Z3 M4 ?* V& V{4 x9 ^" o6 k, C# T8 D( E5 d
return true;& H! p/ L1 _8 |/ ]6 q, O: v
}( B" x- K. g% @( f
// there was no position' ^( H. v) e K% Z2 C
return false;8 D( K. d9 o( H9 D
}
) X# v4 r9 p+ l) l我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
; \5 E0 M5 ~) Z! k- J到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |