启动交易模型,并构建 EA4 P* L/ `4 e8 V8 A- t7 y# O: S
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。! ]- Q% [2 A) Z& z. x- ~. k
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。( L a# j+ w) x6 z
以下是制定这些规则的代码。
1 V4 W$ a4 b. s) x3 m//--- Indicator ATR(1) with EMA(8) used for the stop level...1 i; a q3 T% ^ x) _
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
* h' ]. K: E7 q+ c& l8 ?- s. jint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
( J( j! V" v8 ^ G- e//--- Define a variable that indicates that we have a deal..., }4 Q6 F7 h+ I. U9 I
bool tem_tick = false;
+ j( D- z( U. Q ?- C3 j( t+ E//--- An auxiliary variable for opening a position
/ j+ U, d; N. c; `#include<Trade/Trade.mqh>6 q2 W7 q( i: Z: k0 U, f
#include<Trade/SymbolInfo.mqh>
5 c% `( i* B! `CTrade negocios;2 w- s% D5 ^% ^' W5 P4 J$ b a5 D, \
CSymbolInfo info;1 O s$ s8 _! b. x* T" R
//--- Define in OnInit() the use of the timer every second4 q& {- F+ {- ~
//--- and start CTrade) R. z* j4 k/ u+ n3 f, j7 Y: g0 n
int OnInit()
2 v, C# W' z% _, U- z; D& `8 X{
0 M" R! W6 u- y/ v% |! X, {2 K//--- Set the fill type to keep a pending order' J8 m R- F; X8 k
//--- until it is fully filled
1 h7 E- C p3 @; c; ^# @negocios.SetTypeFilling(ORDER_FILLING_RETURN);' g' Q: ?9 p3 C) N) @) A: S
//--- Leave the fixed deviation at it is not used on B3 exchange
. z5 v, Y7 d! D: v% znegocios.SetDeviationInPoints(5);, A- w* `( s6 Y9 q3 |
//--- Define the symbol in CSymbolInfo...
6 k# v& F& Y! c- {/ t6 d; Tinfo.Name(_Symbol);
, J4 u9 T4 U! {: w7 }//--- Set the timer...
/ l/ x& w! s$ R! z+ T! EEventSetTimer(1);& ]& ^- y( d$ q* E5 T
//--- Set the base of the random number to have equal tests...; f9 [5 k8 W$ {0 L0 O
MathSrand(0xDEAD);
( E( X+ E a3 \* sreturn(INIT_SUCCEEDED);
: K! P* f. X% N: R* v9 j& N: n. r}
0 ~; t( T* D4 j, K$ V" }8 p7 N- a//--- Since we set a timer, we need to destroy it in OnDeInit().8 |' g. c8 x: L1 c* V# N
void OnDeinit(const int reason)5 b- G3 |+ [9 @+ S2 m3 F3 N
{) Z: f; U2 N* Z' b; h$ s3 |% P
EventKillTimer();% B- _( l; s3 o+ z$ d6 r
}8 W% V7 S5 g: `4 g$ [" e
//--- The OnTick function only informs us that we have a new deal( |$ y& V& s; a3 ~* O+ n% [
void OnTick() X- T. \8 _; I* z
{
) w7 r% {/ u; p, |tem_tick = true;
9 L0 d( I) |9 _/ U, z) L% ^}
' @0 B" o0 B$ ^+ Z! c) X//+------------------------------------------------------------------+; {9 ]# ]7 Z- E( s/ u
//| Expert Advisor main function |3 x J9 C( _5 U/ |2 u0 i/ V" ^
//+------------------------------------------------------------------+
+ H5 c7 h+ Z9 s5 h. ovoid OnTimer()0 \. K" D( y# x# J, `) S
{" b) ?- i; }8 G7 H
MqlRates cotacao[];0 W- k& r% ^8 V3 d% f9 v5 o
return ;; P# p# f2 b0 w9 _
if (negocios_autorizados == false) // are we outside the trading window? e7 H; @/ z% P: Z* N) F' R
return ;
' u! n# ~. v* [5 N) n Y0 o% u//--- We are in the trading window, try to open a new position!5 x$ V; _" l2 C7 h0 z1 W) V
int sorteio = MathRand();
; O; _* O* k* F7 q7 d6 N4 g" \7 b% p//--- Entry rule 1.1
P B' m2 X" s* w3 ^7 g, U. n! aif(sorteio == 0 || sorteio == 32767)* r, V' }( J5 j0 _0 G& c) R) H
return ;$ m- v; E4 s5 J6 x2 V5 e
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy5 |/ v* }# c8 N( j( o4 l* M6 U
{
- X: L6 A5 d P" dnegocios.Buy(info.LotsMin(), _Symbol);3 d% B: b# m# e a6 l* X4 ^$ O
}6 y# m4 \ |- B2 W) L
else // Draw rule 1.3 -- odd number - Sell, p1 [9 E' D$ _/ y8 V# b* C( K
{1 y J6 g" T" w
negocios.Sell(info.LotsMin(), _Symbol);! p- o5 c, W* b( i' T
}
# q; K. C6 y# m' K}
/ A" x9 R# ^7 E3 E: G7 R//--- Check if we have a new candlestick...
; I5 { o) P0 \, S4 B @bool tem_vela_nova(const MqlRates &rate)
3 P t. |+ l3 Z0 ?' k{/ R$ L- Z+ o6 k. E# ~, Z$ K
{, r8 R1 [/ G- Z
ret = true;) P* _6 S# S4 G' T
close_positions = false;
& U# C( n: F7 t U5 b1 T d! h}
3 m$ `, X, M8 [) }1 ~; aelse
* }) ^ Y9 ?0 }5 P{! m: F2 r5 Y) j) }# w$ Q6 L
if(mdt.hour == 16)
! E% d0 G5 B6 O: [close_positions = (mdt.min >= 30);1 M6 T( l5 i) G. u2 g
}/ W9 m/ N& k% I4 ~ P o% A! W) B; w
}) V! q) @ x j7 j* S! N8 w7 H6 _
return ret;
/ c6 ~1 T; y( x' d, B}" C5 d1 g. v- w4 ?
//---. W# O& ^- C8 u. H6 U* u# e
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
: N1 J6 r5 q% ^- D! W7 _: u1 N' G$ B{/ S6 f8 ?& i/ |7 H
if(PositionsTotal()) // Is there a position?
- [3 }8 K3 S- ?- v{
w& `2 @! h7 m( v9 }" z/ Qdouble offset[1] = { 0 };' J. c8 s6 K+ N+ ]
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
2 C# t9 K5 I3 ?" j; m9 b, o&& PositionSelect(_Symbol)) // Select the existing position!
% G5 ?/ A) ]% Z{
3 S5 n2 K) A- \2 g' N& U3 a" lENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
& a/ R) y% Z7 bdouble SL = PositionGetDouble(POSITION_SL);. s; I d& ?+ ]% n% m+ |9 p
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));* g9 [2 i( p, H) @6 O
if(tipo == POSITION_TYPE_BUY)4 ~* ?2 T4 a9 C* q
{
4 j" p$ H$ m1 Rif (cotacoes[1].high > cotacoes[0].high)3 `3 N- ]2 H* P- {
{* [* c4 Y& J% H T; E: ~4 P
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];2 r! L5 g6 l) X( ~2 U3 G9 U! k
info.NormalizePrice(sl);
& A# p- l; e$ `/ h- |, s- K. wif (sl > SL)
6 z- o2 _3 E# ~+ f{# C* z/ R1 ?4 x1 r2 L
negocios.PositionModify(_Symbol, sl, TP);
- l. c7 S a* J; k/ C" T# |) {9 D}
5 d( c# M8 C# w: p6 g8 w}
0 r% h, v: }- {: D, C/ u# K7 u}
3 Y6 f4 G1 R* m' \ jelse // tipo == POSITION_TYPE_SELL. H! m' ~! m; z, R* w0 _" Q
{
" C: U1 e) f- x& ~8 }- H8 y% rif (cotacoes[1].low < cotacoes[0].low)& R) Y$ W; p7 B- f" e
{& T6 _( Z$ B7 P* i) X
return true;
9 c2 F' S5 F# r0 T: Z: K}# o( E- n9 y. I/ `2 r/ U
// there was no position
, o, d9 d8 L# v areturn false;
5 {4 p' P$ d, I}
5 E. N; }# b( \! ~) F+ l1 Z- y我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
) T' D/ S9 i0 ^# F到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |