启动交易模型,并构建 EA: i3 u+ s" P! B: B4 w5 E* Y
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。- V* _! ?0 Y" k8 O' P" i. w
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
% `- ~! v1 r, U4 F# h以下是制定这些规则的代码。
& L# G& d3 s9 e% j//--- Indicator ATR(1) with EMA(8) used for the stop level...0 ~& M$ n; S3 n! ^& H8 S
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);- [1 O; N; _/ S; `' X
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
: C9 j7 ?4 D [: I- |: x' C9 L//--- Define a variable that indicates that we have a deal...
# z% I3 ?/ N, `4 P% C: m: \% [% cbool tem_tick = false;
. A y: ~' d2 F( C6 y6 \- H//--- An auxiliary variable for opening a position, y4 O; N8 t% m# v
#include<Trade/Trade.mqh>3 ^6 n3 d# I4 v# n, K$ J
#include<Trade/SymbolInfo.mqh>
6 M/ |3 E' _3 G D, x2 bCTrade negocios;0 ?$ V% r/ c4 G, \
CSymbolInfo info;; w+ Q* }2 S8 _) d4 a) X" Z/ D
//--- Define in OnInit() the use of the timer every second8 M- m, K( j8 v1 T' u
//--- and start CTrade
, Y2 `: T# P4 D8 l/ @int OnInit()
9 ?/ h5 U1 u( J+ W/ |# B6 w7 Y0 t{
' F. k# S% {7 N& q* k3 O5 x! F//--- Set the fill type to keep a pending order
& n2 | i7 ]; j! p4 G//--- until it is fully filled/ ^0 z6 G# G6 c$ ^
negocios.SetTypeFilling(ORDER_FILLING_RETURN);3 j! q4 F9 o- G: ^4 n
//--- Leave the fixed deviation at it is not used on B3 exchange
# ]. |! P$ c: n' ]& }negocios.SetDeviationInPoints(5);1 C+ b' s/ i, G; Q
//--- Define the symbol in CSymbolInfo...' {) v7 d3 h0 d R0 w& x' V% l
info.Name(_Symbol);
/ R: `) c; f8 ]; Q" v! l//--- Set the timer...
! w/ Z/ ]: m8 B' j1 NEventSetTimer(1);
8 W$ O( L9 i" D! b1 s3 ^//--- Set the base of the random number to have equal tests...9 E: j- Z9 [& m" J0 E" k
MathSrand(0xDEAD);3 | ^5 O7 p" r! `% {; E7 g, O6 M
return(INIT_SUCCEEDED);# ~+ v; Q* \, ], o6 X5 ?
}1 v+ c9 G( A) P& B3 q" }
//--- Since we set a timer, we need to destroy it in OnDeInit().1 {1 c* a' G) L
void OnDeinit(const int reason)- t3 n5 F1 O: s; |# \1 e5 r, O; }% K
{' l4 x, W$ |9 m
EventKillTimer();8 e6 P2 `) t( j2 `/ _
}7 R; K+ S9 ^; ]0 U: R) [
//--- The OnTick function only informs us that we have a new deal/ G# p# y' w0 m& O! s) E
void OnTick()
, O# v) d, l [' Y{
9 t% a+ i5 T% Vtem_tick = true;
/ F$ y3 [/ g$ X% @7 Y- q r}* K0 m5 b0 |( l! G# ~( k, l
//+------------------------------------------------------------------+5 ]( o4 M. q1 t5 _# _9 @, z& e
//| Expert Advisor main function |, t+ m$ t/ B0 T- {8 s; J- e
//+------------------------------------------------------------------+
; S, ]$ f& S4 y% ~/ M2 ?& Dvoid OnTimer()% A# J# d0 x2 [' [5 p* Z0 X1 A
{
( j) V7 s+ K( V- p% hMqlRates cotacao[];" I3 P; T8 n: z: S* W
return ;
, ?; |: @# D, O8 n2 c$ Zif (negocios_autorizados == false) // are we outside the trading window?# s! f4 S# J( R
return ;
6 F& K+ ? a& B" Z+ Q//--- We are in the trading window, try to open a new position!
* M a b7 ` K! Q( \' dint sorteio = MathRand();/ X! \3 j" _' h. X! C" f
//--- Entry rule 1.1
/ a4 C/ U x/ p6 M5 Y1 Eif(sorteio == 0 || sorteio == 32767)
F( `. t3 b/ Areturn ;$ k n% Y( l, I" P3 e) @. f
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
. B* v w' m( {2 w8 g{
) c4 S4 e6 p3 J0 R4 L Xnegocios.Buy(info.LotsMin(), _Symbol);) Y3 Q8 L- I6 q5 m3 @ {$ q; _. Q
}
5 X* |9 n1 F) C$ Eelse // Draw rule 1.3 -- odd number - Sell
1 e5 p( e* W1 Q) \' H3 g{
3 Q/ i7 d/ T" `2 jnegocios.Sell(info.LotsMin(), _Symbol);- D( [$ r) R% ~( H
}
; l* J9 o5 V7 H5 T& o5 M! K" W}
3 f3 t) [, s9 B9 v) o//--- Check if we have a new candlestick...
! n+ W+ Y3 W& d+ O' ~. X( obool tem_vela_nova(const MqlRates &rate)
. ?& F, V: F! p5 a) ?5 a% ^{
1 J7 u0 ^) X: u3 y) u D# ?. b; J{
8 x$ ? X3 k2 q* g' oret = true;
% _% y0 f6 A- p2 n2 B- C4 D$ wclose_positions = false;
1 ~4 Q$ E3 R8 g}
5 F f# i! V. \2 s3 M, Ielse! R- _* z# J6 t% ^! `5 ~" _
{. F& I* }( ~* O6 K
if(mdt.hour == 16)4 n- _4 ]/ k+ A
close_positions = (mdt.min >= 30);% G3 R+ U+ s4 Y+ M6 D" _2 P
}
* E* m* g; G# ?3 A}
/ a1 ^+ @, m8 O. |- a# u( T4 preturn ret;
# E+ G5 Z2 D! N' F, K$ c+ r: J}
" v$ q8 ?0 J7 x$ V& x8 k% ^" X//---
5 E, x/ m- ~5 g5 B3 C5 `bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
$ Y0 R6 A, S! a{7 w( c. a* l' x; D6 \
if(PositionsTotal()) // Is there a position?+ |: _; u, Z# U
{
- a! n- E6 |* a) I& Q X, M/ Cdouble offset[1] = { 0 };
+ h- n2 t L% d7 _% Q9 r/ Lif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?- o/ U: L9 `$ r! [% p
&& PositionSelect(_Symbol)) // Select the existing position!
?" g0 a- Y( L. ~$ y& {# G{
1 h( S `, g' ^% i# UENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
! C) R3 {3 l+ \( T) |3 S+ \! cdouble SL = PositionGetDouble(POSITION_SL);
6 u5 R4 p/ C2 V; q* G$ ?$ C- W9 Idouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));( `( T, z0 D8 c
if(tipo == POSITION_TYPE_BUY)
/ t1 h- j5 g6 E5 [9 E( i/ p; A{
/ z# S. E9 f2 i* t% l- G- M: a2 _if (cotacoes[1].high > cotacoes[0].high)
! K* @: X) M$ ?& z# @. c* }{
! X M5 P/ u9 R! {( E% Xdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
2 b7 F: R7 s. k: q! ^! K f2 jinfo.NormalizePrice(sl);6 Y3 d+ M0 |, b/ e( v% M2 o+ Y0 J
if (sl > SL)/ ~) [4 Z. r: }$ o9 G# l) K
{$ `# f$ S% L4 j! X& e
negocios.PositionModify(_Symbol, sl, TP);
) C$ _1 n, z' | \- W}7 C4 i9 M( s" S% D5 O, |4 W2 t- I
}( H9 X* B) b9 x" j) a/ c+ E, Y
}" X: U- F" B( l7 h; {
else // tipo == POSITION_TYPE_SELL, O4 l6 X- j( R& P H
{
& ?7 j0 r) y* a J* yif (cotacoes[1].low < cotacoes[0].low)+ s2 P; I3 h0 u( ?9 E
{4 e* c/ U( e! u7 U1 e0 g
return true;) t+ }! j/ U, `/ s E- {- s7 Q: E$ p( L
}
0 J \6 R! g9 z, C// there was no position" k: `& F+ M* c
return false;
9 M+ I( k. j1 G4 f" ?! I Q4 S0 K' \% w}
$ p1 F( A9 t: j& z我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。) }4 t0 X3 k3 S4 T
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |