启动交易模型,并构建 EA: n+ g5 H6 P4 K2 T$ [4 D2 J- n
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
1 o3 j2 k9 ~' g- k为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
" I. m& `& b3 k' O* E5 B$ T0 Y# B& @以下是制定这些规则的代码。$ r( M8 R) z+ H2 p
//--- Indicator ATR(1) with EMA(8) used for the stop level...% Q2 Q5 q" Y3 G1 {* M3 T6 G4 v3 y
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
* p: H& V! H( Tint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);. R1 p8 R7 r+ z% A, b- c# N# }! [/ r5 M
//--- Define a variable that indicates that we have a deal...
* y* r1 o- ]4 p3 w8 j/ Ibool tem_tick = false;
3 [7 y. ?7 Y0 m5 H( n* s- V//--- An auxiliary variable for opening a position9 c( V3 y! F9 _8 i/ Q
#include<Trade/Trade.mqh>
( G5 V: C. R+ D- O" H#include<Trade/SymbolInfo.mqh>
. K) D; b( q: t" }' a5 DCTrade negocios;
: O3 n g5 v vCSymbolInfo info;
B' f4 P7 e. S S5 C//--- Define in OnInit() the use of the timer every second
5 G. `& U0 v! T) q$ c//--- and start CTrade
- w! E: ?, q' x/ I4 xint OnInit()
! E$ o8 V! K L- D: P{
7 N! G3 c7 [0 o//--- Set the fill type to keep a pending order
8 a3 _% s# G- D; H0 s) L//--- until it is fully filled
( \+ V5 k. y( T$ s+ k- g' rnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
2 A* o1 x; h$ i8 I3 I! ?) j//--- Leave the fixed deviation at it is not used on B3 exchange: o o0 y; S7 m# p% S/ S
negocios.SetDeviationInPoints(5);
9 g6 ]3 X4 E9 `! H& u* j' |//--- Define the symbol in CSymbolInfo...% \- o; w. e% c7 g; k& a2 I/ v" n
info.Name(_Symbol);
; e0 R% _$ b* r2 N. N//--- Set the timer...1 k4 Y; U3 @2 P
EventSetTimer(1);5 q4 ] @8 p4 x0 t5 \ `
//--- Set the base of the random number to have equal tests...- _, E6 ?/ @. ?- S* L
MathSrand(0xDEAD);
& B; V1 G+ @! b* U' n7 Mreturn(INIT_SUCCEEDED);
8 A( g6 N7 U1 @9 f$ |# K/ H3 w}
2 |% [0 f" B# N! a, b//--- Since we set a timer, we need to destroy it in OnDeInit().
6 f+ y1 @& {8 V4 }void OnDeinit(const int reason)( m8 \1 l& K2 b' ?, D; V
{% K! P4 `1 v L" X# d
EventKillTimer();
& E6 ?- C' q" C/ u}
6 ~7 x* U; ~! M+ H3 b4 [//--- The OnTick function only informs us that we have a new deal
6 q) S3 Z# x- Y# {1 V% evoid OnTick() h* }2 D( w9 E
{8 }8 F: A8 m. ], s0 ~' o, O
tem_tick = true;8 N6 L% J9 m* C0 G% a2 B3 K
}8 f+ ?+ Q" ]* i0 F& D& y* H
//+------------------------------------------------------------------+! W9 u- ?; L- ~6 N e
//| Expert Advisor main function |2 S( X F: Q0 Y2 J. P3 G
//+------------------------------------------------------------------+' I; U+ d% H6 w9 @' o. @
void OnTimer()* p: ]1 S8 K- ~! {
{! ?, ?% u G, r; r0 }7 x5 ?
MqlRates cotacao[];" j8 ]' ]1 s0 @0 }
return ;
1 ]( u, W g' m' I: dif (negocios_autorizados == false) // are we outside the trading window?5 x6 S2 B& R& m+ g) o
return ;
Z/ x8 N2 g$ H4 a! B1 A; D5 G. H. s7 _//--- We are in the trading window, try to open a new position!" h4 T1 ~9 J! ], b4 C; I8 h
int sorteio = MathRand();* h# j2 j. g& K! q; V3 R
//--- Entry rule 1.1
0 y, ]& q" J, O9 Y; s* vif(sorteio == 0 || sorteio == 32767)' o9 }) K0 T1 E1 |3 I; J2 D' N4 }
return ;
! P5 m6 ]1 a5 H4 bif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
, v: d1 x9 w G. i. |/ E% U/ H4 e{. u: B8 r% t6 u' g( R1 g
negocios.Buy(info.LotsMin(), _Symbol);5 C1 L' }2 T$ }% `; D( L: g1 @
}
' j. G, I3 i9 G0 j* {0 o" A9 m* \else // Draw rule 1.3 -- odd number - Sell6 J' ~9 ]3 h/ |5 M
{
4 o! j/ r* ^$ Vnegocios.Sell(info.LotsMin(), _Symbol);
( Z! A# F$ ?2 i# _}/ u6 v. L3 }: X- q) W9 l. r
}
! U# Q7 ~6 k( T1 j/ g6 m//--- Check if we have a new candlestick...
7 c" s, }( `$ K: F# @6 n% s T0 K( `bool tem_vela_nova(const MqlRates &rate)
4 m P8 I- A. ]8 Y' k( G* y7 g{' p5 ]4 u/ A+ Y" F. z% f
{
" C8 i5 w/ v& d* E& h7 vret = true;
! w o! a! X7 Vclose_positions = false;" ?0 h* o1 ?1 @& E% \3 ?
}
9 I j. h6 F$ X; |3 d8 g+ zelse. a8 u6 r) \% k7 c6 n
{2 o- [! ~& Z4 t, W
if(mdt.hour == 16)' F: Z2 E& E X9 s( B G. e
close_positions = (mdt.min >= 30);
2 @3 P# U& w! a}5 J1 a( t) I o
}- k9 m6 ?6 k- w K. u+ ]
return ret;
2 C% p# | R' Z}: ]. Y# }8 J2 }) ]$ B2 H8 ^: `
//---; W9 y4 W: @) `+ T' W! {
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
' d$ X. F5 l; H4 p. D{% R$ z/ f% D- ?8 Q$ i* U6 ^
if(PositionsTotal()) // Is there a position?0 ^: D1 {6 o' I/ [
{
& a& u/ J* ]3 W0 P2 A! k h3 zdouble offset[1] = { 0 };
2 L# Y$ I/ ]+ O! |if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?+ K1 O V' S+ }
&& PositionSelect(_Symbol)) // Select the existing position!
9 j& j: T( a; C% }9 J5 s9 S% E{
9 @5 L% i% r) b5 F) f- CENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);' O2 e; |2 w. v; g2 P
double SL = PositionGetDouble(POSITION_SL);
# E6 n0 I4 C, ddouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));, n3 O6 M/ Y* d" I8 D
if(tipo == POSITION_TYPE_BUY)0 x$ l& _# k3 X2 I
{
+ _) P. h( Z9 A7 i+ N, Qif (cotacoes[1].high > cotacoes[0].high). M V* G+ E4 u9 L( U! J. H
{
+ k1 c& A( w: Tdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
0 z7 H! L- H- m( p" t% D" ginfo.NormalizePrice(sl);1 k, h% c9 ]; R2 C \; t2 `
if (sl > SL)7 Z) Y) `' `* l9 J8 l' h) A f
{
; b1 M' ~$ K# Hnegocios.PositionModify(_Symbol, sl, TP);2 }) W' u" T% |$ z
}
! i3 M3 j( ?7 E" a3 h' h. P}! [4 k' R, f0 e/ L1 H: Q' F
}
# a8 t+ v5 ]# ~7 kelse // tipo == POSITION_TYPE_SELL2 y# ?( R( t* r8 E3 Q/ x
{5 s3 M" s% p9 S3 L
if (cotacoes[1].low < cotacoes[0].low)2 f" ^& K+ Z p
{: P3 |: p% l' g* h, {; L& B
return true;1 V9 L$ i/ F/ ?1 p4 E
}
' M' I3 W* z) ]2 m! D// there was no position9 l2 }; w" V6 I) M% t7 d
return false;
3 ]% D$ c" C3 m! a, ~3 q) Q}; y6 j( A1 i" i( Q* I
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。, s0 V9 u+ y( O3 d8 v8 P2 d+ ]/ K
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |