启动交易模型,并构建 EA2 I8 {: H" K1 @& @9 A. Y2 |
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。( [ G3 _4 W/ |, K. w; }
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
9 r- A% b8 e, p5 e. V7 K; B以下是制定这些规则的代码。! w" L, v) P" z! \/ F% L M
//--- Indicator ATR(1) with EMA(8) used for the stop level...
: W7 d1 S4 i2 p8 j/ {" V! Xint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);$ O' a+ I' `9 i# I# c9 X
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
2 w* y _0 S3 ?' \//--- Define a variable that indicates that we have a deal...
( ^7 W+ Q/ O# p) G( o% |9 I: \bool tem_tick = false;4 ]( y1 P% v: U9 a
//--- An auxiliary variable for opening a position
" N8 j* I e1 k9 a% F#include<Trade/Trade.mqh>
7 U$ T5 p/ k$ @#include<Trade/SymbolInfo.mqh>
7 e6 C: O; Q# N5 J1 xCTrade negocios;% R2 J" i% ?& S" X2 o
CSymbolInfo info;
5 j: r: m% p+ a' s% N1 K; V$ d//--- Define in OnInit() the use of the timer every second; P! W9 S5 ^3 D% r# w& ]
//--- and start CTrade9 W' c2 H d$ Z; n
int OnInit()
, ^% m/ a0 H9 \5 i3 S' v{
s3 z' Z' p J& j5 e//--- Set the fill type to keep a pending order7 Q* _- P) _& h% c+ z
//--- until it is fully filled
9 ?; s+ E, j5 s; vnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
2 F) w/ ?- b6 |: S4 q) ^( X- m6 k//--- Leave the fixed deviation at it is not used on B3 exchange
2 b" j$ }5 {0 L6 n' m; {negocios.SetDeviationInPoints(5);' c9 g+ j, w; R! `/ {
//--- Define the symbol in CSymbolInfo...2 g4 A \7 U3 t! q. d# e9 X
info.Name(_Symbol);
" d% _/ h, L! O7 O3 i//--- Set the timer...$ z% ^$ G1 e7 K" Q; {# W9 I- D3 I
EventSetTimer(1);
! |! m8 o! O# f+ a//--- Set the base of the random number to have equal tests... m' K& ~( X5 y9 D$ ^: z' n! a
MathSrand(0xDEAD);
* v+ x0 ?. c1 i% t' e) \) K9 mreturn(INIT_SUCCEEDED);
, _5 H h* w, c$ o" Z}
0 z3 I* V5 q2 R" u. {. r//--- Since we set a timer, we need to destroy it in OnDeInit().
0 D8 R6 N# _3 r4 e6 s' n/ yvoid OnDeinit(const int reason)1 P4 A9 Q8 W( w+ L
{
% o2 z. O9 }1 D' `EventKillTimer();* k5 X6 ?; e, W, j
}
% F& n4 }/ w- [. S1 x2 c9 f/ t w4 g) k//--- The OnTick function only informs us that we have a new deal
: V) I1 j2 Y0 h H$ V9 {% Jvoid OnTick()
7 u. {7 x9 z; m5 K$ a$ J{
6 O* f2 D* h9 m' Atem_tick = true;
0 Q2 T& L7 n4 {}* e$ |8 ?: ^5 f6 J. k5 p/ ^! Q( R
//+------------------------------------------------------------------+
7 J* p/ J6 X1 m* q( Z! V' Z U//| Expert Advisor main function | A2 s2 ~. { X* D# S5 D
//+------------------------------------------------------------------+
# Q9 }7 { Q, U0 jvoid OnTimer()
# C v N$ `# D" d{' n1 l/ h) E3 m7 }& t6 a7 y
MqlRates cotacao[];
. i& g& j+ N ~return ;! C% c, j& o8 j# p
if (negocios_autorizados == false) // are we outside the trading window?
; ?" R8 m. U! S! P/ P1 F _3 \return ;) k& L& G- k( s' r6 }
//--- We are in the trading window, try to open a new position!4 y( o; E/ s( m( a
int sorteio = MathRand();: s% D1 l* U3 n* D% Z; T
//--- Entry rule 1.1! m* u9 M/ X4 @& s' z9 x: y
if(sorteio == 0 || sorteio == 32767)
* S3 t; j. u/ R9 h7 W1 Mreturn ;1 t3 j9 O: e% Q- Q- S5 O
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
6 W: i1 ^; v$ `: f. ?/ L2 B/ D3 ?{& y5 V; p5 |2 M* \1 T# b
negocios.Buy(info.LotsMin(), _Symbol);
& f9 u8 I/ Q# V9 Y6 ?}
- w# S6 a A, `* G4 }* |! V) g) Kelse // Draw rule 1.3 -- odd number - Sell
/ A+ G2 q( d$ i{
- L" F2 e& x* t3 [) [3 P. ?, x: ^+ xnegocios.Sell(info.LotsMin(), _Symbol);
! q' W9 w. m3 s- s}, H. u% @) q) U8 j
}- {- g5 p& ^; V. i0 g2 _ m/ h
//--- Check if we have a new candlestick...
5 E! ~4 b- W) S) B1 b. Fbool tem_vela_nova(const MqlRates &rate)
' r; d8 [% ^. V& k0 Y( e' P& N2 M{
; X$ [* }; Q) N' i7 l) F7 x( J- N! U0 x{
8 p2 I* n' R# a2 `3 |6 X6 ~ret = true;
# }. S5 A/ Y, d; bclose_positions = false;
/ O: h0 x+ B4 |) X5 R7 \: b9 X! q}
) C: _1 c. Q$ v7 _* jelse
9 X& S7 G8 i! z3 }" z; u. a$ w{
9 \- F' H9 O6 r2 x5 M/ {- tif(mdt.hour == 16)
" Q" @8 S& G! Yclose_positions = (mdt.min >= 30);
% `1 I# A3 @ K$ ], ~$ N/ |}+ O8 G4 ~, W5 ~8 ~$ w+ G# Y
}
+ h( U9 H6 ~5 ]1 ]2 \, Jreturn ret;
' N, G9 d: ^ k" v& X- e4 [}
" d: ~; {6 P( K) H$ E% w6 K. z$ {//---
$ i- N" x, e. nbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
l6 [; @ H! K6 e) G' v{
8 L3 J' ? s* o) @0 Q7 ^. e/ }if(PositionsTotal()) // Is there a position?4 P' l5 T$ I- g$ I6 L
{5 k1 E- Z1 x. a7 c9 n+ c; ]
double offset[1] = { 0 };3 @; ~. l& `; W8 a; X
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
4 q9 {1 k3 w! N. n/ s- ]) i( W- {&& PositionSelect(_Symbol)) // Select the existing position!+ L' h) }* a0 I# A: g* b( E0 {
{( V( j( b' e$ m$ Q4 e7 G
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
. A4 E8 `- c4 \/ o! t x+ ^( n$ Gdouble SL = PositionGetDouble(POSITION_SL);2 R9 q' o8 \* S4 b1 o
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
9 w* ?* o6 e0 Rif(tipo == POSITION_TYPE_BUY)* [* T2 {! t2 a
{
7 S3 P6 I: a& Q f6 t$ T9 oif (cotacoes[1].high > cotacoes[0].high)
, h1 D! X$ T. ~: b2 ]) e% V( J{
6 D/ t6 j R4 t3 Udouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
9 S1 I; Q1 ]4 l2 T1 Xinfo.NormalizePrice(sl);/ O7 s; J; f& v1 N; N
if (sl > SL)$ q5 i; g0 j' R# n% Q- I
{
7 a3 }# @; Y' @negocios.PositionModify(_Symbol, sl, TP);
" ^* |( g+ r% G) i- n" x! E0 Z}# b. D; D: t% I9 H3 B' ?
}' O, p" k* O* [1 U% t+ w
}* V+ T8 b* M$ }& r- a! P. g, ~
else // tipo == POSITION_TYPE_SELL
' ?5 ^; T) q. K0 \+ E9 n' u{* U( y" q7 l" \ t! r* \9 C
if (cotacoes[1].low < cotacoes[0].low)
- T0 L: E# }9 Q9 k0 E7 {8 u. w# x{
8 l, j! b- A+ s2 _7 Dreturn true;
. H1 _8 k4 X& F2 S}. D! i' [* H# ^+ D* q) \
// there was no position' z! H1 d6 F, P) L, G+ Q$ K- [
return false;- p. x' a% o. N/ x' b' _/ O$ P- }4 B
}
' d% C2 r% O$ ~0 S- e4 h* G4 k9 C我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
; Y: Z' r, G( f2 O% e" J, i: |到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |