启动交易模型,并构建 EA
: P0 h, q- y* N7 O* T; q r在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
8 @$ a8 F) r* Q5 P& T为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
: j* G! @0 {: b& e以下是制定这些规则的代码。
4 P4 X$ \& e8 ~2 w//--- Indicator ATR(1) with EMA(8) used for the stop level...# x! J( S& C, W0 p% @: v
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
2 ?- M% e9 a, u5 y: V% ^* Rint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);! W- l' b* ~) S' z5 Y( N2 b% Y
//--- Define a variable that indicates that we have a deal...
% D# h" i3 D! p6 Ubool tem_tick = false;
& v/ ?0 t) W" u, [ r9 _/ e//--- An auxiliary variable for opening a position
; N7 t) ?; I) `3 e' h$ J. h#include<Trade/Trade.mqh>
% {( C( L0 j* h Q: R#include<Trade/SymbolInfo.mqh>% Q' I9 w: I+ G4 K( C& _8 K8 H) [4 b
CTrade negocios;
& P8 q$ b" I F- v! J$ K( x: Q/ TCSymbolInfo info;0 N: a* M1 z( x% u
//--- Define in OnInit() the use of the timer every second- u8 Q3 L' R- m
//--- and start CTrade: E. F0 f0 k: Y# _: }
int OnInit()
; H- T1 \8 k0 X1 r2 _9 N! \{& d2 S' [: R/ [' p/ r
//--- Set the fill type to keep a pending order
2 |: s* N7 w+ w! e- U0 b//--- until it is fully filled
$ V4 i9 H8 t, B$ R$ V* ^5 I9 bnegocios.SetTypeFilling(ORDER_FILLING_RETURN);4 y4 q o) Q: J5 u# j2 D9 j7 w
//--- Leave the fixed deviation at it is not used on B3 exchange
2 l. p4 f3 o; W- u# D! Pnegocios.SetDeviationInPoints(5);6 ^4 W( i4 }" Q# O
//--- Define the symbol in CSymbolInfo...
4 `# Y, X% h; N: j0 `9 D3 o& @info.Name(_Symbol);; _" ]& y. T5 g) _
//--- Set the timer...
. Y. @" U% w1 t* Q& J* \EventSetTimer(1);) k/ b! q) s3 N
//--- Set the base of the random number to have equal tests...
# Q: K+ \/ }$ o/ r2 G9 j9 RMathSrand(0xDEAD);6 }( W' o7 D/ ~% i
return(INIT_SUCCEEDED);
6 N/ o/ l: ]( ], h0 u; T}9 Y) g: f5 O- i
//--- Since we set a timer, we need to destroy it in OnDeInit().
& _! h* ^2 J& B4 l. G+ G* Fvoid OnDeinit(const int reason)7 \, U; {9 P8 Y) i; c7 }0 \
{& a* s4 a: ]2 h8 h3 J& Y1 m9 ^3 n
EventKillTimer();. \' N1 D0 e) N9 I3 x% i+ {( G$ _+ q% Q
}
" G* F v/ c: u& L' }9 A y//--- The OnTick function only informs us that we have a new deal4 h9 o* H0 H' p: U
void OnTick()
; n5 f/ I" ?7 y3 @3 A+ H4 D! }{
. _9 q! }+ [1 A* mtem_tick = true;. _% J0 R% Z. L! Y$ ~
}
% y# V6 y* _' y+ B9 a//+------------------------------------------------------------------++ I8 H1 ?' R+ X# Y
//| Expert Advisor main function |7 V6 _7 j3 L- N
//+------------------------------------------------------------------+ j( z c3 k" X* g: ^& _
void OnTimer()" W- }# r2 S n$ r3 p' ^ D
{
$ L! a! ^' E, x- kMqlRates cotacao[];
$ X! d) E3 P9 ^return ;0 Z- }8 r! d. V8 M( M8 v$ ]
if (negocios_autorizados == false) // are we outside the trading window?# c* j& J+ a/ ]8 y2 v r( ?
return ;, V* g/ T9 w- j% c' y1 q
//--- We are in the trading window, try to open a new position!
9 w A/ i+ m( v" F% ]' wint sorteio = MathRand();$ Y/ `( p0 W; g' o
//--- Entry rule 1.1# a$ ~# H% b) c7 t, W
if(sorteio == 0 || sorteio == 32767)! V {7 N8 S: v# i- p4 ?/ r
return ;
( d5 o, J* X1 M$ m6 \) dif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy* V' _7 Q1 k4 B
{, g4 k2 J" E, r' ^- b! Q
negocios.Buy(info.LotsMin(), _Symbol);! m* M1 }) L, @! G( u- q
}
% I! J: d, u$ telse // Draw rule 1.3 -- odd number - Sell
* h* O: X/ d8 e9 V{3 ^& f% u& |7 V( @
negocios.Sell(info.LotsMin(), _Symbol);; J& s9 a$ z, K0 |* U# s% u
}+ [6 b* j4 n+ \% Q
}" u( T: w+ W+ Y4 { U0 Y
//--- Check if we have a new candlestick...
6 g1 w. Q% G3 x# U7 sbool tem_vela_nova(const MqlRates &rate)4 O# ~4 h0 H# _9 ?3 J8 q' b
{
6 Z# y& |8 i3 j/ t# q0 s{
& Y# X2 }! i9 P' C4 Q0 U$ lret = true;9 Y8 Z; Z! w p% C) w, S
close_positions = false;& }5 Q( w; A! e- L+ c; R
}& [; V t: X6 s0 e. W) ~. V/ X6 ~
else
! Z0 f' Z9 p1 G- V3 s% q3 A{" k& T* N" m" Q
if(mdt.hour == 16)0 b0 I3 E/ J+ T6 a- y$ D
close_positions = (mdt.min >= 30);* K9 k' ]; t0 O/ p: d
}# G5 o; ]" Y; s- g: x
}- f% E5 p! j( Y: E& J
return ret;9 Q; }) I9 y% G* c* _3 Y& H9 Y
}
6 @3 X6 p0 t$ r N//---
/ U) E7 C' U$ u0 k; {bool arruma_stop_em_posicoes(const MqlRates &cotacoes[]). H: y$ S- p* ]% _1 T; y' Z m( A
{2 i# l: u* a6 ?% c
if(PositionsTotal()) // Is there a position?
1 `# m; o/ U( s |{
, v2 J1 R' e0 G& n C. X! Cdouble offset[1] = { 0 };
# b8 F7 B+ K/ J1 }if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
H: I0 l3 n6 e0 X&& PositionSelect(_Symbol)) // Select the existing position!
/ o- s4 W8 p3 ^) f$ y z$ ~{; c) ?5 I* F. w, D: V% D
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
9 W! U, v( [: n0 L0 Sdouble SL = PositionGetDouble(POSITION_SL);
% L/ M% J- f5 C P1 udouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
" V4 L t8 r6 x+ i5 Nif(tipo == POSITION_TYPE_BUY)" p, f" ?1 Y) W% N
{
' `0 w6 O2 u4 S& R( Qif (cotacoes[1].high > cotacoes[0].high)+ m1 B1 V F3 ?' u; @! @
{* ^0 d! ]( x8 _! W8 D, Y
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
0 c9 O! a/ S |, [ H y$ ]: Rinfo.NormalizePrice(sl);
V. x9 ~6 T$ j* J' z: Eif (sl > SL)
' ]3 L/ ?) o+ k" ~& A( x{+ ]- n2 ~, c+ O6 P' M
negocios.PositionModify(_Symbol, sl, TP);
" R+ ?! a5 Q k: [$ C8 e4 H6 b2 D' v: ?5 ]}! Y2 O3 p+ S$ m+ I4 x$ i7 u
}8 ~) `0 C- a& P$ ~& F
}
g2 }# p$ F& |% A; Y; x- celse // tipo == POSITION_TYPE_SELL
, K' Y* e# m, @9 h: K+ a{
; L% \* J( _3 l, Aif (cotacoes[1].low < cotacoes[0].low)& g: {2 v; ?: U
{( v8 c) |4 U0 t: `7 ]1 }( e
return true;
! v4 m: g$ v% T}
$ [" H/ `- Z9 H% T$ V8 c// there was no position& |/ o/ e( R: v6 T u9 |. j$ h
return false;
J4 V. t# o5 s7 ]: B}
& \, |* K; q, ?; h; L+ ^' D我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
* z8 o. a3 B2 u p/ V& |% y1 h7 e到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |