启动交易模型,并构建 EA0 {# _0 x! x: Z5 _ I
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。" l+ B; t, h) H6 ?8 j, ]
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
7 |! i4 N+ @/ q" b. m以下是制定这些规则的代码。
% r/ I+ g7 g' q4 t, {% D# G//--- Indicator ATR(1) with EMA(8) used for the stop level...
- C# w4 k4 p! c/ Kint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
3 s s' w/ }! t1 z; u8 \int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
2 R0 }$ m7 |% {, X4 J. r" A3 v//--- Define a variable that indicates that we have a deal...# V6 j5 `8 g+ l* Z6 c( }2 a W
bool tem_tick = false;
* s" @: R5 P) Y0 o6 P2 W' c4 F//--- An auxiliary variable for opening a position6 B* |: t! J9 H
#include<Trade/Trade.mqh>4 e: B, T% R5 V! I
#include<Trade/SymbolInfo.mqh>3 F) O4 [5 |8 O
CTrade negocios;7 Y4 w! \! t+ H+ w- s$ s) |6 H M
CSymbolInfo info;7 e) W( H' ?) C9 G" v+ p8 b, n1 ]% y
//--- Define in OnInit() the use of the timer every second
9 Y* z# K; Z2 S8 g) i$ N% o, H; C9 P//--- and start CTrade: e/ w7 j$ _ g& `) _& N& E
int OnInit()
/ [& U$ a1 | ]4 m7 \) _{) V: J5 o) N2 U( V3 u
//--- Set the fill type to keep a pending order( f8 ]3 s+ g( V9 ~* F. C" h; |0 \
//--- until it is fully filled7 s* c4 r! h& U( ]. H, w! s
negocios.SetTypeFilling(ORDER_FILLING_RETURN);/ j! {9 X4 L3 V. {
//--- Leave the fixed deviation at it is not used on B3 exchange5 W$ F0 ]) u% p; b
negocios.SetDeviationInPoints(5);
5 v, @ A' q/ W- m; w//--- Define the symbol in CSymbolInfo...
& K1 X- v' B) j D- k: l# Z: Minfo.Name(_Symbol);0 q) u" X ?: M1 n- b
//--- Set the timer...
, v8 l# G+ i/ l& K* c! _" D3 cEventSetTimer(1);' J O! Y: @/ E
//--- Set the base of the random number to have equal tests...8 S% i0 D. N2 I
MathSrand(0xDEAD);
+ u; C) j! U5 H5 P' ?0 C! greturn(INIT_SUCCEEDED);
: C, B; B" r L o3 B}
" k3 Y* M. P+ {& ^3 P: i' j* q//--- Since we set a timer, we need to destroy it in OnDeInit()." O# I1 [ O# u& d3 L+ y
void OnDeinit(const int reason)
3 Z$ ~- M5 l0 q2 k& t9 b ]{
) m* I0 f5 b; r' [. B0 yEventKillTimer();
6 o6 L: m% P, f* C/ Q7 a- T}
7 D, ~: v' t) i5 v//--- The OnTick function only informs us that we have a new deal5 |4 k- ^, [% b# M5 W
void OnTick()' b6 ]% K' v0 \- M2 n
{; b4 o' a7 y0 e, R5 j; b- p
tem_tick = true;
& M7 M/ t H+ ~/ }0 }}4 ^ t% Y/ U& H$ P; @7 C
//+------------------------------------------------------------------+
8 `) X! {; o. l//| Expert Advisor main function |
% @% G+ i3 `/ w0 t" |* R//+------------------------------------------------------------------+. v# n0 ?/ R3 }7 v9 X* K! }
void OnTimer()
1 C. p/ U, M4 Q" x{
1 A4 i- g3 ?' S% PMqlRates cotacao[];( Q% `4 D6 W3 H* E+ a0 T
return ;# S9 d7 a; _4 U4 V1 Q- k/ L
if (negocios_autorizados == false) // are we outside the trading window?
( p1 `+ S$ F$ a# a. K2 Nreturn ;
5 S4 `( c2 e9 {& ]; ~+ Z//--- We are in the trading window, try to open a new position!1 h) g$ d& V( Q/ j8 P6 W- H
int sorteio = MathRand();" d( @2 D4 B# Y5 Z, g
//--- Entry rule 1.1
& X8 i5 f; L- k) }if(sorteio == 0 || sorteio == 32767)* S4 [& \: X& O% r9 X s
return ;, O T# R" H; p- [/ w* w8 D
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
4 ?3 `& n2 w$ D+ j7 N{9 y& Z0 B. l8 e
negocios.Buy(info.LotsMin(), _Symbol);
# x7 M0 U. D/ `}% J- C1 ? E: h- L# C5 p
else // Draw rule 1.3 -- odd number - Sell2 J- j' p* x7 k# W5 {: l9 ]
{( n# E( j# F9 Q g) |% z8 F
negocios.Sell(info.LotsMin(), _Symbol);
- ]/ }: b$ a3 T( T3 z}# U7 Y' f) `8 l1 R
}
& |4 z( _3 s) ?. `, z' O, B//--- Check if we have a new candlestick...
' w5 @. G5 I& Y! t% N+ Wbool tem_vela_nova(const MqlRates &rate)
* C3 y0 K; b# u4 X. B+ r$ `) i2 ]{: f' Z6 l4 w' M# Z7 g5 P* r
{9 K8 O) Z9 B& Z2 B: t: k
ret = true;; V" E; r) r3 B* M1 p7 G
close_positions = false;7 \5 v, R) L; u% M4 O, X" ]) [
}" J, i7 ^/ C; s2 L2 T
else
. P, U Y; |$ F( Z) T; F{
- Y) l& b# i7 r s! Hif(mdt.hour == 16)( Z) k$ h) ?5 n5 E2 Y
close_positions = (mdt.min >= 30);
2 P0 s% S' c/ l% e}, ^ [( {5 D1 C
}
; g# c/ t* x+ R0 ?return ret;
9 T- p# r$ v) g5 |}- M e; X P& N: f5 b
//---7 J. h" d9 Z1 h! B' S: _$ [
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
" d4 N$ c6 I* U{
( Q: Z4 r5 K8 J& m' ^3 Jif(PositionsTotal()) // Is there a position?+ m$ I; T# m& `' t1 Y
{! t* O L; z, H7 ?2 D0 U
double offset[1] = { 0 };4 p4 _( r2 K7 _$ H
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
5 [- {; j0 o: F. x0 G1 \&& PositionSelect(_Symbol)) // Select the existing position!2 s7 [/ F5 w0 T! O
{
# ^" I( d- s, i9 y8 X- SENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
" H- ]' F9 y: k: p7 y ?2 [double SL = PositionGetDouble(POSITION_SL);% j* c/ \) Z6 r4 O6 P3 x' y5 J8 U3 N
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));, h3 k% m3 l3 B: O4 f9 `
if(tipo == POSITION_TYPE_BUY)
0 @! L2 e" C1 `( Z) J{& G: t# l4 K6 ?* b. I
if (cotacoes[1].high > cotacoes[0].high)( ?2 y3 ~' O: r) S0 V- G* Z) s1 v0 ~, o
{% O+ k# R/ c/ D% H% Y
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];' T7 `, |2 j* `! r4 M* y4 l
info.NormalizePrice(sl);
0 K7 a% U/ V" \* z# f& hif (sl > SL): L$ y3 W& Y0 b. T
{
6 B# m4 C% B4 |0 R7 I* t# Xnegocios.PositionModify(_Symbol, sl, TP);
" y/ K. t3 y& A}
; \! ?; g5 Z+ H3 j3 m# g}
4 Q; I+ x& [: ~ }" o1 p( }}
* ~. i0 X9 T( {8 J7 w' }% }else // tipo == POSITION_TYPE_SELL
3 L: u' o4 p @$ I- A. E% Q6 p( _{, L5 X, u: ?, c7 v1 K
if (cotacoes[1].low < cotacoes[0].low)3 o5 B/ G9 X( }3 |; T
{
% q7 F6 c1 Q# oreturn true;' `0 [; t) y( w8 E$ ~; d U5 @
}
2 B: f% p4 ]$ [- B// there was no position' `9 v% t- ]0 h0 J
return false;5 m, r0 V# d; i. F
}
$ B9 B* @. G. w0 M我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
2 ]& c4 z' r7 _1 U/ A到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |