启动交易模型,并构建 EA
; Q7 I; _5 u& x在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
/ e* s9 i# B3 }" D' ?2 U为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。$ N6 B9 U. ]0 r. m& ?/ ~, D
以下是制定这些规则的代码。! H9 o" y' {7 a" i! Y
//--- Indicator ATR(1) with EMA(8) used for the stop level...5 F0 z ^' X. K3 x; ?; F' j
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);4 z4 X. e2 G U1 `
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
9 U+ _* T7 y- C. L//--- Define a variable that indicates that we have a deal...: Z! E9 x# g( P- }$ P
bool tem_tick = false;
( e; |: q( f6 t* r$ u( |$ M% H2 N//--- An auxiliary variable for opening a position& R9 h9 t; Y' _; K3 [% c
#include<Trade/Trade.mqh>
/ ?8 I) N% i0 k#include<Trade/SymbolInfo.mqh>; D# \) I3 E8 n* \9 D
CTrade negocios;
m( |1 L& M8 ~$ [) o0 oCSymbolInfo info;
2 a5 l5 L- S2 {$ G. [//--- Define in OnInit() the use of the timer every second$ X2 L7 A9 T* \# ?) E9 j( o
//--- and start CTrade$ X" e* d7 F8 x! E5 b
int OnInit()
" }/ Y2 r; f5 t# k{
' k' {% \8 E# {4 V. x. M//--- Set the fill type to keep a pending order( [7 D6 s5 @- D1 j( D' ~4 s
//--- until it is fully filled
9 j$ M' s+ L# D& P0 v% R8 o' gnegocios.SetTypeFilling(ORDER_FILLING_RETURN);% ^ M5 v7 r! J$ ^: s
//--- Leave the fixed deviation at it is not used on B3 exchange( w# T% {. l+ ]& b+ y* M
negocios.SetDeviationInPoints(5);
5 _& G( c; g% J. n/ f//--- Define the symbol in CSymbolInfo...) I8 S/ m* r$ {& l& a5 w
info.Name(_Symbol);" Q, m+ }3 g& t* W) b( v
//--- Set the timer...9 M; \7 e( ^. `5 B: {
EventSetTimer(1);. Y- p: B8 _" g! g" s
//--- Set the base of the random number to have equal tests...
7 C9 ?6 {$ Y" V0 s0 \7 ^MathSrand(0xDEAD);0 J7 R. x8 Z5 `! e' k+ e
return(INIT_SUCCEEDED);
8 Q+ s" y! j1 y! b6 o, ^}
" i( u" o0 L- I& K1 k6 V//--- Since we set a timer, we need to destroy it in OnDeInit().$ ?! q4 r/ g/ M' u
void OnDeinit(const int reason)
' {4 `, [4 ~ ?# A- X{6 H0 e4 y' v$ k' u
EventKillTimer();7 T) t; l4 S2 U+ b# b
}
+ `- E B8 s8 }" T) I//--- The OnTick function only informs us that we have a new deal
' z. }9 d, j: U4 x5 c. j9 Rvoid OnTick()6 U$ J* ]/ s6 q0 L
{
1 R6 q- j6 w+ s0 N& Ytem_tick = true;% H# H% {. w* L. V
}
3 T$ [' Q+ s- P( a( m" M) U//+------------------------------------------------------------------+
" j( |8 e! e; t1 O//| Expert Advisor main function |
/ m5 Y. S; z8 Y1 B. P7 k4 ]: V//+------------------------------------------------------------------+( e Z% P' X( ?* H" Z) A9 Y
void OnTimer()
3 Z& j: F0 {. g, Y2 ~9 J2 w{1 j3 ]3 t$ t0 Q3 {1 O7 A
MqlRates cotacao[];- X! N8 W e7 P. @2 c
return ;
% O L" {" G- N. Bif (negocios_autorizados == false) // are we outside the trading window?0 q& ^* k" k; @) O$ v( ?7 C: p
return ;
3 c3 i- b0 S; |* ^' S: h6 j//--- We are in the trading window, try to open a new position!
6 ?. u2 L2 b7 _0 e5 Y7 T& E5 Xint sorteio = MathRand();
% e/ W ^6 \+ J1 l% h* q! L//--- Entry rule 1.12 N; A% @5 x& H: s
if(sorteio == 0 || sorteio == 32767)
$ L" j* m. R, M( J5 `2 K0 Rreturn ;
. a2 a2 K. v9 b6 eif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy& j& B) S" X$ _' z. {4 O7 T
{
+ r/ i6 Y7 L! Onegocios.Buy(info.LotsMin(), _Symbol);
' ?$ }, w5 d0 ]}& a0 l4 D, k6 ]6 k
else // Draw rule 1.3 -- odd number - Sell
- Q) Q4 M& L$ S( e( `' l: s+ `{' O5 x9 t& X( Q+ h" L
negocios.Sell(info.LotsMin(), _Symbol);
% \# A2 [9 V9 `; Q' w) `}
2 I# n( m @- k; f" ^. G}
! ?8 }" G/ d4 E D//--- Check if we have a new candlestick...# F6 U! S6 B0 u* i" C
bool tem_vela_nova(const MqlRates &rate)
& u2 j. \# V. M, ?. K' j. G{
6 a7 m8 ~- c9 I7 v3 e4 ?{
: e# @( ^9 n/ C! bret = true;
3 G# p$ u$ w/ F; k/ U5 |5 j( ?+ s+ mclose_positions = false;
# U" O4 r- x# }; z}, W" f! a) i: k3 B7 i; s
else
5 ]; y$ G- E- G) }0 E$ }& u5 {( Q{
, k" E) H4 u5 S( d7 z7 k) \* A# Xif(mdt.hour == 16)7 B3 c2 Z {' U& p) Y* L2 ~
close_positions = (mdt.min >= 30);
( m1 b7 [( U* r1 d2 O1 U; z6 G}
- ]8 c6 }5 T7 p- C) [}" b+ x. }% J9 d+ {7 a5 |
return ret;" m( p) q! j8 D! C( X7 @
}. w) f! @8 y* W' f; h9 Y0 d2 L
//---; V# P l$ v1 n) k
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
! r. c; w0 r! @0 [{0 h9 W" W7 V! I2 W7 u2 A
if(PositionsTotal()) // Is there a position?
! j. \5 \6 S& ^0 [/ Y- }{
I/ D# S/ C" m% w& sdouble offset[1] = { 0 };
) T# m7 x. v2 T; O* Q# Wif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?* n: B/ e5 ?/ ~: U/ D, H: `
&& PositionSelect(_Symbol)) // Select the existing position!2 [7 v0 T) {: Y7 w6 Z2 X
{2 P8 v- a! x. g" j4 s9 J
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
$ w: ?- X" i4 jdouble SL = PositionGetDouble(POSITION_SL);( n$ }& j; g8 Z$ m% C+ J
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
! K3 D3 Q: [1 p$ K9 T' `if(tipo == POSITION_TYPE_BUY)+ b7 E" V9 s+ p5 P" |" N- `
{
5 v5 R2 |+ S9 u/ |8 rif (cotacoes[1].high > cotacoes[0].high)$ t2 E3 Y4 G7 ~" ]( x+ `- f4 u
{
- l& c3 G" x; e" x2 y5 _! s: sdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];! f- s$ n3 g/ k
info.NormalizePrice(sl);0 K3 K" |7 d2 U
if (sl > SL)# n9 G* Q8 }" d
{
) q; W5 x" y5 t- w) T; znegocios.PositionModify(_Symbol, sl, TP);1 E& h7 |) b( k2 \
}
" q6 l& U/ h1 w7 u* F( w$ V}
2 L) ]1 I: I S6 L, J0 t2 m. T}
n( _! N8 b+ ` Helse // tipo == POSITION_TYPE_SELL @- h! e/ ]5 |. x$ N5 K1 o2 D- Q$ Q
{" ?" L# n- x9 P
if (cotacoes[1].low < cotacoes[0].low)
: B0 K( x& T: q# n$ p8 L; A1 B{
) Z$ Z# c6 Y6 `2 t/ V2 V0 Ureturn true;
6 {& f4 d0 C/ _: r. U' @}
: r( m& b9 c. ^0 n// there was no position. X+ g1 ?$ ?# g+ o4 o
return false;
8 q5 U. u: B3 O8 O5 W& a' I' W) m3 Q}
% B; g; I5 x0 M d1 R" j我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。5 @5 X9 V; P' t' ~( w
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |