启动交易模型,并构建 EA
0 \" m4 E. z; i在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
4 c- m) N! t6 ~2 q+ c9 `* l# u为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。. z* }' J; q' c
以下是制定这些规则的代码。! K" M. T/ z" `# U
//--- Indicator ATR(1) with EMA(8) used for the stop level...
9 \& X1 ], }* s4 f+ q, \int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);/ B: S4 u2 r/ L: L* P
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);2 b& L5 s# f% F9 u; g; U
//--- Define a variable that indicates that we have a deal...% C: J0 ]) d5 ], m+ v
bool tem_tick = false;9 S& k5 P L: y$ j
//--- An auxiliary variable for opening a position6 R) ^* l0 o7 j1 c
#include<Trade/Trade.mqh>
' f' C% N1 P7 `) |0 X6 J( l#include<Trade/SymbolInfo.mqh>: w9 x1 v+ f4 S; N6 w
CTrade negocios;8 s3 B: v* T: }7 y( @ O' R
CSymbolInfo info;
% W5 W9 C. i2 i( z8 b& A//--- Define in OnInit() the use of the timer every second
8 s `0 Q( n7 x//--- and start CTrade5 r3 p( k6 [9 z6 L3 L3 ]
int OnInit()
/ q. X& t$ E% {. r5 ^+ ^' X, z{
5 V9 g; R- P# _//--- Set the fill type to keep a pending order
. |. f' i4 w7 W b! f//--- until it is fully filled
! S& H: | s4 L1 r$ znegocios.SetTypeFilling(ORDER_FILLING_RETURN);
3 k' f; N9 e$ X( _//--- Leave the fixed deviation at it is not used on B3 exchange6 e3 ^; U1 ?( ^1 r, ^( q
negocios.SetDeviationInPoints(5);
- Q3 j% }4 w" U$ F//--- Define the symbol in CSymbolInfo...5 E& P! S: A t0 s/ N6 }( \; |5 O
info.Name(_Symbol);
4 i! P, a$ _, a4 D& Q4 ?6 I//--- Set the timer...: m1 I+ E2 f9 ]+ @% X
EventSetTimer(1);) Y, P! e2 p* A! L! G) C% L. B* X' }6 i
//--- Set the base of the random number to have equal tests...) v4 Y% H# Y2 f0 ?/ J6 s
MathSrand(0xDEAD);
; J% T: D. w* _return(INIT_SUCCEEDED);
6 k r$ D; X6 P1 U9 k+ A8 s}
- U8 L3 m, }9 m# T. `//--- Since we set a timer, we need to destroy it in OnDeInit().
2 H2 u* f7 w4 wvoid OnDeinit(const int reason)
( d4 J# X7 @. {- u7 B# h2 _{' X: g# L) [3 p7 E; }" H' K. S& y/ T
EventKillTimer();' E U' C2 s5 M" x$ T& [- V4 _3 \
}
. `3 o$ ? ~0 O+ v: J//--- The OnTick function only informs us that we have a new deal7 n- B" Y7 i% o- g
void OnTick()9 T# g) m4 t; {
{
; N0 N9 W0 a/ C5 _+ B# Htem_tick = true;) S& `1 {, P; ?7 I! t9 B) w
} E* U2 |6 G0 D, L" V) R$ d, |8 C; b
//+------------------------------------------------------------------+
- a- E( ~# M# w5 O( C1 a! K//| Expert Advisor main function |$ N- z, ]: m) L" L
//+------------------------------------------------------------------+! _) \ C: a2 R2 k7 U$ v/ t
void OnTimer()9 m$ R0 a* f/ a# m
{
8 n0 V! k6 H1 GMqlRates cotacao[];
1 ^7 s* O3 b$ }/ `return ;
$ K' P$ J* X/ D3 X' S dif (negocios_autorizados == false) // are we outside the trading window?
/ u( U2 C3 z& K7 R; R# l) ?8 z4 o' Xreturn ;
6 t# S4 ^0 B6 C7 ^& u//--- We are in the trading window, try to open a new position!
# K, I1 c3 P+ j" V: z& Oint sorteio = MathRand();
' ?4 Z2 d. V( ?' q) I+ Y* @$ t. b//--- Entry rule 1.1
; b% H1 E/ m& z6 X! z3 Z }if(sorteio == 0 || sorteio == 32767)
E$ K4 r4 w$ N1 r. n breturn ;
! k- n! G9 l: Z; ^/ ~# Wif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy( A/ D# C" l& J2 b( W% x
{
: A/ L/ X) v, dnegocios.Buy(info.LotsMin(), _Symbol);
+ f& b3 ?6 i# `1 S& e* D- z6 v}
$ `9 S$ {) `, j R$ F% w7 welse // Draw rule 1.3 -- odd number - Sell
3 b$ C" D# L9 x; M( p{
; J, T' `- m v; O! a: b. inegocios.Sell(info.LotsMin(), _Symbol);
; W4 o1 g7 V& Z0 a) U, W2 d+ I7 [# X6 D}/ n! a. j0 |- S# |6 y3 i) g' n2 F
}9 I" S7 _/ }. R; M% W* A/ C% ?
//--- Check if we have a new candlestick...
) l4 ~- m }$ }/ f! k/ zbool tem_vela_nova(const MqlRates &rate)
7 ` o8 e" e6 s$ f- P: g( }{' s- ]) d9 \- {' ?- N* {9 b
{
- Q' |' i" _0 Fret = true;/ J% I0 G) P0 o: p7 m/ {9 F
close_positions = false;5 {. j4 f$ g: u+ n/ }* T2 l' @
}
5 a _& c* E! C+ ~3 O( Z$ zelse m- k6 j# B( g; I
{
& c8 a( ]( B! Wif(mdt.hour == 16)/ M, a" }/ P& x! q9 f
close_positions = (mdt.min >= 30);
3 U: k. Q; [/ W: a4 Q1 b6 _* j}' g: ]( n: L, ]2 j+ q, ^5 Y
}
, N, N+ v' B( N- E8 ^, W6 Wreturn ret;9 i U- b a7 E- a
}
! T) b; Q$ s3 T: h* i! u' x//---+ `' E8 F' F9 a; y+ \. Y, g( j2 v
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
# `3 s2 D/ g, ~7 C* ]1 `{
4 h8 o; {. ^( O, }3 mif(PositionsTotal()) // Is there a position?
& ?+ L( i1 N- A" L" l# F{
j1 D0 a2 x7 F' zdouble offset[1] = { 0 };
/ o5 ~! F+ h% F6 t$ C& R+ a* pif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
) q J; A" p8 S. B$ u&& PositionSelect(_Symbol)) // Select the existing position!
4 Z0 }2 _$ T6 [2 n/ `{, {0 \8 t1 s0 r! y( u) h8 v
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);+ E; V& T% o3 t( z+ C5 \% s/ c
double SL = PositionGetDouble(POSITION_SL);8 f, M- q, Q4 K$ g# j
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
& P1 l. q% n0 {. R3 Q: V5 fif(tipo == POSITION_TYPE_BUY)
. _! m0 `: _5 q; t9 B& M, l{
' U3 y5 a2 Z/ h. E1 wif (cotacoes[1].high > cotacoes[0].high) t# d; g) F8 O: p* [
{4 ?1 a2 Z1 z8 \
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];2 P. Q0 X7 u& f2 Z
info.NormalizePrice(sl);
1 C) I) C' C* [$ Fif (sl > SL)
+ q( S) G; @5 D: N/ K, n3 s{
5 H2 s7 b% G- }) m" J" M1 fnegocios.PositionModify(_Symbol, sl, TP);+ r! ~. G4 W7 R
}( f) p( D9 _, p4 v- Q9 i4 y3 ~
}
. x/ d* }3 T4 G- y9 k4 J}& P7 m# _9 X7 v. Z9 k
else // tipo == POSITION_TYPE_SELL" U" I3 r& k; ^9 V& |
{
) n$ v9 E5 F* Vif (cotacoes[1].low < cotacoes[0].low)( F& Z, A' A: s; `, [) \7 N
{: |, k# E4 H) Z5 r' ~
return true;& L+ P, f1 J& Z+ L" { |" }
}/ ?) ~+ d1 @+ Q
// there was no position2 K& R! W- t c. S; M/ e# D
return false;$ r" [% ]( Q0 f# r- |6 h) r
}
" {9 Q7 K' i6 }1 v D% }+ a我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
3 \9 I: S0 Y z: p# L: K7 @到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |