启动交易模型,并构建 EA
/ s$ j u i4 l# f' P3 S: B在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。, A7 Z6 N% Q. P/ q4 W. ~
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
% | _7 ]5 v# U8 K以下是制定这些规则的代码。
9 K: b; }: l$ ?8 W//--- Indicator ATR(1) with EMA(8) used for the stop level...
8 V( w0 D- Z: u( ]) m w6 Wint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
3 n3 q8 n$ B! s( n) h. R* Xint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);- |: i" Z+ U8 E0 ^+ h1 V6 G$ [% z U6 _
//--- Define a variable that indicates that we have a deal...- m. |6 S- w; Y3 M6 [6 e2 }/ ?
bool tem_tick = false; u1 [" y, t: x2 J/ x; l
//--- An auxiliary variable for opening a position
9 N' m# l7 y: X#include<Trade/Trade.mqh>7 W( b: H0 o4 v' g7 r
#include<Trade/SymbolInfo.mqh>3 j+ y# [+ p) v9 h. m) g8 p: [
CTrade negocios;& m( B( D, Z) m) L8 Z
CSymbolInfo info;
{8 ^2 j0 z* b0 ]5 B6 X//--- Define in OnInit() the use of the timer every second
6 P- N) F6 F$ i& q4 v//--- and start CTrade
5 ^! k: C$ b: _& V& [ Sint OnInit()' F7 h4 U; C$ ?* `3 Y5 p) K
{/ D& a& A6 F- n3 F# W& Z
//--- Set the fill type to keep a pending order
9 g9 l4 f4 q L! ]& ^//--- until it is fully filled8 {* t: Y# m5 d: {0 c
negocios.SetTypeFilling(ORDER_FILLING_RETURN);; f" A9 Z+ ^$ _$ Z W1 R+ b" J
//--- Leave the fixed deviation at it is not used on B3 exchange
# i- o5 r% Z6 S- M3 S; j% x& Hnegocios.SetDeviationInPoints(5);
3 T5 _9 r; b+ U& R8 u//--- Define the symbol in CSymbolInfo...
& n# @/ \, f+ B% cinfo.Name(_Symbol);
7 U N. x7 `, p( h' G( U//--- Set the timer..., ]! ?+ V7 k9 @6 u& J. n+ I6 |2 j
EventSetTimer(1);
; A4 m' I% f8 O//--- Set the base of the random number to have equal tests...
8 W: o- |+ C0 ?1 @- kMathSrand(0xDEAD);
* r- s1 L7 f, Kreturn(INIT_SUCCEEDED);+ o% t; W( S A2 s+ A; u
}
8 d& K8 g0 z \# m0 R+ n+ |: h7 K//--- Since we set a timer, we need to destroy it in OnDeInit().
4 d* _9 b6 }+ b" I7 R& E( Bvoid OnDeinit(const int reason)
2 ~, a2 q. d7 q2 n9 @{
! `4 X. h( y$ kEventKillTimer();
- V) [, I- n/ I6 L0 s0 e}4 h: m: P$ ^4 A- X8 l
//--- The OnTick function only informs us that we have a new deal
, o _0 ^+ ~7 s+ Kvoid OnTick()% l0 i0 i$ Y* V
{
8 A( Y! o- e/ {, R1 \3 T& F" Ltem_tick = true;
* }' r) h4 O: D4 y3 j/ \}
1 Q5 h( p7 B2 s7 |//+------------------------------------------------------------------+
6 `% p" d* r6 K k//| Expert Advisor main function |6 M8 Z. r$ U; P( f; k$ W
//+------------------------------------------------------------------+; B& J3 z' v) K% P& J" q- q
void OnTimer()7 @. p' N0 Q6 Q* ~: h
{ _/ U3 u) D/ {( J8 |2 F
MqlRates cotacao[];8 J$ d; d" h7 z: {3 F G; v' N
return ;- ~2 Q& t0 a( C5 L6 |+ p
if (negocios_autorizados == false) // are we outside the trading window?7 X3 ~% q, `+ y. w
return ;
5 @1 s* s: j+ q8 @& h6 ~//--- We are in the trading window, try to open a new position!
8 `5 K- d4 K, w6 aint sorteio = MathRand();
8 y5 S4 Z5 T) Y' P& K; y//--- Entry rule 1.1- ~* l. O* s; U+ o
if(sorteio == 0 || sorteio == 32767) l4 X0 x" A* X( O) o
return ;1 }0 j. \5 c/ K% l" V( }) Q
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy H0 H! g; S/ o- J. D( q
{
& \7 c) x) m* ^0 r9 `) X5 T* X u7 bnegocios.Buy(info.LotsMin(), _Symbol);: m" w6 t6 \* D* R' H6 P
}
$ w C Z, i9 ]& G6 p Delse // Draw rule 1.3 -- odd number - Sell- B) V) L o) P0 A {( ~/ U) _. e
{0 q' v7 k! i1 E+ Q- y
negocios.Sell(info.LotsMin(), _Symbol);' B% C, x6 x6 y9 D+ H$ T
}
5 g9 p; y1 ]# n5 ~$ ]6 t4 P* ~) w}
# G6 a% c; r0 ?9 m//--- Check if we have a new candlestick...9 a3 E$ H/ r* D5 ]% q8 r4 @
bool tem_vela_nova(const MqlRates &rate)
7 B& K! Q0 b: M# E& k6 j{
% c8 M; E+ W* H+ P9 j/ ^{
+ i9 a# R8 D+ O' M, m- `, tret = true;7 P1 |: R/ E+ v" C& K6 T- V
close_positions = false;
0 ?) S$ i+ {8 j# y8 }% E; |- ~}
3 z, C. W& `* l9 j# ~6 q) }- }else
( s1 _+ n1 B5 [: P# u3 T/ `{- R( O4 [5 {, L$ @$ ~# O5 C
if(mdt.hour == 16)
( f2 E' z; X2 f% Tclose_positions = (mdt.min >= 30);* C2 _9 P( S; _- w2 t! D
}
% Y ?; c; E/ ]; u+ y) I}" V, S0 B8 g: ^7 ?; B- V
return ret;
0 c; |7 F4 D/ g* I$ M' I* J}6 l# w7 f4 r+ P0 a' H, v
//---
, c L, S- O: j$ f/ c/ x& Dbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])/ ~2 }2 i: g; a
{5 F7 ?0 f. ~7 F4 v
if(PositionsTotal()) // Is there a position?
* r4 X8 ]+ Y0 A6 X) [4 F9 Y{
" v+ i: ~6 z3 {- L$ J" edouble offset[1] = { 0 };
4 | ~# R) X& ?6 bif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
2 }+ |# ?6 ?3 X6 c0 ?- E/ } J6 M$ O&& PositionSelect(_Symbol)) // Select the existing position!
4 q* o$ n; @* n8 G' A+ l9 e6 [ e: h' Y{; J- O9 l' r0 t
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);0 \% w$ W4 [% O$ W* c" q9 l# k
double SL = PositionGetDouble(POSITION_SL);
: s3 x* k' r- K3 F! b9 sdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
' X4 k+ Q5 ^3 A; yif(tipo == POSITION_TYPE_BUY)1 ?. o6 \ N# U% v/ x+ y
{; M/ V2 ~ l7 a8 T1 l! ^! h7 _
if (cotacoes[1].high > cotacoes[0].high)
; l. m9 H& @1 ?' J& N{
6 s% ~+ g9 z6 }+ k0 n( v2 o8 K0 Wdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
5 `0 H5 F7 O; D) p- |! P7 zinfo.NormalizePrice(sl);
5 z1 p4 K: o( ^& l! rif (sl > SL)
8 n" m0 i( O' f% P{: e% [- X; z& ]1 t) [; h
negocios.PositionModify(_Symbol, sl, TP);
+ U* D7 z1 A# F4 u$ h6 ~}
$ M: P+ J7 }( F" R2 ^6 x6 j, J6 r}
# t ?7 O2 F* }/ v) `% P}7 [, ~% Q1 r9 B8 y! f' x
else // tipo == POSITION_TYPE_SELL
/ i6 w5 x/ ?3 ]! o7 C6 ]{
8 q! E3 B* @0 Dif (cotacoes[1].low < cotacoes[0].low)2 h2 Y# ~, ^! L C' {) J
{' o- X$ W: R3 F: A( v! [5 K" y9 w
return true;: g, i1 _6 G% ?7 S
}1 h& z& c3 k9 w+ i* B9 h! W! L( V
// there was no position: z4 i Z; L% h% S+ z
return false;2 y2 o1 O0 Y+ b+ j. E! c
}* x+ N% _5 W, I8 H4 n, V
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
" a9 u; d. O6 X) L* b8 n到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |