启动交易模型,并构建 EA
7 u% u$ r6 q+ D4 |" s5 H+ C* N, R在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
! ?( Q; t5 y& O @$ P8 c/ \$ _为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。8 F5 ~9 y1 F) C# x
以下是制定这些规则的代码。; R* R; ?2 h8 T/ ?* e
//--- Indicator ATR(1) with EMA(8) used for the stop level...2 }9 G) Q5 \4 E! B" k- B
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
( Y- e1 d+ U: b0 w" e8 H$ B0 T& mint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);- A/ O c! W4 r8 D
//--- Define a variable that indicates that we have a deal...
5 w4 X* a( p/ r' X4 q+ wbool tem_tick = false;' j0 _6 z# P& O0 `9 }
//--- An auxiliary variable for opening a position; c: ]/ K: x0 ?% G
#include<Trade/Trade.mqh>3 g/ E! T# a7 o. r; f
#include<Trade/SymbolInfo.mqh>5 ^; H) z5 `9 O: S: C( f
CTrade negocios;7 R0 S! d1 p- F8 ~9 D6 N
CSymbolInfo info;
5 r" i3 l( N1 w% {; c9 l2 [//--- Define in OnInit() the use of the timer every second+ i$ a( j; S3 ~7 d' s
//--- and start CTrade
7 \* _4 x" `) t) M& Tint OnInit()
+ _2 d; ?5 A2 d( `. ?# Z{. a# |6 I! ]& j4 f1 y0 y
//--- Set the fill type to keep a pending order6 x& t5 |% F1 z% a7 r( s! O# s* n/ l5 |
//--- until it is fully filled' p6 G8 Z- u( C
negocios.SetTypeFilling(ORDER_FILLING_RETURN);( O4 ~) h1 _3 r* ~4 y0 n
//--- Leave the fixed deviation at it is not used on B3 exchange
- A. I% {+ a& b* a/ }4 ?* qnegocios.SetDeviationInPoints(5);
6 C& [% G6 B. w/ e+ Z( E//--- Define the symbol in CSymbolInfo...4 b9 h- J, k# S( k9 g3 @. i
info.Name(_Symbol);3 I& L. ~) N, o/ U4 o
//--- Set the timer...
4 T8 ?9 T4 _2 {/ i6 dEventSetTimer(1);7 `8 b* q3 N l: q% l8 {' s/ Y5 I
//--- Set the base of the random number to have equal tests.../ I. z% ?8 I! t8 y! J# A
MathSrand(0xDEAD);! k) b% ], U. p6 G! X) ^
return(INIT_SUCCEEDED);% M2 a1 I2 K* E6 l
}$ g6 R0 {1 t: b9 I; w5 {# [
//--- Since we set a timer, we need to destroy it in OnDeInit()." r2 N7 {4 {2 ^4 A3 J2 }" ^
void OnDeinit(const int reason), s* \9 y7 w) Y; @9 J
{. y" z9 l; n+ [4 c' l
EventKillTimer();
% k) a# @: F* G, u} S) e/ Y" j, K9 _' {
//--- The OnTick function only informs us that we have a new deal3 Q, y( D# T A3 P' T/ E, S- ~2 D' b
void OnTick()
0 R, Q8 w- C% S{4 S0 D5 {9 l- t: V4 X
tem_tick = true;
% k! `/ C' A% ^( y: `8 Q! \: G1 @}& \, e1 \+ p: r T! K9 ]4 ]
//+------------------------------------------------------------------+: l/ p b4 B# i; h
//| Expert Advisor main function |# e7 e$ W2 N8 P; b
//+------------------------------------------------------------------+
, q6 @' S, \# Y, qvoid OnTimer()+ z! H8 L* V5 F7 D o& e
{, j3 w5 I: Y2 A& B' A
MqlRates cotacao[];: [, t, @, g. b$ _# @( I
return ;0 r: V: w1 d6 r* L# X9 v
if (negocios_autorizados == false) // are we outside the trading window?2 q: I+ c& k( Z' s% |
return ;
6 p$ l# S I. N% Y$ W& G9 A. j//--- We are in the trading window, try to open a new position!+ J6 R7 o5 [; a& F
int sorteio = MathRand();
/ P9 K+ j9 V6 ^$ P f//--- Entry rule 1.1# D+ S. E" O m. _/ ^
if(sorteio == 0 || sorteio == 32767)& y2 K) E& T% Y. r) j3 f7 C
return ;
" F/ `- }! a0 G7 ?if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy; d8 r1 S( L9 M
{$ I! P w( L' k; R7 w% `
negocios.Buy(info.LotsMin(), _Symbol);3 o0 V6 @0 @/ I3 r
}1 |. r% K# F, b$ P6 B0 y5 \
else // Draw rule 1.3 -- odd number - Sell
2 \# h# s I7 Y6 g- z{
! K& ?0 z) t7 K5 e5 t' T R6 \0 mnegocios.Sell(info.LotsMin(), _Symbol);3 f* W$ _2 Y. U; U. A
}
3 j3 I0 Q1 m, @. P( f- ]) v}4 x) W; [/ A9 \+ k. {
//--- Check if we have a new candlestick...
# k9 l, E! q' s' u; H* f( hbool tem_vela_nova(const MqlRates &rate)" i6 e N! q( E# V1 q+ `$ c" a
{2 P; `0 S0 w* R9 S9 ?, \
{) K1 V( c! B9 g( A3 Q
ret = true;) d8 a$ U" Q+ D2 `1 q
close_positions = false;3 l0 D+ o0 V0 G0 M' L6 D7 W
}3 y( V1 N y# K+ {1 q$ |9 F. r: L
else+ }+ u2 l1 Y! k; W) k( U9 A
{: ]' Z5 E6 [& ?; b2 p% ^5 N
if(mdt.hour == 16)4 T# g8 a A: p1 k
close_positions = (mdt.min >= 30);+ l: a; f$ O+ h- w3 Q/ ]3 y* F
}% L5 d. q. s: h* K. O
}: l* `8 v4 B+ q2 X* n3 D9 G
return ret;
1 P3 q" B* O1 i `2 h+ A}& \) K* K2 c( s
//---
. E4 b+ F. e. w" v; jbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])( k- b+ j: u) K
{
1 Y4 s3 H3 c" N- X$ i3 ^+ j+ Eif(PositionsTotal()) // Is there a position? t' h [7 U) I( T
{
6 K" m: ^9 W9 |. s% m- gdouble offset[1] = { 0 };7 M1 [4 T' X+ H9 u4 B9 r
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
' ^1 p: Y: F* M3 f8 h# C&& PositionSelect(_Symbol)) // Select the existing position!6 w# U! i+ Q* d. Q. \5 Y
{/ a2 L ]1 F! @' o
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
/ I7 _# C0 N9 `7 Y4 S+ kdouble SL = PositionGetDouble(POSITION_SL);
$ H% B7 B6 o4 U( ^5 T8 H( V7 Pdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
; I7 k0 Y! v1 j! @2 C5 Y! iif(tipo == POSITION_TYPE_BUY)8 k( ?0 U+ z0 p( V5 M
{" p0 J* {6 f' {' e# h8 v9 [
if (cotacoes[1].high > cotacoes[0].high)
( P8 W4 g# P; m/ p, f" F{! V2 q/ w3 n S- n* w1 y& L/ Y1 L3 e" {
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];1 \( x# ?+ E) B5 I9 @' j
info.NormalizePrice(sl);
1 Q/ U% {. a" Y+ ?9 @( iif (sl > SL)
( e8 O5 R5 E+ W0 d7 p5 y/ V{! O( E8 A8 g0 g& U
negocios.PositionModify(_Symbol, sl, TP);) C. M. N% U+ o) U
}
! n+ f6 M( u. Q0 I& q/ c( l}8 G+ x e$ ?$ l9 M; A
}
8 \$ M- ~3 S7 h6 S/ \else // tipo == POSITION_TYPE_SELL2 D) {/ u/ @ t+ d+ ^ H
{
" h/ C% K/ G' Y/ [; Qif (cotacoes[1].low < cotacoes[0].low)
5 b+ i( ~0 G; E* B& D7 g0 Z1 Q{
- O3 @; @3 e8 n N {, C' c6 w/ f, _6 m' [return true;
2 v6 h4 k7 F6 _) u4 J# L}
& h8 g) c. Z6 D5 l2 u# T// there was no position
1 @5 o1 J2 h$ c! ^! E2 wreturn false;
* X: T( ^0 x3 F, E}
! [( R! a- a( v4 c. p! I8 Y我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。/ B* C8 Q8 d* u) Z1 S
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |