启动交易模型,并构建 EA
# [# ^# r( a% ]% r8 a2 y在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。& l- Z! w/ ^6 E# R
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。$ k* g9 K! v7 ]7 Z0 a* q* J
以下是制定这些规则的代码。
3 ~1 P" e" l, E: W0 j& {% H//--- Indicator ATR(1) with EMA(8) used for the stop level...- i$ X+ U" U b+ b* s$ _
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);9 |) X& k8 }: u( {
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
8 R; D( H& n1 I& o7 `//--- Define a variable that indicates that we have a deal...
1 j6 r, |$ x$ @" C6 \* w; T m4 C0 ebool tem_tick = false;
( C+ t1 {! f# q, h; `. }! I- J4 P$ T$ A//--- An auxiliary variable for opening a position
8 B7 K. t M: m5 c) I$ e* H. O#include<Trade/Trade.mqh>
2 d8 d0 ?! E" K' o% X#include<Trade/SymbolInfo.mqh>
% a" C1 Q2 W; \CTrade negocios;
1 g q" e( u7 ~CSymbolInfo info;3 z* e& h F- L$ F+ _" }
//--- Define in OnInit() the use of the timer every second+ l1 v& B" Y6 x& L3 c3 ~
//--- and start CTrade5 v3 P( L* _8 h+ ]5 Q
int OnInit()+ M. U$ p6 U {' V% Q
{* b o3 r/ t2 U6 ^+ X
//--- Set the fill type to keep a pending order* `( ?+ s5 Q; ~# S* f8 M6 q
//--- until it is fully filled
, B; ~" Z2 S& ^$ w6 x; r6 Qnegocios.SetTypeFilling(ORDER_FILLING_RETURN);3 G, f# \2 }% U; O/ |1 i
//--- Leave the fixed deviation at it is not used on B3 exchange
# [" M' u2 d5 w- U# inegocios.SetDeviationInPoints(5);
2 p5 a$ C2 v" @% V//--- Define the symbol in CSymbolInfo.../ G U' E" L) u6 m
info.Name(_Symbol);7 E7 I) t% K' A- g) j
//--- Set the timer...
6 d* t, t/ M, q, x6 qEventSetTimer(1);, M/ v/ L; o( k8 U" V
//--- Set the base of the random number to have equal tests...- i- t8 k y) D7 f
MathSrand(0xDEAD);! T0 Q$ r4 T* U5 a' T
return(INIT_SUCCEEDED);$ e$ o2 h; H4 a) R0 ?
}. K7 ?* A5 X0 Z
//--- Since we set a timer, we need to destroy it in OnDeInit().0 X \' Q5 ^& l
void OnDeinit(const int reason)
y: X8 m0 {+ T{
, Q7 p3 k$ O9 r4 c+ oEventKillTimer();, a: N1 M% g) r8 \
}
9 u. u" F" s5 j1 _ l//--- The OnTick function only informs us that we have a new deal% @2 Z J: O) @/ H$ v* r7 w
void OnTick()
2 g/ e. A$ c \% M{" L/ i1 z( w) L+ S6 N; A
tem_tick = true;+ ~2 s3 S# ]; @& c: c3 l* g! p
}$ ~$ Z4 b7 `- ]1 p" y, V4 c1 @
//+------------------------------------------------------------------+
1 b6 |0 F! v. ^( ^: E# s2 i! m$ N//| Expert Advisor main function |
& S9 C; h8 D; D2 v//+------------------------------------------------------------------+
}! D3 N% b4 j* o* t2 Svoid OnTimer()6 k/ \6 ]9 M$ z) Z
{/ {2 Z/ `; D1 M
MqlRates cotacao[]; K, Y0 l* T, m3 w% r6 ^3 n* W
return ;9 E n( e( I* X# V9 ^4 E7 H
if (negocios_autorizados == false) // are we outside the trading window?
' x2 ?" q0 ^! ]; O( Sreturn ;7 v, O0 Q- a; {. g; h
//--- We are in the trading window, try to open a new position!
3 H4 [$ i. o) B1 u+ |, u: _) R, ^: S9 gint sorteio = MathRand();
9 D7 q/ ^8 H/ H//--- Entry rule 1.12 X1 F& B& E% ^3 P: e7 e
if(sorteio == 0 || sorteio == 32767), _, ]; g& s/ a0 O
return ;
9 f! \. Q/ ^) [7 ?if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
# `1 [2 ~& i3 |( _( Y{( j; B ]7 U$ \7 r
negocios.Buy(info.LotsMin(), _Symbol);6 S8 m" m, r" U/ M+ |6 \& ] l2 i- H
}
. A! V' K+ t9 R, G4 P, Aelse // Draw rule 1.3 -- odd number - Sell
5 r: l+ \( D4 z( H7 i9 d. d{
$ {5 L9 k8 N4 L; dnegocios.Sell(info.LotsMin(), _Symbol);
+ A1 {# i( w9 S. B' [}
9 _, E2 n0 l9 r! {% ~! u3 }: `}
; f3 V+ s$ a, F i0 Q" r//--- Check if we have a new candlestick...8 V. [1 N q) _; P( s2 u! g
bool tem_vela_nova(const MqlRates &rate)
2 Y% A6 ~5 o, W/ [; Q; n7 @. ?{
9 C8 P* V( m( G8 {* {{
: _ J7 {# Q4 H. M0 d- {) }0 oret = true;
7 ^ p; |3 h7 j, G4 L+ E9 `. b$ qclose_positions = false;3 l6 H" O1 |7 U; C# D
}; K4 K" Y5 d; Q0 T0 G4 m( f
else
2 V4 d& S* k; ? o' ?/ r{ r; q" Q N- i: P1 W5 r) ~/ g/ a
if(mdt.hour == 16)
3 \$ X$ F* h/ A$ {close_positions = (mdt.min >= 30);
: R$ \* m' T% X( d" y9 b$ P}
8 }# w5 t& o6 }3 w& X}( n' e' ~, A# x6 f9 I t+ ^: r$ r
return ret;
3 K9 }. f2 H7 Y3 J}
5 ~6 O; D* x+ p//---
( G5 X( a) J% b0 ], l9 W- ibool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
0 V0 w p2 g9 q; V# L{
( r, K# g6 F% c+ ?, o7 P: Tif(PositionsTotal()) // Is there a position?& }1 t7 g/ H% ~0 ]9 r: F
{. \: i4 H6 Q; t; Y
double offset[1] = { 0 };, t1 x# N% K& ~/ C
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
3 [9 t p5 G9 W: C2 x z# g&& PositionSelect(_Symbol)) // Select the existing position!) X$ s! U: P4 N/ }
{/ J. O" G) z) A$ u9 t! `% W
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);# B3 W* \ M. s. Q! v$ y
double SL = PositionGetDouble(POSITION_SL);9 Y: ~! C7 e2 w$ M# N" l1 d
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
1 @$ q; `# x/ S0 Yif(tipo == POSITION_TYPE_BUY)0 _+ Z6 ?* @/ P- Q
{' u$ w# V. G N7 W, M6 m& P: r
if (cotacoes[1].high > cotacoes[0].high)* o" X" S i( E+ p7 S% l, E
{* i2 l# q l% N+ l$ {! B
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0]; ^- y# H; A1 r3 E& R
info.NormalizePrice(sl);
; ^3 P8 \- l4 nif (sl > SL)
: y! R1 D4 C4 b9 b! C8 ]- c{
I) t5 N4 [* G( Q7 M+ G; Q+ o( @negocios.PositionModify(_Symbol, sl, TP);% }# n0 ~0 I" x1 j4 p; M
}6 d) J" M7 x6 D7 G, W8 Z6 d& P3 M
}, F" p: z5 E1 x5 K
}* U( F# P4 h7 b
else // tipo == POSITION_TYPE_SELL9 {3 d; p- s- k) l, N9 n
{; s1 n1 J$ X: k" \8 I6 x
if (cotacoes[1].low < cotacoes[0].low)
/ a) F9 l U# U& \+ |0 u) `{
/ ]/ Y+ p5 w' z1 B7 s9 l, j! H4 Nreturn true;0 `+ L9 y8 ]6 G* X
}
- @9 o! U9 P/ a! h// there was no position) a6 n% w2 o q" A% C; v# Z; p
return false;
8 s) M4 v3 [" `/ r& u}
. H& _ O, y5 A我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
4 Q0 a( n$ C. m/ B+ m6 _' K+ x$ O到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |