启动交易模型,并构建 EA7 k R3 f0 B* @' Z7 n- K3 X+ g$ W
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。6 C6 C* A% ]- F& H, K5 t7 |+ c9 m- S
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
( q4 \/ J$ z6 B以下是制定这些规则的代码。
( ~- {- [" ~8 Z* O. {/ \! x//--- Indicator ATR(1) with EMA(8) used for the stop level...
/ m- a% Z) l$ qint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
! b# ` f. C" P% K+ Qint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
- D0 Y( m; e! X6 K+ m6 x G//--- Define a variable that indicates that we have a deal...
1 n8 H: F; [2 q: L# O5 H4 Jbool tem_tick = false;
: j' x& i* X$ C) z: u4 h: e1 x3 ?& U//--- An auxiliary variable for opening a position# O9 j* ]$ A3 n9 Q1 N
#include<Trade/Trade.mqh>) \+ ~; p$ w" g4 W
#include<Trade/SymbolInfo.mqh>
& V1 c+ ^0 x1 o% e; d4 ZCTrade negocios;/ n( o7 P5 S& H! R X
CSymbolInfo info;
! g3 g( |3 B, I+ h0 ] a& R) t5 M//--- Define in OnInit() the use of the timer every second
r; H; e' Y4 {, Z$ a" _* O//--- and start CTrade$ n! E, G9 [, x$ x2 W
int OnInit()
, W9 T! ^8 d2 b3 j! m5 Z{
' N) R k; S6 ]) X8 _//--- Set the fill type to keep a pending order2 j& w; Z% P( g& h- X' b) X; |
//--- until it is fully filled5 m) P: K: V. J8 U1 B
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
t2 f0 p" M1 Q; E; B+ [//--- Leave the fixed deviation at it is not used on B3 exchange
" P3 C; E+ \6 gnegocios.SetDeviationInPoints(5);
9 p. I M) T1 s# Q" w" F//--- Define the symbol in CSymbolInfo...
% j- v7 P7 G, T& P& ^3 vinfo.Name(_Symbol);
/ Z- {6 C1 g% S% i% k% Y//--- Set the timer...8 Z# n% B, m, ]: l q0 c( C
EventSetTimer(1);
- z( _7 ?. Z9 T//--- Set the base of the random number to have equal tests...
6 c) i( I% N$ l# U) CMathSrand(0xDEAD);
$ V# }! s+ q- r, s* a. Y. ]3 Y+ w0 vreturn(INIT_SUCCEEDED);; E* l# z2 c( P9 n1 C
}
0 ^- h& z+ N* v4 R- W9 T//--- Since we set a timer, we need to destroy it in OnDeInit().( B) P2 w3 J6 g% ~( K5 T8 ?! i! q
void OnDeinit(const int reason)7 {( t/ L, W+ H: A/ ]7 _
{& y n# C- S8 w3 `! n+ r
EventKillTimer();1 P0 L% r6 W+ @4 r
}8 s6 w: c- }' D3 j7 Q
//--- The OnTick function only informs us that we have a new deal
3 c1 h; B. O, {/ C6 Dvoid OnTick()
# p P, o; f9 \' k# }{- B& J% ^ }% w
tem_tick = true;
+ U: E4 J, x9 r5 ], v% M}% r% X* {: P' [! Z6 b
//+------------------------------------------------------------------+: p8 {/ s' V8 P2 M. Z/ U1 l9 ^
//| Expert Advisor main function |0 O( |* m1 Y- E5 u3 t
//+------------------------------------------------------------------+
3 q" A* f4 ?& g! rvoid OnTimer()
+ W- Y: B, O9 E4 [: V& Q{
+ f" c# V+ n, ^MqlRates cotacao[];
- d1 i5 y+ m( ]* r5 e8 [1 a$ _return ;
* D+ ~1 [# ~. Dif (negocios_autorizados == false) // are we outside the trading window?
. F. t9 g( t2 T0 w, e+ H' Kreturn ;+ B5 N8 @0 Q' o# U
//--- We are in the trading window, try to open a new position!
( Y# D. O! e7 Y2 g; {int sorteio = MathRand();0 R4 P) o% W) K( u- \& ^
//--- Entry rule 1.1, Q. }7 J: l+ Y
if(sorteio == 0 || sorteio == 32767)" w) w2 y, Q v; s2 m
return ; {' i8 {3 |9 v: H/ B3 h
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
' Z: G V- x& K" q, U# V3 w1 I8 g{
3 K, X7 l M; t! y3 }4 ]* onegocios.Buy(info.LotsMin(), _Symbol);0 z; B9 c# ?& m& ?3 y: z8 k
}; C2 B5 U' _/ Y( H; X
else // Draw rule 1.3 -- odd number - Sell
& H: T/ y) v* o{
( c" g, U$ a% o& Fnegocios.Sell(info.LotsMin(), _Symbol);
8 \7 J$ A1 a% S9 m4 n- I}. @. M) P$ k$ [1 v
}3 i) ^5 t. B1 _2 c
//--- Check if we have a new candlestick...( b( D, D, F$ @' l h
bool tem_vela_nova(const MqlRates &rate)
- x* ]0 Z) j6 e: Q{
, I# e0 t* i s2 `2 _{$ i) t! |* H8 A% N5 c# I
ret = true;' u3 r1 B( s0 \( U( b
close_positions = false;0 E: X; E( [9 V* i G
}" O$ U- D6 G' L! L0 m% V, K* t- @
else
" R* c @$ L7 [1 J- _{
$ }/ X+ H. x* j% l& t H3 V8 F' _if(mdt.hour == 16)! C4 k l s2 W' M1 _
close_positions = (mdt.min >= 30);/ U2 t) G. A. E( S0 t
}! b6 l, S5 F. W- {( v' v4 l
}
) c/ L( Y6 Q; Q$ ~5 @9 Z! ereturn ret;/ o. K" v* }3 b$ C
}
. G0 j5 i9 T! S/ `//---
( E; [4 R& F0 b5 m( b% v/ o4 D8 lbool arruma_stop_em_posicoes(const MqlRates &cotacoes[]), X6 W) a3 _2 E
{) K0 O8 D7 }& ~3 g' V" j
if(PositionsTotal()) // Is there a position?0 S& n9 x: I9 |( p
{ l& x, O6 n S, v
double offset[1] = { 0 };; w0 u& F3 x7 \+ B% X) X5 s& H- V
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?3 o7 Z: I x3 C& j& a; Q y# \
&& PositionSelect(_Symbol)) // Select the existing position!
: Y5 `1 c, ?! V* k{
- {9 F/ O' O( Q( m% A5 `7 FENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);+ Y7 P1 _$ ^+ S D+ a
double SL = PositionGetDouble(POSITION_SL);9 g2 u- d* B4 Z) y) \) c) \
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
; i) S8 C3 |% s3 I) i8 b! H! a' uif(tipo == POSITION_TYPE_BUY)/ C; a+ z# f5 \3 b& M3 }, x
{
) c0 X% d; K. `9 N/ C+ uif (cotacoes[1].high > cotacoes[0].high)
9 V2 _5 s: [7 p3 E; d7 F% M! ^0 x" ?{
$ i% m+ ~& t% ]' ddouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
: g/ J7 \& S6 ?info.NormalizePrice(sl);% q2 q3 [% I; q ^% k8 B
if (sl > SL)4 y y& ]6 {- N8 @' ]- K
{
4 ]8 |' @. n1 \negocios.PositionModify(_Symbol, sl, TP);
n7 i% m8 v" q" [1 w# Q1 z}8 z% b2 v( f% {8 K0 A- K: R
}! f' b; T* u% O) i- x6 I7 i
}
2 g1 U+ S7 ?" v! Pelse // tipo == POSITION_TYPE_SELL
7 a1 x0 f9 z& X+ g{. A B# C: B1 V7 o: E" q" }: Q0 k5 M
if (cotacoes[1].low < cotacoes[0].low)
5 u( [/ O0 Q' l) E. K4 k{2 Y2 H: f+ j* W4 }+ {, o- w
return true;
" q( n# D/ F1 L& `* a5 P+ w1 R' T}
8 a9 S& s5 q7 S7 r4 f: D. V3 O// there was no position
8 w; m" j# c' k4 @ q7 _0 Q* jreturn false;
( r6 V6 R3 a7 ^}
: N5 ?) Z+ D* \! ^2 o我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。8 ?. I" Q* g, t$ J* n
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |