启动交易模型,并构建 EA
, \+ a' B* D/ h' i; I* U6 q在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
, F4 k5 @8 C2 A为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。3 w# k9 B1 q5 D- V7 `
以下是制定这些规则的代码。1 D, a9 b0 v4 x) V: L `
//--- Indicator ATR(1) with EMA(8) used for the stop level...
2 n9 @1 v; {8 Y) c% w7 }$ E0 Zint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
& }7 m8 I7 Z4 ~0 F Y3 Iint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
8 i" i8 T3 r3 O; e) E5 C, _* s//--- Define a variable that indicates that we have a deal...$ ]1 E' o# k+ A" {
bool tem_tick = false;
" ^6 [# }; [ _& S//--- An auxiliary variable for opening a position
' x8 @# j$ C% |4 m+ l9 s#include<Trade/Trade.mqh>
0 l$ z* D) o$ X8 B8 E3 P& e#include<Trade/SymbolInfo.mqh>
/ X# C2 C, c# p kCTrade negocios;$ Q, E! a6 g8 i4 z9 M
CSymbolInfo info;2 E- |8 n/ E, k
//--- Define in OnInit() the use of the timer every second
: ~* Y& u4 T% J' r# v//--- and start CTrade7 T& C* _ b- T0 [9 Q, `, n
int OnInit()
4 i0 O3 U( F7 p" L8 a6 T{+ l7 D( ^! B9 Q1 m8 r$ W
//--- Set the fill type to keep a pending order& W! O' J* H! v: W' P9 e2 G! {5 h d9 z
//--- until it is fully filled
6 q* H5 R2 A8 ~" E) z/ Y; bnegocios.SetTypeFilling(ORDER_FILLING_RETURN);# x* w; x C# Z: X; N# b" X, |+ m
//--- Leave the fixed deviation at it is not used on B3 exchange% z" G. ~0 N. }
negocios.SetDeviationInPoints(5);* A! j; b. Z3 A$ X [
//--- Define the symbol in CSymbolInfo...
* T- E/ P, z8 ]. h# oinfo.Name(_Symbol);
* _" @3 Q$ |# A# C& e! n7 K/ S//--- Set the timer...
r3 R+ w7 ~. t' ?EventSetTimer(1); H2 z- `! a5 w8 B
//--- Set the base of the random number to have equal tests...* t( K! \! f( S' K+ A
MathSrand(0xDEAD);2 ]2 n4 ~. N- K; [$ X* S
return(INIT_SUCCEEDED);7 J* X* T, {# M/ a
}
j, s+ U+ Q2 ^ i4 y& w//--- Since we set a timer, we need to destroy it in OnDeInit().
8 y2 D+ \. E. H+ ]void OnDeinit(const int reason)
% ^' I D1 w& g/ l" O G- G{
) q; T1 v( A5 L+ s0 [0 L# QEventKillTimer();5 j0 ]/ H1 N: c$ z6 k3 c
}+ a3 q1 v7 g8 z4 g, h0 H
//--- The OnTick function only informs us that we have a new deal
: c) n+ }8 g9 I8 A3 t% u- Tvoid OnTick()- {7 B% i3 ~; m% d
{
P) O+ D, e" Z+ I5 B* ztem_tick = true;
9 t% Z& ^. i& P0 f4 E}
: f0 k* L; h+ ^" z//+------------------------------------------------------------------+3 H" P0 v# {4 ?) p
//| Expert Advisor main function |( ~+ X5 q! c8 W, ^% ~& J0 ]1 k7 |7 k
//+------------------------------------------------------------------+8 m$ C! G6 s2 [ S' M
void OnTimer()
$ x, m$ S, z) ?8 Z{3 ]" d H! t \3 f8 d( T% k
MqlRates cotacao[];; R- l# _9 T/ w% p! h6 o! o! d
return ;
5 z3 T" X/ A! X7 k" w6 L0 wif (negocios_autorizados == false) // are we outside the trading window?4 s' o7 H2 O0 A
return ;
* H- O' o3 ~3 y4 i//--- We are in the trading window, try to open a new position!
# b. y4 ?$ j+ x/ d) y2 O# Nint sorteio = MathRand();
) }2 t7 o( I' d( `: `/ L/ n6 t//--- Entry rule 1.1
4 }5 A# ~) ^$ ~- l# ^2 I1 cif(sorteio == 0 || sorteio == 32767)
i! m; z& i, T3 ireturn ;& J: E: I* f" I9 W- p* s" S' O
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy5 K; k( U9 ]8 A4 {) o0 ^& T
{$ x# I5 B1 B' c9 ]4 F K9 y
negocios.Buy(info.LotsMin(), _Symbol);
% l( J1 g9 ~% Y( D! X" b0 @0 B}) w. _. q5 S5 P1 T$ e
else // Draw rule 1.3 -- odd number - Sell
, t2 Z, U! }4 ^" `- B{! O2 I8 F, f6 z
negocios.Sell(info.LotsMin(), _Symbol);. r9 _- ~2 d$ d+ `, N0 X% j
} K9 h# L& T0 ~
}
* ^) V' d! z/ o% j5 V! N//--- Check if we have a new candlestick...
$ c0 U. Q' e' n5 n6 m5 U) A/ nbool tem_vela_nova(const MqlRates &rate)$ K5 `/ _* a; O% v
{' f' f" m- L" W* k: h r, T6 y- }, C3 k1 E) f
{9 l" ?0 `' s! k# a% R8 H
ret = true;
/ @5 J' X- x4 C. Z4 F1 e( Zclose_positions = false;5 U* M6 f* y. T
}# ]0 r2 B: L: z
else
6 A- O% D1 R! h/ W, ]' `( g' f{
1 M% ?9 f! q( Hif(mdt.hour == 16)1 m" D* x5 u% I6 m W
close_positions = (mdt.min >= 30);% e8 K" v# o G: g6 W- A
} _( W. |0 L! y5 A5 w& G
} y% E9 M# ?! v. r
return ret;0 I: y4 U3 I6 y# }7 |. E. S8 w
}
9 J# E l- {. k8 z2 j; n//---) P5 A9 g2 g# a' E8 _! ?2 k
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])! P; ]2 b5 t1 t: r7 a
{
3 \+ x# x* O9 Kif(PositionsTotal()) // Is there a position?3 k1 s t/ j# u& Q
{4 b/ L+ ]4 n z
double offset[1] = { 0 };
9 C0 u1 S2 M4 }9 Z3 xif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
- } V$ r4 E! K, @1 n&& PositionSelect(_Symbol)) // Select the existing position!
% d! g* n; ~+ E- c. b7 H- X{+ H6 Y! f# e2 c; i! h2 u# `
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);0 ]4 v1 S4 c* X2 X
double SL = PositionGetDouble(POSITION_SL);% z+ _2 j8 C5 I' W' k% Y* t7 f0 E
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
/ t% x: Y3 y2 w$ Q" @if(tipo == POSITION_TYPE_BUY)
8 x, |7 U, X/ \7 q( W, E. V{+ ?' Q* Q! n" w& e" a
if (cotacoes[1].high > cotacoes[0].high)1 h% E5 N! k+ h6 Y4 B" w1 A. Y
{& N4 ]& @- i+ z% x; t! @
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0]; K8 a9 k: z* G; [" w# X
info.NormalizePrice(sl);. C/ F" Z* D7 v0 K1 J4 n
if (sl > SL)
; P4 w! T! o7 K{
+ R* t i: u& V1 F8 j7 {! Anegocios.PositionModify(_Symbol, sl, TP);
0 A3 Y* V" t$ j2 g- ^}- _. D7 {( N0 L0 N3 k$ Q
}, c, J! T9 }. c. w, Q* g/ f
}
$ a5 o, m+ j: x `9 delse // tipo == POSITION_TYPE_SELL: D" I& P$ b# G! k w
{0 @4 D' j( d$ b
if (cotacoes[1].low < cotacoes[0].low)
: z/ h$ x. p! e6 n{1 y' h# O E6 [) ?
return true;
( [8 U/ d) N: m* i8 p}8 V# J0 s) v5 t2 S
// there was no position7 @ `( Q7 L; {$ X& M
return false;
$ H7 @+ G( }5 _( T: G T}' ]& j: ~$ }6 f* E& I4 e0 _( H* n6 {
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。$ Q* ~ f+ n# P2 z* Y
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |