启动交易模型,并构建 EA
$ a& {! K9 ^1 W2 f ?在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
; ~* A: m5 P% `# L2 |! m为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
6 k9 Q8 V( {2 e, T0 M8 j: q8 t. p2 s以下是制定这些规则的代码。; O9 ~' U# F h. T: _/ U# K! y. K
//--- Indicator ATR(1) with EMA(8) used for the stop level...: ?/ u6 y1 q8 O( ^, z
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
0 h& d L+ @" @- Y- rint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
, Q; a7 H( N3 V: @: B* N//--- Define a variable that indicates that we have a deal...8 y% d9 w- z0 w/ x
bool tem_tick = false;
9 P9 [2 D7 w9 C: `4 ~' k2 b5 I: w5 h/ P//--- An auxiliary variable for opening a position
' p6 N" Z9 f2 |! ?* ~6 B#include<Trade/Trade.mqh>* a( W; U2 i% @. c) D% \7 m5 @5 A
#include<Trade/SymbolInfo.mqh>
' F: b) r; }! V' w2 SCTrade negocios;: e/ O4 h5 j: i. ~! ?% ^9 l8 P
CSymbolInfo info;9 L1 d1 W$ A1 A( _+ c& @- @
//--- Define in OnInit() the use of the timer every second
) M2 f# ?- P" ~. g6 @2 I//--- and start CTrade( y. z- H* N+ e9 C6 |
int OnInit()
1 e% |# G* {! s0 C) R) P) \{4 [. i( K& J- b! x8 ^: m
//--- Set the fill type to keep a pending order: f1 E5 c1 ?) L* n& f( I
//--- until it is fully filled0 j# ^. n5 r3 X0 U: a
negocios.SetTypeFilling(ORDER_FILLING_RETURN);5 e8 R7 _- w" [: O
//--- Leave the fixed deviation at it is not used on B3 exchange
7 @1 ~% D9 ~; d" {6 r }negocios.SetDeviationInPoints(5);; l+ B/ S" k4 a8 v( M
//--- Define the symbol in CSymbolInfo...) W/ `+ b2 k5 Y" L0 b
info.Name(_Symbol);7 k! v* r, L3 M" O6 `
//--- Set the timer...6 z$ D l* N8 E$ o8 p3 H
EventSetTimer(1);& L! O; E2 [3 x
//--- Set the base of the random number to have equal tests...$ P; \, P- g ~- z9 F8 q( w
MathSrand(0xDEAD);: F! R+ ?% k8 i
return(INIT_SUCCEEDED);( h8 G. m* Z8 f6 K9 E$ O# q* b A
}
: q( `4 y- z, R/ l, r- r8 Z1 D//--- Since we set a timer, we need to destroy it in OnDeInit().9 B9 q4 d6 l9 U# ?: r
void OnDeinit(const int reason)# U6 R* c5 `$ e/ l) d+ }
{5 }: z7 q, J% A8 e- ~# ?
EventKillTimer(); v* t# B" R4 L, i/ @
}% [7 Z7 v1 z6 Z0 b# Q" d
//--- The OnTick function only informs us that we have a new deal3 K, z& s, |, E7 e. p5 y" b
void OnTick()
: R3 N$ Y8 B5 V9 u( j) P9 j" ~- x0 W{# Z# Y) t$ ]. @9 S9 F* D( h9 I
tem_tick = true;
8 o% a6 k- Y7 } X$ ` Q: K}
1 }" Y! _4 [& q# w8 F) N//+------------------------------------------------------------------+' j% h( R2 N: W( s
//| Expert Advisor main function |
& G! d" x8 K/ p! {5 y2 V//+------------------------------------------------------------------+
$ a, b! {5 h8 d# y1 a, kvoid OnTimer()
7 j6 v' A* A: @0 u# Y) f6 F/ d{
* W: r% g4 P3 X; Q) \) UMqlRates cotacao[];
( o1 e9 l/ u2 _2 I$ l7 |return ;' G/ S& o' ?% w R3 W' }2 b
if (negocios_autorizados == false) // are we outside the trading window?* f& u- L1 p' Z3 K1 v/ e
return ;
4 c: e" b& ^$ ^//--- We are in the trading window, try to open a new position!
( A: _7 i2 M" f+ S) A% J$ I: Vint sorteio = MathRand();3 {! \, m: x# g; p
//--- Entry rule 1.1
) t; K/ I7 Q1 e* _ bif(sorteio == 0 || sorteio == 32767)
" d z4 D4 k+ J$ Yreturn ;
2 X- ~4 k, r& ~$ i% zif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy5 [ M ~: a9 k+ D. E
{2 p# E4 z- N' Z" U
negocios.Buy(info.LotsMin(), _Symbol);: L4 c: n+ K1 p# g7 s- o0 M
}
2 Y) b+ {1 O; i+ C8 [' P) aelse // Draw rule 1.3 -- odd number - Sell3 W0 s3 Q7 s1 n6 } [8 v
{
; Q! W' g7 j9 z: T9 Fnegocios.Sell(info.LotsMin(), _Symbol);( g6 z7 X# v$ r B; c; R5 f
}# {- @5 N' w: _# T9 f' \" H
}% F K9 u9 [4 e1 H8 h
//--- Check if we have a new candlestick...
& U# T/ c0 W& O# U, dbool tem_vela_nova(const MqlRates &rate)
0 L3 o2 E2 |" R' v" q5 T& Z{ v% m4 N) }7 m3 z/ g
{5 i9 j4 U4 g @% }6 r4 b9 b
ret = true;4 x& ^7 Q0 U% c' o" ^% L" [5 D w
close_positions = false;5 z( t9 u1 G$ z( f X l
}$ _7 M- W7 G0 e2 S& v
else
z/ u' b7 z* j( l, b" M4 W% I0 E% O{
+ h7 Q# r( @) cif(mdt.hour == 16)
0 [9 ~/ w" u5 Z7 Xclose_positions = (mdt.min >= 30);5 q5 g6 I: D _( U0 @
}
+ F$ A1 V- i4 @, M}7 r& v+ E% R* d I9 A6 |
return ret;, W9 v0 X+ Z% ?; J
}
2 B8 j9 V Y4 y//---" ]% V" N- G5 Y7 o
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
& p' `/ q" A2 w! p7 A/ G{0 A- u. A* l& }( R
if(PositionsTotal()) // Is there a position?
& N& f: y4 w. o7 v{9 [; i+ v& L0 u. d
double offset[1] = { 0 };
+ R& o: P, p# y; l' Fif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?/ g3 G" k1 q' X* ~3 M% `2 }* R
&& PositionSelect(_Symbol)) // Select the existing position!, _0 E: R9 y% L3 t2 W9 q
{: ~9 X0 n# ~5 O$ a7 A
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);' W) m* ~" f9 v
double SL = PositionGetDouble(POSITION_SL);
' d6 P! O8 h9 j1 D7 |: G, d9 [, fdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));+ A1 F! ?- X5 c8 l* z
if(tipo == POSITION_TYPE_BUY)
, I. T1 |) A( f1 q9 X9 t{
/ Y) Z# S6 W; c4 I2 Q) Jif (cotacoes[1].high > cotacoes[0].high)/ j$ }$ y1 r$ Z7 R' m J" h- n8 r
{, d5 ?% d2 i7 o
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
& i# E' y0 {" J4 `info.NormalizePrice(sl);
# D* w- @, j( cif (sl > SL)$ c: T$ \* u: [9 g5 a5 F- t( t
{0 \2 r0 N8 u3 p+ d9 B) m9 c* q
negocios.PositionModify(_Symbol, sl, TP);
' Q3 l4 s) v1 E! V+ I}
7 F4 O- G P" B4 Z8 @, _$ r}
$ m( f5 _+ Q" b) K7 d+ Z1 L' N% }}
" F/ M/ k; Q4 f' welse // tipo == POSITION_TYPE_SELL
! {' l7 ]$ z( c+ Y' m6 Q w{5 j w" V, S/ H/ M
if (cotacoes[1].low < cotacoes[0].low)
$ p* w& r) @+ S! c8 C* ^{
: q8 T. B5 f/ g+ [5 @! r/ }6 c& Vreturn true;0 c3 H4 |9 G# L* U- F' q7 {
}
8 I4 n7 u& G0 Q: ~// there was no position
1 h1 `3 t" x I z4 A/ q6 V8 H5 D% Freturn false;
% N/ @% N" x/ x1 L7 V, e}
6 C. @9 R$ Q- Y) N/ e% h5 h4 F# C我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
6 o5 X, G2 v" d }! ^* @! y到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |