启动交易模型,并构建 EA
7 v- e+ K: q) ]+ N6 a: V4 l, h在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
2 B- Q; I% N, r3 a. x: V* j: m为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
2 }! \! A3 Q6 d+ a% U4 f以下是制定这些规则的代码。5 L; k" l/ S' f
//--- Indicator ATR(1) with EMA(8) used for the stop level.../ |) C: y) q4 d* Y' w' C
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
* T' F4 d" R2 y5 c5 Y- Rint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);1 c3 f6 \; J& @( Y, _' @
//--- Define a variable that indicates that we have a deal...
; Y8 q5 G: ~0 [) Zbool tem_tick = false;
) i. Z- l2 |& z//--- An auxiliary variable for opening a position" a; w* V7 Z2 L
#include<Trade/Trade.mqh>
" i# }# w0 g! }" [1 k5 e2 E3 K#include<Trade/SymbolInfo.mqh>4 @* Z4 n1 I/ }! D
CTrade negocios;- r7 F$ b& `, l4 t* ~4 P& F7 }
CSymbolInfo info;( T1 B# n3 L/ Y4 }' q
//--- Define in OnInit() the use of the timer every second
! P$ I3 C: O) @# i; }//--- and start CTrade
' S: T( h! j$ `& q- ^int OnInit()
( `5 ~& Q8 X( @3 z{, X. E# B9 o9 a/ d4 [/ ]# l
//--- Set the fill type to keep a pending order9 Y6 T. G, y0 l' x$ v! v# P
//--- until it is fully filled; {4 R2 D, A/ j
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
. o0 q8 A5 N- q9 e//--- Leave the fixed deviation at it is not used on B3 exchange: ?) f5 n$ D" r# Z! X" F* }2 K
negocios.SetDeviationInPoints(5);
" {& ?/ u* M- G! n/ c2 R5 K//--- Define the symbol in CSymbolInfo...- O9 a% o* ?% ]! [. b% }$ o( t( T8 v
info.Name(_Symbol);7 U& k/ W3 V. ^& B5 \: h; j. e
//--- Set the timer...
' Z& p+ F1 c8 ^; x( n& eEventSetTimer(1);* l s f( K& n# Z& j
//--- Set the base of the random number to have equal tests... \4 o" {( `' L* z% {
MathSrand(0xDEAD);- Y+ B& W% T+ B) R, y, G
return(INIT_SUCCEEDED);
6 M* T" V3 X% F. T4 c}% V; R2 |3 _4 }2 |/ h
//--- Since we set a timer, we need to destroy it in OnDeInit().; Z0 D1 W1 w) u+ R. h( O; z3 x* u2 L
void OnDeinit(const int reason)% `, w; S8 M% c# u6 K! t: k
{
1 K" u6 J" \2 ]EventKillTimer();
6 E, e8 ]. ~ _/ p; }+ a0 @9 W}8 M( \+ @" U t2 _
//--- The OnTick function only informs us that we have a new deal7 g. P# ^8 J$ B6 I% v
void OnTick()
I6 ]. D Y# N$ d{) d" D, C8 F1 Z' x5 @7 B$ {, T
tem_tick = true;6 ]+ d+ Z' T8 i& q: c
}
3 P: R2 Q$ `4 q//+------------------------------------------------------------------+( P. ~( C/ V; o6 h% I% G0 I
//| Expert Advisor main function |
1 v- r9 o" r. ~* V//+------------------------------------------------------------------+- ]' }, o; t7 U: W
void OnTimer()% r, N0 v) w/ j: M6 p( [. |. m
{
; Z" K* e G/ o0 \( lMqlRates cotacao[];
+ Q% g9 a1 s, Treturn ;
; [9 H3 ~4 L% J9 g: eif (negocios_autorizados == false) // are we outside the trading window?: h! ^5 b) W) p0 _$ }8 I" W
return ;' C2 \: ~4 u) O( k) N: e u
//--- We are in the trading window, try to open a new position!) \6 M0 d% X( i
int sorteio = MathRand();
' y& ^; B( D3 M* | X; Z//--- Entry rule 1.1
8 P) R1 m$ {5 A' f6 c- B& |if(sorteio == 0 || sorteio == 32767); f7 g9 a, t( `
return ;
1 h' N5 E2 A- q) i# s) e& Tif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy$ c/ ] H1 R: Y8 W+ m
{! `7 s, \7 t8 ?) v( W, }! ?
negocios.Buy(info.LotsMin(), _Symbol);/ A' S5 u0 f! ]# p" u. r
}
/ J( ^. ~( H# m S. Xelse // Draw rule 1.3 -- odd number - Sell/ Z2 M, \1 n9 Y" ?1 }% g5 x# N
{
$ J4 I% u8 d9 S& c: onegocios.Sell(info.LotsMin(), _Symbol); O: Z7 c, V* I
}
! Q, A6 m9 e; F/ q}3 ]: w3 p7 l. _0 t0 {2 F
//--- Check if we have a new candlestick...8 H1 x; t9 T% _. V# s1 x) B
bool tem_vela_nova(const MqlRates &rate)
# S, p# h( Q8 g. @{
% D ^, j, ?+ M9 }0 u, j{
( f( n* L# `( Tret = true;, s3 n! ?5 }! f
close_positions = false;
( U0 ]& w$ v; ?* V6 z- R2 Q}
3 a( K# n# w# r% l5 K$ Celse
. A6 o3 ~7 t0 t |: N& m& ]9 X{
% j/ J V# ?, q: {$ Jif(mdt.hour == 16)9 g) Q. W# W1 `
close_positions = (mdt.min >= 30);
9 Y7 y9 T. h/ `0 R* r9 [6 W/ J}% V& n% a+ Q: K
}
- b. p7 Y p" m. q4 H6 Greturn ret;& J7 y9 S* o" ^
}
, h* x7 A) J* b: i- c% c//---
. T: c2 R; f0 \bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])4 D' l! t0 m, s+ P' w
{; t6 m w: R2 a3 E/ h; q2 f
if(PositionsTotal()) // Is there a position?
; M2 E5 T: m6 n+ E{# S4 M" t/ e1 `3 [
double offset[1] = { 0 };0 e: b. b3 l9 |; M. l
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
/ H+ E& J$ U* n&& PositionSelect(_Symbol)) // Select the existing position!: c H4 s1 q% N! K0 C1 w4 d
{
, o. [. l+ o! T' h+ PENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);) q& L6 A) _, Y5 ~. J" e
double SL = PositionGetDouble(POSITION_SL); n6 {5 B7 A+ Q3 U' M
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));: q1 m! @, r: Q7 d
if(tipo == POSITION_TYPE_BUY)2 s( a2 r7 v3 d v7 @+ `2 l7 A4 _9 B9 d
{" ^: C* q4 n( i% Y/ E6 B e
if (cotacoes[1].high > cotacoes[0].high)9 I2 n$ P; U& l8 q+ d0 Q! e5 X
{
' ^7 H/ w: L( L( X/ \double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];' P* t2 z2 I/ r. y, g
info.NormalizePrice(sl);
8 P+ M5 u* _- qif (sl > SL)
# A5 u: N" [4 E. ?0 b( _( }4 _{3 x6 k5 z* g7 y- n2 `8 }
negocios.PositionModify(_Symbol, sl, TP);
% b9 C( l/ K* v. h}, A1 B7 P) I: C
}# ?/ c) g( K# N3 P c" E
}
! s, {0 a" Y! w8 J- i, X+ Z4 U0 D1 aelse // tipo == POSITION_TYPE_SELL
& R0 w) c. T/ t6 t3 y% x2 n8 n{
$ y; @4 G% Q$ g# G+ l# r! vif (cotacoes[1].low < cotacoes[0].low)
: o7 k- s) }& g1 J{, t6 O( Z: ` d/ z8 y. V- ~
return true;
. [6 l# T6 B9 x2 L}- z0 K% J. V% t/ I Z
// there was no position
% i! G; Z% X( @! J! \ {$ U2 U. preturn false;& G. g- A6 B0 g) w3 c2 M
}
& c+ U4 s+ Z. [* L8 K* q我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
! |, |1 m7 T4 S到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |