启动交易模型,并构建 EA
3 r8 `) n' n5 D" l/ v在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。4 X9 i) I0 r" i4 g* p/ }
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。9 L+ N6 {! g0 u$ H, ~ b: r
以下是制定这些规则的代码。/ N4 r, e! I( c8 p5 v- a% V' X
//--- Indicator ATR(1) with EMA(8) used for the stop level...: a5 L* i5 j2 F- D' t
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
5 i8 q) x6 R" Tint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);3 X+ M0 r( H p5 L5 ^" D1 O
//--- Define a variable that indicates that we have a deal... D5 @, J1 O- P3 z, G& e) k* s( p
bool tem_tick = false;
4 \- H/ }2 O+ d: D0 |6 y Q//--- An auxiliary variable for opening a position8 Z2 S) d/ v3 K9 v+ B
#include<Trade/Trade.mqh>
9 X& m" l4 U+ `( h8 K7 c& u#include<Trade/SymbolInfo.mqh>& a8 t0 `; d+ b7 ?- Y) z; [0 }
CTrade negocios;
# y8 F! x2 a( I% pCSymbolInfo info;( l5 n) `* Q# B( j/ N8 E8 J1 o& @$ y
//--- Define in OnInit() the use of the timer every second
/ @: h5 V9 l% x$ O//--- and start CTrade
: {) H4 {, X' h& b" Dint OnInit()% i$ j0 k# s) d8 ]3 M% _
{
' j6 j0 l# d' ?/ j: Q) U0 n//--- Set the fill type to keep a pending order& r: q' a% N0 U! W4 v
//--- until it is fully filled
5 E; U0 Q" h, g G2 Q8 mnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
, p, Z4 k) l; z& c- O//--- Leave the fixed deviation at it is not used on B3 exchange
$ I- `1 W5 }3 t4 d( n8 qnegocios.SetDeviationInPoints(5);1 c; F$ M, u, b. z! g, ?
//--- Define the symbol in CSymbolInfo...3 s" M9 M" [) h+ k
info.Name(_Symbol);
' ^* q" \& T c: N# h//--- Set the timer...
2 |- t) X1 r4 ~7 o, n' N/ B4 p @EventSetTimer(1);
6 k* y2 O/ x6 V2 k- @//--- Set the base of the random number to have equal tests...6 C4 b1 d1 w+ |
MathSrand(0xDEAD);
. k1 `, v; z+ M* T5 breturn(INIT_SUCCEEDED);! }8 l4 v' x8 u2 O. }
}
; H" c8 R% i p, \, p+ w//--- Since we set a timer, we need to destroy it in OnDeInit().1 q \& ?2 X5 G
void OnDeinit(const int reason)1 C: \( ]" O1 n% A* H5 B9 _
{
# z9 @- a: U1 j, f& S5 eEventKillTimer();
. u# k$ r( Z0 R" L$ ^! G}7 \0 h+ f# R b0 |. q
//--- The OnTick function only informs us that we have a new deal
: b: e! ~8 y; T7 b: jvoid OnTick()3 a ~/ ~$ D3 W0 r3 K, R
{
1 y0 X& H ]6 f* G) l3 ttem_tick = true;
" C# t3 q5 i4 {1 f" m" j}
* p% F5 d. D- x6 E6 }//+------------------------------------------------------------------+# ~, V! `9 g! n# ^$ ~! \. N |) [
//| Expert Advisor main function |
! W# V" k ^: r; i5 s. Y6 p//+------------------------------------------------------------------+3 k) Z, c( @9 \3 N0 k
void OnTimer(). F; R. z. f a9 _* L. s6 e& K4 A
{" ]: B0 E S& K9 T/ U, V
MqlRates cotacao[];% \0 `( C3 g) `* D
return ;
7 Z& P+ T! Y- F+ [1 yif (negocios_autorizados == false) // are we outside the trading window?# M; T7 i! O$ w7 R$ e3 N7 z$ X& q) H
return ;, ]% O9 I) Q7 `% i: a2 E
//--- We are in the trading window, try to open a new position!4 T# S4 X" M1 f0 Q) M) K: ^9 z
int sorteio = MathRand();
- `- e4 m1 l" d- g' U//--- Entry rule 1.1* i g6 l' l, e" K; v1 P
if(sorteio == 0 || sorteio == 32767)7 a' U/ p2 B" g; d, V) p
return ;# T& y% X2 ]9 \) E1 V
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
; z/ C7 l$ P* C: k{
3 \0 `+ |- i6 x3 r6 {negocios.Buy(info.LotsMin(), _Symbol);
7 L4 k# s2 K) w% B% X. F1 T/ @5 V5 U}) D7 J, y$ m8 N; i+ q3 n ?
else // Draw rule 1.3 -- odd number - Sell9 z9 B3 q2 z% v1 u* `2 T4 `/ J/ F
{& B2 m0 ~ j( x: G3 x
negocios.Sell(info.LotsMin(), _Symbol);7 i# L3 g* L l$ F6 a
}* P; v5 z! M7 _# Z- w# A- _% W5 _
}
" H6 D9 @6 D4 \# K. V//--- Check if we have a new candlestick...
% P, @/ ~" w1 ~) G0 ?bool tem_vela_nova(const MqlRates &rate)( A; [, {$ ?9 c- l1 E' g% e. p; H. Y4 Z
{
- l; j% M/ A* j3 `{
7 X) D a, p( ]" A- `ret = true;. d2 {9 c0 C1 f) F
close_positions = false;( u. ~. y8 @% g+ n; K) p
}7 r3 K* R. B3 |
else
0 C1 `% c( O( K6 T5 Y' M{
# u( c/ ~: T0 H8 F7 gif(mdt.hour == 16)5 m4 c9 L/ M) T3 q% y1 [9 G. T2 T7 @5 N
close_positions = (mdt.min >= 30);
9 u2 F1 P3 a; P: o8 S/ ]}
, s/ s+ @% s9 P$ F' D0 W}
# w \# X' L, C7 }: T. Xreturn ret;2 w, H1 q- x- E% p" C
}- l* |: H3 [: Q0 [& H
//---
6 \; w2 _$ r2 d- Z" o rbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
) D4 V: a% m7 v. y5 s. ]{
4 ?7 s) o: B O3 Q! yif(PositionsTotal()) // Is there a position?
3 J% p& [; x( p% q- F/ \1 C7 k{
1 n, s, @/ S7 K* C1 xdouble offset[1] = { 0 };
) [ @$ |! Y- |, _! B* O: @( x! p) wif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
: g4 W% @# {4 x/ K# `& ?, }+ o&& PositionSelect(_Symbol)) // Select the existing position!
+ s4 s G' D% p& w( Q{0 p% n+ Z- I. N& ~( v8 w2 v5 D
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);2 e: H* }. G, i0 @( ~7 B: p
double SL = PositionGetDouble(POSITION_SL);
7 f( P2 m& F/ T. O, ^double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));/ _3 c) l ~" j9 q8 U$ j( e+ c9 ^
if(tipo == POSITION_TYPE_BUY) \# |8 P+ P0 x$ p3 P8 o5 D H
{: [9 ^' x) c1 N: T
if (cotacoes[1].high > cotacoes[0].high)/ t) u3 C( [2 Y7 Q4 s2 z7 J
{/ q6 t j; @6 y/ n" i
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
+ \' r! x$ e& Ninfo.NormalizePrice(sl);
8 [7 p" e2 A# L' `$ X6 x* u) e jif (sl > SL)
) Q& a, V3 v. k. [( ]{* ?3 {1 x' A: ?7 D
negocios.PositionModify(_Symbol, sl, TP);/ T8 D ~4 |, [4 V# {& ]) D
}
' L" {# W8 D1 o, d}1 J' d4 m+ x% @1 a
}) f* f- m/ Y/ b8 Y# N2 `
else // tipo == POSITION_TYPE_SELL
: t* ]; f7 ?7 T" w. `. j{, X4 B; h% n' B! ?# q
if (cotacoes[1].low < cotacoes[0].low)
% d2 b) B* r; ?{
4 |% A% o2 j8 v: _5 ]2 s3 l0 Kreturn true;' y0 O7 n7 J, T% m
}* \! ~" `* [3 C. U. U4 J! F: [2 L
// there was no position7 j6 J; m* H. G
return false;( i2 U" d, A3 `4 k# x
}9 h9 ~' _+ w0 {1 ?; |
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
4 m4 x9 O$ o+ G到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |