启动交易模型,并构建 EA
% o6 M; f# W) c4 `) ^7 F4 n在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。" c# d( O2 T9 `' K
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。2 v" |, }8 f! d& ?" m* T
以下是制定这些规则的代码。/ F/ E5 D, A0 c: `
//--- Indicator ATR(1) with EMA(8) used for the stop level...4 E& h* @# z S# P; ]* U# ~
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
- a: u3 N1 F- z$ C. t) h5 |4 eint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
+ R: n" @: T9 O' @( f//--- Define a variable that indicates that we have a deal...9 `7 m7 V6 W/ q+ p/ q. L
bool tem_tick = false;3 p- s3 g: _* P H! G/ F" p. m! Q
//--- An auxiliary variable for opening a position! j$ d' G3 p+ @0 w2 I! G/ f& G
#include<Trade/Trade.mqh>
5 \( h l' M) W$ e- Z#include<Trade/SymbolInfo.mqh>
y1 u- O$ l" RCTrade negocios; c: ^+ |" s5 d# O! t: v( O7 ]! u2 O
CSymbolInfo info;
g; Q5 _. `: w. h4 p" I& D8 B7 u//--- Define in OnInit() the use of the timer every second) b: k$ y3 R; q
//--- and start CTrade
9 g& V1 Y+ c6 u/ t n+ L0 u7 _int OnInit()
, e& e5 Z! T/ ]- X6 _- P{# p$ U7 k( d8 u# `- z& {
//--- Set the fill type to keep a pending order
! n0 S) {9 G1 b v ^! q//--- until it is fully filled
: M; {5 X5 @3 T0 b. Nnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
# d) h& Q- i0 C0 b0 @" D//--- Leave the fixed deviation at it is not used on B3 exchange' T4 G1 ]0 A! M) l
negocios.SetDeviationInPoints(5);
) v6 F6 V! o4 H+ l( P//--- Define the symbol in CSymbolInfo...* t/ j/ y8 l$ I$ i$ A5 o
info.Name(_Symbol);9 o' |. }# k0 s
//--- Set the timer...% J8 P$ |" p6 b, @! w1 H0 S. ^
EventSetTimer(1);
& c- U& n8 ?- i, K//--- Set the base of the random number to have equal tests...' b3 P5 x9 e: r4 z8 E% }
MathSrand(0xDEAD);# @! K- M7 m7 D! Q
return(INIT_SUCCEEDED);
) w. \* \7 H9 {2 |2 e! u! Q}
- N5 [4 }1 q4 l//--- Since we set a timer, we need to destroy it in OnDeInit().; t8 z: v* t6 v6 o
void OnDeinit(const int reason)2 w: c7 ?; V: U+ r( u% D& f
{# h5 }; m+ r1 M& @: n$ `. S
EventKillTimer();7 W: k2 ^! F6 v7 N/ ~
}
2 H1 x6 P8 g/ w3 f//--- The OnTick function only informs us that we have a new deal
2 j- b: _$ N* dvoid OnTick()
8 Z4 P. T* K: K{+ y" I+ C! r. I
tem_tick = true;
: {" r6 T7 t/ w7 o0 m. k. x/ f ]}2 O4 ]* m+ ?' b: j. h: Q0 X8 a
//+------------------------------------------------------------------+
: U; a: W8 T5 A' B1 i' T9 c8 s//| Expert Advisor main function | J4 }( s% ^! l# U% Y/ r
//+------------------------------------------------------------------+
+ I; y. o! j7 K1 k. b8 mvoid OnTimer()
@9 E# I6 f1 v$ L, H1 x) K' w{ }5 ~) } [8 K% p+ X
MqlRates cotacao[];& ~7 b" M' X" l( m( [5 r) M
return ;! F" X5 t2 W; M, p0 U
if (negocios_autorizados == false) // are we outside the trading window?
1 L6 C' r/ x Nreturn ;- E. j% a4 Y* A, l9 Z" l4 n& d2 \
//--- We are in the trading window, try to open a new position!7 C8 `1 J1 a2 f# \$ R. t
int sorteio = MathRand();
7 \0 B$ v8 D7 s4 g r* K//--- Entry rule 1.1
! K% l) |$ S* @( d+ A, ]if(sorteio == 0 || sorteio == 32767)1 E' M0 f# e' \. r
return ;
. j( [$ {6 [- P% j- `if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
6 Q& M3 K3 s& w3 S9 G1 m6 |{, ~7 ~1 M! ?6 Z/ A" b! t+ X
negocios.Buy(info.LotsMin(), _Symbol);
& E" E1 e( a6 u- o, ~}4 n* c- C) x, H* w0 R8 L& ?% i
else // Draw rule 1.3 -- odd number - Sell$ ~, T5 r+ M3 D
{. \' ~# J1 l$ ~3 p0 b3 M }" @
negocios.Sell(info.LotsMin(), _Symbol);) {5 S" `9 Y/ f0 P$ A; h, }1 S
}* Q( u' E/ E6 a% p H: ]2 n0 c; x# h
}6 r0 G' h1 h. r! c0 ^; ]6 x
//--- Check if we have a new candlestick...( N4 h7 o4 }) I5 _) g9 c4 M
bool tem_vela_nova(const MqlRates &rate)
2 k% |9 g: L" B3 f3 F{. ~6 D: j: p$ H& R* ?
{
9 Q* L9 E5 u+ ]4 c6 j$ ^ret = true;8 O. i2 i! p4 a5 ~0 S- C& x
close_positions = false;( d# G& p9 c2 Y& B( I! n
}! Y) g) E# N6 Z. H/ |/ Z/ u8 x
else; ~' o8 d* j$ z: z/ z' w
{
7 p" S t4 R2 [) @$ n# Pif(mdt.hour == 16)& F: x7 y9 q' }% u
close_positions = (mdt.min >= 30);
% _0 C" |+ h+ n8 w: Z}
$ f- H1 \8 Y( y3 r1 f: O0 |8 Q}9 J, Z& F9 V$ @- C. k1 p2 ~
return ret;8 I$ A5 X! o1 y, N5 Y) X" F
}$ r9 \: Z; C8 E9 f4 ?- S0 K; }. Y
//---: X+ s* ]) S9 W% O" e
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
: N" g t7 A. A. h6 ^{9 e- f5 w+ E- g1 B
if(PositionsTotal()) // Is there a position?
0 I! ?' ~& f3 }8 O; ]" [' p' k7 Y{1 x6 q/ H% d: r6 R( H
double offset[1] = { 0 };
& Y' P8 F8 b1 K- ^& U$ G$ A5 Mif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?2 e2 S4 r; I3 Z3 u3 c+ g
&& PositionSelect(_Symbol)) // Select the existing position!6 i/ ^% y: `, M5 q! ]
{
/ _9 b. r% v8 R# N3 i* r) h. bENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
6 I: ?/ w. q! Q, v0 a4 bdouble SL = PositionGetDouble(POSITION_SL);
5 _* e' H. M" ^3 H: O1 b# ^0 odouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
. h; B: D1 b" R% Uif(tipo == POSITION_TYPE_BUY)
5 m5 i. Z m3 s0 M+ s! z7 u{. ?2 m$ ?7 i# s; z9 l1 I! D
if (cotacoes[1].high > cotacoes[0].high)7 ~ D5 X. B4 d" Y0 ?
{
1 m; k# i) b N) c# w7 s1 Ddouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];- |" k' g* @! A, r4 ~# K
info.NormalizePrice(sl);
( t0 x) ^8 K* [! N0 d' n1 P: Cif (sl > SL); M- l! }& F+ F' v8 F
{, A4 c3 r2 s' L. u/ L! P' _
negocios.PositionModify(_Symbol, sl, TP);
& B3 O4 U8 n) c$ K s}% p: y% F9 J; \$ y- ^0 [
}4 O# W) X* S3 r) O- ^
} ]0 i* d" W$ A+ d3 C9 n
else // tipo == POSITION_TYPE_SELL" H. C3 H( q" G( l' A" H
{; i1 y/ ^+ M- O; i( i5 m
if (cotacoes[1].low < cotacoes[0].low)
% J0 U" h4 D! {{
+ o A0 R- ^$ N: q, |6 l3 m ~return true;, w, y, }( B$ a" O- c% u# x8 Q
}- ~) F- y* V$ w9 k& D1 q: m. a" m
// there was no position
5 ]3 l7 a' z- J4 P; V5 Creturn false;- o- Z9 [& Z! D3 C! b
}
- z- [0 B9 O; \4 v# U4 R9 U5 h我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
9 |8 x$ A; I# m( o2 {到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |