启动交易模型,并构建 EA
% f2 Q% a: ]8 R: b" U# x在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
6 P' I" a6 y( B为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
4 v& d$ G7 L5 c2 U; f/ e$ W( M+ d以下是制定这些规则的代码。. ~2 F/ [, ~7 O* n, s. z
//--- Indicator ATR(1) with EMA(8) used for the stop level...
) h9 ]3 Q7 t A; E2 X: Jint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);7 ?. J5 `3 b* \0 K
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
" y0 t" h# u/ D+ h2 O! q3 g//--- Define a variable that indicates that we have a deal...8 ?- @8 g. e# l% x
bool tem_tick = false;1 J" l, x% ^4 }0 c( O
//--- An auxiliary variable for opening a position+ D: p" p4 ]% B3 I. Q
#include<Trade/Trade.mqh>
; u1 o2 G: y+ b$ m( q% Z#include<Trade/SymbolInfo.mqh>
3 J9 G4 f+ u/ p# [CTrade negocios;! K% [) i! g' i
CSymbolInfo info;- k R1 k* c2 K
//--- Define in OnInit() the use of the timer every second$ V* w2 m+ K! a1 R& T! p
//--- and start CTrade
* o8 c% c0 {8 V" ]2 ?- iint OnInit()
3 W1 o" Q# S2 _+ o# x. ^{
0 J" L, Q" }* _6 `//--- Set the fill type to keep a pending order
# l$ e5 }- s, v4 M//--- until it is fully filled
7 @" Y/ {: B( a# B8 X' O- E9 _# H/ unegocios.SetTypeFilling(ORDER_FILLING_RETURN);: G, e0 P1 s7 V
//--- Leave the fixed deviation at it is not used on B3 exchange
S6 I( p3 V) R1 ~1 knegocios.SetDeviationInPoints(5);, Q2 y' a4 G+ ?* a
//--- Define the symbol in CSymbolInfo...
# u" e* |) A4 m. A N( ^! Kinfo.Name(_Symbol);
6 h* B9 I: Q; L. d3 @! D' u//--- Set the timer...8 _, c/ I# p/ U6 {- n: q9 f
EventSetTimer(1);6 a4 G m; [& _4 [( L
//--- Set the base of the random number to have equal tests.../ m( N4 G0 r1 n4 O, h) U) V$ l' C
MathSrand(0xDEAD);
, m4 [" Y5 G4 a2 d/ Q& g, z. breturn(INIT_SUCCEEDED);& f3 m5 G1 g5 ]! w6 Q" {+ T
}
" g% \- Y) x7 D* ~//--- Since we set a timer, we need to destroy it in OnDeInit().; ]0 l( u, A* `, K6 H: Z" H( ?
void OnDeinit(const int reason)
g+ ^+ |5 D, |2 Q2 T# h" P{
* t6 D; h- N3 f9 U. }* TEventKillTimer();
* P; H. b" S0 P- L; o( F' i}; ]2 b, [$ _. N9 O3 f
//--- The OnTick function only informs us that we have a new deal9 m: l8 Q7 M0 d6 y2 p/ T2 a
void OnTick()
; `3 Y% T& W6 D8 O K# U! x{
+ V* s- e$ i+ |. Ktem_tick = true;
& n5 a) ~0 o) {4 @: B4 ~/ m}
" B' x: p7 c& h: F! E7 d//+------------------------------------------------------------------+3 a& G+ V$ ^: _; _8 Q" O p* w* m
//| Expert Advisor main function |
: A. t U8 B t; f//+------------------------------------------------------------------+
9 Q; ~- Q: h( x qvoid OnTimer()4 V- H2 K8 _* m6 W% n) y9 j& {* ~
{
- v# W: d! F6 [% a9 }3 u! s: H- AMqlRates cotacao[];3 M1 d3 K. t. _. A% m
return ;. X3 i, z" @5 c( `7 @& p1 v, D d6 r
if (negocios_autorizados == false) // are we outside the trading window?7 o3 A& c* I( ?3 d8 l1 m
return ;
2 Z7 c; C z5 F1 U6 Y//--- We are in the trading window, try to open a new position!
' K$ F$ {$ m/ L. {, J8 B. ]int sorteio = MathRand();2 }. j, L0 | H0 E
//--- Entry rule 1.1
" S& t0 h/ @% G lif(sorteio == 0 || sorteio == 32767)
5 d5 u5 T+ Y# t9 Yreturn ;
+ j: }/ b; y: x% A3 uif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
. i( J- D6 R: u1 x) h0 R+ R# ]" ^* B- X{
$ J4 u! [5 L" k+ ~2 s& Qnegocios.Buy(info.LotsMin(), _Symbol);
8 ?) j% K3 @) ^7 ?" M}
$ N3 ]- Z/ D: u5 ]) T, ielse // Draw rule 1.3 -- odd number - Sell/ A; p5 [+ b0 Y
{9 ]" E* B$ o; B! c3 T; G# ]
negocios.Sell(info.LotsMin(), _Symbol);
0 [+ l$ Z6 J: S}% i/ f3 M, W' n( j( w
}
: U# E! c, h% G3 v//--- Check if we have a new candlestick...* y# M5 l, V5 o: c( U
bool tem_vela_nova(const MqlRates &rate)
4 o1 x) w1 e+ h4 T( f% i g( s{' i& p$ a0 q) M& D$ ^
{
1 `+ i0 u& r% c3 x$ nret = true;
1 J9 P" Q5 O! V; ~$ Kclose_positions = false;2 x8 G' l/ Y" C. ^" }% `
}- B) B6 {4 ?3 r+ _
else
0 i) a" S+ \5 d0 E N! \! y4 a1 T{7 i4 I3 }+ F" p! \6 L3 p
if(mdt.hour == 16), p# \; R$ J& i. ?* q- B
close_positions = (mdt.min >= 30);
2 M9 `- `$ [& F2 o- O* E9 H}
$ u& _% D v; T9 m}
. B) y( P- w+ ?8 Q' b7 j) Nreturn ret;3 ]) Y% `+ S1 i1 T% Q! i3 E4 ~1 R
}4 B3 k+ o9 y( { v
//---
& u; ?* `6 n dbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
% x: M' x B: u8 [/ S8 G& R{) x1 `: t. \. a
if(PositionsTotal()) // Is there a position?
6 f1 j3 A4 }& F8 t) r2 \; f{
- l1 }) ^) S; W$ k+ I, ~) pdouble offset[1] = { 0 };
. C( ?1 P+ S, W# H) bif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
- s2 z" k* o% | }+ r&& PositionSelect(_Symbol)) // Select the existing position!
. {( r2 `2 J* p Y+ R/ N/ G4 Z{$ I$ m3 j7 {9 A, x/ Q M! [
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);2 R1 [4 H0 m7 y
double SL = PositionGetDouble(POSITION_SL);
3 u3 k/ R' ^) s8 i2 H* ] _0 Jdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));. b2 G' Q7 M+ U$ z% w
if(tipo == POSITION_TYPE_BUY): |) @7 }% t: ?# Y% e
{5 N$ V/ H; _1 E
if (cotacoes[1].high > cotacoes[0].high)( R/ B3 |" f% ~- J
{
& h0 G* Z4 J& Jdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
: ^+ w1 n% c, ?, i/ Y" y+ C, d6 \info.NormalizePrice(sl);& g% ^5 ]9 ]9 s
if (sl > SL)
2 O& r" ~ T$ ~1 j+ l{- N6 h/ q& q! e# q
negocios.PositionModify(_Symbol, sl, TP);( r2 ?4 k+ R- w5 ] s
}
* e8 ]) }1 M: C: u' V7 J6 Z" j' F$ N5 W}
' X4 C- C( f z( B( U- O}5 k$ N; h. x1 Q D' M0 G
else // tipo == POSITION_TYPE_SELL
6 ?! L- O0 V1 t, a, {/ L% \{6 X* I2 j6 r6 U. G& ?( V; G
if (cotacoes[1].low < cotacoes[0].low)
& i9 T, [; v. C{8 x' n4 Z' ? i z& e5 E' c! w
return true;- b( w. r5 s5 i$ w% X
}; J3 h! B/ m* P3 A- E, |2 T
// there was no position
Y5 F% |) c& }5 Ereturn false;5 J0 ?7 G. Z6 ]. ~
}
) k. B9 H7 I3 Y `我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
. h6 F; ^7 e4 j5 J* o, o# `到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |