启动交易模型,并构建 EA
9 Z! ^9 B; L; I c& E$ m在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
' ~0 }3 k* R' I, N为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。; Q6 U. U! I0 h
以下是制定这些规则的代码。
0 e3 z0 s" |+ M. u5 G//--- Indicator ATR(1) with EMA(8) used for the stop level...
' d- n3 |/ B3 x" F& r5 b( Y9 |int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);' ~* L5 h# ?; B% L
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
2 p) L& Z& j! ]( g//--- Define a variable that indicates that we have a deal...- m0 d3 l9 f1 k# `* _# i3 A& }
bool tem_tick = false;: O. H; l+ Z' S& U4 G, O
//--- An auxiliary variable for opening a position
/ M- z7 s; r8 f#include<Trade/Trade.mqh>
6 H1 Y5 e( T/ |& z: B#include<Trade/SymbolInfo.mqh>) ^+ W' ~4 a& Q8 ~# F+ I
CTrade negocios;$ d4 p7 k" S/ r7 I( r+ e1 q T( j# W
CSymbolInfo info;
/ l9 _: S- D# H8 g+ c//--- Define in OnInit() the use of the timer every second% E/ [0 F( a+ v5 H; U
//--- and start CTrade
! O5 O$ U% Z* S: L% iint OnInit()( U- h. [: |3 [/ n
{
" o* m; e& o: I0 Q I//--- Set the fill type to keep a pending order
9 W" w8 _1 f9 q2 C3 J2 n) _5 e//--- until it is fully filled- e5 S& D- B& ]2 m
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
. w7 j% M% e" O$ c" K; @% u" D//--- Leave the fixed deviation at it is not used on B3 exchange8 K% L5 k( r0 K' T4 z1 ^, ^# |( O
negocios.SetDeviationInPoints(5);" y- _9 w; X! l
//--- Define the symbol in CSymbolInfo...+ Y0 h) w' z0 o. K5 k b/ }
info.Name(_Symbol);+ D# O0 Y s, l9 n+ P
//--- Set the timer...
# W f }% F0 a4 FEventSetTimer(1);
9 \3 H( g' ]' j' \. f//--- Set the base of the random number to have equal tests...
h& }( j8 Q; f8 L. P6 fMathSrand(0xDEAD);
/ w* r& M& b3 o* U$ U2 X1 Xreturn(INIT_SUCCEEDED);& ~0 [# u( y: U
}$ j0 V+ K4 W p4 }# d" \
//--- Since we set a timer, we need to destroy it in OnDeInit().
+ p7 s0 d5 v8 p% D# q2 r L% jvoid OnDeinit(const int reason)
" E" [* b; G! n- X% b0 k% a{
# V8 c" j1 [$ F2 h+ y: UEventKillTimer();
v, @$ a. ^/ o2 ^$ U. b' M1 ~}1 A5 t" S" l7 E9 k
//--- The OnTick function only informs us that we have a new deal
9 x2 F% E' q9 {8 _9 n' o* q8 Vvoid OnTick()! M) A; |5 ]9 F+ n+ O
{1 q& ?$ u/ }3 f" i$ B
tem_tick = true;
1 O# Y# m2 W1 F}
5 H8 B+ ^3 Z5 ~8 J/ S//+------------------------------------------------------------------+
3 p7 O' `. i6 x0 V2 [; G; i. W//| Expert Advisor main function |2 O: A# N* X; u8 X
//+------------------------------------------------------------------+* u, v1 X) g8 b7 b; {3 p
void OnTimer()
2 J2 Z) ?/ o0 _{
( t, e6 x& X" v2 gMqlRates cotacao[];
8 z0 Y5 K [* z. f' ^return ;: x" I- u; _$ F0 }* }
if (negocios_autorizados == false) // are we outside the trading window?% r3 [, `) {4 v& O6 I# W
return ;
) C% P- | l, b, M) M6 o//--- We are in the trading window, try to open a new position!
/ K; w$ C- v7 rint sorteio = MathRand();
1 C& {+ j; D! b, i: \- q& ?//--- Entry rule 1.1
- w/ d6 g8 E% C/ L0 B4 Xif(sorteio == 0 || sorteio == 32767)9 O, i0 l. y# P/ O. G# V
return ;" a* `6 L: T: t
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy0 }9 R x9 x) F- b5 _
{/ a3 _( L) u% @; h g. j
negocios.Buy(info.LotsMin(), _Symbol);
# L o v. U7 Y}) k4 L, X+ j- b v, L
else // Draw rule 1.3 -- odd number - Sell
' i- A7 r; | X: P" v" u- V& u{
0 X* O( V" m8 U( ?negocios.Sell(info.LotsMin(), _Symbol);
5 q4 `9 E' f* z. V+ x1 f# d}
0 K" h, }* m' ^- }& I* n3 f}
7 n/ ?8 f* W9 Y& o5 n//--- Check if we have a new candlestick...3 y* b( o" T# t4 P$ Z! C: W6 b
bool tem_vela_nova(const MqlRates &rate); V4 O2 r0 }) o
{- f ~3 v5 r4 C" y+ t) w( e
{
" a4 R+ f" D6 ^: R7 h! @$ n/ s3 R% ?ret = true;
% L' w0 D2 G* J1 wclose_positions = false;( [: H# K& h- l
}
$ ^/ k5 s; C# U. G3 e6 g% Qelse
2 D+ p. Q! K& |7 l s3 M$ N- q5 e, ]" R( ~{
/ w- C( A0 ?; b! F* ?, t& yif(mdt.hour == 16)
& W a8 [% S Z( u8 Y$ vclose_positions = (mdt.min >= 30);
" h- x3 g, _9 ], Q0 s}
- W$ c1 n" X5 i4 e# Y' U}
+ r; F( W- Z/ U/ Z, a8 l4 c) Yreturn ret;
, s* G6 S9 [ {6 b}; i" M c) h6 a
//---/ t% V [! @8 Q$ j N$ f6 {( ~% R( R% t, D
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
9 O2 d2 i, z+ i, @{
: J* b* P# [$ hif(PositionsTotal()) // Is there a position?
' r9 U/ R2 A' ^$ Z& i9 q{# L1 U# k2 W. z" \: d4 o+ V5 G% X* K! ?
double offset[1] = { 0 };; ^7 `% X( y6 {1 p% I. I
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
! H9 i' j1 ^! [; R&& PositionSelect(_Symbol)) // Select the existing position!6 I1 e/ b {+ K% x
{; U: n% i1 R+ ]: E: N
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
" o: T& F& `8 T9 Qdouble SL = PositionGetDouble(POSITION_SL);
* D: r0 n; ~; ~! pdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));( b3 u5 C" u* ]2 B- u$ _ i+ I
if(tipo == POSITION_TYPE_BUY)6 h k H6 H( ?% I* l
{8 U& `1 s/ z9 ~, m9 G7 G+ W7 h
if (cotacoes[1].high > cotacoes[0].high)
1 R& D5 T3 a0 D: v: C+ r/ M{! O- c3 {! w2 p0 z8 Y* A
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
[1 x" Z( \" H% Xinfo.NormalizePrice(sl);
4 |( ^' X. l1 Q0 M: z- Gif (sl > SL) ?( \/ y, M6 O0 Y8 ]
{! U6 a/ b# i% j4 s; \
negocios.PositionModify(_Symbol, sl, TP);) J; F* e1 L/ d# K' Z) b
}
/ t5 ~5 @. {7 E: e# x+ a}; }; e- N r, i" Q: y
}; o# c- w$ ]' L1 L! U
else // tipo == POSITION_TYPE_SELL
( I4 n! w5 E# z D/ r3 r{( s$ c5 d' N$ V
if (cotacoes[1].low < cotacoes[0].low); l3 y, R# S$ F% c; ^, t; g) {- V
{+ t Z; K! K1 D1 a) K/ w" o# ]% }
return true;
+ S Y+ ^* m8 H) S}
. e6 U* W* Q$ u. u( w// there was no position
$ u6 W% d( q- ~. p+ ~4 Ireturn false;* B# _+ Z4 k! K
}* W+ O) d- j# u W! l0 f
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。) X5 A# [3 p2 E% N
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |