启动交易模型,并构建 EA
0 @- X6 r, M$ o9 \5 Y8 ~; n在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。 W7 r6 E+ k5 u* t, K5 ]0 n
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。, A/ a2 m" z! s3 }5 K7 r- t
以下是制定这些规则的代码。1 E4 R" {* e/ @5 U9 L/ T! \
//--- Indicator ATR(1) with EMA(8) used for the stop level...
* F% r' n9 i$ ^% _$ `% \1 t2 nint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);& Q4 @% v0 p# A6 s) {& E
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);- H9 t/ A$ C5 u1 v
//--- Define a variable that indicates that we have a deal...! X! V r( x( s
bool tem_tick = false;
$ X! T* a9 R3 m d" z" i//--- An auxiliary variable for opening a position }* L- T' g9 i, N' J: o' R$ F
#include<Trade/Trade.mqh>
8 z' |' g* ]" }' H5 Z! M#include<Trade/SymbolInfo.mqh>
0 {7 x' E& M6 g3 W( M8 P! oCTrade negocios;7 Z1 |) Q7 {' U$ E7 I* G
CSymbolInfo info;
4 y1 V6 l& u; z# G! W% ]. u+ W//--- Define in OnInit() the use of the timer every second. T- b: f3 ?& K& ^
//--- and start CTrade
& v5 L" M y: K# r; [2 c7 z, v% sint OnInit(), c( f. e* ?- q3 _4 t( X' _
{ ^# s7 D) A7 j2 |4 `$ A4 C2 f3 h
//--- Set the fill type to keep a pending order
! v1 E$ G. {0 k: i- Z; F. _) _/ W//--- until it is fully filled
1 m* L; f V# u; Y7 u9 Enegocios.SetTypeFilling(ORDER_FILLING_RETURN);" J) Z& e7 j: |- U% h
//--- Leave the fixed deviation at it is not used on B3 exchange
9 V5 Z2 T. t) G) @4 O3 w4 k9 p* r# Enegocios.SetDeviationInPoints(5);
0 U5 R& ^# v; j* D# c//--- Define the symbol in CSymbolInfo...
8 Z- ]' i0 d0 Einfo.Name(_Symbol);% d! ? `5 i! L( H' V$ g F
//--- Set the timer.... C6 _$ K$ _2 ?7 i0 y
EventSetTimer(1);. O9 {( @, Q0 F; o( Y, N5 O- V
//--- Set the base of the random number to have equal tests...4 u) r! B( f- a; O3 z6 U6 O
MathSrand(0xDEAD);
6 n6 ^( d; r1 N) q9 ^: Wreturn(INIT_SUCCEEDED);
) f( p/ P. _- @5 m}$ N/ @; M$ [6 B: v( Q
//--- Since we set a timer, we need to destroy it in OnDeInit().
( k( P. W7 A6 }5 pvoid OnDeinit(const int reason)
# ^3 g! C3 u' r' _1 R& L4 q. H{' r9 s2 D: i+ F2 N6 ^( K
EventKillTimer();
$ ^. V/ g* D* b- _! {}- a. m0 R2 m2 v. @( x7 L$ {
//--- The OnTick function only informs us that we have a new deal* W( [* p+ L6 D
void OnTick()% b$ t5 X' D! ^; u" e% f4 ^/ w
{/ I4 u. e) b! B/ }% w i! u/ W
tem_tick = true;
) {7 `: U2 O+ P- X2 U J}3 c$ c/ w) U J% x: \6 U- i g
//+------------------------------------------------------------------+
" c2 i# }' a- d1 ^: O+ K//| Expert Advisor main function |0 X. z& \$ z2 y
//+------------------------------------------------------------------+
: ~7 T; O+ ]1 q8 u' ?" lvoid OnTimer(), S1 i! E7 B B" o+ U# l4 Y, [
{
4 C/ i7 o P `5 oMqlRates cotacao[];
/ Z, g( e1 u. L1 T* u# W0 Freturn ;
. b6 q u, A% l) w( Y7 cif (negocios_autorizados == false) // are we outside the trading window?
" H2 M: W* y& treturn ;5 P, q0 `9 |" o* Y, E0 g7 K" H' s
//--- We are in the trading window, try to open a new position!
0 R% k2 x: g X; ?: Hint sorteio = MathRand();
4 e- Z W. {, h//--- Entry rule 1.1
) M0 o" t }4 b. b+ oif(sorteio == 0 || sorteio == 32767)+ U. T' _6 j$ A9 ]/ _% s# N/ E
return ;
/ a! Q9 r& X; h! C) Sif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
/ X5 l1 H8 l( X+ E; l w/ Y{
1 y! V9 Y- }4 `* f& hnegocios.Buy(info.LotsMin(), _Symbol);
- Y# j( J& x1 v. P}
) {; V9 }3 p4 ^8 i! C1 Welse // Draw rule 1.3 -- odd number - Sell8 Y; [: k3 @$ R! O" \% d( x# ]3 j
{
# E0 Z/ Y+ \8 h1 Knegocios.Sell(info.LotsMin(), _Symbol);
3 g( M9 h- I2 N2 y/ I g8 l}
6 R5 M" V1 E6 a5 _}6 a9 j( S3 F. s. L3 f& V; k
//--- Check if we have a new candlestick...
" g2 r+ Y9 A5 Pbool tem_vela_nova(const MqlRates &rate)
( }/ L) F5 v. T% W O{4 A7 x9 E c6 p J; O# J
{
: `7 ]2 C/ T) N) Eret = true;
6 }6 g! a0 T/ Q& dclose_positions = false;
) d$ _+ p& N3 v- M4 k}
! }+ I2 y8 }* \$ U, }2 u2 G$ _else
. G3 I7 K1 h0 |$ E6 a: p P{1 I" {$ j8 w; w) y0 J
if(mdt.hour == 16)$ L2 z* H1 H- K' x* N6 f( I
close_positions = (mdt.min >= 30);) o- T( L! h8 J; U8 j! u
}
" ?* r# n0 R8 L/ H6 |8 U}+ P9 t$ x7 z* f6 l' F' G7 d" b
return ret;" N! |+ o' Z2 G5 d$ u9 J4 f
}! A I7 W1 w, @" z9 z( r
//---
" U. o& g6 N0 [- P8 Sbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
6 _2 l) U% i, ?. u" m, f{& A" i0 P$ I+ T
if(PositionsTotal()) // Is there a position?' s5 z2 k9 Z5 y+ m# K# [
{* q+ ^- Z4 P$ W2 t3 s& v& s. j
double offset[1] = { 0 };
4 v2 H1 ?& [( rif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?+ R' W- E+ h) f! t" ?" d. a2 T
&& PositionSelect(_Symbol)) // Select the existing position!' f/ z, o2 d8 P5 c) z& z
{
$ ?4 E7 w: g# z8 F! H4 [2 R/ G/ n0 ?ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
5 r) I4 N2 d& b% `+ z" t5 t$ {double SL = PositionGetDouble(POSITION_SL);
: d8 Z, A, y! i: t5 }7 R- Xdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));7 y2 E( n' F$ w5 [4 U: d, H- R) p
if(tipo == POSITION_TYPE_BUY)+ G, Z. }6 n' H) O" _
{
4 M) ?$ v( G8 `/ v# qif (cotacoes[1].high > cotacoes[0].high)
\/ q6 n$ i2 @8 u{4 r2 i# u7 c( v a9 f8 n
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
/ b7 p2 m T$ ]" b minfo.NormalizePrice(sl);
8 T% c& b+ x5 ^- t5 ^! ~if (sl > SL)6 c7 _+ ]7 ]! [
{
) M; h G7 K. V9 U3 Vnegocios.PositionModify(_Symbol, sl, TP);
. }# X9 A* ?( V* V" q- X. O) `}* D8 J8 R \* K: h
}
2 Y) ~! c9 ]5 U6 d+ f$ ~}9 Z. y9 |2 T3 j" g. s$ d& L
else // tipo == POSITION_TYPE_SELL+ X3 T0 x+ x* A& p, C+ d6 @0 B) L
{ S R% a! T2 G$ ?' |% t! ^% X! y. c
if (cotacoes[1].low < cotacoes[0].low)# l8 ^3 N7 m+ L) L
{1 O7 r0 F8 n- C& X. S7 ~
return true;
+ g! N* z% D1 B h' N0 e: P4 D}& \) F, l8 }, }$ ~0 y
// there was no position7 a; ?4 \ I0 o4 H& V, I: E
return false;) u3 z8 J! S* o, s1 g7 m/ R1 [( {
}
% W- t8 h2 ~5 g, W& j* ]+ y+ C我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。/ Z" z7 k, w" U9 ~& V
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |