启动交易模型,并构建 EA- F0 k/ A1 C3 i# { w. }' ?
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。1 P: V( o' D9 q5 S8 v
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
4 }& g' A H; q) [, S5 N以下是制定这些规则的代码。
. a0 f. [: n5 ~ b; r9 P//--- Indicator ATR(1) with EMA(8) used for the stop level...
" k3 c$ s: ~4 U* g3 ~6 y& ?int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);; u4 S* ~ ]# |4 e
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
) f7 X) i& \5 _. }8 p' u6 D0 \//--- Define a variable that indicates that we have a deal...
9 Z* F( v4 A: d( Y$ W2 u4 o/ |+ nbool tem_tick = false;5 Y- _4 ?" r, c; W8 e" j! p
//--- An auxiliary variable for opening a position3 s; R; F) p7 c% P) R8 V7 j
#include<Trade/Trade.mqh>
! b! k" }' X/ d. U1 c, _#include<Trade/SymbolInfo.mqh>
: o+ F, k; _3 Y; q" K) F. h2 F0 H! pCTrade negocios;
2 Z4 G' j$ ]% e3 p; J- uCSymbolInfo info;3 j# B' @7 F; F# ]. C& t
//--- Define in OnInit() the use of the timer every second
( Q) x: K- i; C% _9 P" d! A//--- and start CTrade+ y# ]5 b, G! g* L; ?, R/ O
int OnInit()
. s) r2 o+ o$ d* T0 D! u2 |{. J6 L- K6 p9 v: E
//--- Set the fill type to keep a pending order! k3 _' @2 c3 H: S6 q
//--- until it is fully filled
1 z5 u' l: w3 snegocios.SetTypeFilling(ORDER_FILLING_RETURN);. a) n/ J& F. b0 ?& i: ~
//--- Leave the fixed deviation at it is not used on B3 exchange O/ Z7 k2 N1 e2 @& @# S
negocios.SetDeviationInPoints(5);
" A* A5 d: M( g. z6 t+ W//--- Define the symbol in CSymbolInfo...
' ]+ ?% z k3 |( O9 Ginfo.Name(_Symbol);' c. a, S# Z8 C6 f7 V0 u
//--- Set the timer...8 R* G" P L1 {. e7 @
EventSetTimer(1);/ V( A# p: I$ l! L1 Z2 [1 n. E8 e
//--- Set the base of the random number to have equal tests...! T, e2 `. F$ u r+ Q
MathSrand(0xDEAD);8 F" A% @8 T" `( b d1 T
return(INIT_SUCCEEDED);
: \6 P1 q& U- W. Q! M/ b}0 j, D2 U: i i3 G7 ?) {# d1 d
//--- Since we set a timer, we need to destroy it in OnDeInit().- {- `' I7 F `) c7 V; s, g- C( _
void OnDeinit(const int reason)
4 A: Y' V' |' H3 a{
/ z! w- _+ j( bEventKillTimer();* `4 W/ p: \: A$ ?/ n k
}
3 j# Y9 A$ R o1 r9 {! z' C4 _//--- The OnTick function only informs us that we have a new deal Z" F c- F, M% s
void OnTick()
4 u7 K) r+ s! n{
- ?7 v, o D: Ctem_tick = true;
- g! M1 n+ B8 p}
) q \/ D' O4 w* s' U" b+ s//+------------------------------------------------------------------+! ]1 K6 H& s. W1 K
//| Expert Advisor main function |7 P% y& X o& ^4 Q9 s4 j0 |
//+------------------------------------------------------------------+
1 \; ~' T/ ~' H4 u }! U" kvoid OnTimer()% t# [- s' o- b6 T+ \: e
{, k2 y) P3 ?. u8 P1 {7 ~7 A$ z3 N9 Z
MqlRates cotacao[];
6 H: i1 j+ K2 p. X- M6 Y( n, ]" hreturn ;
1 g% h# t0 y' C" \- O: L3 t0 iif (negocios_autorizados == false) // are we outside the trading window?
& w" E) t F- N# o* ^/ Rreturn ;6 K; G) U' @. s$ [
//--- We are in the trading window, try to open a new position!
& a: O! y" s8 q$ b, y6 z1 ^5 ?: Eint sorteio = MathRand();4 T/ i" `! j7 e3 _! `* p W
//--- Entry rule 1.1
3 q% z1 e1 Z5 b2 P$ r( r- c" N; Hif(sorteio == 0 || sorteio == 32767), b; n) m; d7 J
return ;
B+ b! J# u+ j9 h# o" qif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy$ C: T! |% Q V' O
{5 k$ E* p, z$ A5 w, n( [' r
negocios.Buy(info.LotsMin(), _Symbol);$ M8 N, k$ Z4 w) y2 k
}+ {6 q+ t F, Z" W
else // Draw rule 1.3 -- odd number - Sell
. X0 ]0 f# i. @- o0 j. D{
# l9 S3 u* Q: q' F4 hnegocios.Sell(info.LotsMin(), _Symbol);
% t& |# |6 E$ S$ A7 R! y}
y4 W2 e! G9 d) Z}9 y- s$ e* N2 }5 y8 g
//--- Check if we have a new candlestick...* B. R$ `9 C3 X, D0 d
bool tem_vela_nova(const MqlRates &rate)# Q; i# @! P/ s% q' Z* Z
{0 ?, I3 w8 v1 @3 {7 M9 {6 `
{
: I% U2 _* d. Y' Qret = true;1 F6 o D- c! }" l7 J- h% x
close_positions = false;7 @+ {# h5 P$ k, n' t4 V, T
}
& N5 `; D) B1 k8 o/ S! k" `else2 M, @& m' t5 V" }8 Y! T6 r
{% R- P- x+ _, j; V6 e# g
if(mdt.hour == 16)
6 I, [# Z* u# x) } nclose_positions = (mdt.min >= 30);$ D9 [: R; {. S& q. n% |% m
}
- p {: K" d: \4 }: o G2 l8 V0 z}
9 u; T! @) j) c+ J* greturn ret;
# R; {8 O# n! g- `' |}0 m; n* D. M9 |# m
//---
4 s e& ]* M! N+ z" J; ~# Tbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
* {% O4 t# ~3 z7 Y{
- H2 K! F# O! Qif(PositionsTotal()) // Is there a position?- u% L2 j+ o+ W8 o
{ D( ]% u7 F3 a
double offset[1] = { 0 };
5 P" m; N6 O2 j8 S0 f5 lif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?1 L" y7 R; z/ J$ A4 Y, `5 ?
&& PositionSelect(_Symbol)) // Select the existing position!
6 b' ? y( g1 c; a+ s1 b% R{
+ \1 ]" O- N0 s7 n/ Q) ZENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
: |( @. p4 F8 P: idouble SL = PositionGetDouble(POSITION_SL);2 E* p8 P! G. h* u
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));! w4 O3 D" _. y, G; h
if(tipo == POSITION_TYPE_BUY)$ h3 {" P; E8 M
{6 p+ m3 ~" l' d, i- @. E; }
if (cotacoes[1].high > cotacoes[0].high)
+ x8 x$ ^$ B4 H! \1 s1 N; R! y{7 m$ _$ B# D+ I0 i2 o8 c3 R
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];& o9 l* P% Y! a# V/ V T P4 H
info.NormalizePrice(sl);
+ e" J3 d& Q/ ]/ @! Mif (sl > SL)
6 q0 m& Z! e* m{- k( w+ C `6 m: G/ t w9 L+ n8 a4 k) u
negocios.PositionModify(_Symbol, sl, TP);9 C9 k0 ]4 w! _) k8 ?: Z, s- Q
}
. @: B3 s$ M: Z# i% _2 Z}, K" H1 D9 \6 P4 i
}) X2 K4 {! G9 y, s- F; q3 f7 ^ _
else // tipo == POSITION_TYPE_SELL
9 H" \/ O3 @( [4 n3 j{
6 t. u' K5 ^6 M& l- Xif (cotacoes[1].low < cotacoes[0].low)$ D3 ~$ T& |# J1 |6 W
{' }! P; x/ H% f7 B
return true;
" o' U4 ^: u+ K}
( a) }) f9 o% L: a. h2 C// there was no position
& k/ i& ^% k. ?, i0 |4 f) v( freturn false;/ A+ l7 u& a D
}
& T$ ]& {- `9 N1 j. N2 Q我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。7 z+ |# @+ U! h7 C
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |