启动交易模型,并构建 EA; z3 g* w0 \5 \
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
; s$ F2 _% f9 s- Z& [# S. v& N$ W为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
# u, K5 t" i6 c+ [) s5 `/ @以下是制定这些规则的代码。
n* y" g. X) Q/ V//--- Indicator ATR(1) with EMA(8) used for the stop level...
9 b* O& ?* B, Aint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);% e( S+ p, B0 }) h4 i% z$ Q5 V
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);/ ^; Z6 f" e% p; s+ r; y3 o: c; M, j
//--- Define a variable that indicates that we have a deal...6 E) v/ e; g( e3 i$ }$ R
bool tem_tick = false;- I" Y( D Z6 H0 w0 G* Y
//--- An auxiliary variable for opening a position
6 v: x! o: R- p( }3 o& o4 P! W' K. i#include<Trade/Trade.mqh>
, m. Q0 h# ?' V" f#include<Trade/SymbolInfo.mqh>
' D0 }9 @2 E3 z" J5 P$ E9 i8 I+ \CTrade negocios;7 r$ n. z: j; i& C
CSymbolInfo info;
- X& c( h7 y, c [3 F0 E8 X$ e//--- Define in OnInit() the use of the timer every second
' d! H0 l5 L" A9 s//--- and start CTrade
1 g3 t6 v+ h I: j! Eint OnInit()
. Y. Q% A R# J6 E4 R; f{* s O6 l$ I: O ^0 g
//--- Set the fill type to keep a pending order
! d: w8 e/ H, a% \//--- until it is fully filled
2 E* U; C. j' a& M9 h4 Mnegocios.SetTypeFilling(ORDER_FILLING_RETURN);! t# w2 P" z) }: H
//--- Leave the fixed deviation at it is not used on B3 exchange
* W" x6 y1 U: u, @negocios.SetDeviationInPoints(5);
) z' q! N0 K7 q0 k- V9 X1 m+ [//--- Define the symbol in CSymbolInfo..., Z. q2 B: n6 z' Y5 B1 _
info.Name(_Symbol);- e" h" }8 p/ j% s I# ^; m
//--- Set the timer...
]% X) f Q( G* FEventSetTimer(1);
" P7 M6 V9 \" R* s2 H( q//--- Set the base of the random number to have equal tests...
3 f, u# T S+ a, k7 C1 }* k% NMathSrand(0xDEAD);6 F& ^, v& u6 C
return(INIT_SUCCEEDED);
# o, F( x! o3 ^6 x' p}- b, g. M# i# i. L L
//--- Since we set a timer, we need to destroy it in OnDeInit()./ i% N) c e5 M
void OnDeinit(const int reason)! k9 B1 C* H; E' B+ {* c( i
{ S2 b/ ^/ ^/ J) `
EventKillTimer();+ }( I/ m6 D8 P. w4 V9 ^
}! r5 B: V' l4 n( D: b1 M# u% o
//--- The OnTick function only informs us that we have a new deal
& p. C2 X+ p/ K2 P: p8 qvoid OnTick()
) e# c6 U" I! M, ?{
1 O) E$ m- _2 Q! ~tem_tick = true;
, o- g1 e, X: f% F}
) I; p3 O( q, e//+------------------------------------------------------------------+( l" ?& y$ c1 N* ]# x7 O/ L {+ k7 g
//| Expert Advisor main function |
- q# ~# f0 |5 A) r( \7 ?8 u3 f//+------------------------------------------------------------------+
; L3 l1 X; [8 M# kvoid OnTimer()# }, Y4 v7 s* X
{
( g: G2 k; n7 ^# b1 g g1 i LMqlRates cotacao[];
# c; r; B' A9 j9 S# G" X+ x' Wreturn ;
8 ?, v& e' K0 Jif (negocios_autorizados == false) // are we outside the trading window?
- `: N$ ^9 F( Kreturn ;
9 c O" G0 O, {! w; O# e//--- We are in the trading window, try to open a new position!
/ L: _3 Y. m, _9 O bint sorteio = MathRand();
+ g0 X( d2 t" }//--- Entry rule 1.1
9 N5 g3 @2 \+ h5 @6 ` f) B! O9 T& yif(sorteio == 0 || sorteio == 32767)9 ^5 {; d2 x T( g
return ;
3 V# E5 v" s2 }/ x8 p, Aif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
) Z8 P* d4 l2 Q0 U{
) i @8 `' |+ |. o- y# j% q. `negocios.Buy(info.LotsMin(), _Symbol);
2 y( \9 r* R! X+ I7 h) c& l}& Q) G2 q* m H9 w9 o% T4 _3 J( r) O
else // Draw rule 1.3 -- odd number - Sell
. U0 Q3 y1 W2 W( k$ N{! M, R" Q$ J* S: J& }& u* ~" ]
negocios.Sell(info.LotsMin(), _Symbol);
% z7 k$ C! E9 j) k7 h1 T} O8 n& C2 }6 s1 y$ h
}2 a8 a1 w7 x, F5 _. p/ L4 p9 B
//--- Check if we have a new candlestick... z; t3 v* e: N; _8 m$ [
bool tem_vela_nova(const MqlRates &rate)3 _) X& }4 r3 q4 D, ~+ C
{
$ M1 s% `, t4 H: C8 F# {{6 C9 c# K5 F/ a/ @9 { `5 {
ret = true;- C. g0 d% J8 y8 T; n$ F: Z# z8 k
close_positions = false;
& q6 X a8 L. ^5 l}
0 g+ L7 P) \" B3 T+ \1 H+ ?1 [2 }else
6 u3 h, \: p& s$ v8 {{5 L+ T* L# u6 ~- I; T1 B' n3 ~9 y
if(mdt.hour == 16)
7 g% ?1 b. E; X6 sclose_positions = (mdt.min >= 30);4 C; b# y2 i L
}% F% |& r: ?6 _4 Y2 g+ C
}2 k) |3 ~- v0 I! n
return ret;
) W ~7 }9 |! N! V; n' @}
4 l9 B7 u9 |" W& i& _" u/ J* V//---
1 J. ]/ F3 J1 x* s& Bbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 Z& ]7 w7 s9 x- v+ ^{
4 b( h( ^2 [4 @4 X, u; Mif(PositionsTotal()) // Is there a position?
- {: r3 r9 a6 g; S{
: s8 m! @! k, v6 e! Rdouble offset[1] = { 0 };2 V- Z6 X, {' }# z5 Z/ ^
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?4 W. \7 q: f9 t* r7 }, o
&& PositionSelect(_Symbol)) // Select the existing position!/ ~4 Y x- s4 b6 I
{
0 m& b2 o% f& u2 B3 X: ] xENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
5 D3 i" v* i9 G# ?, @, H# |( [& g! \% Ndouble SL = PositionGetDouble(POSITION_SL);( K: ~ {* N0 \, `. y- ?
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
$ f1 g' v# r0 Qif(tipo == POSITION_TYPE_BUY)
- n( x1 o- z4 K5 F$ |$ o{
; Y- y5 x4 T: K! _2 @8 |: N2 Rif (cotacoes[1].high > cotacoes[0].high)
2 _" r& w# C m4 N: e{
" U& w$ y) f1 x# e% o1 j3 odouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];) E; u: S3 h- H/ m# r/ @' O s
info.NormalizePrice(sl);
- \# G L: p5 A8 {if (sl > SL)9 a1 G$ D/ M: L8 P* d
{; R1 o& w7 t; E& W' o
negocios.PositionModify(_Symbol, sl, TP);/ h$ V% M* v; S5 [$ g' \3 X
}+ _1 m- n# I9 r" @0 f! u
} x1 `' e' l9 f* d& a' ?
}2 F, ]/ ]6 [2 N! q8 r }: y
else // tipo == POSITION_TYPE_SELL
5 s: W: s& G% D5 V5 W' P% x2 E0 U{" D6 o. o0 W8 h/ B- H7 h- _. J
if (cotacoes[1].low < cotacoes[0].low)* `1 ?7 b5 G0 l* t4 I
{
% G0 I4 s/ H( P# t: sreturn true;
! H& U9 l" r1 K+ ?$ ]2 e}
' n* _' M9 N8 q6 }. O K) G/ ?// there was no position* J: E3 y) @% n" O6 d/ r% f) Z/ X/ r' g
return false;
3 r! L$ `* Z% g+ c% K- ]; D}! T/ [- \5 |+ a" e' C- a
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。; M, o0 n* B4 `4 p. a% { o' I
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |