启动交易模型,并构建 EA6 I$ [ s& `7 f! H" `
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
7 x& y9 @7 U4 ]; }为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。5 L h+ n) \- @% F
以下是制定这些规则的代码。* X# o x# w3 M; h) j7 S# b
//--- Indicator ATR(1) with EMA(8) used for the stop level...% q, E4 B5 b9 A- |4 I, T7 d
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);" T' X2 j# n/ p7 P$ m8 ~2 o
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);/ C+ X1 i6 b) y7 x" _+ h' y
//--- Define a variable that indicates that we have a deal...4 c! G* u" U6 z! f+ W
bool tem_tick = false;
3 M! }* k* I. b% g//--- An auxiliary variable for opening a position$ m5 _- X" c1 W6 U
#include<Trade/Trade.mqh>% @# Q) }: o1 T, y2 a
#include<Trade/SymbolInfo.mqh>7 S; V1 M3 W) Z/ p; r7 G
CTrade negocios;
! e% E0 Q/ j& e Z0 ^1 Q6 I' TCSymbolInfo info;& A* J* k3 X8 H2 s
//--- Define in OnInit() the use of the timer every second
" j9 d, @9 X. E: O# I0 _. B4 T//--- and start CTrade
3 J* E4 ]$ U! c( j3 Q, h- Rint OnInit()5 b6 |9 d7 s" F2 N, u
{
# W& e5 l, G; T, w6 E( a2 @* z# ]//--- Set the fill type to keep a pending order: ]! f& ?, r/ d. p, Q
//--- until it is fully filled) m4 Y k" A& V7 l
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
5 _7 H x/ g z, y5 ^0 O//--- Leave the fixed deviation at it is not used on B3 exchange* d4 Z- V# z: N; @$ }- i1 {
negocios.SetDeviationInPoints(5);' o6 o7 v6 g% b4 X" }. y m& B2 z8 Z, G
//--- Define the symbol in CSymbolInfo...
* H+ h% [7 i8 g# _: p# h2 O7 G9 Pinfo.Name(_Symbol);
* m0 n5 H& e9 k4 L//--- Set the timer...
) x& m' p% Z, d, h* eEventSetTimer(1);
% o' e) A" m# T$ @//--- Set the base of the random number to have equal tests...3 l* B: Z" J/ H
MathSrand(0xDEAD);+ k6 |6 s5 Q# u
return(INIT_SUCCEEDED);0 f" e% e/ R# W% x/ w
}
. K. ^$ ^# G3 x' [& y/ e4 U2 N$ `//--- Since we set a timer, we need to destroy it in OnDeInit().: ^' l: S! Z7 J( V$ [3 \ Z: u
void OnDeinit(const int reason)
5 Z# n. W; r. q6 T3 K{! j. @3 {* ~ c" s4 U c
EventKillTimer();$ w# G% f7 D: u4 S' ]5 R7 ^
}
6 F: m0 x. m& v0 J//--- The OnTick function only informs us that we have a new deal
: c7 w$ U: |9 m$ s# a8 ?2 V( }2 F$ Evoid OnTick()' O* ^( N+ w- _3 X$ ?
{
% `% C( _7 S, i; f7 s0 t1 ~( Ctem_tick = true;7 m+ l, I) L0 J' F" d
}& S$ G+ n ~. C9 q5 O$ {" g
//+------------------------------------------------------------------+7 ?6 J( Q5 N/ \& W9 O0 J1 W
//| Expert Advisor main function |
1 Z- U% A& g _. I W% n* x4 g//+------------------------------------------------------------------+
/ p! e1 E2 r" P2 Z) a/ N+ W7 Fvoid OnTimer()
5 I; P6 @* X: I+ I/ u{
( I- H! t8 b% Y4 v! l# x7 x4 TMqlRates cotacao[];% y4 i; R# C, V+ `$ E
return ;- F. {* w: r# p# _
if (negocios_autorizados == false) // are we outside the trading window?
8 X6 M7 D2 d- D4 ]. E0 u' j; Dreturn ;
9 v7 g8 h r7 e2 K8 S+ E//--- We are in the trading window, try to open a new position!
! ~5 w* u, a% l- u0 A& ^int sorteio = MathRand();
9 Z0 N* O! z/ i% _: K$ i//--- Entry rule 1.1/ k" y1 a* J( o0 j, n8 u8 v
if(sorteio == 0 || sorteio == 32767)
- s- b! f# _$ g: S8 [return ;2 C% T. K8 D8 \
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy, a9 D8 d7 B8 h q6 |
{7 S( t+ n8 u% Z. u$ {5 d6 M
negocios.Buy(info.LotsMin(), _Symbol);
' j: k8 j0 {! D. s3 p% E/ x0 Z}
6 y/ Z$ B2 T8 H6 w5 j2 h# D. d3 Aelse // Draw rule 1.3 -- odd number - Sell
5 K! H5 j+ Q9 ?1 T! z: n{ w S& k" p4 P
negocios.Sell(info.LotsMin(), _Symbol);3 T3 T/ d% ?0 d5 n' G
}+ v. @( Q/ n! s- o) r& U
}
# ^6 T. E9 T' z//--- Check if we have a new candlestick...
4 X0 p6 I% ] U( w4 N9 z) z2 Dbool tem_vela_nova(const MqlRates &rate)
! m% ]1 F9 D' c{
! F2 ?5 }1 A) i9 t: `& P{: W; L" g4 { l t' e+ z
ret = true;
: G; G7 P2 b4 F- h5 @7 i+ A6 {close_positions = false;
# l/ \8 N }/ P7 D2 X4 s% s, M}
5 C; h3 i0 ^7 j7 r. }; w- u* Ielse
6 q5 T' L% b% H6 ^" W: U) c: t{4 K ]/ a% P) ^
if(mdt.hour == 16)/ }0 e& }. M/ r1 v" W- S
close_positions = (mdt.min >= 30);
$ v( _6 h0 K( h& E: }( w% V}
0 [8 H9 x/ n# q}0 [+ R* u2 H+ B9 h; l
return ret;
/ S, j: D7 [- l4 |$ ?4 A. Z v}4 ], ~) z* S; t& u8 B) G( m# _
//---0 u6 Z- T/ `7 n9 U
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
9 [& _( n& P: c* S{, O- B4 ]% b$ P1 i3 U
if(PositionsTotal()) // Is there a position?
h% P" k) ]3 d1 }" C3 O/ ?$ j0 k{ Y# S; z$ |9 W1 {
double offset[1] = { 0 };0 N% _# p8 z5 ~5 J) k
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?0 X/ p5 p5 ?: k3 |+ {# |
&& PositionSelect(_Symbol)) // Select the existing position!! ~6 g) e2 n( t; |/ Q) v
{
2 n4 n. v# t2 G+ L" Z o0 Q' hENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);" J2 P i U, U) H
double SL = PositionGetDouble(POSITION_SL);# t3 ?( T# x2 M% o. B O8 T
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));# ?5 N4 Q0 t1 C
if(tipo == POSITION_TYPE_BUY)
5 ~( [% k2 I0 C: v* O{- d& x" t' b* \
if (cotacoes[1].high > cotacoes[0].high)
3 g4 _4 a5 y/ t8 x ]2 `; E{
6 n3 R; g( T& o0 Ldouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
1 J0 O( Q, V v9 Uinfo.NormalizePrice(sl);* U0 q6 }' N. K1 g
if (sl > SL)5 R5 ? S$ L( X: \ B
{
: Q" H |( q6 @. wnegocios.PositionModify(_Symbol, sl, TP);5 t5 p+ H- f1 R& e
}) z9 I# S4 G2 v% b! Z& P
}" X+ `( m( b4 Q$ R% M' C
}
/ d* \0 X; P0 {' @1 \$ }else // tipo == POSITION_TYPE_SELL
% F/ a( v9 _) h2 r) `1 E. x{
; _5 [% W$ ^1 [if (cotacoes[1].low < cotacoes[0].low)
0 n+ w+ b# X" p3 T: d7 [5 f P{, J. H1 n6 `8 P" k/ X8 J
return true;
$ L+ S6 E1 `# |3 q e' q0 I}: ^( X# J* L1 v- w& Z. V4 v
// there was no position, L5 ~2 ?) f4 m0 t& x: g
return false;1 w/ I0 T5 `/ P% J$ k7 W, _, r2 ]
}
' m$ \. S6 n$ y- }. L. Y. O: T4 x我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
, M2 m" A) ~/ O/ s! S1 _到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |