启动交易模型,并构建 EA7 w9 G8 x$ {8 C7 Y
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
3 R' n" F8 Y+ b为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
" E6 D- P* h6 k' a3 E以下是制定这些规则的代码。; ?/ E- t& B$ `& q. I# R
//--- Indicator ATR(1) with EMA(8) used for the stop level...
3 A& P# n* H, |: i7 Nint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
2 c7 V( D* u8 V5 B/ v9 v H( z% gint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
. \* n N6 p/ O6 g//--- Define a variable that indicates that we have a deal...1 k9 t- k: a( v4 y5 H
bool tem_tick = false;% ?& B5 N& |; E1 ^& O0 z
//--- An auxiliary variable for opening a position
6 m6 s$ z( p8 e) W4 }#include<Trade/Trade.mqh>6 ?( Q+ A3 p, J' A3 j
#include<Trade/SymbolInfo.mqh>
+ M4 s) K, n$ S3 VCTrade negocios;* J. K, a; E$ L- ^5 [
CSymbolInfo info;- u) w7 ]3 K: `3 ?# V6 d- x; p/ a: T9 `
//--- Define in OnInit() the use of the timer every second# o) J9 s7 J/ K# z: m C
//--- and start CTrade
5 S" B( ^9 I+ p9 vint OnInit()
& @. |$ \4 @( L, ]8 j" f$ l{1 b, |4 H* r5 {; `# e& I. g7 E
//--- Set the fill type to keep a pending order
, s6 Z. u% R! N//--- until it is fully filled
5 U9 h! u4 J2 ~& s6 pnegocios.SetTypeFilling(ORDER_FILLING_RETURN);- N' u2 Q+ @7 O/ t. G; U$ ?
//--- Leave the fixed deviation at it is not used on B3 exchange
; D! O. i1 k7 V3 m3 h$ |( Nnegocios.SetDeviationInPoints(5);/ \* B; B+ q- l4 t% d
//--- Define the symbol in CSymbolInfo...$ l0 s8 t6 Q, V p0 R
info.Name(_Symbol);# j4 r. |4 C/ v' H1 C1 ?
//--- Set the timer...
- L% I Z$ G" G p0 wEventSetTimer(1);
9 q4 N8 q! Y3 x4 Z, F//--- Set the base of the random number to have equal tests...
$ U7 d T0 u8 h+ i% x- g' TMathSrand(0xDEAD);6 O; W: u4 w% o) F8 C
return(INIT_SUCCEEDED);
' O) b6 c* _5 I6 w6 k0 _9 n}
7 T" Q6 c( P; S1 [0 m//--- Since we set a timer, we need to destroy it in OnDeInit().8 n6 o$ G; |( r7 [% Q1 W5 R( v" |3 q
void OnDeinit(const int reason)' W. o) W; B0 `4 W
{7 N* ^+ L( m8 K. z
EventKillTimer();
5 M. C, F- E+ ?% c}/ }, X0 O4 F9 p) c/ ~
//--- The OnTick function only informs us that we have a new deal
4 G4 ^8 c2 V& o6 G% e7 Hvoid OnTick()
: Q+ x5 S' w7 X{
1 z6 n* E0 j# r p2 n! L2 otem_tick = true;
- }3 F# u! X- Z) @}
% R' I( y1 M" ^9 o! z+ H# A//+------------------------------------------------------------------+
- k" O9 ] G G//| Expert Advisor main function |( ~$ K' C- O1 O* F3 w+ F
//+------------------------------------------------------------------+: H* \+ ~- _ G7 m0 W: |+ T4 z; V
void OnTimer()
" r% m# b! Y K5 s{: r) e0 E T9 ?7 P- g0 G
MqlRates cotacao[];
+ T, F. C9 N s$ F: Ereturn ;* |9 P: `. Q4 _& D
if (negocios_autorizados == false) // are we outside the trading window?9 }: y! j, s$ T1 e3 x
return ;& }! |9 l, [* c/ G
//--- We are in the trading window, try to open a new position!- D9 e( S4 D J* c
int sorteio = MathRand();
9 t5 G' M, Y7 F; M2 c( h0 ?//--- Entry rule 1.1
& q4 ?- c L2 L& n/ X$ Y) Pif(sorteio == 0 || sorteio == 32767)% @* f2 l5 C6 ~+ [/ i
return ;1 V) V$ y# c$ e4 h
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy% [4 ? P7 M+ ]/ F
{
) H6 |3 {1 w/ `, Q! L2 ^3 Fnegocios.Buy(info.LotsMin(), _Symbol);5 ?4 o e/ i* s) E% B) N% `: r' g2 Z1 l
}* h$ g7 q( y, I$ |) ?/ |
else // Draw rule 1.3 -- odd number - Sell
/ ?- ?. q5 h$ g! \3 V% k{* m6 n* E5 O0 W0 h3 {; k% Y8 }
negocios.Sell(info.LotsMin(), _Symbol);$ A% P/ {4 m. w s7 x2 g! d' J
}& D- k: ?/ A* t5 b
}
6 a4 r; C3 P4 L4 w( N y8 S" w//--- Check if we have a new candlestick...
$ D. \4 L# |- L0 {3 p- vbool tem_vela_nova(const MqlRates &rate); w8 j5 R! A2 ]) s- y; f) c
{' Z+ {7 g3 ~1 h% h5 c/ E- B
{
& h/ I3 z! b5 Q6 G1 @ret = true;$ M8 z: s% Y& q4 K9 c# R% q% M% Y" j
close_positions = false;
5 s( Y( o0 |2 r2 N( |6 f}
7 S1 _7 Z. R) j Belse" a/ u/ F# j% V) W7 r) g7 n
{& B& h$ X5 b+ d x/ I
if(mdt.hour == 16), I7 I; c3 O3 U! [
close_positions = (mdt.min >= 30);
e5 M O) A) L; f2 Y}! C5 M% G4 _# ~" e# I" \9 @
}9 ?: ~# U3 }* u; ~: q' n
return ret;
/ w0 m! D+ ^0 |4 g( ]9 F4 i}! C G2 o9 l3 p5 Q/ ?( ^
//---9 `! p/ N* m5 G) C5 T8 ^
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[]). p t) j0 M" r1 C; @0 V
{
7 f9 d2 c& y: f* M3 P* Eif(PositionsTotal()) // Is there a position?, @; q/ J N2 ?4 X
{/ _7 |0 D+ @, D% B# @, P
double offset[1] = { 0 };
. a, |+ ]) c. o+ p% Z* R/ mif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
+ }$ s/ t A6 P; V&& PositionSelect(_Symbol)) // Select the existing position!. \) M% L) `! `: m7 u9 A7 A1 c+ T
{
0 g; }6 Z e( W2 [5 OENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
! x$ I1 {% V' B% a, Y" v' x5 fdouble SL = PositionGetDouble(POSITION_SL);
# M$ N/ z+ M! udouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));) I. U! c5 `4 _3 O+ S: ?
if(tipo == POSITION_TYPE_BUY)
5 D9 @. W$ @; M{7 |, F4 u6 r) E7 `' d
if (cotacoes[1].high > cotacoes[0].high)
1 B% G8 O* h0 I{
+ M+ A" v. j |' k9 L6 z7 O, Vdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];* C+ w3 r) @8 q+ n& p
info.NormalizePrice(sl);
9 G) V/ v. u- t( @4 K' lif (sl > SL)
* y" m5 f1 w4 r6 Y0 ]. T{
0 [% \+ O% Z- v! P) cnegocios.PositionModify(_Symbol, sl, TP);
8 J0 u' E4 t! K9 \2 F% C- F}
8 h+ Z+ u9 f, V}/ Z/ M' C7 q. }! }5 a
}
) e7 y [! r% M* v- v; Pelse // tipo == POSITION_TYPE_SELL' \2 F# G6 O) j
{ d% d& W! Y3 Z4 y' U. g' o: u
if (cotacoes[1].low < cotacoes[0].low)
, {: [/ H% W% v l7 A4 X2 v% T{
/ G# u2 @+ u/ a: g( F7 ureturn true;
" P" U D: a$ Y7 ~# Q$ X}$ w! z) N* V1 C8 F. @
// there was no position
7 n7 e2 `3 }2 J: }% q. t/ N4 dreturn false;
5 ?6 v" h4 j' b- z0 V% ~5 f}
# ?4 A" U% h$ y R2 j9 N我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
' S4 E: [0 T( C, e9 `到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |