启动交易模型,并构建 EA% U+ z, K7 R, l; ]- V( ~
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。0 Y! Z. q$ P& h0 y( Q# R
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。2 W% f& j4 p, \% K
以下是制定这些规则的代码。- J5 b, s. `& s3 f) _* ^6 ^
//--- Indicator ATR(1) with EMA(8) used for the stop level...
a' {! r! G4 Z+ ~3 o# n+ e6 |int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);& T- N8 x3 ^: j# [* x
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);4 e4 u- x! j) j6 j( i4 B
//--- Define a variable that indicates that we have a deal...& @4 \2 ^ z6 z3 z6 u
bool tem_tick = false; c/ N0 A+ ]' s4 {5 I
//--- An auxiliary variable for opening a position2 A7 N8 ]% F9 N% W2 s1 D5 ~
#include<Trade/Trade.mqh>
% J0 ^1 }4 j1 t6 T#include<Trade/SymbolInfo.mqh>: C0 ~ [, m4 |' F& L
CTrade negocios;0 U7 g6 B$ |6 ~1 ]3 ` W
CSymbolInfo info;+ O* w2 Z6 L* T/ l" B% ]/ D6 R, S
//--- Define in OnInit() the use of the timer every second
! s8 y3 @ a% ?# `9 g& Y5 x//--- and start CTrade4 w4 f% k6 \' ~; Q) S- O4 j
int OnInit()$ L* _* T1 m% `1 A4 t# m
{
; b7 n3 H3 x- ~$ @- k0 @//--- Set the fill type to keep a pending order/ W. U0 W0 b& c3 q; D; ?/ O
//--- until it is fully filled L' f: T: S1 P8 B
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
P0 g% k* a7 R# F! F$ N//--- Leave the fixed deviation at it is not used on B3 exchange
; V( x: X2 k+ {+ |) Y1 g% Unegocios.SetDeviationInPoints(5);
, l' Z; N6 r% f4 k0 O//--- Define the symbol in CSymbolInfo...5 d( c! O* V" }$ M
info.Name(_Symbol);
* h* q- J; q# @4 E$ v//--- Set the timer...
3 p X, q# t* v2 X+ \% MEventSetTimer(1);
5 O: W- W! U1 g1 X; K//--- Set the base of the random number to have equal tests...
6 z* m$ v2 X, P* u9 x# hMathSrand(0xDEAD);
/ n" ?! ^* @$ S8 g9 H% Areturn(INIT_SUCCEEDED);
& q6 k/ u% B0 _9 ?2 I& u$ L0 q}$ @ s2 L5 E1 c8 ]
//--- Since we set a timer, we need to destroy it in OnDeInit().
2 p8 C2 ^ c& R; ~0 L, Vvoid OnDeinit(const int reason)- K, \/ z7 F6 @4 h# B9 {6 X1 {- X
{7 s, Q+ A% ^ D9 Q' b7 x
EventKillTimer();# W1 {: n4 b+ ^% s% v! r- x
}
- f6 g9 X9 k9 ~//--- The OnTick function only informs us that we have a new deal
( j5 u6 d {% N: n. \) A ]void OnTick()
* i. H5 U Y# {- O{8 j1 Z4 s7 \- ?
tem_tick = true;
. {6 u$ v. F' b0 z1 \% y( a# ?}
! ], U! j' k- f0 c6 v, r5 V//+------------------------------------------------------------------+
' w& S+ {$ C* z" N( |' R//| Expert Advisor main function |7 X/ E/ S' H( |1 H E. i% w
//+------------------------------------------------------------------+7 \9 V/ ~" G" v9 o% g
void OnTimer()
8 D% i. p+ p q3 M# b2 @$ Y{
' ~- M0 e z" \, ^+ W ]MqlRates cotacao[];
; Z }5 p: V( q( A/ Y ?return ;# w, V3 H5 `* o9 y0 n. K/ y% `6 d
if (negocios_autorizados == false) // are we outside the trading window?
1 g/ |3 Q T- ]( a9 jreturn ;0 W; z( n& U% f% J6 F
//--- We are in the trading window, try to open a new position!
* ^) X' W4 O. i0 ~int sorteio = MathRand();
+ K( B/ f, j2 t# K4 o `. E/ _//--- Entry rule 1.1: E8 e3 x$ `# V. y/ ]! a
if(sorteio == 0 || sorteio == 32767)7 q+ D j* { p- d& |2 D1 v
return ;; n* M$ D2 ]8 @3 V- f0 S) I; @9 X
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
9 O: z- h( `! ~; p, V7 h# o- a$ j- E! a{
5 Z F9 @. O! L3 o, H Onegocios.Buy(info.LotsMin(), _Symbol);
1 u$ T- P% ^* A7 i: `}; e) u1 o& E0 `8 ]* N
else // Draw rule 1.3 -- odd number - Sell
6 A1 |6 D" P; \{
: } ~$ _3 F! J' Q! c/ wnegocios.Sell(info.LotsMin(), _Symbol);
$ f2 P8 K$ P; _) j}
5 K& m A! Y1 V5 ~& h; ?7 V) N8 L, U}
7 R% D" B' C C0 m//--- Check if we have a new candlestick...
. b' E- n$ R4 \# k' W! k% O+ Mbool tem_vela_nova(const MqlRates &rate)+ M N' C) T" ?
{
6 f- ^: y2 F) J5 B3 Y8 V3 n& A0 U6 B7 s{
3 I, u7 r& f7 _4 ]; K7 G: h3 r: [ret = true;3 u; \+ {5 }3 X
close_positions = false;
9 g- V+ ^2 I' C& U P3 S}
% J: Z; N- z) S6 r5 c+ Oelse
5 {0 g* Q4 i. ~& {+ V{
1 |0 E3 J. ^8 Iif(mdt.hour == 16)( F" z9 ]8 ?6 r: B/ w$ S( @
close_positions = (mdt.min >= 30);
& m+ Z8 B1 ]9 Q: ^% \3 u}# A6 v) D7 R4 `9 C5 B: V3 j
}
# x- b3 |" z& Z( p( q# rreturn ret;
* | k6 t' O, Z% m( p( b}+ s; a- g( k' B7 w9 t
//---) S; k d0 K8 p( b- x
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[]): {) H- t* ?: d6 r; t( R, Y: s
{3 A8 B: G+ H/ w! C, C( w
if(PositionsTotal()) // Is there a position?
0 n) Z7 e3 R6 C{& z0 D2 B9 u, b$ I4 d4 y8 |/ g) a$ w
double offset[1] = { 0 };
. Z- x+ m6 t, w+ x. U( eif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?! m0 `2 y4 r; w
&& PositionSelect(_Symbol)) // Select the existing position! a( P7 x- H& z9 }; y
{
% s8 f# S5 I& s h H: oENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
4 y, M3 E9 d& ^3 V. @7 i# ddouble SL = PositionGetDouble(POSITION_SL);
0 E; @2 T6 k' jdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));. D) Y) [& {% }: B3 q' l7 ~+ B2 L
if(tipo == POSITION_TYPE_BUY)
; w; U9 L- z- `! U( D{
+ M: m1 N- S( o, t$ e, Bif (cotacoes[1].high > cotacoes[0].high)
# x0 @ r2 l$ R% Z3 o5 y{. d' m; q8 S# }' F/ X
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
- s0 L7 }2 r7 v0 g4 w9 o" U) J8 L6 `, einfo.NormalizePrice(sl);
2 W" L. \- R4 g; Z9 {6 h, N& {if (sl > SL)& B% W& l& {) R' h
{
% t+ y) Q- B7 {; \4 z. x9 qnegocios.PositionModify(_Symbol, sl, TP);( O$ x, y" @0 j
}
0 S( t3 e# I4 f' X4 Y6 y}. X4 M) L3 a% D% B" j
}# { W2 _1 e" m/ G7 b! X
else // tipo == POSITION_TYPE_SELL
, g, P& Y. A. k2 m/ T4 @/ B4 N- h2 Y1 J{2 w" W/ J h5 A7 y C* l* h. R
if (cotacoes[1].low < cotacoes[0].low)% A3 n- W9 i5 W0 |
{
: T! S9 P5 L& y& V1 W& m, dreturn true;9 S; U. ~- A ?+ \0 F
}) `' P2 j, `0 j/ K5 ~
// there was no position) q ?# }0 W9 z/ q2 D) W4 d
return false;- ?, `9 e: ?- d7 X
}
# U# B- R; c9 W7 Y& P我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
n( z' U) Y2 V/ x0 l到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |