启动交易模型,并构建 EA
- E" G, ?& y5 R- t c在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
+ r: n9 ^+ I0 w9 S; t- }" H- s为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。$ m5 i* K: E3 d; g
以下是制定这些规则的代码。% m5 I& Y0 l& k; b8 C1 e; r3 `
//--- Indicator ATR(1) with EMA(8) used for the stop level..." f2 m9 D% v: S' K4 [# Y, Y* L
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);* X$ l% @' g1 V1 r2 c
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
) O/ @- M; p3 [' O1 t//--- Define a variable that indicates that we have a deal...; ]( Y/ l7 l( @9 \/ b
bool tem_tick = false;
( H7 O+ Q# g6 m; P/ h- A( g//--- An auxiliary variable for opening a position
: y- [, B2 h$ c% A( _1 @#include<Trade/Trade.mqh>
( m& S+ {4 ^$ E#include<Trade/SymbolInfo.mqh>
4 }8 S) @1 \2 _# h( ACTrade negocios;& k8 s) E' e, {, R- @2 ? C
CSymbolInfo info;
% e0 t/ a5 | }) z! O) ~//--- Define in OnInit() the use of the timer every second# c2 o: f7 E: \& C
//--- and start CTrade
1 G& t% N2 u- [2 R3 K1 c3 vint OnInit()8 A; C1 U+ g4 T
{
( s6 q! g2 c: J# c//--- Set the fill type to keep a pending order7 ?. u/ A5 }+ V# Q$ K( C
//--- until it is fully filled5 p* L2 q+ }+ J# O
negocios.SetTypeFilling(ORDER_FILLING_RETURN);. W% Z+ U0 q$ b0 e S6 W
//--- Leave the fixed deviation at it is not used on B3 exchange# a8 Q9 p1 U1 @$ N
negocios.SetDeviationInPoints(5);
! z# n1 _, i8 \" k5 i: |( C//--- Define the symbol in CSymbolInfo...
- t/ B: ^. U. c4 a% j: P7 sinfo.Name(_Symbol);
' @" Q$ `0 b0 a/ d) }1 G* S" B//--- Set the timer...: |( q, ?- }1 w O
EventSetTimer(1);6 l1 f7 S: j5 F( M' o
//--- Set the base of the random number to have equal tests...2 [- P9 [, n5 _& D' F
MathSrand(0xDEAD);
2 |" c8 x1 u5 z: N2 b8 F5 vreturn(INIT_SUCCEEDED);0 G# m4 K) A4 z( `* y/ }; J% x
}
5 z2 j% m' W2 x# D( c//--- Since we set a timer, we need to destroy it in OnDeInit().
! H- V; p; a; f, \, t! a; Tvoid OnDeinit(const int reason)
1 [$ C3 O: c% w) [8 Z0 J# C) Y4 s) f9 T{
5 t# c" _. w5 x8 f! |- WEventKillTimer();+ z$ r0 ` ?# z8 z& G6 |
}4 M, |/ D/ X6 C" J4 t+ H
//--- The OnTick function only informs us that we have a new deal8 S% _ u/ e6 e, I
void OnTick()
7 y4 \4 g% ^5 e0 c8 N! k# e- k{
( F2 i% [& A4 w! a1 z* Qtem_tick = true;
* w0 J; N% ]. w- B X& ~+ ~; M}
5 l. Z5 E! ]* R# b% V//+------------------------------------------------------------------+, c3 |& R' q6 |' U8 X V/ M
//| Expert Advisor main function |
4 L% b' p5 m, D/ F _' e3 g//+------------------------------------------------------------------+
) w/ K& D7 p, _1 D2 q6 [& a$ ^4 @void OnTimer()
1 j1 \5 V- w! X% V{( D9 Q4 J% O6 C
MqlRates cotacao[];% `) ]4 U. u$ z/ t
return ;/ ~( p3 }( y D @* X1 u% I
if (negocios_autorizados == false) // are we outside the trading window?: h% A5 l7 `" f4 V
return ;
+ I! N2 i, ?6 S$ T5 \9 P//--- We are in the trading window, try to open a new position!, g/ F& a/ |, Z6 F( s/ w
int sorteio = MathRand();
Y+ r+ r' b. h x4 M" {; ^# q, b//--- Entry rule 1.11 Z* Z: X6 @& O! X; c8 ` g. w8 q
if(sorteio == 0 || sorteio == 32767) m; a4 w! W9 l6 v, D, g% F: d
return ;% ?7 A) t$ V& `+ q
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
$ Z; R' V' `2 W$ v# @9 u C, b{
8 r6 b) m* [9 k; B0 ?* l6 mnegocios.Buy(info.LotsMin(), _Symbol);
( o/ y3 J. g, P" n* Q# t8 [+ [}
" [# ]3 S3 T: A9 M" e- {else // Draw rule 1.3 -- odd number - Sell* ?5 N3 e; G. D, ^* D% {' D
{
$ Y' Y) P) V9 E) S$ O5 }& d6 |negocios.Sell(info.LotsMin(), _Symbol);) E8 r9 L4 R# V. ]" d
}
" B! B$ L* }( A7 j: K}
7 i* P4 g/ ]# ^% p; ~ ?' c//--- Check if we have a new candlestick...
, z0 b) s8 K; e# q& A# Q: s! |bool tem_vela_nova(const MqlRates &rate)3 @4 I: I3 R& U4 x3 B& A+ v
{
/ i' g8 x* `! D& F/ y$ v) P{
2 t0 I0 H% c" ]5 t2 b2 n0 ]8 kret = true;
4 s: m) a: i# C" D9 Q, Dclose_positions = false;
# _# t9 H4 B+ w}
! A1 [* K0 w5 Z- |5 m' }9 helse
+ `. r7 }* h. k: O* Y% m4 P+ Q# Y{: Q4 u& P0 z; U4 Y5 {9 J
if(mdt.hour == 16)# ~; G3 g$ L2 v' h8 N* f1 J9 F
close_positions = (mdt.min >= 30);
' h& C- _( w, o' `}! F: U+ Y+ e3 }$ O+ }& }$ b
}
: V$ }+ W6 j# O4 y o! o7 k" rreturn ret;1 Q0 r. {' k5 y% o4 H. G
}/ @1 J! l! d5 E9 X2 T# |) m
//---
+ M1 X2 Q6 t) jbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])! C) e e7 R. e6 o! d3 v, f1 D
{( b8 n9 A& R# K6 i' b5 g4 `$ J
if(PositionsTotal()) // Is there a position?
6 L6 a/ H1 x& }. {{
; b) b9 t! a$ s4 T, x) u. Adouble offset[1] = { 0 };
; n0 p5 ]2 P" k6 U+ S9 q; R! [& Eif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
# ~, ~5 b" y* K! h&& PositionSelect(_Symbol)) // Select the existing position!
" S/ f! V; W2 G9 s T, I" t{
) b `0 B, K0 ]: `- z* I0 Z6 nENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);' s4 q# R$ v: f! b, E3 J! _' D
double SL = PositionGetDouble(POSITION_SL);. t) D; h3 ^; I( q7 A/ ^
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
& q- a" ?2 @' |if(tipo == POSITION_TYPE_BUY)
4 i& q) f1 ?; i+ C. L{& @9 C! p% B ~7 l) E
if (cotacoes[1].high > cotacoes[0].high)
+ t2 {% i* g H7 u6 K d; a{$ {" |5 c$ _0 G, H
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
: D( _1 ?, l2 B, ^# Yinfo.NormalizePrice(sl);5 k5 I) W' A6 E: i
if (sl > SL)$ C0 g! F* _0 C8 K# ?% Q7 W9 r
{7 f ?; U }0 ^$ a1 r4 w* Z
negocios.PositionModify(_Symbol, sl, TP);3 ]1 [1 m/ Y1 P/ v( e T
}- i& ?4 v0 |+ S5 b+ s9 Y4 v
}! T! U2 l0 J- F# c5 d
}
! f1 r) @; T$ k5 A @else // tipo == POSITION_TYPE_SELL, q/ ^0 y3 x; p2 N
{
3 J& P4 @! s% O& c T" n; s* z$ s. @if (cotacoes[1].low < cotacoes[0].low)
4 n! t2 J- A, ?) P9 S{5 Y+ i* h! m/ x& f
return true;
! |% n& x3 K2 p5 v& R* Q3 x}
, I8 q) N* B3 F8 p4 X// there was no position, {9 }2 P- {" N: {7 D* M
return false;
6 \2 o$ \9 T+ {3 ~6 ?6 c" q+ y$ A6 h}
4 H# R+ a! @( E& L) a我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。# C/ J$ l2 h! @6 x" S, C( b
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |