启动交易模型,并构建 EA3 v Y- }. T' F2 z$ J
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
+ m9 S8 k9 i' t' d# h, W( F+ c4 k$ r为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
0 }! V$ r+ F% u1 g9 }- Z以下是制定这些规则的代码。' P8 T9 R* ~6 O
//--- Indicator ATR(1) with EMA(8) used for the stop level...& I' C5 ]( V! @/ }
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);+ E4 ?7 s, a' p* e7 V4 [
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
2 K& u5 q' |( ]# _//--- Define a variable that indicates that we have a deal...
' ^7 g8 b7 Q# Y8 }6 U S6 W, I% z( Nbool tem_tick = false;
7 d+ X8 H$ g; J. m//--- An auxiliary variable for opening a position
+ ?, v& \9 A: M s#include<Trade/Trade.mqh>( Q1 r# B" l7 z
#include<Trade/SymbolInfo.mqh>2 X! [( i$ P, ]( X7 Z: a
CTrade negocios;! Z$ o7 o0 [$ Q! b" o8 F6 w( E
CSymbolInfo info;$ ~% e j X3 }$ I0 S
//--- Define in OnInit() the use of the timer every second
# R1 {# c" _( `# s3 ^: f* v//--- and start CTrade# N, O4 ~; P2 c
int OnInit()
: z& D4 |. X6 @' u ^8 i, ~1 t{
1 {# \& z' M+ {4 G; U$ k+ s ?. w//--- Set the fill type to keep a pending order. v x( r. ~) ?
//--- until it is fully filled/ I4 K' I8 [$ J9 y# G) P2 p+ W
negocios.SetTypeFilling(ORDER_FILLING_RETURN);- A; Z2 y; H/ H8 x! Q9 J! r
//--- Leave the fixed deviation at it is not used on B3 exchange
0 _4 x) s: }$ n0 _ k" V% Anegocios.SetDeviationInPoints(5);, p- S- e' l: k) Z* K! Q A1 Y
//--- Define the symbol in CSymbolInfo...
- w- ^3 ]( {3 i4 V d- L/ Linfo.Name(_Symbol);
% a( ^! B4 V; v, X5 E, K0 I/ _/ ^( _//--- Set the timer...
& q: Z& Y* d6 [4 J1 i* PEventSetTimer(1);
4 n9 {3 _9 _" B& U- d7 Y1 O+ q//--- Set the base of the random number to have equal tests...
$ M2 X5 A' E5 A) q8 KMathSrand(0xDEAD);
2 |2 L( `0 }' L, sreturn(INIT_SUCCEEDED);4 S G- f M* r/ Z: T8 A
} ~! ~$ S8 ^0 o! H
//--- Since we set a timer, we need to destroy it in OnDeInit().
" e# T" h2 z* y. R$ B3 o+ v3 w1 |" V% Gvoid OnDeinit(const int reason)
. @: ?8 S, x1 i8 q{
/ z8 R0 _+ K1 u. XEventKillTimer();
% D; w3 [5 p2 j' }}
' F% ?" t! T1 V, g! s//--- The OnTick function only informs us that we have a new deal
+ G5 _/ d3 |$ w' L9 }$ pvoid OnTick()
/ i A- L2 C, |4 j6 }3 J{7 o/ \; M0 K8 }4 {
tem_tick = true;0 e& D0 U) s# \0 f8 A0 s/ X
}" f% h V2 ~" ?3 |7 }
//+------------------------------------------------------------------+2 Z) z6 c8 f6 j/ ^$ S/ b8 S
//| Expert Advisor main function |' M5 ?6 U. l8 h9 a
//+------------------------------------------------------------------+
/ u0 \3 M$ c- d0 n0 F7 C1 tvoid OnTimer()
3 Z, ^4 G4 x* O5 f0 l{- E" d8 ?" r0 Y% }
MqlRates cotacao[];
" f# x6 c, l$ E1 Xreturn ;
`8 q' W8 b& M( A5 L6 eif (negocios_autorizados == false) // are we outside the trading window?
9 D3 E) K* L2 E$ o+ \return ;
& w& M$ y# ]! a- T( t: G( E* d+ V//--- We are in the trading window, try to open a new position!
+ J3 j1 z1 H& ]; O6 e9 dint sorteio = MathRand();0 F1 K, H" G; k, N
//--- Entry rule 1.1
* [: p* |" |, ]5 vif(sorteio == 0 || sorteio == 32767)7 j O' v* i% m
return ;
" j8 ~9 `+ Y7 P) F- Q* f/ G, Rif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
! q8 E: l. q: c7 x! s3 k4 c{/ D9 M- Z6 z O
negocios.Buy(info.LotsMin(), _Symbol);, G3 P" L8 R8 V/ U
}
8 T. @7 ~4 i6 z* a- `3 Gelse // Draw rule 1.3 -- odd number - Sell2 m5 I7 C' X6 y$ n$ D7 |& O( I$ P
{2 `$ p% s4 _. x) k. L9 a1 i3 {
negocios.Sell(info.LotsMin(), _Symbol);4 T; d8 Z5 y4 y' T1 q
}% ?5 M( T- q; O9 D" M* B
}, U* p4 P6 F3 q1 x6 {( [, ~4 Q1 V
//--- Check if we have a new candlestick...$ L. h# o3 T4 K$ C$ e
bool tem_vela_nova(const MqlRates &rate)
: x+ U3 Z( ]+ z+ a1 f. }2 X{
4 k- J4 d5 }7 v1 s0 j( R{4 y$ L& s1 z) @. G& |* z. ~
ret = true;& _2 i2 x( m0 K- l: b# p
close_positions = false; @* x4 ]$ _2 L) e: H$ v! U
}
: R. Q3 |. e3 D) Lelse9 \' d1 ]7 k+ y3 u/ ~' X
{
Z! i" B9 a# e; O$ T3 F7 nif(mdt.hour == 16)
/ D* D/ p9 Q P% m9 s1 }2 bclose_positions = (mdt.min >= 30);3 M/ B8 d/ _: U4 x. d
}
/ {9 C6 A. P8 r% a}
9 H7 v0 ]2 V! j/ M5 a# @* areturn ret;. Z8 Q7 t9 u& K' E( \2 b3 U2 _
}
( {3 K, o, q( I }2 L; }//---
7 [) y. ]% S& T7 Bbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])0 F8 e2 a9 q% Z
{
1 t, X, x4 w! G% Vif(PositionsTotal()) // Is there a position?
% a8 w+ P4 b. _; }8 Z{
/ u4 p, O) a7 ]' n$ {' G, Adouble offset[1] = { 0 };
3 s. b: N( j7 Cif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
4 |. N) a6 V; V9 Y. L9 J$ R&& PositionSelect(_Symbol)) // Select the existing position!
& x7 s. z+ G1 H, M# S6 v* {6 D7 s{
6 p3 z! ^$ C$ |) ~ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
7 [: s$ O3 \. q2 o# U5 i2 q- Udouble SL = PositionGetDouble(POSITION_SL);
! G" O$ \. D3 S8 W% mdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
: P2 C4 O8 c+ K- ^ k3 Fif(tipo == POSITION_TYPE_BUY). R% b( b3 b) t8 v0 U! _6 D
{. Z0 Z. W! [' W! l4 _# q, m0 _) `
if (cotacoes[1].high > cotacoes[0].high)
4 A9 Q0 V& \9 k5 U9 U$ Q4 r{5 T" C! Z: B5 i2 O6 r# [
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];# G* O- u1 S, A- w
info.NormalizePrice(sl);, F) z; d5 H5 \' R
if (sl > SL)
( s: w1 _. v, }6 j, K{: j( O2 U' Q0 U3 }. X
negocios.PositionModify(_Symbol, sl, TP);
& G3 j+ B. J" m2 {1 N}* L! \. W1 y- d$ r) q
}
( a) N9 B/ r! d2 Z5 i( Q( a' O}
: Z9 g6 e9 p5 r; n5 F' Z. \1 i" T kelse // tipo == POSITION_TYPE_SELL" |" d7 R6 v ~: ^0 Y" Q
{
, D- S4 L q* J& R. T cif (cotacoes[1].low < cotacoes[0].low)
0 I* c7 m' E5 ^$ v4 C{
4 W9 {3 D2 W1 R% y2 I) K3 a/ ]return true;8 s2 Y% I/ f1 g) L* |& v+ A2 |
}; F: f0 L: T; u- o D5 C
// there was no position2 ?: A% j2 ~( ?! @/ \3 q" h
return false;- h! {' U* N G, n3 o Y9 m
}9 K( z6 Z8 p& Q9 x1 w) c# t) L
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。+ m4 B8 ?# U, F( e) s" D* B8 a
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |