启动交易模型,并构建 EA
6 ?) d: W9 ~+ _( M在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。$ H% Z/ \. f* Z/ M" b
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。2 |; Y! o+ T7 \* \3 ?6 ?3 F
以下是制定这些规则的代码。' Y' N3 _# N! }8 F; _8 K
//--- Indicator ATR(1) with EMA(8) used for the stop level...
5 g$ [) o+ h ?8 R1 @/ uint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);9 u* h1 Q, G6 `
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
: P( c- k: u' v# M j2 a//--- Define a variable that indicates that we have a deal...
/ s. l! _+ a; }7 Y; l4 ]bool tem_tick = false;
; k- M9 g, u# k& z: C" f//--- An auxiliary variable for opening a position5 Q5 @* G4 r( r) i0 @
#include<Trade/Trade.mqh>
1 ]+ Z( E) C& C ]: B" A7 L#include<Trade/SymbolInfo.mqh>. b( |* G7 d- m* `4 F
CTrade negocios;
/ S7 F, N6 r7 w5 @0 ICSymbolInfo info;; `2 l% ]$ {, W2 M) f" e9 O1 \
//--- Define in OnInit() the use of the timer every second
# T2 a$ y8 n5 B4 \& r6 k0 g//--- and start CTrade& n& z W4 F! j
int OnInit()7 m# D1 J7 x) O2 G1 Z2 j t+ l- F
{5 C+ c' ~3 l9 O6 d
//--- Set the fill type to keep a pending order
4 h4 z) i$ }" l0 v2 n//--- until it is fully filled! \0 h$ V7 c/ u/ }: Z4 \
negocios.SetTypeFilling(ORDER_FILLING_RETURN);6 U& W9 R8 {0 M1 l
//--- Leave the fixed deviation at it is not used on B3 exchange6 J3 A/ V: v9 F$ [
negocios.SetDeviationInPoints(5);4 o$ q2 q2 y; { S* \: o3 q
//--- Define the symbol in CSymbolInfo...% g( D: S8 M) k' c3 p
info.Name(_Symbol);
7 E* @) n x1 C4 E4 U! e//--- Set the timer...0 v% w" f3 N- U* O* e
EventSetTimer(1);- A+ T- i4 N/ W* a6 y2 l7 p/ R
//--- Set the base of the random number to have equal tests...$ F2 [( G z% l( C
MathSrand(0xDEAD);
" }8 B c7 c% }- Ereturn(INIT_SUCCEEDED);
! O: o3 P* e' k. E}4 g f2 @8 x' F/ {, M: U, l9 D3 A
//--- Since we set a timer, we need to destroy it in OnDeInit().- d: X% |1 N* H% \. w' b" `, D1 u9 t
void OnDeinit(const int reason)
6 o" N7 O7 T' q& e5 v" U{
2 {# s) h0 ^/ v! r" HEventKillTimer();4 x7 F; \/ U* w3 ?) g9 Y. n
}2 m# ^+ X$ j; ~# P$ A: n8 t* v
//--- The OnTick function only informs us that we have a new deal
0 O5 Y! o" G( B4 U* b6 Pvoid OnTick()
/ Q3 ~2 ~* R# H" d7 V$ K* M6 C{0 K3 `# V3 C/ [$ `( m) X
tem_tick = true;4 c1 K: D4 Z# Q) m
}
& A# ^8 {8 c+ b5 D+ O* u//+------------------------------------------------------------------+
* `1 [% a& F; Y//| Expert Advisor main function |
6 ^( ?( O8 }% f; S" K8 ~//+------------------------------------------------------------------+
# f2 \: A) |5 o$ z% bvoid OnTimer()
. J4 y) D' D) z* W9 u{
}6 N, \/ Y6 B4 ` ZMqlRates cotacao[];
3 k N/ ~4 k% K G6 Wreturn ;
# w' X1 j: @# s; i# d/ R/ @if (negocios_autorizados == false) // are we outside the trading window?
8 k) q- E3 y" X' e+ [6 jreturn ;
' C$ R. s7 W$ l9 W//--- We are in the trading window, try to open a new position!
7 ]1 d( b1 \, ]- @! K4 o( T7 ?: \int sorteio = MathRand();
6 A, j1 z6 M8 X8 J( E% X% ~2 c; ~//--- Entry rule 1.1
* u: C5 B0 X1 E% Fif(sorteio == 0 || sorteio == 32767)
5 l/ D g* i, o" `% c; F9 y8 yreturn ;
, H5 J/ ?$ G ?if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy' ?- a$ _7 S; r6 V0 A$ `8 K
{
5 M0 u/ ?6 t7 h! Jnegocios.Buy(info.LotsMin(), _Symbol);! i1 y( }, j$ @
}2 L# U+ H. f* Y3 x
else // Draw rule 1.3 -- odd number - Sell
, N, ]2 ^. d9 X: @! e! o, s{
# d. j5 a' k6 {) Enegocios.Sell(info.LotsMin(), _Symbol);8 ]8 x) n' ~" z+ H1 Q
}3 |" m5 i% P7 b3 u
}
) F- G( ?$ o9 R2 ?7 E//--- Check if we have a new candlestick...9 X' @% k8 V# {2 ]8 e
bool tem_vela_nova(const MqlRates &rate)" A; a d% B o/ N- ]- Z1 `$ M
{
) a+ ~0 b9 r& F' V* D{
. c; @" B! z' b, d" qret = true; w! b5 P1 D9 Y. \
close_positions = false;0 i1 N8 O0 W4 X6 F) N/ C3 L
}# b l& \8 F/ t# U5 A, g" ]
else
) r( Y5 a- i0 _1 K" r{
$ k; G) X7 a6 ^5 eif(mdt.hour == 16)
* ]9 b. w1 ~2 M Sclose_positions = (mdt.min >= 30);
( i# j5 X k9 i- Y$ x) d}
; Q. j) g1 b5 f6 I, T}0 A) T2 m; B/ Y6 K1 N
return ret; L% ~7 J* y! k$ q' L
}0 R5 A% n4 }: Y3 d% a; D$ U2 ^
//---
* t8 a9 l1 I' w1 Y1 W+ Hbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 s- d: g$ V3 e: e{
! V5 a1 u; W4 _' vif(PositionsTotal()) // Is there a position? y8 l k5 e. Q% W- r. W9 A
{8 k8 q/ A" G6 W7 H" f ~
double offset[1] = { 0 };( H/ N6 Z5 S* [3 m( J3 }
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?# T/ ^1 [+ F; F2 K; w) ?" \' ]6 i0 r- u
&& PositionSelect(_Symbol)) // Select the existing position!
1 F1 k1 |( g7 m4 ~& i" a{6 p( ]- O& K+ \7 @+ `/ j2 j
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
7 s# O6 S$ `7 K& h s7 ddouble SL = PositionGetDouble(POSITION_SL);+ \* Z& e5 u, z; N1 ^" L, J
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));: @( Y3 A/ M; X$ }
if(tipo == POSITION_TYPE_BUY)2 y# o- h! z7 X6 [0 f- l
{& ~7 I) L4 Y1 M/ f, W) F9 u8 }
if (cotacoes[1].high > cotacoes[0].high)
V( o6 i3 ]/ r$ I Q& O{8 Y2 |2 n# n+ p' E, H5 `; l
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];4 r6 q4 f4 c1 w Q& ~
info.NormalizePrice(sl);
6 S- E. Z+ |! ~0 a \; Wif (sl > SL): J6 G7 x Z0 i4 {( h% G
{
5 [4 C# y8 E# y( x) ?/ ^. p, enegocios.PositionModify(_Symbol, sl, TP);
| I4 E8 l) t. L1 H. D}
$ M( E( Q3 p% f0 v; g! h5 ]}
4 w) B2 p; a3 j: P# ^) H. M# e}# b! G3 i4 I1 ?& s
else // tipo == POSITION_TYPE_SELL
6 m) v( S' a, _9 p2 l* e; X{
8 }4 {4 S# f' i6 b# Y! l1 aif (cotacoes[1].low < cotacoes[0].low)( S+ b& f# ? o$ D0 {9 c4 M
{4 {( t7 F6 B u. N0 \, H$ G
return true;
: U/ I+ R5 d% t- Z, y: j}/ s7 r, |5 G7 }9 _( T8 D
// there was no position
6 k- d1 a$ i8 a5 Xreturn false;
5 K+ r' J# F% f7 P, E}1 s- ~% S: _3 o, b3 [
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。' s& B+ V5 u+ H1 K U
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |