启动交易模型,并构建 EA
+ i. T# ~5 `3 Q- a* _在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。( ?- V9 H) L' m! p6 B' B; K
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。 O/ q# B/ Q7 w W; ?
以下是制定这些规则的代码。0 U6 _% H" \. U$ ]# h! }
//--- Indicator ATR(1) with EMA(8) used for the stop level...
3 r# h- `! m; t6 D# _: Cint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
1 [3 g: {& \2 t! e9 ^: J$ uint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
4 V# Q9 B; b4 l/ j, {//--- Define a variable that indicates that we have a deal...6 r: K+ r/ t5 ~8 @
bool tem_tick = false;
8 Y- J0 H7 }. C: ~3 I7 I% }//--- An auxiliary variable for opening a position$ l. T+ }% g& T6 v4 \9 b+ [8 R+ O9 G
#include<Trade/Trade.mqh>0 p, J1 F* Y- W1 a
#include<Trade/SymbolInfo.mqh>) M) X7 ~- j; u4 A. u- `( n
CTrade negocios;+ `4 t0 `: F$ g% {6 h! C
CSymbolInfo info;
8 M* m |1 q m" z: R: X//--- Define in OnInit() the use of the timer every second6 ^$ a8 t4 c7 `7 S9 K( R1 m
//--- and start CTrade
; |; o2 t0 Q' j- Y: l) qint OnInit()& k5 A4 P ^5 R
{
# Y e# b/ g {6 w( K% E//--- Set the fill type to keep a pending order! T3 u" X" J% Z6 z9 B
//--- until it is fully filled+ _0 ^0 A% }9 J4 ]$ w2 H
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
; N% t3 T9 v$ e6 Z+ g5 \+ U; K$ ?//--- Leave the fixed deviation at it is not used on B3 exchange2 `2 I+ c, e" w4 P" b5 V
negocios.SetDeviationInPoints(5);$ l0 m( l% O* Y, y
//--- Define the symbol in CSymbolInfo...) M5 V9 Y5 k! W
info.Name(_Symbol);( ~: C; A" C5 E5 D* d
//--- Set the timer...
h# ]/ T" b5 I$ a. aEventSetTimer(1);# z: y; [# b/ D& a' M: W5 [* G
//--- Set the base of the random number to have equal tests...
# N; P F6 L7 t+ cMathSrand(0xDEAD);6 J4 A( v. z, r" ^% y# ^2 I
return(INIT_SUCCEEDED);
% B4 R3 m0 I' X}( _! m; D4 U7 V4 D
//--- Since we set a timer, we need to destroy it in OnDeInit().; L$ ^+ A( b( A7 c3 A2 H
void OnDeinit(const int reason)9 y. e+ s" Y3 @( ^
{1 Y1 s8 }* p0 P/ t% K0 A
EventKillTimer();
4 V X+ V4 W: B; N4 U8 l% ^) [+ j}
) b! I" g+ ?) s, a//--- The OnTick function only informs us that we have a new deal
, e2 Z- N# h4 Wvoid OnTick()
. K$ V& V. e6 g/ j/ M& F{
) m$ r" L4 R$ A0 |5 J, Btem_tick = true;
% X0 A. H ~& G- W0 R' y" t0 J+ m}
1 t* }4 k! N- }1 F//+------------------------------------------------------------------+
+ \8 y! N- k0 h4 N9 P% I+ K7 q D+ H4 B" K//| Expert Advisor main function |- l9 o. B8 x) m. O8 t0 D& r+ w* [/ [
//+------------------------------------------------------------------+
$ x% b; a6 A W1 y, {6 r: Jvoid OnTimer() p. ~; d7 K$ {; Y8 j/ [7 s
{
. [) {4 s* r1 H& V1 f. zMqlRates cotacao[];
! K, j! G* C3 N) E' v& U# R+ ?return ;
( I0 Z/ H# |. X4 p+ j, S" [if (negocios_autorizados == false) // are we outside the trading window?
4 V- H: p1 g- ^1 Treturn ;4 T" N Q' G0 j+ {
//--- We are in the trading window, try to open a new position!
; u& N5 f1 H7 s2 Dint sorteio = MathRand();
1 Y9 C/ j6 }0 O) ?7 [/ `5 C//--- Entry rule 1.1& _8 H% e# \- z) i- O- A
if(sorteio == 0 || sorteio == 32767)- F* G6 M9 o" N. w" f5 Z
return ;8 S! I% }. c5 z9 T' D( w+ J
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
& n8 k5 p8 b4 _+ M/ U8 V{* K+ g d$ v8 S9 M. h1 K; v; N
negocios.Buy(info.LotsMin(), _Symbol); p5 `, P9 X* p c' Y" B
}0 T$ d) c' \( ?3 r! O% e
else // Draw rule 1.3 -- odd number - Sell
- S4 y( E" U+ `& F' k{ O! `5 {6 O, B" ^) }
negocios.Sell(info.LotsMin(), _Symbol);
8 g+ |* W4 L. C0 x* R}+ Y& i' z# P8 k) s$ x) s
}
' f6 X' Q7 q" C' v6 X8 _//--- Check if we have a new candlestick...
% n2 B- ~; c) N+ J2 f9 t# Pbool tem_vela_nova(const MqlRates &rate)1 ~9 N& l+ D1 g, q1 \0 G% M
{& i* D, [4 B# u% T- U
{2 }. Q9 ~$ L/ X0 r( r
ret = true;7 {8 a, i X" A1 c( {1 u
close_positions = false;5 _5 y# d* J% C' h! a, t
}
" M t) h5 G: n$ Relse7 G6 `& `& u# O% _% N! m4 x* q
{0 \0 w. j0 S) x, L T2 B3 D
if(mdt.hour == 16)
$ f6 V8 n" K( ]" Fclose_positions = (mdt.min >= 30);( U$ X& M6 W ~, l2 |& i; Z$ L ]" w9 s
}
+ E6 Q, n, x& n}
: E. L& g8 \) A, D( Freturn ret;5 H8 {0 c: M; a% P4 H
}
0 U$ r9 \2 |9 o. a, ^& Q$ W J. h) F//---5 _5 m; @- {4 V# l6 t0 o# o
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
9 ^2 H" D! H$ H" R% b{
( k3 w C/ {3 i- c$ L- Rif(PositionsTotal()) // Is there a position?3 @. T- A/ j/ D7 O+ ?. U' N
{
}: t2 X+ O7 v/ y- l2 W/ Gdouble offset[1] = { 0 };
) `2 J& M0 }7 _! T5 F! p6 e2 A: jif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
~* e! R9 j5 [8 w1 ?&& PositionSelect(_Symbol)) // Select the existing position!1 V1 w# l- i' O- W. x- |: s4 d
{1 o1 X2 l a4 O% y7 G7 D# [
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);; m. z( }9 o. M& {* r5 ^% v
double SL = PositionGetDouble(POSITION_SL); b- o5 `+ S( y4 a! N) n
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
& P0 B! a3 B# S! h* qif(tipo == POSITION_TYPE_BUY)7 C0 N6 X1 z# B/ ~* U/ M
{
Q- P/ [: y- n$ E/ j" [* g3 @3 |if (cotacoes[1].high > cotacoes[0].high)$ A3 Y! r# G; r. i& ^ }! o( Z
{+ r5 G& \( r0 v3 \& a% Z
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
; l8 k5 m7 ], cinfo.NormalizePrice(sl);
! z) y! g7 ^: s2 ?- q# Yif (sl > SL)' ^; O0 `1 G8 D$ D
{
) Q2 _' W, O/ {+ tnegocios.PositionModify(_Symbol, sl, TP);( {( H& g/ k; i: z$ f
}/ B5 F7 P' r( [$ r
}+ ~7 a" E7 G/ o3 q. I" ?" V
}# F9 A8 ^3 u! z8 s0 G
else // tipo == POSITION_TYPE_SELL
% L# m4 q$ E' m+ j7 P* n$ P. L{5 N# K- L. n: w6 D) s- e: K
if (cotacoes[1].low < cotacoes[0].low)2 v# q+ O+ T# G9 W3 d& @- }
{" ?8 T7 p0 s) [/ i5 R1 E4 k- ]
return true;6 I; c! H+ e: E
}, C0 j7 X0 J- H
// there was no position7 h. O8 P, H$ x5 _' A+ K% z. V0 ^
return false;
0 k: @/ s! x9 g3 }}
+ f/ U v8 u7 m/ Q& Y我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
* T% U: F" \; D0 r" D到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |