启动交易模型,并构建 EA
0 {) }: m, @9 C; J. Q1 k4 u; R g在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。7 R! f7 o" h6 m1 V; ?5 R
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。; N. a. S& V% B5 B4 J1 n1 z
以下是制定这些规则的代码。
' Z8 Z3 s9 Y1 L. ~4 |//--- Indicator ATR(1) with EMA(8) used for the stop level..." L7 k6 S1 b' q& g
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
% N. {, R* b6 S/ Aint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);! J' p0 q$ Q; Y/ R3 n/ G
//--- Define a variable that indicates that we have a deal...' L" r2 ?' c" s
bool tem_tick = false;; I* v- H- E0 t' C
//--- An auxiliary variable for opening a position
% }& {! z4 l. D3 F' h! }#include<Trade/Trade.mqh>' n6 O1 l" q& Y4 U
#include<Trade/SymbolInfo.mqh>% e& G$ H4 Z, p3 a" \5 c8 c: H
CTrade negocios;3 y1 b: r: R& h* X* k) t1 ^
CSymbolInfo info;
& a9 N6 ?# i6 P" E" P% U* V//--- Define in OnInit() the use of the timer every second( V0 K; _* U" w& @1 m: ]
//--- and start CTrade
1 A9 k# W' E, b5 }: ^/ qint OnInit()$ T1 W4 e0 C7 @- q
{9 H9 s7 G& Q1 q0 W. N3 b
//--- Set the fill type to keep a pending order3 m. U, y* l' Q; ^
//--- until it is fully filled" m3 e" }2 Y6 W7 `5 }4 [3 L
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
8 P m* n* z. |6 V* v5 {4 F! A//--- Leave the fixed deviation at it is not used on B3 exchange
, Q) Z( f0 l$ Nnegocios.SetDeviationInPoints(5);" ^1 R3 l: s# Q
//--- Define the symbol in CSymbolInfo...
# E- d( C' P. L- N- p( winfo.Name(_Symbol);
6 m' i( U1 k6 ]+ D& T' t/ Y//--- Set the timer...( l. ?# U( ^! ]1 b1 |7 P# g
EventSetTimer(1);
& }4 \* R# d, X: v6 h//--- Set the base of the random number to have equal tests...
& i, r6 J$ W0 ?; \! |0 ^MathSrand(0xDEAD);7 j( C* B, r' z% s0 X* f s
return(INIT_SUCCEEDED);
: X- J3 o/ ?. `' a( p6 d}
7 g4 E a3 Q5 S8 x( [" [; K//--- Since we set a timer, we need to destroy it in OnDeInit().3 A8 a( G4 F2 m- h
void OnDeinit(const int reason)
/ H+ X8 }' p" ?2 s5 [7 w{
- R- N8 z0 s& }& z% i7 mEventKillTimer();/ K( k$ \0 I' H3 b0 [/ ?" e
}+ U5 P" w J! {) {9 `6 [
//--- The OnTick function only informs us that we have a new deal
/ ~: C |5 @7 m9 l6 {4 ~' x1 Dvoid OnTick()
8 A5 A$ o4 ^( I$ Z$ q- N+ E" r{0 W( Z2 Z% k* M; R2 X5 W* K
tem_tick = true;
2 C" \/ A9 v% b+ I0 }5 B. T}
# u: E. B1 c# a! _7 o( C//+------------------------------------------------------------------+, w$ t' q7 p3 _" c* R4 F: c
//| Expert Advisor main function |
7 F! V) l! j$ B//+------------------------------------------------------------------+) R* }/ f/ _. D
void OnTimer()8 E6 h* x9 y: p4 t, J a; Y/ [
{
! a( J7 j: f- A9 E! I' C) m1 p6 pMqlRates cotacao[];( Z' y1 d2 h6 l6 [' T' ]
return ;
8 O! r, k& Q3 A q* n0 d# Sif (negocios_autorizados == false) // are we outside the trading window?9 ~# w1 u: Q+ @: @1 z7 s* [ c, l
return ;
! |! M) @* _$ W/ C! ^. k//--- We are in the trading window, try to open a new position!7 c' d, ] U* u7 r
int sorteio = MathRand();
$ `* y, X2 P7 _( l( \//--- Entry rule 1.1( w; M& |: L7 ^* ?% a2 i
if(sorteio == 0 || sorteio == 32767)
1 c. ^. @* {' P0 {+ l+ Hreturn ;
4 n/ I/ M% h% e$ J8 G, `( R( }" sif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy* Y6 g2 w j& K( W; K
{1 R3 B/ {1 e" g! s* [
negocios.Buy(info.LotsMin(), _Symbol);
6 g( C& n# N7 U/ d, a4 F7 k6 M}
; X2 \" @% a% K" a# r0 |else // Draw rule 1.3 -- odd number - Sell
8 |3 w+ _, V/ {{
/ |$ U% w2 c1 U! fnegocios.Sell(info.LotsMin(), _Symbol);$ \2 G& \' K/ j! ^ x
}
! m! N0 U2 c' G6 @# m/ U/ W1 V}" V% Z( b5 I9 r9 c
//--- Check if we have a new candlestick...
~$ p1 F% T+ }" a4 F9 fbool tem_vela_nova(const MqlRates &rate)4 Y$ `8 T$ i2 k3 K
{* o B+ Z% \; D3 @9 w: R! E
{9 X+ X6 ^9 X; X f
ret = true;3 W% ?$ ^( H1 m7 @
close_positions = false;3 m3 ~) q9 v% T" }
}
8 {1 k7 I+ q+ |3 {2 ~3 aelse
( m7 K; P( N3 C( G5 X, V{; |) i( Y) Y u% Z
if(mdt.hour == 16)' [3 }3 `" J9 K" E1 h# q$ P
close_positions = (mdt.min >= 30);
1 t% j& J" v9 A4 j# x- v}: X' M S- A8 g: e! \$ m5 @0 d- }% q1 i
}
* P& C, ~+ {& l# n: [7 }0 D) k; treturn ret;
' \$ k. f4 {+ {$ S}
; S% z) C- Q5 B4 g9 H//---3 b3 d! P+ K/ N
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 F# a) Y* E) ~{( w- @ F7 z) a
if(PositionsTotal()) // Is there a position?
# @5 F0 _% {- Q8 j( e. A{/ J& |) Y- g- c
double offset[1] = { 0 };5 s: R/ B- d G/ a) q
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?9 V4 ~: f2 F& V" [' j
&& PositionSelect(_Symbol)) // Select the existing position!
1 I! L+ l7 ^ C6 B+ \5 c3 F{- g o& a% y& w6 w5 n+ L
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE); x* P7 Z, ]9 q0 ^# f: V
double SL = PositionGetDouble(POSITION_SL);* D ]* N: v3 P* C
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
7 S- }! J r. f/ P/ }4 Vif(tipo == POSITION_TYPE_BUY)" }4 y9 t$ k% z q1 v, _3 m% ?
{
0 w; s4 C9 d( J6 Fif (cotacoes[1].high > cotacoes[0].high)
2 r* s" Y* X% N p, l: Z{, A2 r( i2 _* i
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
1 i/ d, [! e5 T" `/ L. ^" I' \! I! q/ X kinfo.NormalizePrice(sl);
X# M5 L4 {3 `0 U3 f' zif (sl > SL)
1 O# W* K' {& g# R0 m/ Q{: u* [' j6 o! O# T0 F( {+ [
negocios.PositionModify(_Symbol, sl, TP);4 ]( @5 z& n0 ~% n! w/ b) L
}8 u; d( H7 F* d% z0 I
}
! I4 R0 `% b2 B" p" \. @}
Y" O4 A3 ^! c0 g/ ]7 i8 Kelse // tipo == POSITION_TYPE_SELL
6 Y# | T1 _4 a/ j+ T. _! H8 \{
& \* c; B. g8 c v& I( uif (cotacoes[1].low < cotacoes[0].low)" t' _+ W+ k, J( B
{6 c5 O9 ]8 I+ L5 u1 x) h
return true;
* v3 C8 C) P6 \4 _. [" h}
6 o: |5 _8 Q4 E. T) V// there was no position: X9 M9 }% r8 |8 \* [
return false;; ]7 D0 S$ ~5 U- m* U
}! N( j; m; D( h7 O/ l; w# g
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。6 `& ?6 F" `* d( ?; W; l
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |