启动交易模型,并构建 EA& _- H D1 U* w, c( J* L
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。) i- r- z. u1 x
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
$ F& b8 y7 q( v$ _9 O# u4 z8 s$ p以下是制定这些规则的代码。+ z* q; d4 f# ~4 q: X9 q
//--- Indicator ATR(1) with EMA(8) used for the stop level...
" x' ?+ y3 g* w, u( X9 ^int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);/ T8 p% m2 R& S& G
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
+ v. k$ `8 @- e" M" h. w5 O7 h; p+ E' g//--- Define a variable that indicates that we have a deal.../ c0 W; v- o% W3 ]1 x% M; W
bool tem_tick = false;1 R$ j0 K' w$ U" B2 Z$ ? I: X& L
//--- An auxiliary variable for opening a position2 h4 [2 F6 q/ J( i9 \# V. ?
#include<Trade/Trade.mqh>7 T V, |( U! T
#include<Trade/SymbolInfo.mqh>
6 N! Q) i, Q C8 j& W' y3 j H' BCTrade negocios;3 I' r% P {" @$ o) {
CSymbolInfo info;
/ A9 j0 {/ }) E$ q//--- Define in OnInit() the use of the timer every second
% H+ r& y+ o7 t: |* H, |( W/ g//--- and start CTrade
4 V8 g# S1 W6 {& w$ Yint OnInit()! |* t6 o5 _ X; ~
{
! }4 I9 O j* G- R* B//--- Set the fill type to keep a pending order3 L4 C! C! l; h% j3 l+ ]. l1 R
//--- until it is fully filled
0 Y" j0 I1 s. G& B/ qnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
! i4 j, T0 ~" S% t$ v//--- Leave the fixed deviation at it is not used on B3 exchange- D) h6 ]2 b. F( P) T
negocios.SetDeviationInPoints(5);
; E. G2 k% L. e4 _7 c, q; U//--- Define the symbol in CSymbolInfo...
, o1 d6 A+ |' q) |. e6 ^- ?info.Name(_Symbol);6 G* s1 l- `( S1 ]
//--- Set the timer...4 C C% f! o2 u; ?3 M1 M4 ~
EventSetTimer(1);, u8 T& Q; ]& Q" ^ _7 [- e* M, ?9 r
//--- Set the base of the random number to have equal tests...# v7 D7 ?; J ?
MathSrand(0xDEAD);- C$ A( C/ J7 g5 p. @+ x
return(INIT_SUCCEEDED);& G7 r' Z+ W* F9 Z, j* d
}
1 c; C3 G2 d7 `//--- Since we set a timer, we need to destroy it in OnDeInit().
4 t) K1 `3 p: i$ avoid OnDeinit(const int reason)" y, B1 Q. I/ x$ r) T) o k
{
- q/ }6 E- Y+ \6 s _1 hEventKillTimer();
: g7 o3 F9 A1 E}
- }. q- y, S( l" p//--- The OnTick function only informs us that we have a new deal
$ d7 I$ w s! Q; [' Qvoid OnTick()
- ]. |% a4 X/ o8 L; x: G{
9 b) T& I/ [0 |& N( y: W/ C1 Atem_tick = true;% [* H/ \4 G3 X' o9 K- q" M1 M9 A
}
^. t# \6 N* a2 T% @7 c//+------------------------------------------------------------------+
E9 `: N2 D3 z( j//| Expert Advisor main function |
4 s6 z) [$ G1 |( l//+------------------------------------------------------------------+5 B- x+ p) n9 v, _9 ~) M
void OnTimer()
9 v: `8 N$ F" |{1 Y4 O( u- L+ s% p2 c6 Z( R
MqlRates cotacao[];
4 \, |; y+ {( xreturn ;6 Z; ?' L1 W; M1 _/ T, K6 o
if (negocios_autorizados == false) // are we outside the trading window?% [7 `0 i9 y+ |: `+ t
return ;
( A6 Z+ V ^% Z//--- We are in the trading window, try to open a new position!# d/ P# Q# }( z+ ~
int sorteio = MathRand();, \& o [. {5 y+ p5 g g& D7 ]
//--- Entry rule 1.1. b/ k: M" w. p$ |
if(sorteio == 0 || sorteio == 32767)
" e& M% G: I( d X) s: g& s8 Ireturn ;2 q3 Z4 ?: d1 {% M: c w4 I7 A& D
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
3 ~* t) l' l# g8 O8 P{
8 R% e2 O' M0 @: {2 @3 knegocios.Buy(info.LotsMin(), _Symbol);
& x. l5 ]# Y" k9 }( i4 q}
' d! F( S+ t4 A. W6 Relse // Draw rule 1.3 -- odd number - Sell6 p) a5 V+ b! m2 _9 T; u5 m; [( g
{
- _! \, a9 }- ~' r' j$ I) nnegocios.Sell(info.LotsMin(), _Symbol);
$ d) m1 u# c/ M; Y* t3 S}
6 Q4 c7 ^0 |6 U. o- R}- a0 P4 k9 U; M( ]( g ^7 Y
//--- Check if we have a new candlestick...
4 {& L- O9 n' ]/ }' q( h: ~bool tem_vela_nova(const MqlRates &rate)
% [; S/ i3 S: P9 y4 M' o{
7 V/ K6 x. G. y{
1 ]- I! x1 D% u. J qret = true;, h- \ q1 z$ _& o* w1 X
close_positions = false;& A* [' z, b8 ~7 Q/ d
}( \2 Y6 m1 R( i# R3 w$ i" k$ |5 a
else% f4 O" A; A! T3 Y* @9 o! h6 E0 p
{
' E7 l, a: A5 o1 @if(mdt.hour == 16)
3 r: Z& {% R& J# G2 Kclose_positions = (mdt.min >= 30);0 I* i, `5 x5 F) ]6 q8 `$ m+ r) I
}
8 x% F" Z& P4 F* R}) O" u H. `* c& A6 ]/ S
return ret;
1 |# X" u' [1 X' q}" y/ Y1 \ f8 D/ g+ q3 G1 ]7 u$ r9 w- K
//---- m; U7 E7 P. w% ~: Q
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
% d5 |* N& V: F% c# V r{/ n' d% e [) \ S4 c9 s0 q$ z A) m
if(PositionsTotal()) // Is there a position?: A* V- U+ F# X9 l/ j+ x
{4 O8 q" R+ m1 ~ F5 c
double offset[1] = { 0 };
/ x2 V% l) g. k; j4 M3 d" Gif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?) O I f0 }# s
&& PositionSelect(_Symbol)) // Select the existing position!
$ e& T1 {5 v4 r/ k{2 R& x+ `+ @, a$ P) o( u4 t
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
5 @3 S) _2 q3 xdouble SL = PositionGetDouble(POSITION_SL);2 P* @7 f( L1 `" t! h7 H4 ]/ D
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
% s8 P0 Z6 K/ X. ]( x0 Jif(tipo == POSITION_TYPE_BUY)$ q4 I5 {) R* E3 C' ?
{
% t1 _- ~) N; X2 Pif (cotacoes[1].high > cotacoes[0].high)
* D% f- l. f7 ?5 o+ H2 h$ S1 @{: Z% Z5 H+ q$ M5 {) C# t
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
, U' r1 ]; ~( o' a' m4 iinfo.NormalizePrice(sl);
( Y4 s9 r1 }! h) f7 rif (sl > SL)
7 M' ^' p' G0 ^, T! `/ _{! z ~4 L# f/ P( W
negocios.PositionModify(_Symbol, sl, TP);9 `% n, ~, I- a" y
}
. |6 s7 ]! E. _# s}- u6 m" R7 p i- ?
}
, ?5 e- C. E E1 l5 Z& helse // tipo == POSITION_TYPE_SELL0 S# j8 k0 X, O! g0 Q. Y
{$ f8 r3 @; m5 s' H& x1 d ^
if (cotacoes[1].low < cotacoes[0].low); D3 W$ Z2 u; J0 ]! i
{
% q& w1 T# q) q5 z& ereturn true;9 o5 ~0 q4 d" D$ S: C
} u7 J F+ H( v8 J6 c$ E, u& b8 M8 |( F
// there was no position
3 j: E1 Y: u2 v' W7 Q1 |; freturn false;
H. r5 `8 w* K& v2 Y) Y: q4 \}/ I8 R0 ?" n& U/ g3 Y* F) h' h
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。+ h8 H, ?5 S2 H3 v8 `
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |