启动交易模型,并构建 EA! f0 w5 |7 {# A
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。. L/ b" a% B& U. U5 ?1 c. Q+ }
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。. n5 P2 o. v } _) q$ }; B
以下是制定这些规则的代码。9 _0 t, l. ]/ g; J
//--- Indicator ATR(1) with EMA(8) used for the stop level...' G8 M; c, C7 d! B4 l2 o5 w
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
/ s! A$ t W5 Nint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
5 s0 x& P, _% Q; }- }! ^8 D, K//--- Define a variable that indicates that we have a deal...
% f+ F, |* ?5 E/ Abool tem_tick = false;) x4 Q6 m; n, t. r& e) H
//--- An auxiliary variable for opening a position6 t. M( K3 a$ A+ y0 C! A
#include<Trade/Trade.mqh>5 u' p& H5 O. W
#include<Trade/SymbolInfo.mqh>; D: a/ B- F4 A6 u
CTrade negocios;4 \: g) p6 }5 Z& k0 X; h* m5 r
CSymbolInfo info;+ I; {& |6 I: ]' a. c
//--- Define in OnInit() the use of the timer every second% u; N3 e K1 o& m4 f
//--- and start CTrade# Y9 C5 j$ r$ a1 o4 c
int OnInit()6 c3 ?4 A8 q! N8 q
{
; K7 I% n" k. |7 y$ n7 R//--- Set the fill type to keep a pending order
/ G7 J: \( L. u' n* {; Y2 i//--- until it is fully filled L' R/ L( f7 h! _5 c5 ]' X9 [- y
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
! G+ I0 w! g) K5 z//--- Leave the fixed deviation at it is not used on B3 exchange
4 e2 F( { Q6 g- jnegocios.SetDeviationInPoints(5);
3 [3 _5 ^+ ^8 I+ y//--- Define the symbol in CSymbolInfo...
3 C6 A: |5 M' I; b" }8 qinfo.Name(_Symbol);. E7 P9 B ^9 } r; e- E
//--- Set the timer..." Z8 t* ?# }) V+ t
EventSetTimer(1);7 }# y! Q' j0 g
//--- Set the base of the random number to have equal tests...
0 T( P/ m& ^, w& A& w: [2 F$ _MathSrand(0xDEAD);4 ^5 P% k% Q4 m4 j
return(INIT_SUCCEEDED);
1 q: z, k) P* F: r+ `}# f- o6 O* n& `- g! ?) f, ]$ C
//--- Since we set a timer, we need to destroy it in OnDeInit().8 K- j3 q2 R" R4 O
void OnDeinit(const int reason); C. j" A* n3 k J' Z
{1 \0 V$ {2 \* P5 S
EventKillTimer();
; o5 P. ^8 `' B T}' `6 D* @2 n1 T" J3 {* A
//--- The OnTick function only informs us that we have a new deal6 @: H' U6 W( F2 F/ V& p
void OnTick()
1 v& z, _, h, [. Y% s! R$ l6 _{7 n3 c k; | I( ~5 j2 s) d/ I
tem_tick = true;
# S$ }. l* [( t& X+ E1 U1 g}+ A' I/ b0 h, @: ` E! D$ k
//+------------------------------------------------------------------+0 r$ H+ |' t! K8 A
//| Expert Advisor main function |
7 P. |2 H: s/ G" { n8 a( v) ^# C//+------------------------------------------------------------------+' I* c- U$ F3 m1 d% Q4 L, T
void OnTimer()
; S) j# w8 F$ o+ N: M/ W" s. o{2 e$ v7 W0 x+ V1 B; y7 p" v) r
MqlRates cotacao[];; D) Q5 w1 F' P
return ;
- Z" d9 E8 x5 N8 Uif (negocios_autorizados == false) // are we outside the trading window?1 _0 W- B) m( C3 Q/ i2 k, E) ]+ c
return ;% @9 C q8 x1 d5 K
//--- We are in the trading window, try to open a new position!
: b3 y4 z# {' H" eint sorteio = MathRand();+ O/ L) `+ a% g a O, @
//--- Entry rule 1.1
# z; V* A2 m. D% Oif(sorteio == 0 || sorteio == 32767)
2 l0 h. x+ H1 t3 d# C! O$ R. A. ]) Jreturn ;
& q6 A7 U8 z; L4 gif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy# A% c' t' E' t5 E6 w
{: s" b2 K; r+ r( Z- G
negocios.Buy(info.LotsMin(), _Symbol);( I4 D5 E3 `1 [4 S+ g7 a/ P. R
}
2 u8 f% p+ J; E$ k1 ]: o* Telse // Draw rule 1.3 -- odd number - Sell
# {1 k- l4 ^! m* y0 n6 G6 o{
8 M( F, d. ~2 l' b8 ?$ O" h" G- jnegocios.Sell(info.LotsMin(), _Symbol);
. R7 u" _3 E# u4 i}( ^. h" B% w, c% f+ D+ C9 H5 {
}% J+ i9 N* X$ P- h7 ~: S* x4 q4 U
//--- Check if we have a new candlestick...
+ k4 X+ W5 v2 d5 s3 Z* ^8 Mbool tem_vela_nova(const MqlRates &rate)$ T# D- Q" G# o7 }% B5 r
{! i" U2 S& r# x
{
" }; T8 i4 j8 R2 H6 q7 E( u$ Oret = true;) o% e1 G. |) _, i
close_positions = false;9 B8 d" j1 f& v6 `; _+ y& u
}: f* e5 X2 [8 N/ M5 u9 j
else
: c# G1 Q/ u+ M; @# H2 q{
8 N% Z. R2 i: g, k, @/ L. {4 U4 }if(mdt.hour == 16)
" {* Q. q9 r' S9 s: Pclose_positions = (mdt.min >= 30);* |( [# V- r& z! L/ Y
}/ @$ n9 w( ^+ b4 ?7 q
}: ]3 F/ |- y! X$ T7 l: l4 D% {
return ret;5 E- K0 k. \: C% _1 ?
}5 z+ v6 k" [' h9 c
//---
9 V. p8 L4 u7 y) m" C. v; S6 mbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
+ p* V1 y) _+ B{
% a4 W6 m2 r0 b }$ C! Gif(PositionsTotal()) // Is there a position?2 d7 U1 ]. f4 l2 q" L! T5 z/ w
{- N8 L7 Q; \ k1 K) V" E
double offset[1] = { 0 }; e6 ]7 T2 H4 g$ W% _0 y
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?/ t! z& n0 Q6 v9 `9 d! @- q
&& PositionSelect(_Symbol)) // Select the existing position!% }! t; R' R& i! ^
{6 y& O) ]0 W& r: _
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);$ l, X8 b! a& B# V, j8 \
double SL = PositionGetDouble(POSITION_SL);8 h- I# g8 R$ p
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
6 ~9 `: |9 |1 Eif(tipo == POSITION_TYPE_BUY)
5 J8 t3 t5 E9 D' T4 O& ^{
& h* D: w& s; K- p2 b3 oif (cotacoes[1].high > cotacoes[0].high)2 r% V/ N- @+ z& B+ O4 [
{
Z) X n2 F: e8 |2 {- m! mdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];7 b3 O1 m1 H2 r8 Y& a
info.NormalizePrice(sl);
+ i! U, O1 _* p! B iif (sl > SL)
+ c- f2 l) N) W+ q8 b4 ]{& ~1 T& |5 h* G2 [4 B# U
negocios.PositionModify(_Symbol, sl, TP);- E7 B6 u. [9 ]
}
$ T6 l. w& l- z# `- l1 a$ b}
, a' Q( {% P b" C) Z}
* z$ }2 {" W. Aelse // tipo == POSITION_TYPE_SELL
6 _" U+ \- N' A2 |( b8 w{! p( K0 t P1 n. X! w- D
if (cotacoes[1].low < cotacoes[0].low)
$ }9 I) H* V: Q; M# h{
" s/ ]* _& w+ X% W7 }3 f& Xreturn true;' [$ E% y" R7 S: S1 ?# ~
}8 X) w8 T/ v& n0 a! L4 S
// there was no position/ l3 X& m% k) v; G. G+ c9 Y0 _
return false;
7 n# m% f6 X& r7 k2 l% X3 {4 N}
) l: T4 V. Y& \- t- A; R" d1 e6 c我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
t0 b0 ?$ s! d: |到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |