启动交易模型,并构建 EA
" E' d. D/ y P# d& ?, i' f4 a8 i在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
8 f& Q' J9 G' d+ v$ I5 y6 x为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
% L( r( H5 z. h; u# A以下是制定这些规则的代码。/ e# x/ s h. w; t* y
//--- Indicator ATR(1) with EMA(8) used for the stop level...- h2 _) r0 ]7 k! B6 ~
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
; c E1 L+ E- Iint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);% y" H0 n% }1 m: Q
//--- Define a variable that indicates that we have a deal...
9 Q- j9 P! n7 k1 U3 Obool tem_tick = false;. r. D* S3 j4 n. A, B% M+ O
//--- An auxiliary variable for opening a position7 v0 }$ P9 [% P9 k0 T
#include<Trade/Trade.mqh>, t# `, g T8 h* Z& o
#include<Trade/SymbolInfo.mqh>1 w6 H7 X. e2 n
CTrade negocios;& k6 i# p6 M8 h5 z
CSymbolInfo info;
8 _6 a) M2 L$ U//--- Define in OnInit() the use of the timer every second
+ w) z% U1 b, N' T5 Y! A" |4 L//--- and start CTrade
) t$ ^/ z! N. T$ `# U4 t8 eint OnInit()
1 E, F. F$ k2 [0 j% v; T{! ?% q- t% r/ F' d
//--- Set the fill type to keep a pending order1 N' ]0 a8 ?$ ?- A
//--- until it is fully filled
: Z. Z2 D( f: k: Anegocios.SetTypeFilling(ORDER_FILLING_RETURN);: i. k* Z4 A* S% a
//--- Leave the fixed deviation at it is not used on B3 exchange
* I, l! ]" j! p: e% J1 H6 H( \negocios.SetDeviationInPoints(5);/ n/ Y4 }5 b5 s( {4 c7 D- L
//--- Define the symbol in CSymbolInfo...
! P- t- U3 ~+ H& v8 Kinfo.Name(_Symbol); `$ p: W4 A A* w) J8 q8 O
//--- Set the timer...- W G. i0 M0 I# F Q
EventSetTimer(1);' k- o& b' @: a% l5 T
//--- Set the base of the random number to have equal tests...
0 V+ H/ [# s* d% n/ Z: Y' iMathSrand(0xDEAD);$ V& y" \- Q8 Z. Z2 Z! Q
return(INIT_SUCCEEDED);6 b- p+ D. _4 N! y& w7 f
}
~/ `2 h9 ^% s% Q t3 Q//--- Since we set a timer, we need to destroy it in OnDeInit().
( `0 F( i3 G3 b* }$ L( a( S% mvoid OnDeinit(const int reason)
% L, U8 U R2 H9 e7 C! G8 S{7 j! H5 z# ^6 J* ?3 h
EventKillTimer();
3 N+ ?9 H# I; R7 p* Z. I}
; S5 r, _1 [ g* g( g0 s//--- The OnTick function only informs us that we have a new deal
) k, A" c+ T; M: {5 |0 svoid OnTick()- i! a/ }, Y0 K
{2 e. I$ O$ D: C6 |; |0 M2 n0 B6 B8 f
tem_tick = true;
( H! g& q/ b- ?& S}: Z: K& H# y2 V& b7 O# G
//+------------------------------------------------------------------+
* r8 R; G( k( U; V9 t @//| Expert Advisor main function |5 @" |" S% N+ \7 E
//+------------------------------------------------------------------+% t1 A6 ?. g0 x0 \) e
void OnTimer()
1 B+ Z6 \9 |. m' b1 P u{$ x8 H6 h' `/ C- a. u: i
MqlRates cotacao[];+ \3 j1 S! t8 ^4 V9 c. _
return ;: }7 |& `; D# x
if (negocios_autorizados == false) // are we outside the trading window?
* r8 f9 c$ r0 ^6 o3 t4 ]return ;
0 n1 n0 U6 ^' c0 N& s//--- We are in the trading window, try to open a new position!/ k% X# W2 e* @! b" P7 q9 w i
int sorteio = MathRand();
# q* @ F0 o5 K) |/ T* K//--- Entry rule 1.1
( J; P, U7 {4 f+ H* sif(sorteio == 0 || sorteio == 32767)6 G# |2 m! ^4 D' S
return ;: y+ C9 g3 z0 J: K) Y( U
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
% n! G3 H% W0 w{
3 q' I/ {/ q& I3 ]" }negocios.Buy(info.LotsMin(), _Symbol);
8 [# @2 W" S0 W$ Q9 W' ~8 y8 l0 _$ F+ D}
0 ~* l$ S; `8 T* A- V0 Uelse // Draw rule 1.3 -- odd number - Sell
+ L \- \+ t0 D1 e9 C6 u{, b8 z& e3 p) \% I _
negocios.Sell(info.LotsMin(), _Symbol);& r( L. I1 W/ q7 D3 F3 ^; u
}* W* b8 ]1 \: @1 R" ]6 W
}( w c% e& y h( I+ B
//--- Check if we have a new candlestick...; u* D' _( K% w
bool tem_vela_nova(const MqlRates &rate): r8 E- e! M, W& c' @! T$ B; ^
{
1 B1 q& Z& X$ C8 T- {{0 I7 z0 ^& A' \. g! q& T$ ]
ret = true;$ X6 L" {3 f" o! c
close_positions = false;2 k4 I4 P( H8 u2 p( i
}
3 q8 O m0 `$ ]else5 L+ X- O5 U( T+ t- V
{% X" d1 E. x7 w! U
if(mdt.hour == 16)
2 }7 K/ C, s* q7 D3 Wclose_positions = (mdt.min >= 30);: c* {- t+ V4 c2 k+ _2 J- e& p3 g
}
: J! H9 m) r1 {! }. Y}
7 T! s( z+ E6 }. k8 k9 p( {3 Areturn ret;
5 ]! u, _* g. b; ?2 q4 G. B( I- c}
* a1 p; z# ?# m+ a8 @4 ]4 ?//---
# |3 C& m* O1 F4 P5 v& d& c% Cbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])' o& c- x+ d" q& h9 R& C- V
{% y# a" R8 s9 J1 b5 c
if(PositionsTotal()) // Is there a position?
/ @% G! O1 L! v& T( c3 \/ \) z& J{) Q$ K5 T( }: j" E( `
double offset[1] = { 0 };; E' B1 w$ n% ^- e
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?6 V$ n' j0 R$ _( N
&& PositionSelect(_Symbol)) // Select the existing position!
3 s( T) o: \2 w, \' p+ i$ L{/ P* j" V: ]1 R' i$ i3 k
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);" k9 H1 Q9 V9 }/ Y& R# ?4 Z* f( z
double SL = PositionGetDouble(POSITION_SL);
* q* K; \5 ?, X$ kdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
# b+ K! W- |7 `" }, _7 \if(tipo == POSITION_TYPE_BUY)" O! W0 u: Z1 v3 a5 `
{
% }& _6 F) ^# ~5 cif (cotacoes[1].high > cotacoes[0].high)
; i+ V6 x9 _: s1 d2 I1 ]{
7 P2 L+ }7 c, C* N' P5 zdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];( W2 C+ T" K- S) Q
info.NormalizePrice(sl);2 v4 x. y' U6 g _
if (sl > SL)
# N: H8 g7 c$ T7 @4 y0 L{
% N$ i5 z, D- Q' j# N7 Onegocios.PositionModify(_Symbol, sl, TP);
8 h9 g ]. y. ^( |" i}
# B7 D# ?$ w5 N}# n( c% x" J- ^0 G2 H- X* V7 L$ J
}
, q5 J( p8 L) R7 ?3 O# X; I- K8 welse // tipo == POSITION_TYPE_SELL$ G' E7 i% I: y' E( e, m
{! Z( f$ } Z9 b9 }! f
if (cotacoes[1].low < cotacoes[0].low): c+ y& ~- ?+ y/ G& ?0 ~3 L( w
{ C' A5 _! I1 S
return true;
; z! g5 g: l" u9 s}
4 ^: g& t6 }2 H. h// there was no position
9 v4 f; U4 O1 Y5 l7 e8 }5 {$ \return false;
( H0 l/ _2 v8 I& U1 C* ]}
9 ]' A7 Y% B' f* @' q我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。9 p$ G" `0 k9 I; I6 ^, l! j
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |