启动交易模型,并构建 EA2 k2 d% L( Y1 H) y) ]/ r3 q: f
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。" ?9 F6 w' ~1 G; i
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
, A6 ]/ ~- E3 }以下是制定这些规则的代码。
! @9 r, C2 U7 b//--- Indicator ATR(1) with EMA(8) used for the stop level...
7 T' y3 m" V5 j% F" f) C( _+ ~% Xint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
5 A* }1 e( k7 o6 G0 U+ S$ I% _int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);9 t+ [3 s: a. ]- A; d+ N
//--- Define a variable that indicates that we have a deal...
7 J9 I h- Y2 F; S% N! r3 H& Fbool tem_tick = false;
9 K6 ?. W: c2 ` o//--- An auxiliary variable for opening a position, p8 w0 m% T& m& f
#include<Trade/Trade.mqh>4 W. T! Z- G1 [) k2 B }
#include<Trade/SymbolInfo.mqh>
) ?$ e* r8 c) g5 a% P' C$ O; eCTrade negocios; S) X8 s- a5 } I4 [
CSymbolInfo info;4 Q, q% _# q/ ~3 T `) f% X
//--- Define in OnInit() the use of the timer every second
0 ^ u* O8 j1 x8 M- Y/ J* n- T$ L//--- and start CTrade
% w4 g+ I% G8 L1 Z; i. f( U* vint OnInit()' M `2 @/ V; S( H) }1 ] j% E
{
& r+ {, V- r. {( j0 {; i5 [ |# a//--- Set the fill type to keep a pending order
3 A4 y, Q% z. Q6 O- d: V) R- h//--- until it is fully filled
, V# {" E& H* D% ?" Ynegocios.SetTypeFilling(ORDER_FILLING_RETURN);. I5 e. C5 m ]1 w3 T
//--- Leave the fixed deviation at it is not used on B3 exchange
" @' e( n$ g K2 R: lnegocios.SetDeviationInPoints(5);3 d1 J: Z# B/ K, w# B
//--- Define the symbol in CSymbolInfo...
/ l3 ~8 s1 J( vinfo.Name(_Symbol);5 |+ m! L5 i) |" Z& U
//--- Set the timer...
! C+ m, ~$ W9 F4 p5 H6 kEventSetTimer(1);- d9 D- P6 N1 r& y9 P- L; h; l
//--- Set the base of the random number to have equal tests..." I! [3 {" i$ e
MathSrand(0xDEAD);/ c7 v2 I6 X, i9 |$ t
return(INIT_SUCCEEDED);6 I0 h7 D2 @7 V! ]% H3 Q- ]
}, A! z+ s1 E& o; m# r- v: k
//--- Since we set a timer, we need to destroy it in OnDeInit().% w, W8 Y+ A* X. B3 X( D6 O$ a1 f# c
void OnDeinit(const int reason)
$ U5 W9 M. ~3 I{+ w+ s) r, B- K
EventKillTimer();0 T; I) N7 K1 u2 h1 | e
}1 C7 W' L! n" \' F* r7 [
//--- The OnTick function only informs us that we have a new deal
% F. p8 v. \4 |5 {) X9 H1 B9 Zvoid OnTick()6 m, Z* Z* b7 y" R7 _ l
{% L0 a# L9 y! T( {
tem_tick = true;
# K. ?. ^3 s! l# Q% [}7 t# {* \. C3 Y4 v* I
//+------------------------------------------------------------------+
" d; b1 w0 c& E//| Expert Advisor main function |
t$ S+ u7 C* B- u: ?8 u% a//+------------------------------------------------------------------+# f# }6 `# {0 A- F P% s! Q( k! @# |
void OnTimer()
9 F. U4 z, I- z6 K, ?{
6 T( e* d5 ~4 |( b. F, o# [MqlRates cotacao[];% z! n4 s" V, C( ^& G2 h- R) k6 e
return ;: I8 Z# o) W. l, Z8 L8 [$ U
if (negocios_autorizados == false) // are we outside the trading window?, t. U# u/ `2 s! _; y. a( [
return ; m( c8 p# ]4 U
//--- We are in the trading window, try to open a new position!
, }' n4 {& V5 r/ M9 v* o( M8 Rint sorteio = MathRand();
% l: X* j8 f) m% l//--- Entry rule 1.1
2 ?: H1 m, N, T" gif(sorteio == 0 || sorteio == 32767)
* c6 A8 N% C7 rreturn ;( c6 t1 a+ b7 S- o5 M. y9 `
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
& q- D. b! O4 C/ y/ p% p{
5 O) n% } H. n4 Anegocios.Buy(info.LotsMin(), _Symbol);
- Y0 F. {/ I u/ e}* i" o- |7 Z$ A' Z* T% [' f
else // Draw rule 1.3 -- odd number - Sell
$ ~! [+ Y4 u( }{2 W3 W0 {) ~, O; i
negocios.Sell(info.LotsMin(), _Symbol); g, H1 Q) F) a8 ^* r
}
& Y+ f+ C# J# W0 w}/ m- U0 U1 C* L- r* }# N: Z
//--- Check if we have a new candlestick...
- p& K: C# [4 mbool tem_vela_nova(const MqlRates &rate)
; T; Y4 w5 a. l% [) S* y{
, d, W, g& ^ Y1 [1 Q6 B( h{7 z y9 K$ }! b9 j+ ~9 x8 w
ret = true;
( u% w, t7 K s( J" u& eclose_positions = false;* s2 ]( [8 R/ v1 O$ T" _
}6 Y# u) K& {7 g7 Q% _5 ?1 i! ?5 b6 b
else; C% |- |6 t; m2 _. [! U* I& k- }
{8 j& r& Y5 N. q3 `# S
if(mdt.hour == 16)
& l, w4 T- y% xclose_positions = (mdt.min >= 30);4 k: Q; D8 h/ B4 }
}' ]9 y5 q0 S' Q J4 m4 Z
}7 c8 h& ?* G' \. T' ]3 g! J3 K
return ret;
6 |& K# t* h' t7 d X/ a1 A6 r}6 [ U3 u5 w8 g6 ~" e5 h, ^6 P5 C! `
//---
5 t' i! u ~3 q; q; gbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
8 D M+ n4 M3 J2 ]{9 H2 a: c* U, N# V1 U* y8 h& z
if(PositionsTotal()) // Is there a position?
; j) p' l0 [! t! S0 X6 y{
* [0 s2 Z+ C- o% D8 g" { Zdouble offset[1] = { 0 };
, q& S# \% P1 |* e! q8 hif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?4 s2 R$ J9 @+ S* q' T
&& PositionSelect(_Symbol)) // Select the existing position!/ A( P2 H: D( s$ D
{2 l- r( d+ D, l- |
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);) [9 X' m/ _% e, I# Q
double SL = PositionGetDouble(POSITION_SL);
5 d% {; s( i$ q4 z0 jdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
5 m' d3 p5 Q" F* P' Hif(tipo == POSITION_TYPE_BUY)8 i* C% a& e4 f: M1 ]' V
{
. Y7 D2 t4 C9 m% J9 w5 i# I2 Q! Cif (cotacoes[1].high > cotacoes[0].high)
* F* c/ F5 o0 V& H' f{) x. `, b6 {' e: d. a% w: l
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];1 U; l; P5 a9 n- K; [
info.NormalizePrice(sl);* X3 @3 \1 q# l2 B5 V
if (sl > SL)
% ], b# t0 r5 M{4 `' G- f# }4 A F' E
negocios.PositionModify(_Symbol, sl, TP);" n4 {: R% _- B7 k+ E% T' O- A4 y
}
$ ~& x. J& Q6 ]$ n9 M' |}
: T. l ~1 u" y6 _( y! g. A}) S+ w5 Z2 p/ {8 i6 d3 S6 W8 j
else // tipo == POSITION_TYPE_SELL
6 M- J% E/ T* B{
8 L5 N; r" m! A- B9 v4 s# Bif (cotacoes[1].low < cotacoes[0].low); y% q# S/ K6 A
{
& v" |! ]. X/ c& Areturn true;
* ]* l: X" x1 ~4 o# ~- U}
. T$ F2 I A, \, Q. c8 ?// there was no position
. B! p, a& A8 N# H0 k, Hreturn false;! e" A, E7 A4 `7 l; Q2 N; f
}
: Y) S) P4 o3 N, s8 V' J. r我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。. T( p: O. U# n# }( P# @
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |