启动交易模型,并构建 EA6 @' X; h; ?$ Y+ | \3 y+ ^+ {+ g
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。: m4 e+ }7 v: C8 V5 ?$ X
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
% B" S+ K% w! K2 ?1 J7 Q {! Z以下是制定这些规则的代码。
7 u- C) C s2 ]" L3 Z% ^//--- Indicator ATR(1) with EMA(8) used for the stop level...
* X2 z# F) l$ u) rint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);- e' y$ }6 t5 ^4 o$ g; @
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
2 T+ q M/ O# q$ \//--- Define a variable that indicates that we have a deal...
6 U) n3 z% {, ]: }bool tem_tick = false;
" k& a2 G; {7 X" J* c0 v2 d//--- An auxiliary variable for opening a position
% U# z7 @ r( t6 R6 i) X6 z#include<Trade/Trade.mqh>
9 K1 m# u, N" W3 i+ @#include<Trade/SymbolInfo.mqh>
/ R$ \6 E- J% e. K0 k, e4 l; e+ G9 ]- TCTrade negocios;
1 }7 s+ _- D7 C6 c4 rCSymbolInfo info;7 b C3 h( H5 Y; `( X% @" j& s; P
//--- Define in OnInit() the use of the timer every second: I- z! H$ g* u2 ]; x
//--- and start CTrade
" s1 Y, u/ z5 o- l3 C/ y, yint OnInit()
+ X; ]1 B6 T/ o B1 F W{& j+ @7 r, ~* F- F; B
//--- Set the fill type to keep a pending order' B9 \/ a/ Q! T9 Z) e1 o1 e
//--- until it is fully filled
/ }" }* a% v/ f% k0 Dnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
; S7 U# q4 W ^5 R7 L//--- Leave the fixed deviation at it is not used on B3 exchange; |# ]0 }2 ]8 R% e
negocios.SetDeviationInPoints(5);- Q, J" D- F9 q/ e. [
//--- Define the symbol in CSymbolInfo...
& R: L- c O6 ^, o0 P7 `info.Name(_Symbol);4 h2 [1 n0 q+ c
//--- Set the timer.... [7 K) P- J1 g! _
EventSetTimer(1);
6 A# A8 w+ q4 p; `//--- Set the base of the random number to have equal tests...
* [ C- E5 \# {2 P: t BMathSrand(0xDEAD);. Z" ^, `8 I3 c2 T) l( c; k
return(INIT_SUCCEEDED);$ h: N- Y. t- s, J' V) }% Q
}
' V( O3 v' H; p* x) q//--- Since we set a timer, we need to destroy it in OnDeInit().
6 ~ d. P! m) H+ c% Fvoid OnDeinit(const int reason) J4 s- t& t9 b0 f
{) }# t4 w: e$ m% l. q2 ^3 k5 q
EventKillTimer();! V. c8 A! K4 F+ V6 ^/ C! K
}7 U7 ]! c: I& t. g' o8 H
//--- The OnTick function only informs us that we have a new deal
2 v+ O* ~: }) g7 T$ V; O1 \ Dvoid OnTick()
% a% b5 _4 K3 Z+ i( k$ n{
1 d3 H" u5 o$ {! J6 item_tick = true;
2 i) W# ?9 D+ g4 I& @/ Y, I}
. ~' s/ v$ c8 H) W5 }: _//+------------------------------------------------------------------+
9 c9 X0 s7 q: `7 @1 w//| Expert Advisor main function |4 s- |$ x. i$ }7 U
//+------------------------------------------------------------------+
3 I, V% g1 O0 ?, S) s- xvoid OnTimer()
2 F, ]3 b% M& L1 D" K' b4 @{2 i# I: i7 f8 b/ w; q* v
MqlRates cotacao[];" a# V: [* f5 p9 R, k: J
return ;
; S; R2 ^ r. X1 u) p5 p6 y- Oif (negocios_autorizados == false) // are we outside the trading window?
. n5 i' f) L" {2 K& ^return ;
) K& V M4 U% y. d3 h! n. S//--- We are in the trading window, try to open a new position!% N. X' m. T1 A n1 l p0 ^
int sorteio = MathRand();
; ^2 x2 q2 K7 V5 S2 S! F% ~. v% M1 |//--- Entry rule 1.1
/ l$ A" E$ h: k2 e' s; u/ Q' w3 b0 Fif(sorteio == 0 || sorteio == 32767)
% N* m7 A' e: p% l0 Vreturn ; Y+ u" \2 S) l7 y! K, J$ _
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy2 b: s; q: e D, s" x1 i
{
2 T/ n/ f9 O" ?' v& Z% Inegocios.Buy(info.LotsMin(), _Symbol);
# ]/ L6 x! o0 a8 v8 L}# Q) o9 x7 {; s1 t g4 {
else // Draw rule 1.3 -- odd number - Sell- A5 X" m* Z( B- \
{
/ s* G( @- l5 n+ d. Z, Qnegocios.Sell(info.LotsMin(), _Symbol);! v, n; H* _' g
}) X! @2 J5 f1 v# [: h; F7 y
}
/ G% N" v- y5 a. }' I- W' w//--- Check if we have a new candlestick...
( F; p: W- S I2 v0 M6 hbool tem_vela_nova(const MqlRates &rate)
1 l4 f" h# E9 _6 s8 |8 X1 k{( j9 x# \8 W$ F( h
{- E# |- Q5 l5 w" P
ret = true;- ~% z8 R% D2 R' ^+ ^' z
close_positions = false;4 l$ P% P$ y8 ?
}
! S, ]) ]6 t" j6 }' _5 z0 Lelse
: o- K4 _7 L/ w3 b: _' F. Q/ W) P1 x{
0 j2 T8 u& z3 c: t) a3 Rif(mdt.hour == 16); e3 z7 h( \0 I" y% {8 z3 o
close_positions = (mdt.min >= 30);
h" S7 I; F% n w, T}* E& Z; p4 `/ k* K5 i
}3 a. |% K5 Q& J+ a
return ret;
! |) J# K9 {. {) H0 r. F6 Z5 k7 X; q}% I1 v8 d' k5 H$ R( f
//---2 b1 b) B. O$ ^' e
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
) J) B& W9 s+ h) g( k p5 N( p{
5 T) k1 y3 M9 V) y* r) L: Bif(PositionsTotal()) // Is there a position?
2 I' e0 m8 U5 l& |9 E* T{
& A f5 |" z+ z7 xdouble offset[1] = { 0 };; N: H, ~0 e. e
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
; W* b9 e9 n# E- K/ Y&& PositionSelect(_Symbol)) // Select the existing position!& C6 Q1 F! d. [$ K( V8 z: C
{* i$ T/ b! v& x0 y9 H1 T2 p
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
) N/ M0 V3 R- r& O2 h) F: T5 J9 Udouble SL = PositionGetDouble(POSITION_SL);
9 i/ v6 k3 P+ `) Z/ Q" [0 [double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
. s' h% ?: G, g# w. s' t) ^if(tipo == POSITION_TYPE_BUY)) a, E: `+ w$ w. I1 _1 V' d
{
' u0 h g. {/ P$ F# G+ ~: iif (cotacoes[1].high > cotacoes[0].high)% C' G; I8 J9 ~! e R1 j6 }' E" e
{
% B0 o# x. _: ~" T7 f1 M$ jdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
+ Q L' U' e( q9 K0 H! kinfo.NormalizePrice(sl);
$ K- V" T: l, M* ]$ r3 \if (sl > SL)) v* R( Q C) A3 [
{
6 D, j0 ^ |2 }7 I- anegocios.PositionModify(_Symbol, sl, TP);* X; k9 k0 ]) e; R
}
9 [) P: c: a( ]; F4 C}
# N h: ^# u/ P/ Y8 p" G0 o}
: l( K: \! Z7 k ~. H& ^9 Z1 {) v2 felse // tipo == POSITION_TYPE_SELL
* i+ }) x3 M( c* p& x{
! X3 B( h3 j9 B/ L7 w! Eif (cotacoes[1].low < cotacoes[0].low)3 a1 i/ A5 B1 i& \2 P
{& o( Q/ O3 @( v% P4 s7 s
return true; _, r0 ~7 ~+ o8 P0 w3 T1 ~
}/ i" w$ Q4 J: j6 D( b
// there was no position9 B/ X7 W* L5 F: K4 f W
return false;$ a. ]9 u+ k- W6 Q+ ~
}
9 P0 A1 A9 {0 g! M: U我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。, p# c1 D' v1 N- n9 f4 v& X
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |