启动交易模型,并构建 EA
1 ]9 b: t+ Q; g2 X在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
% x* o2 k6 T8 ]3 D' _2 {为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。+ N; |2 }) u. w6 I: j+ }
以下是制定这些规则的代码。
. @6 l. @% G$ ]//--- Indicator ATR(1) with EMA(8) used for the stop level...
( L8 \3 c5 f7 ?: Yint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);! i" h8 ?! K$ c) d! `) G' J
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);. R1 y0 r2 K# ?, t: u1 @9 b
//--- Define a variable that indicates that we have a deal...4 V7 J* L: V8 K, s; C
bool tem_tick = false;
! }+ r: D* R, G. S; i7 _, u//--- An auxiliary variable for opening a position' _# I, z" {. A# U+ i
#include<Trade/Trade.mqh>
# t1 l* e, f$ O0 u- V#include<Trade/SymbolInfo.mqh>
* D/ F( s9 a1 \6 g* V, mCTrade negocios;6 p! W3 G4 _/ ]7 E
CSymbolInfo info;$ P/ M! Q [$ L8 s
//--- Define in OnInit() the use of the timer every second. b3 J U3 \1 Q+ j: e6 a4 g
//--- and start CTrade5 S% B( E8 O9 I9 K& u% V1 F
int OnInit()' \5 R- ~ w5 Z
{/ a. s: \% F1 ` {' K" S' b/ x9 ]- _
//--- Set the fill type to keep a pending order& r' o: e8 S6 q( U
//--- until it is fully filled
1 R5 V6 h( g$ knegocios.SetTypeFilling(ORDER_FILLING_RETURN);
& e) s% J8 Y* a//--- Leave the fixed deviation at it is not used on B3 exchange
# ?2 F. W) o! i+ J7 {negocios.SetDeviationInPoints(5);' |+ z& o+ T) Y, P( T
//--- Define the symbol in CSymbolInfo...
/ r% ?1 E1 V* s' ]. h( Pinfo.Name(_Symbol);4 `- j5 g, L5 J* R7 V3 u! I
//--- Set the timer...+ \- }/ c8 n B7 |$ ^
EventSetTimer(1);/ O( N$ c% z. r# K9 Y
//--- Set the base of the random number to have equal tests...
7 l3 Y7 K$ Q3 v. V. d( }MathSrand(0xDEAD);
! x X# l0 m6 Z9 b( l" K3 ireturn(INIT_SUCCEEDED);2 ^# o: [3 B' n. \3 n( ^: V: `; \
}
! m9 E! ?* O% {0 v+ `//--- Since we set a timer, we need to destroy it in OnDeInit().& w, Y9 G" E ?) {. H* j: c7 v
void OnDeinit(const int reason)4 [ q9 p' v8 v, w$ p/ F
{
0 [. S& P( N6 G0 Q" q1 ?8 r ~, G1 DEventKillTimer();
! Z* i- P2 b# s( O% u' S}4 u# y1 J3 \3 A' _5 I4 h; ]# r
//--- The OnTick function only informs us that we have a new deal9 _$ F* H p" [# m; ~* O
void OnTick()2 ^/ o& M$ {, i' T2 z0 E
{
' ?' }! s0 P; m' s; ?tem_tick = true;" \5 r; {& V5 ?7 y. }
}
) F8 ]1 K4 m0 p( t- ]5 g//+------------------------------------------------------------------+# u. D/ Q% R' s8 Z
//| Expert Advisor main function |2 c. [3 C# n0 N& S+ q' d7 W+ ]
//+------------------------------------------------------------------+- V/ o# U- G, _0 y c
void OnTimer()% \: Y8 j2 J& |% N4 p/ U4 p
{$ `) d; z8 f! }0 V" e
MqlRates cotacao[];
- G }* M2 R) I$ nreturn ;
- G) S3 `2 Q' I; I Rif (negocios_autorizados == false) // are we outside the trading window?
# H. t& }+ h8 d f+ t) z: Z" H' Qreturn ;
/ \+ K3 q, B* p2 [* w# S& e% g3 ]//--- We are in the trading window, try to open a new position!7 X/ p& u0 j$ f( L1 U/ h
int sorteio = MathRand();) M( Y' r% r+ e: a3 R" _8 ]4 v( j
//--- Entry rule 1.1
: ?4 n4 k1 Z* W- W, k7 {if(sorteio == 0 || sorteio == 32767)
( G \# U: n: [8 X. Treturn ;
0 P" J% H) l0 Rif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
5 m5 [2 ?7 ?& S& r! V0 U9 Z) ]{- f. B& h) C k* O
negocios.Buy(info.LotsMin(), _Symbol);
! ~% Q& l) ]+ n: Q g! P9 y$ {}
1 A: r, ?" d$ Ielse // Draw rule 1.3 -- odd number - Sell
3 d: j( _1 j, E6 x! j( Q* o{
/ V) P' o. o8 @. X7 O8 v5 _1 ?negocios.Sell(info.LotsMin(), _Symbol);
8 a6 d" E+ ^0 `- }}1 j) u y8 X; _) V7 M& _: @
}
0 x ~+ K- O" z6 h* S! ~: {* H//--- Check if we have a new candlestick...
' _. i3 T+ W. ~: O( Xbool tem_vela_nova(const MqlRates &rate)
. Z* H, K( n. E& D8 x( B{
2 l' u0 P. Y/ m, f- _" v6 n{$ K5 T& ~& ?# [% Z( D- p% @
ret = true;* L$ E0 ` @ l
close_positions = false;& w; x* ?+ t! i: a6 S
}1 g4 ~! Z8 A; O+ K5 E# X+ {
else% W; G5 Z |. @6 l8 H% k3 g: G
{
2 J# S+ u0 s, F( j- a) n gif(mdt.hour == 16)
% N3 _& I3 H- Tclose_positions = (mdt.min >= 30);
4 M& L# {# e9 W4 U3 Y6 ^}4 I. w+ \# O8 M, _" @
}
& V, e5 K4 y/ t; S" U! W1 W: Zreturn ret;
; q* [. a1 \2 O5 m- [3 C" q8 h}
& X3 `& w' h* S1 P; W//---
0 o1 g2 l" g9 n' Bbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])) W4 ?$ [, [: W, t/ e: F; Q
{
1 w3 ?+ w$ ^% \+ Xif(PositionsTotal()) // Is there a position?5 i; Y3 [6 P0 G# \) Q5 V, m! T- i1 ?( O
{4 H# K7 o* B, e. a( J0 P- ~% V" s7 C- T
double offset[1] = { 0 };9 ]- x, ^2 q9 ]) x8 R, W- R* i
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
% R& I. l/ m: [9 H8 b2 {&& PositionSelect(_Symbol)) // Select the existing position!. S& T' K, N) Y) ^% G- i
{
. y0 f g+ P% L' H$ x" i: vENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
2 D' X- [. y3 j E4 ydouble SL = PositionGetDouble(POSITION_SL);
/ G- ~1 o) _. s" xdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
& {- h4 d* d' {) R# Y& tif(tipo == POSITION_TYPE_BUY)% h0 f% g( M/ j% z8 ~) p
{' R; _' A- ?* B! c7 i
if (cotacoes[1].high > cotacoes[0].high)' D/ I. P8 A% j5 a
{+ a0 s/ Y: p4 L8 Z
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];- {. l8 L1 z, S% ~1 }* U
info.NormalizePrice(sl);
2 T- Z& P1 }* jif (sl > SL)
" s0 ~7 {4 z2 b: d2 H& J' j5 n P8 ?{# B) y+ h7 A( V8 }
negocios.PositionModify(_Symbol, sl, TP);
1 {& N) y+ o# u( \9 @7 w. C8 D}
\' b, v; e* w* t5 C! r3 p}
3 t, p, A& a3 { ~! W( A- Q$ L}" k C. z+ K }7 z _8 v0 [1 E b3 {
else // tipo == POSITION_TYPE_SELL$ e1 i4 g+ T- F
{
: {0 e8 M' ^, Y: X5 A: {if (cotacoes[1].low < cotacoes[0].low)5 u t) @2 a0 ~( y a
{
5 q: `4 b$ V; @1 q* J2 V# Y6 k- freturn true;) A" B6 {! d( ~0 c+ d* \ T
}
1 e$ o2 _- D: u- v// there was no position
8 r- J+ _2 ]7 {8 B* f( [return false;
8 U _6 S. S; E8 @3 b. O2 ?}
, Q; i5 r1 v7 I, a4 U6 K我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
+ `5 l$ I( R0 A! J4 z7 |到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |