启动交易模型,并构建 EA
' H6 ?- J; u) [8 x在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。: u8 U4 s. `- }+ { n
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
, \# f! S! A% c以下是制定这些规则的代码。
% ?" e/ t! q- b# e2 h$ c( x) }/ r//--- Indicator ATR(1) with EMA(8) used for the stop level...$ w( o3 f$ q9 x5 F$ I
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
4 }; b0 X1 O/ Iint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);$ ~9 v; y: s) x( t5 @% x! {
//--- Define a variable that indicates that we have a deal...
* l3 v* a3 N# ~bool tem_tick = false;
7 O( H; b& i3 d: D* m0 ^//--- An auxiliary variable for opening a position
' c H( y( C }1 F% w1 ~$ G8 S#include<Trade/Trade.mqh>
# k9 U4 v0 V& [6 `* z#include<Trade/SymbolInfo.mqh>
7 A* ^& W1 }/ L% X$ j) h4 tCTrade negocios;1 [1 ^3 u+ F! m6 O) |+ z
CSymbolInfo info;
4 r9 L+ C; F7 {5 V//--- Define in OnInit() the use of the timer every second
) ^$ @# v7 O% i O: H8 w8 _//--- and start CTrade1 C2 D( ~/ y& v! o- ] X
int OnInit()9 W4 E. }. f( g1 t3 q+ }
{
5 ^8 e, w% G0 y8 P0 J//--- Set the fill type to keep a pending order8 n: w+ [( }, w# Z0 C) j+ B
//--- until it is fully filled
. @2 H, ~8 F3 \+ `) R" c% Cnegocios.SetTypeFilling(ORDER_FILLING_RETURN);: m9 W. x" Z7 x' z) D. ]
//--- Leave the fixed deviation at it is not used on B3 exchange
5 C* c' W* j$ D5 N8 E7 _negocios.SetDeviationInPoints(5);9 I" [2 f/ W4 R" f- s! W# M( W
//--- Define the symbol in CSymbolInfo...
# O# c! ^+ c! {3 Sinfo.Name(_Symbol);
- f! Q2 z( e8 G: E! b//--- Set the timer...
u0 E- E; }9 G. F9 d6 K$ BEventSetTimer(1);
4 O! K2 i- l. j) h1 S8 p//--- Set the base of the random number to have equal tests...
) H/ m! k4 W$ ~+ BMathSrand(0xDEAD);" S; {/ D6 |3 |/ S* P
return(INIT_SUCCEEDED);2 r+ b& K# j7 f, H1 N( s+ j
}
9 t/ j5 G* a2 H% e//--- Since we set a timer, we need to destroy it in OnDeInit(). b6 `) m* i' m5 H7 P/ ?3 B
void OnDeinit(const int reason)
2 d4 ~6 m6 Q! m" K{$ O+ @5 b- M1 m2 u
EventKillTimer();. q0 _/ Y* [# t1 V1 b$ T" M g
}
1 S* ]# ~1 U1 q5 z$ `//--- The OnTick function only informs us that we have a new deal& r2 m4 `& j3 }, B, A
void OnTick()
0 K4 ]0 P, Y# K0 V2 o" \8 v{0 j( n: {( o4 ]
tem_tick = true;
0 \% S9 V, }" U7 p7 h* U7 v7 G3 A}
( B* K4 \/ v, S2 U: ?/ Y4 X' H0 h//+------------------------------------------------------------------+
1 o6 j2 O6 U1 ], H {" h: V/ v1 u( a//| Expert Advisor main function |
4 ~. u5 L! \0 H5 k, \//+------------------------------------------------------------------+3 u/ U3 g7 K9 a, S
void OnTimer()! |- l$ e* ~( ?- ]- m
{
. q3 ~: y! K* XMqlRates cotacao[];" u. Q# }2 h$ h+ w" j0 T
return ;
, i5 _, e! O) F& ?. Eif (negocios_autorizados == false) // are we outside the trading window?
- }6 M: P( p, X/ q) [7 treturn ;/ ~* }9 ~$ u0 ? ?; f5 i) |0 A
//--- We are in the trading window, try to open a new position!
+ f5 Q3 |" [ z8 y4 R. z. M* Aint sorteio = MathRand();
9 Q+ ~) ]$ z; ~8 K I( y" C//--- Entry rule 1.1
5 T& x- \# c, A' t4 P2 [if(sorteio == 0 || sorteio == 32767)
7 K* E7 g$ h5 O- O' j5 F# e2 ureturn ;6 X1 G- G: b+ K, {7 c
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy/ q; Q1 c4 b; b
{
, F( v+ F% k- S# h( J9 n- U( Cnegocios.Buy(info.LotsMin(), _Symbol);
9 u2 s6 s& v6 X) ~}
$ o& Q4 m' }0 l* celse // Draw rule 1.3 -- odd number - Sell$ S$ b0 S: r5 u* J( L2 |: Z
{) C3 @( h& d6 p
negocios.Sell(info.LotsMin(), _Symbol);
6 O' j2 r) v: M( R) h( b+ y, ^- B}
* E9 e4 @" |5 ]9 K8 M}* j5 l1 X8 S) R+ Z3 u
//--- Check if we have a new candlestick.... n+ q; s* t% F7 Z8 v+ j
bool tem_vela_nova(const MqlRates &rate)3 D! ~ s( a& b3 C0 v: P. W
{7 O! d ~" B2 J$ W, z& C7 ]
{2 ~ H8 T5 _3 X7 q# u4 ?
ret = true;0 r$ M2 o0 S. i- T6 b5 s
close_positions = false;
" Y! I3 L; I n( N/ I}
; u' _6 c% X, c5 }, Eelse8 I& l5 Q" P0 {' ^7 o- u: ~$ a
{
0 S T6 M: W5 e8 |/ vif(mdt.hour == 16)
]2 M Q8 x2 O Y D9 B5 fclose_positions = (mdt.min >= 30);+ r$ j3 |( M) ]; O% `; J. R8 o
}5 q7 Q. C. N/ J+ K+ i7 B
}, f( Z! Y4 B/ F9 B2 D
return ret;
/ J, r2 M& a5 S6 y7 H8 R}( x, n% J! y/ L+ b' ]
//---
: n. h& V" V/ Q: u9 { Ubool arruma_stop_em_posicoes(const MqlRates &cotacoes[]). s2 D' m! J* y" [- T/ ^1 a5 ~6 A
{
( V5 s* w6 T4 a, K( n l, }if(PositionsTotal()) // Is there a position?
+ Z' ]. ^) X/ [0 l{1 R0 n3 {, c E; j% U* J
double offset[1] = { 0 };
! O# ]0 y; u0 [$ A) g0 y/ Y9 fif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?0 G/ h1 c& x! f+ j
&& PositionSelect(_Symbol)) // Select the existing position!9 g0 r8 S. w! r0 S8 E
{0 }) z7 G2 u+ e1 N* c- _
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
5 z* f6 r( F: Z5 a5 C) I) Mdouble SL = PositionGetDouble(POSITION_SL);' W/ q8 _8 f" n% X1 y4 m! G
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));) X9 Z, ]6 x, h& F+ `; S" [% P
if(tipo == POSITION_TYPE_BUY)4 a! L' B1 Q1 S' A' _
{
% f+ R }$ f# Xif (cotacoes[1].high > cotacoes[0].high)
2 |. N# o0 |+ z1 m8 W7 _" A/ f$ f{
; m% K) ?" ?) G9 X0 h pdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
5 S K% S' X4 b9 V; N' h9 ~" g1 Zinfo.NormalizePrice(sl);
4 m8 w& k; ~7 G$ w3 tif (sl > SL)
5 h h4 X2 G# J# `{! X4 L' a( K; e( q, O
negocios.PositionModify(_Symbol, sl, TP);
' n& W, i9 K8 w) |}
9 Y1 y' P7 n# O& C5 \! O}
% K8 E0 Y0 G$ F}- z9 ~# @9 A# d; f
else // tipo == POSITION_TYPE_SELL+ N# Y% ~6 U* } J
{
; W% z( p7 `( t o& Pif (cotacoes[1].low < cotacoes[0].low)
- H; V6 n* U, r% Y9 I. r{
& g; B1 `" k# ~) Q) M# p1 t+ k, Lreturn true;
( ? m8 _# V' \6 s7 h}
1 D% P8 w/ V8 ~& t. B( X7 w// there was no position" I6 l* Q2 g7 U2 u1 W# G+ {
return false;
! f: r$ Q+ W* X4 U}1 ]& s+ u( b1 U$ M1 v5 g
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
/ a: r$ Q4 Q9 r7 U. E7 i到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |