启动交易模型,并构建 EA
$ C' t7 ~; d4 s& V' R- `在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
% \) k' x. w. E. U: h! t2 T- ?为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
+ R) q4 P8 D4 S1 u4 O7 {; B! u以下是制定这些规则的代码。
" F% t$ M7 [) }! N, L//--- Indicator ATR(1) with EMA(8) used for the stop level...
/ Z# u! n! K5 f% p. K5 N& w/ tint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1); n, y, y, \; u0 [
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
, H6 L9 u$ s1 { K- F4 K//--- Define a variable that indicates that we have a deal...: u6 U7 T" x9 v" _& {9 d+ [
bool tem_tick = false;
& ]6 x2 |* ]7 P% o8 S//--- An auxiliary variable for opening a position8 }2 y! i; M# h: Z" o
#include<Trade/Trade.mqh>' o; G& U1 {, M5 z
#include<Trade/SymbolInfo.mqh>
" O) K' T: } c/ T$ C+ K6 v0 MCTrade negocios;
' q. z, p* u* qCSymbolInfo info;
C* ]( B9 j" l% r) m//--- Define in OnInit() the use of the timer every second2 c) B7 l0 S: }$ I+ V% R, D
//--- and start CTrade
) r) t. d) u0 R. F7 [; ?6 Qint OnInit()4 @# B4 l) T8 e9 |7 T. @; f- x
{* _. ~* S V/ W/ w4 ?4 b7 G
//--- Set the fill type to keep a pending order; ~! {* i0 j5 k% n1 ]; y8 X
//--- until it is fully filled
, C% O* G. `1 Z e; e5 H- \, B9 bnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
: ]" _- J3 s B8 W7 \4 C5 W//--- Leave the fixed deviation at it is not used on B3 exchange
6 n% e& {/ a0 ~9 snegocios.SetDeviationInPoints(5);
) f# l( G+ A d+ d( d$ }2 o//--- Define the symbol in CSymbolInfo.../ c$ o# @2 y4 [8 N: n6 A' ^
info.Name(_Symbol);* a; ?/ L8 s" P3 v
//--- Set the timer...0 f% q ^' O3 H& y
EventSetTimer(1);$ u, N& H: r. K% x
//--- Set the base of the random number to have equal tests...
# M$ |/ D3 ]) m0 Y8 |' o+ n% IMathSrand(0xDEAD);" ]; L: G% ~8 O3 U& R. n1 F
return(INIT_SUCCEEDED);) O" N. n1 u, o+ |+ X; V, Y _5 ]/ w
}& i# e# ?* }/ k7 w! e/ E P
//--- Since we set a timer, we need to destroy it in OnDeInit().
5 d" G% _1 F' Q6 L) @$ `- Tvoid OnDeinit(const int reason)
! }( ~4 X+ y; M) r{! T* h9 \% }: G z
EventKillTimer();
4 E" S# g4 c/ Z1 p. h}
& e5 u( m# n9 _7 m//--- The OnTick function only informs us that we have a new deal
, d/ h6 Q3 k' f% pvoid OnTick()
4 B2 M. F: O5 O* C2 @{
& @- E& a# A: f" s% Ttem_tick = true;! I6 ~) F, A" N+ n; ]
}* B# v7 M$ i K' M1 j! h* X
//+------------------------------------------------------------------++ Y# ?" y* l. W6 @) k$ w! `0 m
//| Expert Advisor main function |
: }+ k3 ]; l% v) Z: D* m* p//+------------------------------------------------------------------+% y1 `$ x- m6 O0 J. p
void OnTimer()
8 K2 t9 T+ G' H( S7 j* @{+ ]. N5 S" F( Y$ C. c
MqlRates cotacao[];
2 T2 G: t- z/ E# U) l$ Sreturn ;
0 N& C9 }% R/ Z, I0 C% I C* pif (negocios_autorizados == false) // are we outside the trading window?; M# T7 U% V1 k
return ;+ e# {6 B: F# k8 ^( x% g0 f0 V
//--- We are in the trading window, try to open a new position!
+ R4 l7 L; v1 V7 W5 u! ?8 Rint sorteio = MathRand();
( S9 a- Q: u r( W, y//--- Entry rule 1.12 k: T3 S" ]9 {' R
if(sorteio == 0 || sorteio == 32767)
$ z2 f5 h" P' H3 k# \/ H. m$ freturn ;
5 [7 [1 ^/ W1 n8 G, Uif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy# A- C* _1 l: b. Q( \' W
{ B# q0 M7 `% H" e( W6 Y0 U
negocios.Buy(info.LotsMin(), _Symbol);" |1 g$ g7 O: y; j8 J
}
- i' q9 g$ I( D* Y) Pelse // Draw rule 1.3 -- odd number - Sell$ R* `) `! p! n0 J1 U7 Y/ T. V/ R
{
! ^* s6 y) K4 [( ` O2 Y1 ` K3 r9 {negocios.Sell(info.LotsMin(), _Symbol);
2 G6 m* C0 u9 |, V' S- I: O}6 X+ b9 p; S* B8 i% D
}
) L& S0 p! N) _1 D% q0 ]- ]//--- Check if we have a new candlestick...4 V; N5 q1 N. D0 }
bool tem_vela_nova(const MqlRates &rate)
* M, I i' h" o/ j; u{
5 M: G/ X- y$ H- M+ D2 s{
) M; N. p; F% n# ~( Eret = true;
* D& q3 ]' d' d# P- N7 T, ^close_positions = false;
8 l& E& v+ K5 v8 P2 E1 @5 v( D4 E}
5 ^- f: m/ ]- ~+ g, ~else, G0 V8 r$ C/ R3 q& F/ I% R: M# {$ _$ M
{
: d* `/ v i: `4 \5 qif(mdt.hour == 16)- l' ]9 J+ L9 {$ b' {
close_positions = (mdt.min >= 30);2 w6 ]# o' w+ _" l. e. W" u
}
" h- W- i' s* L5 O}' n e$ h- Z: @, D! g
return ret;( Z. j3 G3 Q2 M K/ {6 r4 u
}
6 ^9 Q7 e# u0 p2 p7 Y//---9 Q2 ?( R3 F1 N- R. _1 l( U
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
8 f0 }3 Q" N: Y{8 M x9 X' k2 ]* Z: J+ u6 U
if(PositionsTotal()) // Is there a position?
7 `! p3 R$ g0 z8 w2 H{
r; X1 `) ^" B8 gdouble offset[1] = { 0 };8 y" a+ ]! A. q. j4 a& N
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
: A7 f4 | |. p0 l; {* g! z&& PositionSelect(_Symbol)) // Select the existing position!
# e8 c W# A! j. v! u& \! E) h{7 s9 n p% E; ^) h9 _5 E- q3 f
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
- _1 f3 n) a/ x/ l' Gdouble SL = PositionGetDouble(POSITION_SL);
5 U% |4 P* _. c+ K5 p1 l- Odouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
' M5 o$ H4 q2 t4 |' F$ g9 Wif(tipo == POSITION_TYPE_BUY)& M3 v. A4 h+ q, q, \9 d
{0 A9 i9 |. L0 X+ f- Y& M$ V- u5 \
if (cotacoes[1].high > cotacoes[0].high)
+ D/ k7 u' f- t2 |{0 b" B- l. o& W+ R H6 L% f
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];" x0 n: {5 @; X. U
info.NormalizePrice(sl);
* D; I# F# _& p# R" J# qif (sl > SL)
" e! P; [7 Z: X/ ^/ ]; w# ?5 C{) I, b5 }; Q3 ]7 o' u" q8 @/ n
negocios.PositionModify(_Symbol, sl, TP);' G+ X, V# n1 Y- J3 v
}8 l6 Q7 C, U8 X, m" G6 W2 c
}4 @: D: t" R) h3 o( I
}
0 `' ^. n2 I8 {6 ]* }' n' L0 H6 Nelse // tipo == POSITION_TYPE_SELL4 }* H9 o# g4 {" t
{
3 H7 q) V) P$ i6 @; pif (cotacoes[1].low < cotacoes[0].low): W" c& T, J# B: O1 X6 W7 n
{
0 l4 X+ u' z/ Preturn true;9 R+ ^ z2 T4 r1 r
}
5 E E7 @9 e. F- X5 L1 e$ @// there was no position
6 A7 N; ?" L* ]- j+ z) nreturn false;
" L8 f$ O. H. W0 {3 @% j}
2 P; G& Y' z7 t4 I. V, d; K4 R- g我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。5 u2 N" N1 g, ?4 _8 {$ Z# N( O, L/ I
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |