启动交易模型,并构建 EA6 |2 w. p# y) x
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
) T8 ]" F4 t4 ?为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。( H7 G5 B1 @9 t5 v4 ]
以下是制定这些规则的代码。
0 C; c; @4 s3 l8 Q" U8 X//--- Indicator ATR(1) with EMA(8) used for the stop level...- g/ P' ]% r3 P
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1); Z) F4 D' v; X( e
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);/ X* [8 ~* M/ r7 c) u
//--- Define a variable that indicates that we have a deal...
9 o: O5 |) L6 ^( N9 Pbool tem_tick = false;
: G8 j& Y0 n( X' Q4 h b% ^//--- An auxiliary variable for opening a position) R0 o6 {/ J3 T B3 x* ^9 B: S0 w
#include<Trade/Trade.mqh>
+ E+ ^) g) f: }+ ]# E% X#include<Trade/SymbolInfo.mqh>! ^4 o6 G& w2 J
CTrade negocios;
& G O9 e1 Z0 F, f9 d% R) Z1 x9 HCSymbolInfo info;
- v S: ~- C1 G, H' w1 x. J0 t//--- Define in OnInit() the use of the timer every second
) b7 M# M w% ?% k: ]; l9 ?//--- and start CTrade
& O! W$ j3 p; }9 _int OnInit()" e% h! f& u4 \# }+ h5 n
{
7 V; Q" [, d' [! `* g0 s//--- Set the fill type to keep a pending order
. ~# R' R q7 v- }& v9 G& Q//--- until it is fully filled
+ w* u& W( {" b" V3 s2 @negocios.SetTypeFilling(ORDER_FILLING_RETURN);: f- H3 H9 M# l0 J6 k& s4 D) w
//--- Leave the fixed deviation at it is not used on B3 exchange
3 V4 `: ]& H2 Z+ F' }negocios.SetDeviationInPoints(5);, l3 k( ^4 V9 i/ b: {. h {7 Q' T3 t
//--- Define the symbol in CSymbolInfo...
1 z2 u# y) n6 L/ g, iinfo.Name(_Symbol);9 o5 J3 D1 a: [5 `) _' G
//--- Set the timer...2 G; f! Z6 g7 u: k: E) o, j
EventSetTimer(1);- W4 _% c( q7 A, I& ~
//--- Set the base of the random number to have equal tests...3 P8 o$ T; p [( H' ]
MathSrand(0xDEAD);. B w: u9 e T! D. [8 W5 e8 B# f5 u
return(INIT_SUCCEEDED);& _+ B; \4 h# t- E% W$ |$ w1 j+ d6 s
}1 ?: k) }' F3 z1 x: \
//--- Since we set a timer, we need to destroy it in OnDeInit().
3 e0 M) ?) ?2 H. yvoid OnDeinit(const int reason)
7 l/ @. [: v6 V{' N- x) O- g: Q$ E. c0 d
EventKillTimer();2 M# q- `+ O1 c8 {
}, I% Q" O. u0 N- Z( ~9 M! y
//--- The OnTick function only informs us that we have a new deal
: q, p1 i; k9 U+ C( Q. H1 ^, qvoid OnTick()
4 u3 l6 Z3 G2 v" m" d7 j# D{
& b0 a. l! j/ I0 Y7 j$ Otem_tick = true;/ v: [1 y$ K' @% }( j
}1 g0 ^/ _1 K! f+ X
//+------------------------------------------------------------------+
5 V2 D) h9 L# c$ w% N: Z& H& O$ z7 D//| Expert Advisor main function |
( A& x4 R9 ^7 r+ @# V& ]//+------------------------------------------------------------------++ P) Z6 J9 @) k( k9 S% C, o" E- M7 T
void OnTimer()9 B9 j; N9 F3 ?# z" u
{( a1 ?1 f& R: z. X) ?
MqlRates cotacao[];
8 I I c3 |* |( P" ureturn ;9 t6 n6 V7 P9 a! Q- h
if (negocios_autorizados == false) // are we outside the trading window?
t) _$ I0 y3 |3 z( _2 ?! areturn ;
7 O4 c' q( L- ^6 }: n, S3 J1 N0 ]3 y//--- We are in the trading window, try to open a new position!4 X) v% P! G& V- \8 H4 e$ S
int sorteio = MathRand();$ S& x W7 F2 ]; o1 F a
//--- Entry rule 1.15 D) }6 b) A7 y; k4 p' x
if(sorteio == 0 || sorteio == 32767)8 D5 h( S0 G( a3 K6 q2 U; H
return ;
1 J7 ^; ]. Q% v% B- @if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy9 ] I1 ]; G' z ?% ^6 m# G
{
, j% g) L+ x' [0 tnegocios.Buy(info.LotsMin(), _Symbol);
! D2 u- d; Y* U1 k. _}
% Q- p8 Z1 Z% c, @, @3 W& helse // Draw rule 1.3 -- odd number - Sell5 d1 u, C( H9 r0 y9 \
{
$ {4 U* y n5 f5 anegocios.Sell(info.LotsMin(), _Symbol);
0 S& U3 M4 h. }8 [# q: Q0 _ e}
* M7 a N; c; w7 g}; J" k X/ C/ Y4 Y6 J
//--- Check if we have a new candlestick...
! e/ N- c* }: X9 x3 {4 p! e; ]bool tem_vela_nova(const MqlRates &rate)( b' p0 H/ A- f) o- A" q( o
{
2 b0 J( T. o! c; ]; E. Y{
/ b* U. g# z5 L3 d" Wret = true;; }% H5 B) N* e' |& F. V& E: o7 A/ u
close_positions = false;# m! d. V4 U% w$ d/ E7 A
}- _0 ^. Q, w( g, r! m" y
else( t. @' E. j3 s( D+ J7 i, k0 m) k9 v
{& O) Y6 T6 N7 H: |# L- Q4 c
if(mdt.hour == 16)
5 j; u2 k& p+ w8 ?. _+ h9 C5 Mclose_positions = (mdt.min >= 30); w, f& n/ X+ D8 @2 i2 g/ q3 [, \ `
}: h1 T- L, b* C0 K& ^/ @
}/ B# H5 g) q3 [
return ret;" H" ^8 z2 X: P# z
}* ^) f8 C. N, k6 h5 I8 S$ g
//---
- U, s: Y& r! Y# ?bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])- Z1 b2 z4 F) X3 ]6 D
{+ s" l Y6 C- k7 W
if(PositionsTotal()) // Is there a position?
/ a6 H" O! R2 E' j{
: ?9 T! H( V; `9 N% ]: H4 ^double offset[1] = { 0 };1 E6 y0 j: p* E$ a: B; D: c% X
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
9 h+ a9 J: P: c( w2 C9 T&& PositionSelect(_Symbol)) // Select the existing position!
7 [$ ]! Z5 _/ M# M- c. j{
2 O0 w% B: O0 T0 a% x' GENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
7 x) A m- L. f6 zdouble SL = PositionGetDouble(POSITION_SL);, m8 h' B) V, {/ R; R
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
" l) h0 ?' H5 d! y4 B& z+ iif(tipo == POSITION_TYPE_BUY)) L( n% q7 [9 k, j$ i
{
5 {; R, v' [! d/ x& f: q. aif (cotacoes[1].high > cotacoes[0].high)
/ v5 G# A3 q7 h0 X5 ^- z- s{
3 N5 o; c5 l% v) p& @; w+ {8 {double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
+ U7 s! E5 B% A: \info.NormalizePrice(sl);
9 E+ o" W- h% P8 Cif (sl > SL)" e' z: J% [( S S% Y4 _
{
, q$ f, J. ]' c) i* N4 C3 s6 _negocios.PositionModify(_Symbol, sl, TP);
! V) w* e3 }: @0 Q& O! \2 V}
6 @1 S6 f- n# e}
' l3 a- [& r4 ^4 M) l& f}: w2 _- Z6 B% ?3 I. N- n
else // tipo == POSITION_TYPE_SELL
" @, U1 {# [! @# h{
, j& ^) t, P& w/ E7 M& f3 x0 }if (cotacoes[1].low < cotacoes[0].low)3 q N9 f( N- J6 o( }$ X k5 ]" q
{6 _4 P( Q9 W* z4 O0 }. R; q3 F8 m
return true; f- A6 g+ [' V3 w& B
}
' b1 E8 B" z* J! ?1 O! K* J// there was no position& @2 G- [/ J3 y P6 p$ E2 r2 B
return false;7 ]8 ?/ S8 e3 ?2 I9 v, O1 U
}4 \9 ] {& h o+ v* ?
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。" D" z v% ] I
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |