启动交易模型,并构建 EA3 n- w' h6 B* N! K
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
' d/ U+ S3 c; ^为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。, q. n3 F# K2 R" p; g4 w- P0 j, R; g
以下是制定这些规则的代码。
& [2 B8 d# F. B Z8 b$ y% P' J: g//--- Indicator ATR(1) with EMA(8) used for the stop level...
% F1 V( j1 O1 ~- A) Z8 Mint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);; j0 w6 j3 @! I7 @! N$ B' {
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
. E% M/ S$ x: f//--- Define a variable that indicates that we have a deal...2 E$ H; Z0 q; h' }
bool tem_tick = false;2 X. E% r! P2 v8 D; @, X- M s1 R6 U2 r8 ?
//--- An auxiliary variable for opening a position
" @8 R( j, Q0 ?1 @+ t. ~#include<Trade/Trade.mqh>. u& T; H' d6 Q8 U
#include<Trade/SymbolInfo.mqh>
) x/ P& Z6 n! V( S3 bCTrade negocios;
! U, m3 S4 P! X6 P" LCSymbolInfo info;
) o* x" ~$ V5 E! F//--- Define in OnInit() the use of the timer every second; Y' d0 I- L# m' E, _7 B! N
//--- and start CTrade
+ y5 \; x0 r; k% r, h9 bint OnInit()
8 j5 S9 W4 M; f, a2 x4 C+ \{8 _- z9 C& l A- j( J- B" }
//--- Set the fill type to keep a pending order
! X6 J4 ]) R" f! b9 T//--- until it is fully filled
! {, \9 m7 J1 l* g: [negocios.SetTypeFilling(ORDER_FILLING_RETURN);; ~5 t: Q* d5 B) x) r& N" f* ^: w* K
//--- Leave the fixed deviation at it is not used on B3 exchange
* ~9 a/ M/ _$ P* y5 O6 x7 T; S; knegocios.SetDeviationInPoints(5);
# N' y+ L, `; B* a/ o# ?) l0 R//--- Define the symbol in CSymbolInfo.../ \5 B# o1 N8 c8 g; O' F
info.Name(_Symbol);
" |4 U; v5 y7 j8 O- [4 v ]//--- Set the timer.... I) l% p3 I% R0 K& Q5 g4 k' g
EventSetTimer(1);# L" p; I( e) \7 q
//--- Set the base of the random number to have equal tests...
1 a$ l" H9 i! P! F ]2 I9 \, c6 kMathSrand(0xDEAD);' j" U5 B1 c) R3 ]; m6 L' m$ O* V/ P
return(INIT_SUCCEEDED);! f! e) L1 c) w
}
( ~" T b5 s9 K! G) X$ M u) m//--- Since we set a timer, we need to destroy it in OnDeInit().
. ` p# G4 O1 t7 \5 T& _void OnDeinit(const int reason)
/ V; ~3 _( Y Y0 n* U9 c4 G{- P) K9 u2 h! s
EventKillTimer();
$ W1 |. h9 P; {7 h# n}5 V! K5 \& E+ M* v5 N9 D) P! z
//--- The OnTick function only informs us that we have a new deal
# l7 t- [4 | O( r0 G& X! l# f* W7 Jvoid OnTick()0 S# F! m1 A2 y1 v
{
8 q& s% r6 w/ q- n: U; o! {tem_tick = true;
) w! G3 p( T$ u4 N9 H}
1 u) M8 \$ W1 Z' V# r5 M4 l//+------------------------------------------------------------------+
" S$ @0 e. `8 T: |, A7 }! Q+ @# ]//| Expert Advisor main function |
2 ^$ l, X, M6 @- `3 J//+------------------------------------------------------------------+- A' \9 ?1 @5 [& d
void OnTimer()6 U \$ O2 s" b5 N' ]3 x
{- v7 O) F9 x( N+ p& `' z
MqlRates cotacao[];' z* F# D" t. Y' r4 C
return ;9 y B% B4 H6 q5 l. o
if (negocios_autorizados == false) // are we outside the trading window?) P# c; B! H, M3 [) |/ d
return ;1 p( v7 S1 T" l1 O: `5 H
//--- We are in the trading window, try to open a new position!
* w( ^3 N8 g: X* ]2 |9 T7 _! Gint sorteio = MathRand();5 x# `# Y: B* P# ?% T y
//--- Entry rule 1.1
- `9 |# R& L1 J3 g) z! Dif(sorteio == 0 || sorteio == 32767)$ P" U" D" }$ m! m, I
return ;) G! k/ R: D, @- e: U6 \
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
! K8 P7 ~/ \2 q, [4 w3 i( G2 S& h8 B{5 k3 k$ u" W$ S, q
negocios.Buy(info.LotsMin(), _Symbol);( c6 ]8 D& _/ a
}5 I8 P" r. X* c$ r
else // Draw rule 1.3 -- odd number - Sell; Z, r# ^9 E0 v+ h: U
{
: p' H6 O$ n+ A; y! ^# pnegocios.Sell(info.LotsMin(), _Symbol);
2 b9 C, y# n0 y9 y}
5 W: h4 A* b. n6 j3 j}
* C# J0 L" T2 f2 N6 R- {) Y7 b//--- Check if we have a new candlestick...
) h8 I! h' ` f j8 Wbool tem_vela_nova(const MqlRates &rate)* B. O) ^/ U: N# ^ q W3 q
{9 ^1 o! L k, v) a2 o3 W6 \+ U
{
9 A8 R1 `' S# J" O1 t; b% \+ {ret = true;
. s% H6 T+ J* J0 y: y* J& Wclose_positions = false;. e1 k6 r# M" Y3 ~. g( x: r+ v
}
; b$ k/ }, S0 d! o9 K, Oelse/ f: J! e$ _) ]0 y
{
1 L/ o/ a8 j& P7 oif(mdt.hour == 16): U% @+ B9 D& A7 l) y! C! r# X
close_positions = (mdt.min >= 30);
- C& l0 w. G9 y/ t. {# l9 K}
" ^) k6 Z3 d3 r1 c}
' P3 m+ y n4 z dreturn ret;% w# \8 K4 ~2 Z2 M' }
}
8 X4 y6 x+ H# m% J9 _. p9 g v//---
- C. T5 G8 ^5 l+ wbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
/ ~9 D8 I' E0 R- o- t- q{6 Q. f* P& D7 ~' \; L. S) E9 R! g& {
if(PositionsTotal()) // Is there a position?% g: y( r( ? W5 u1 M
{) l! y9 ~0 L; M) J( n
double offset[1] = { 0 };
& S8 Q' c- O% d5 x& Hif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
. i, V! V4 X% a&& PositionSelect(_Symbol)) // Select the existing position!9 z2 F: j$ z( B' Z0 O; `% {
{
8 K0 L9 T% W$ F" }( n \ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);9 w' ?3 T" x! O0 K
double SL = PositionGetDouble(POSITION_SL);2 R* c- k! t3 C# S; A
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));) \9 A8 D6 Q& `) N ~7 a2 k
if(tipo == POSITION_TYPE_BUY)2 A/ _/ ~6 x4 d ^# |. U
{
: G2 ]2 w1 y: W; B+ Y8 E1 zif (cotacoes[1].high > cotacoes[0].high)
d! C- x' P+ b{5 _$ {/ q& J& z2 c
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
9 H6 g+ N2 I# T! f( hinfo.NormalizePrice(sl);
% q/ b/ `+ e g+ [, N, Vif (sl > SL)' c6 `% I* m" W8 _6 i
{
) y& X3 Z2 F8 C$ Nnegocios.PositionModify(_Symbol, sl, TP);
- F- H- L7 l; \, X3 r# F' l! Y}" v, o0 q+ I4 G: K n
}0 B- J T+ y- G
}
& \- x% \. {( M) J* x; ~else // tipo == POSITION_TYPE_SELL
/ O, @ A7 l) R& ~" j4 R{
) G! i3 _ J5 ~4 ?& p% ?2 ^if (cotacoes[1].low < cotacoes[0].low)
2 p8 ~- d3 z' L4 f: x) u% ]{: g7 R8 x I. r5 X
return true;6 m' g! a1 U, k3 b6 J
}; T. _; c- C7 x/ z( P0 ]/ X
// there was no position
6 Z. _& U7 N/ J! r/ B9 ]return false;; Y* h& C9 l1 a1 T. B. k, v( c
}$ d8 I6 d! U% O& J. z$ o! I
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
' l: D$ X; C$ }, l5 Q# {到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |