启动交易模型,并构建 EA
0 P$ x8 c0 t% }; j- ^& E. H8 `" v在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。/ @! {" Q9 K" n; ]
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
! s# \& d) D3 Q以下是制定这些规则的代码。
) n: J' y! ]) i$ c: m" w# {//--- Indicator ATR(1) with EMA(8) used for the stop level...( h8 o% z4 }* o) i8 |4 V
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
* K, Z! J _0 S3 [/ u9 Eint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);8 t% ~! i" D& G/ b3 N6 k, A+ T7 F
//--- Define a variable that indicates that we have a deal...
, j/ J* h7 m. _- j* Bbool tem_tick = false;) D! U6 u: F8 {7 ^: s
//--- An auxiliary variable for opening a position
. c/ L& q& [: D# S2 x#include<Trade/Trade.mqh>
5 t3 f: [. n& L% u#include<Trade/SymbolInfo.mqh>5 p3 c# M. ?$ w7 w( I8 s
CTrade negocios;
: Q1 x( r( I9 ~: q6 g( U+ `CSymbolInfo info;
- _/ W1 {, F# B7 R//--- Define in OnInit() the use of the timer every second
; L9 y7 M) s/ y. t2 Q//--- and start CTrade$ {) c5 T+ p! D* H1 A% L: g
int OnInit()5 C5 w5 D+ A; K3 V' z' I
{
& p+ a) i. |, U1 e/ Y0 B//--- Set the fill type to keep a pending order* R, g; q w+ ^1 D+ S9 q; p7 J
//--- until it is fully filled3 [! Q: M$ u! Z2 K, _' W% J3 C0 B
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
5 T; d4 S+ i0 W+ B/ W; H2 r3 T//--- Leave the fixed deviation at it is not used on B3 exchange
C. ~: h- Y; Q/ a" lnegocios.SetDeviationInPoints(5);
9 y$ [ p: D( u. R s3 a. @//--- Define the symbol in CSymbolInfo...2 P _. `4 W7 @% E6 _0 f h0 O
info.Name(_Symbol);
( x, q* V& p" g6 _& ?//--- Set the timer...
* ^2 L( X" E: d8 VEventSetTimer(1);# k8 S. O& N. t% u3 B
//--- Set the base of the random number to have equal tests...7 _! Q- P' t" l9 b' X$ a2 J) ], n8 m) \
MathSrand(0xDEAD);
1 w* ^* o2 y3 Creturn(INIT_SUCCEEDED);
! a+ l+ w) D* f) M}% v/ K" v4 {( K2 H* d
//--- Since we set a timer, we need to destroy it in OnDeInit().1 E0 m/ _# c3 \- `6 [6 Q$ h, x
void OnDeinit(const int reason)
; @ }: Z& b# G* b. Z1 ?{
+ W0 J" i7 Y" H8 o" dEventKillTimer();
* k7 e- l0 T$ A3 p9 Q& J6 [ z% T}
5 T2 T' N" D) V5 M7 E1 |//--- The OnTick function only informs us that we have a new deal) G9 x1 k6 A7 e" u4 K( X
void OnTick(); F5 `1 P2 b, I0 Z5 m! \
{
' p: z# }7 m# w) d/ y( r" Ntem_tick = true;+ Z: I6 j9 U; K: u+ f
}
! x5 {0 U) ~8 t! D: D9 t//+------------------------------------------------------------------+" z$ @( k. f9 j f; M
//| Expert Advisor main function |8 i& o2 W) q- C$ t3 ~
//+------------------------------------------------------------------+
5 a, E. L& j8 Z# m: _2 Hvoid OnTimer()
% c: u2 q, O& Z5 B# }2 d& q{1 _' M! f; }! V5 n* ~' R0 [5 _
MqlRates cotacao[];
F- z. v8 e( ]( j9 o( M! d/ L" _& Hreturn ;
5 T- x$ B9 P m" d5 Q7 ]7 X [; ~if (negocios_autorizados == false) // are we outside the trading window?* X% d7 W% i- v3 J: y0 @
return ;
( \/ u/ u% F4 |# V& v P4 j//--- We are in the trading window, try to open a new position!) w- `/ w; l. Y: X8 p6 N
int sorteio = MathRand();
9 n' y( t8 {7 Z+ k1 J" b5 ]//--- Entry rule 1.1. L+ I, S/ ^9 i& V* V
if(sorteio == 0 || sorteio == 32767)
; ?) w8 i2 {: ]+ ^" d! h+ Sreturn ;/ l* c k* D2 q& A: I+ p
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy; @+ N# t2 n9 ^) i1 a/ }
{
r! ~- N9 a8 a+ s0 W$ d: [! R3 ^3 Ynegocios.Buy(info.LotsMin(), _Symbol);
m% s# o. `0 T9 u9 I/ d2 f}: \9 j! j- ?, o5 P
else // Draw rule 1.3 -- odd number - Sell2 Q4 O# y+ H/ q
{
! U' V" x, T- m, r% {negocios.Sell(info.LotsMin(), _Symbol);
* ~3 T6 L/ s! W J5 N, P# n}
( [' k' V8 m0 ?}5 u0 i6 C% w# ]6 R Y
//--- Check if we have a new candlestick...
/ g2 Q* L8 E0 S$ cbool tem_vela_nova(const MqlRates &rate)
3 [/ D7 ?2 E `8 { n& T{2 e$ f! n) z! K) B1 }1 H$ a
{7 d, X! i* r0 E1 p9 D6 v
ret = true;
' G4 B' o( K" e" A/ R w' f. U0 |0 _9 J: Kclose_positions = false;: h- ~, }8 R& Q. d8 E* t2 N
}8 n) L6 P. K) O W* e
else( n$ B+ X6 c3 N8 @8 b
{
! H* t. |, { \4 ]2 e* k% Tif(mdt.hour == 16)
- Y2 Q1 [ Y8 H9 p7 O& u3 Fclose_positions = (mdt.min >= 30);) G$ l* }9 G: j, J7 T
}
! M% f6 k e9 r+ A) P4 g}# D6 ^, P9 e+ T$ Y- T8 e- @" ?
return ret;5 {: `2 g7 ~7 f/ K8 ]" \. d3 _
} N, u$ m5 b2 L( [1 B1 l
//---
$ {0 L; J t6 x7 A9 fbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
( A/ Z( X2 m6 V% o{, m4 v& x1 ?5 q X# x t) w% e
if(PositionsTotal()) // Is there a position?9 X! x/ Y: w2 X
{: E _0 ]) R7 i" [8 H) d- u$ z) J
double offset[1] = { 0 };0 i) |9 ]9 U$ a. ~: H m
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?: Y& R6 R) T7 E+ M4 ]6 r9 _
&& PositionSelect(_Symbol)) // Select the existing position!
5 a( v6 }' N: Q e7 O6 y{- g _ P/ s. m
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
3 l, x: g4 p6 p i3 O. Jdouble SL = PositionGetDouble(POSITION_SL);
7 J! r) _/ \6 @9 p4 G) adouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
) Q$ J' S: I$ W& a& eif(tipo == POSITION_TYPE_BUY)2 t! y0 b4 d9 |' I# ]# ?/ X
{
8 J) |+ G. Z. x& s( s+ s. ?if (cotacoes[1].high > cotacoes[0].high)! a% Y% n9 c5 @( t0 r
{; ]* e3 d) c9 S! j
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];& ~0 [: ^/ m1 x* H: J: M! x
info.NormalizePrice(sl);
; r* E; u2 Y" N/ i9 K& w3 I6 uif (sl > SL)
8 Y4 Y y: m# R{
. j! N9 D8 {; z- w) unegocios.PositionModify(_Symbol, sl, TP);
& y! G8 Y0 _- b2 U0 Y. T# |}1 i& g: \8 _; \! E& e. ^4 N; I
}% R' f+ P' V3 `" h" ^
}3 l: \2 s" e9 G! A8 b8 F
else // tipo == POSITION_TYPE_SELL6 C' F# u3 P+ g3 U* e
{+ _$ {9 }# ], J4 h/ c
if (cotacoes[1].low < cotacoes[0].low)
1 M' A$ X$ Q3 L6 O, C{
) V. m* t# ~! v) Ureturn true;5 l8 t( }- [- T/ S& t
}
7 U3 U# T! }. V3 x% |// there was no position" B6 c: `' I7 U
return false;
) f& J7 v* C( |4 M}. C( ]9 @6 o; z& p' B. g3 D {
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
% \5 }' V3 Q4 W% }; ^, m到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |