启动交易模型,并构建 EA( u% |! b: x8 B+ i! N$ f
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
* @; ]( J$ L0 S- y为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。4 m7 S, D$ ]4 P. y! k1 v! a
以下是制定这些规则的代码。
/ y: l! c E5 K//--- Indicator ATR(1) with EMA(8) used for the stop level...) `$ H- s& G2 `* y* n
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);9 y% e/ D9 c) i/ g& q9 V* P
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);' N* N# O* Q+ }; T) P
//--- Define a variable that indicates that we have a deal...) w6 u* ~! `* ?* Q
bool tem_tick = false;
- O2 R" ]- A1 ~4 L. T/ J0 R//--- An auxiliary variable for opening a position8 b& r ?9 U" D# L+ W; ~1 D! d
#include<Trade/Trade.mqh>
* d6 |' p9 s4 S& J#include<Trade/SymbolInfo.mqh>
9 N% [+ U, G5 K7 H! ACTrade negocios;
+ |* Z) [( T* S& I1 ~+ G2 ?( q& XCSymbolInfo info;; A- A7 j7 |3 L( h
//--- Define in OnInit() the use of the timer every second' i6 n; C# c1 V7 q |+ G- w. G
//--- and start CTrade
$ x) r3 o- C& z. ^9 [int OnInit()
- J" A$ O4 e2 x# u6 S g{
& L, {& L7 l3 b$ ]//--- Set the fill type to keep a pending order$ V8 p/ O) M( O! {
//--- until it is fully filled
* p6 w2 L% l7 K Vnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
/ u" Y8 m& a' V2 P//--- Leave the fixed deviation at it is not used on B3 exchange: l2 M9 B: C) q/ A" [% F
negocios.SetDeviationInPoints(5);
; ~' [: a0 u6 o6 R- C. `4 m//--- Define the symbol in CSymbolInfo...! Z: E& q' k, p
info.Name(_Symbol);
( v, B1 |' x9 e2 E0 }# E//--- Set the timer...0 y! C4 t( v: h& \4 Q3 \1 A( i
EventSetTimer(1);% E" v: K u2 [8 {8 F
//--- Set the base of the random number to have equal tests...: _: W# b$ F5 j: r7 h
MathSrand(0xDEAD);- c7 n5 z* }" c8 x$ I ~
return(INIT_SUCCEEDED);
; n! f# l5 l1 W. q. W- [}) }# b" @4 J3 r6 P7 I: h
//--- Since we set a timer, we need to destroy it in OnDeInit().
7 i2 U4 p6 e1 G. X6 Z( y9 a3 Vvoid OnDeinit(const int reason)
$ }# W4 V1 ~+ r, f{
! O& K8 ?0 d0 b0 F0 ^EventKillTimer();9 q: _0 [7 ]$ y0 }
}
s* v J$ x |0 D& r; h% o//--- The OnTick function only informs us that we have a new deal: Z# f' Q- _# S1 }
void OnTick()
' \9 O6 e2 I! Y0 x) F/ y- b{
8 K2 U' ~; i0 v0 \7 R, G) K# C7 R' t3 i' \tem_tick = true;
6 Z1 J/ h1 N1 L: r: I5 z; @}
6 Y0 A6 J% Q: e) \# K6 Z4 Y//+------------------------------------------------------------------+- g; `3 G2 w" U: X; k! v
//| Expert Advisor main function |
& s7 C) `, ^' k! v% r( z) Z7 |//+------------------------------------------------------------------+0 ^ u$ ?4 b" t9 l* Y3 x& T
void OnTimer()
, x+ h% x7 {3 Z L. ]3 n( ~{
8 v/ [& @6 I) I9 N8 y6 V3 dMqlRates cotacao[];
+ J' K i, h' G1 dreturn ;
" q |8 a$ a% l X, ~* iif (negocios_autorizados == false) // are we outside the trading window?( t" v7 {' T7 H: o3 w& m
return ;
; T* j1 l; J; ?+ w/ }( @8 K8 W//--- We are in the trading window, try to open a new position!
* y5 `7 N" i; U! L% e5 Pint sorteio = MathRand();4 z. J) C6 l4 K6 S
//--- Entry rule 1.1. T7 Z! t# X/ `/ W* `
if(sorteio == 0 || sorteio == 32767)
/ {' D0 @- E4 n: [- {5 Ureturn ;
# J( J* l# G) i, F7 X% {if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
5 j f4 x2 @7 ~/ C6 ?" C{* [, N* G/ g2 s, B
negocios.Buy(info.LotsMin(), _Symbol);
& W( X' C! C1 c! S! T5 ]}5 J( l1 j/ N. Z/ L, \5 T
else // Draw rule 1.3 -- odd number - Sell" q2 i/ b9 B# o% q$ m5 m" y! ]
{
, z8 v$ ^ ]6 Z; j" _' {negocios.Sell(info.LotsMin(), _Symbol);
; c- p( p8 p" j+ ?& [}
6 V" j! i/ {" q% b+ A4 g4 r7 `2 z}0 J4 ?/ p$ V+ v7 B/ H
//--- Check if we have a new candlestick...
) p3 \# a, _7 \% |$ n2 `4 hbool tem_vela_nova(const MqlRates &rate)2 g/ r2 z# I% i6 T3 |( p) `* V
{
# a" Y" T- M0 T{ H) R! p/ E4 b5 p- [
ret = true;# T D: T# X2 P0 U, F S6 u
close_positions = false;
1 z- n2 t, A( |" p: y. ~7 w}
" f8 E, j! `, ?/ D! D0 Celse
# s5 u" A" V1 h/ P m/ E{
. o" Z1 w* u1 p% X; Fif(mdt.hour == 16)& R5 N' ^1 K1 Z2 g( h
close_positions = (mdt.min >= 30);
- k9 s; j. L; Z& u% X}
) |1 Z2 o4 W/ S/ _$ a) C}; M/ b* @$ p% N
return ret;- F+ O0 P$ F. c, x# l2 q
}
8 f3 b: [9 Q! ` Y$ V6 B/ s# O0 |//---5 k, A8 ^( d X9 r% L3 b' W
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])& I% {* ^7 w3 L! U
{9 z7 D6 Z( B |$ ]- |
if(PositionsTotal()) // Is there a position?
/ ^ @; b' b& \& K& b* s$ J{- e$ F6 G2 M4 y$ A) e4 c, }
double offset[1] = { 0 };
- K) }/ T. Y5 @& @/ w; eif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?" x6 i2 Y: ]/ x6 s l5 c
&& PositionSelect(_Symbol)) // Select the existing position!0 c9 [9 [1 r/ k1 S- E* _- b- ^* l
{
8 X+ U4 a$ b. n+ J o9 E+ Y5 VENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
$ S4 i. c4 F* T! V. H+ R6 \double SL = PositionGetDouble(POSITION_SL);0 O( o) ~6 T1 s( W; z4 j
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
$ |% W' G, W+ E1 ?+ V6 Nif(tipo == POSITION_TYPE_BUY)6 s, C% \3 _, g' K7 ^; y, d
{1 A) A; s: `% U2 B2 @% T
if (cotacoes[1].high > cotacoes[0].high)
# v* R; V3 [* G7 m/ x4 b, e" {2 s{
3 j/ A( u* l" ~: k- n' E% Mdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
! N. j. l$ b' O6 a; g% N# W. h4 Rinfo.NormalizePrice(sl);0 w4 X+ y( S$ S1 C( K; o7 |- u
if (sl > SL)
d+ e( B+ _, p b) S{
9 `7 L# n0 n9 Onegocios.PositionModify(_Symbol, sl, TP);/ L" v1 \% t& ~
}
# W- [$ e& e- E7 ~0 m, _4 a}
6 b8 s% @% m9 G) [. O$ p. V- \}. u) `- h1 q2 r" j W+ M9 C" D h
else // tipo == POSITION_TYPE_SELL
" j# j0 @8 o! k* x/ x# {{
4 d2 U' Y/ B9 e3 n* Vif (cotacoes[1].low < cotacoes[0].low)' ~6 Z6 }$ w( k5 A: q! x
{' [5 V+ S2 |5 w. ~. N- O N3 v
return true;
( a) D0 _5 k1 f}
- k" _4 P9 `$ Z: M// there was no position
. e+ l8 v9 ~$ f9 v+ e [return false;7 t0 {* o* i+ E3 z
}
: s+ o7 ?$ L; ~) [. y" o& z. ^/ ?我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。0 a C% i; {0 ~. ~
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |