启动交易模型,并构建 EA
; v9 C% m! Y& z( h# L O在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。" a; m; q& h8 N
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
: s% Q8 ?% M" A: @( O! G以下是制定这些规则的代码。/ W/ d+ A0 q/ l4 m0 M
//--- Indicator ATR(1) with EMA(8) used for the stop level...3 W: ^4 j0 y" A: L6 M
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);2 a5 {' m- l5 i" a4 I0 x6 M2 P
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
* S4 H' k( T7 b; ?& Y- }: Q//--- Define a variable that indicates that we have a deal...
/ G2 m) o& g9 z- m) a& Y7 {- u W r, Bbool tem_tick = false;, `- m* J# a5 G. T& R" w
//--- An auxiliary variable for opening a position. `8 K/ \' J) u) s6 X( V2 @
#include<Trade/Trade.mqh>
& V, x+ T4 `' D t; a; g+ X#include<Trade/SymbolInfo.mqh>
- D [% c3 }: a% s; ~$ PCTrade negocios; ^5 h; p; w# X7 f; \* p4 L; x
CSymbolInfo info;
, u1 s- b& t3 {" n* ]//--- Define in OnInit() the use of the timer every second$ j$ @. W6 @/ P% w1 ]
//--- and start CTrade
8 l8 |2 r& h ^! F+ rint OnInit()
/ B8 q$ B0 g4 [4 h/ p! D- i{
, q6 _( t5 I5 X# z//--- Set the fill type to keep a pending order
8 t5 z5 u0 X4 W0 u; n s9 ^7 b//--- until it is fully filled
5 C H; p M5 X8 J9 Inegocios.SetTypeFilling(ORDER_FILLING_RETURN);% B# T8 O+ b- w1 H( x3 [, T# K3 u
//--- Leave the fixed deviation at it is not used on B3 exchange
0 b8 m" c1 B# L: B% \negocios.SetDeviationInPoints(5);
% p0 Z, i* j% a& U- S: _3 b9 b//--- Define the symbol in CSymbolInfo...8 ?! r7 N) X, i/ g$ A
info.Name(_Symbol);9 {3 y# F" b* _8 e. A7 r1 {
//--- Set the timer...
0 T8 n+ k; Y- ~; R' m: K: BEventSetTimer(1);
3 E6 r7 l7 }* R& h# |//--- Set the base of the random number to have equal tests...
4 j( b9 m- _/ a% o Q: `* p- IMathSrand(0xDEAD);
; ]$ s# S) h, dreturn(INIT_SUCCEEDED);3 E1 o, e9 N. R: o
}
* r5 u4 c) J8 B//--- Since we set a timer, we need to destroy it in OnDeInit()./ I3 s/ E+ _, @
void OnDeinit(const int reason)3 o' G6 F- U; n0 l4 r( c
{& m2 _0 t# p# t3 H) a c7 P& N+ h
EventKillTimer();
9 m9 Q1 M' B' @. B V1 z/ H; Y% ]/ J}" \7 C7 z% y( V9 j1 _3 I* M4 g# z; J0 w
//--- The OnTick function only informs us that we have a new deal
, {3 B& w. {6 evoid OnTick()) T" J) c7 \- O' _+ B/ i, m/ m5 o
{
4 k) K0 g2 S: G4 j% \* {tem_tick = true;
1 u! A$ B7 d5 ]6 e' {- C+ G- y}0 m* ]+ a0 I! ^9 a& W
//+------------------------------------------------------------------+
7 T& h% K* K4 v6 S. Y! [//| Expert Advisor main function |( L, E; e' W. y( I2 }1 p- d
//+------------------------------------------------------------------+! q! F8 [$ |1 v) r
void OnTimer()1 B( M4 V- a' }( F/ S) E( t! k
{: [% K* o4 ]; T5 M4 Z- F
MqlRates cotacao[];
y! b4 l/ z- |- @6 Greturn ;" G, c! U( A6 U+ T
if (negocios_autorizados == false) // are we outside the trading window?
, Z6 ~7 y+ {% X# |2 T1 X6 i. Q0 y1 lreturn ;$ W9 ]' I" ~& K- z1 {
//--- We are in the trading window, try to open a new position!
/ O* j5 Q2 i# Q4 o/ [int sorteio = MathRand();% y. ~+ d6 v8 r/ }0 I- }1 N+ I
//--- Entry rule 1.17 m0 P$ L' m5 z6 H
if(sorteio == 0 || sorteio == 32767)& m# j' r# }% b% B q
return ;
; y0 S( R H8 D" C( _2 \if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy/ S3 v7 Z& u% u2 ~
{
! D; m; f' ~# Y9 rnegocios.Buy(info.LotsMin(), _Symbol);
. c5 n5 j% |4 A) t( }; N" L* v& I, e}
9 i1 A/ P7 j T0 G% C0 ^4 m. xelse // Draw rule 1.3 -- odd number - Sell
* ^' U0 r5 {6 Y* C [{
% F+ w3 L: E9 T4 z2 k7 ^& snegocios.Sell(info.LotsMin(), _Symbol);
4 P4 y6 j6 S% L0 H6 b$ m}3 u+ j$ M# A( c5 ?7 @7 }
} d9 S6 s' y$ P0 w& T1 k# C
//--- Check if we have a new candlestick...) @8 B3 j) Y6 V$ ]0 S
bool tem_vela_nova(const MqlRates &rate)
9 [$ Z: a# v) O0 k; b{# Q! r! X6 b. r' V
{
; B1 y* a6 [7 B) Vret = true;
, B# ~ `$ h8 I1 rclose_positions = false;) d' u$ C1 [- f3 s
}4 F9 l3 l y( N
else# q4 J4 s; t X$ O( I t
{" D0 u. x. u1 P5 q4 W6 m
if(mdt.hour == 16)
& e& `/ G0 L5 s/ tclose_positions = (mdt.min >= 30);/ _ i: z; I2 u9 W ^
}, z# c3 w) c% P {6 j
}. W- U3 k3 x, k5 S K5 d
return ret;
3 d8 G: a* L: U- n ]2 }8 E}
' R5 z7 T/ [2 u8 w0 x; r4 [//---; r( e4 R/ U: _, b/ ?, P0 K
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])3 R* E* H3 F8 S( g' s7 t
{
: c. M; t$ e* y3 a- gif(PositionsTotal()) // Is there a position?
# }+ e* [+ T7 C6 y: r1 G! y{% s, I- n- g, }. U
double offset[1] = { 0 };$ @% m# n; H2 `: M) z7 W) ]
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?/ Q2 n( V4 W8 ^8 f
&& PositionSelect(_Symbol)) // Select the existing position!
1 E$ e8 C5 K2 X+ _{- f/ P' t. q& F* V
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
0 S1 G$ M! T5 T" b2 ydouble SL = PositionGetDouble(POSITION_SL);
4 }5 Z1 x) Y3 p* ]1 H$ |double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));/ ?& _" l1 z/ M. \
if(tipo == POSITION_TYPE_BUY)4 q( D! z5 V8 j' z! X/ _( z0 u$ z
{1 J! F# o9 ]2 q; P; M6 U
if (cotacoes[1].high > cotacoes[0].high)
* G3 y9 v4 N1 R) T1 s. x4 x{
- \: u- q- ?; O9 ddouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];3 a' n: S9 u% a' e3 m# Q6 t' V
info.NormalizePrice(sl);
$ N N9 Z8 Y0 z% G+ @; O% e0 ?. ?if (sl > SL)7 |) N; ^3 a# Q% F
{1 L4 L- k/ K9 u& w! K3 z* e5 z4 J
negocios.PositionModify(_Symbol, sl, TP);
8 j2 }6 }8 J' S P4 A8 `}
2 a3 T4 m) S' p5 m' Q T \}
1 K+ t. J. J0 q7 u2 Y1 V4 R}
4 g, L# z3 ^$ J& W( X) J, V+ `- e6 Gelse // tipo == POSITION_TYPE_SELL: M8 P9 _/ s6 u! i" e( e
{ V( y. ?. s" E2 N
if (cotacoes[1].low < cotacoes[0].low)
/ e% ?1 P4 E8 T W" Q! x- G{
" ?* W; r0 P9 s3 |$ I/ x* E! j1 q$ Vreturn true;$ s, k. T) M5 E! a4 {
}
. E: [0 Y. C4 d- ~' G7 |7 ^// there was no position& h, [% a2 }5 j; y F* K2 u! L
return false;
7 s Q' e3 A A+ k, g}
3 Z9 N+ s8 g4 F. _) R6 c( ?* {; m我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。8 D" y& Q E! T, @+ ]* K F
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |