启动交易模型,并构建 EA, s) f3 s0 g4 ~: j" z
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
1 n i g4 c7 a" a( s3 b1 u为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。: E1 \; E4 h& r6 i- x
以下是制定这些规则的代码。3 ^2 \+ m. `) [' N
//--- Indicator ATR(1) with EMA(8) used for the stop level...
7 H) k' w4 h N2 ]int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
& N2 T& I/ K& ]( u. eint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
1 G3 M8 E- |6 M" Y) R9 w//--- Define a variable that indicates that we have a deal...
& F! X( L1 X- ]- Z% @7 ~5 ibool tem_tick = false;: A# F3 m! y* B' ~ [; O
//--- An auxiliary variable for opening a position& }) K2 a8 W) V4 H
#include<Trade/Trade.mqh>2 H6 h& r/ H: W3 k9 f# Y
#include<Trade/SymbolInfo.mqh>
1 [, ~: m7 S5 w7 ^* G$ J3 OCTrade negocios;
3 |* P% V& b; A8 e8 A/ dCSymbolInfo info; u$ ~" K7 y% ?, }
//--- Define in OnInit() the use of the timer every second$ E0 m5 v. R% c6 a
//--- and start CTrade7 t& V& ^+ b1 J# Y7 r# w, G* `
int OnInit()) O8 a1 |0 E) I+ N% Q/ @
{
' d7 ^, [/ C, n" T3 C//--- Set the fill type to keep a pending order
. x6 K/ X4 K6 q! w* J//--- until it is fully filled
b: B+ E$ j, s+ m1 x: b/ unegocios.SetTypeFilling(ORDER_FILLING_RETURN);$ e3 _$ O& E- |- J# h5 H& @
//--- Leave the fixed deviation at it is not used on B3 exchange7 v( x, H, h8 W$ P$ m5 c5 J
negocios.SetDeviationInPoints(5);
0 Z( u' P1 m& H$ I; _5 J//--- Define the symbol in CSymbolInfo...
" e4 p6 f0 U# ?% |5 H2 zinfo.Name(_Symbol);% a+ ]0 V, l$ w, g
//--- Set the timer... N N; i& \6 D( {8 C) Z
EventSetTimer(1);
5 j0 Q: l# N+ w+ k( k0 t; C9 T. R//--- Set the base of the random number to have equal tests...
+ J# E& m% s3 |7 AMathSrand(0xDEAD);
+ x% i9 P* c+ M. B) N2 l& C. j, yreturn(INIT_SUCCEEDED);
$ P- D! w( Z: D/ J# e0 Z7 Z) o}' I3 A- t0 i& ]% p6 Z7 B/ R
//--- Since we set a timer, we need to destroy it in OnDeInit().
( S2 n8 M. {6 t1 v' I7 i; Pvoid OnDeinit(const int reason); U+ b( A) _7 P7 H
{( x* T; J' E3 G
EventKillTimer();9 m% c" h) Y; H3 U& `
}3 W7 X3 M3 `4 ]2 L8 E
//--- The OnTick function only informs us that we have a new deal4 J3 p- C5 Q* h H3 d! w+ g
void OnTick()
! h2 X/ N! G8 n" o{
0 }' l" _6 Q, O9 O+ wtem_tick = true;7 p Q$ W, v ^
}
% i3 G+ R4 z! g7 D) I//+------------------------------------------------------------------+
$ ^% t! _4 O- h% A( c, }# @! z6 l//| Expert Advisor main function |
2 m- x; N) T) v7 J6 u/ E//+------------------------------------------------------------------+2 S" p0 K% ]5 l& J9 h6 u# `
void OnTimer()
) N( K$ O8 G" E' Q: b* V+ }{
! x( [ R$ _0 r2 M+ w" YMqlRates cotacao[];
8 Q* z$ x+ |, U$ R+ _! y5 Lreturn ;
1 N8 O2 u" z" W- d- j2 x) b6 xif (negocios_autorizados == false) // are we outside the trading window?
+ s6 U ]& I) c* w: m* P$ [' creturn ;
4 p# e0 Q# W& ^& M//--- We are in the trading window, try to open a new position!& U. N9 T* y7 F( y" N: k, L( o
int sorteio = MathRand();
( v) I& @$ R1 \4 k( o) u$ y$ f) g//--- Entry rule 1.12 P% t- f( N2 e b$ ?" r
if(sorteio == 0 || sorteio == 32767)
) G# b' W% s, L* f3 \! y9 P- Kreturn ;/ z* A8 _* c9 v. P4 Z) y
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy6 c- Y% i$ m, A
{
; g6 S: A& Z: [; E0 U W& C; Inegocios.Buy(info.LotsMin(), _Symbol);
# U5 B- v* }; q6 Z) {! x4 a}
0 j3 V( g( Y, s* [. ^else // Draw rule 1.3 -- odd number - Sell
& X) ^* O4 K# L! R- }( e; T{
- d% N2 B$ a+ B. K, n, Xnegocios.Sell(info.LotsMin(), _Symbol);
0 Z1 f# e' R9 N0 w6 V, a! J}
. R5 s4 i2 }7 d" i. ^}
0 B: z6 n7 Z6 [1 a: _; b M//--- Check if we have a new candlestick...
B6 J" r" ]/ c6 W# ~/ qbool tem_vela_nova(const MqlRates &rate)
/ Q* W6 U9 `' n a. b{
0 r( P& o0 G9 y{0 C+ S- X: Q2 Q8 P8 N9 x; B4 `
ret = true;& b1 T3 Z6 D7 }/ r, u
close_positions = false;* Q9 v9 r' C5 h8 W. W2 s. y
}
w% ~. @5 {' X" b2 d" o3 X7 _: @% oelse
! J6 c. n/ q: |6 @: j* ?{! _) k4 U, |; C0 c* v
if(mdt.hour == 16)
: c. ]( t5 i7 U/ kclose_positions = (mdt.min >= 30);3 d, G9 n4 ?, }
}
. i, p6 K$ R' m0 _* O}
* S( s# @1 T% t$ N/ ~1 lreturn ret;
+ |$ F7 _, a& G3 e8 M& o( t+ ]% b}
' v( `2 b0 d$ T& R//---
# j( I: b, b- p2 Z# ], B( Hbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 ~2 n/ e3 u9 w$ X# d{7 h0 J" S- r( u
if(PositionsTotal()) // Is there a position?
5 J( ]) d2 _* w{
' p3 X" c% R" E. s4 Y0 k; Ydouble offset[1] = { 0 };6 {: A$ V. t, }* z
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
% S7 ?4 n' [$ p& P. ]&& PositionSelect(_Symbol)) // Select the existing position! M1 s7 l7 l2 b! } K5 c4 A+ ~' g
{
3 `" y( e e/ V7 J7 }ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);1 X+ Y0 S; Z6 ]" f
double SL = PositionGetDouble(POSITION_SL);1 t! n) l& P" q+ P8 Y
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP)); h2 f$ t" K- H c7 u* M
if(tipo == POSITION_TYPE_BUY)
) B/ Z+ k! Z6 X6 v7 ^7 w+ Q{' e4 v- p# p8 H5 W
if (cotacoes[1].high > cotacoes[0].high)2 @9 S: r ~' C$ M& ^6 W
{: B4 z% _8 `$ X. f( W% w- l1 b
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];- F( H# [, x6 B+ ~; G5 l
info.NormalizePrice(sl);
; y' ?8 a* Q+ ]if (sl > SL)
) C, ~" u( w: t, J7 x' V{
* Q% f! W0 i6 A/ ?& Cnegocios.PositionModify(_Symbol, sl, TP);7 C! o, e& P9 T8 a7 O, K# y4 q
}( ^# y H* I8 A Q0 X' ^7 C
}
3 P+ N0 n) @- G; c3 X}
; y# t5 o) h% ?$ j% p- a1 ielse // tipo == POSITION_TYPE_SELL$ I; ?: {+ ^( z2 P% @/ U
{
& \2 M5 }2 ]' z* b7 M* R3 e* Xif (cotacoes[1].low < cotacoes[0].low)8 W7 R! L s4 t
{
0 j; ^5 D, d# `! O, H. @" Creturn true;1 ~. ]( M) |2 h( x
}9 {7 @+ \! r1 O+ T- b" @7 t4 ?: x7 Z
// there was no position9 I2 b( F3 p! ^% u2 i1 F5 E/ s
return false;: N) ^. \" p3 \, |. _% A: {8 }
}& V& Y6 |+ W N0 j
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。2 f+ | R4 G0 J V5 M
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |