启动交易模型,并构建 EA! p3 N6 A/ N1 B& {
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
8 T. t! b% l( V% T ?为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
0 g7 f h/ m; t$ T* {以下是制定这些规则的代码。, x- }+ Y2 [) F/ b
//--- Indicator ATR(1) with EMA(8) used for the stop level...
1 S2 s* f1 f2 ], B# fint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
h1 a2 n1 f- r0 @int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
1 t8 K& S+ k/ j. [' n: ?//--- Define a variable that indicates that we have a deal...; u- W, x2 Q9 ]) W2 R3 _7 U# u3 N
bool tem_tick = false;
3 v2 M0 |$ G+ D M: v: j//--- An auxiliary variable for opening a position. }& S2 N( M8 w4 u" L) w( T
#include<Trade/Trade.mqh>" ? C' ^5 y4 [4 X) q+ I* e
#include<Trade/SymbolInfo.mqh>
2 ?7 I$ Q6 \$ m0 o$ d! xCTrade negocios;3 F8 G( r! g5 M( K, {/ F
CSymbolInfo info;
" v8 D m: Y" p/ I; B& V+ D//--- Define in OnInit() the use of the timer every second
: R- K# i3 k! ~2 Y" r//--- and start CTrade
" O2 t- Y4 N, cint OnInit()
6 Y4 ?/ G( c3 b/ c6 _8 Q1 i$ I( b{
" Y* C' i" j, W: G( L2 r//--- Set the fill type to keep a pending order7 q, B9 X" Y9 i! c; Q7 o# L
//--- until it is fully filled- [0 \1 {0 g3 e* w$ g
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
\/ c$ c' L7 E& M- c//--- Leave the fixed deviation at it is not used on B3 exchange/ D m. C" l2 |' ~
negocios.SetDeviationInPoints(5);
: y% H: P$ `' Q' |//--- Define the symbol in CSymbolInfo...
: ]& c/ q f' Pinfo.Name(_Symbol);, a6 d/ U+ Y) w+ t( o
//--- Set the timer.... ^* j$ J1 T0 ?% h# v: ?
EventSetTimer(1);+ V4 k" I7 A: Q" v7 {
//--- Set the base of the random number to have equal tests...
1 q$ @2 T4 D4 I, v; y) X: CMathSrand(0xDEAD);
! c% K2 v! H5 ]% M: l& ~8 mreturn(INIT_SUCCEEDED);% n! e9 G7 A+ N; P
}
2 ~& P" i% \4 }/ y8 i2 t. M. R//--- Since we set a timer, we need to destroy it in OnDeInit().
8 {( \$ y0 Z* \! W, x* _" Q1 Vvoid OnDeinit(const int reason)
; a( S; q+ v, e! |6 b; v/ e% z# w6 E6 p{
4 q( U$ G+ ]& J" g% p* ~7 AEventKillTimer();
% T- U! V, V; Z}. @; P! k* c# L4 e
//--- The OnTick function only informs us that we have a new deal! N, N& t5 G3 s2 ^" k
void OnTick()
2 L; Z/ r1 E* T* _* L% N; O{
8 P& N0 S) {& j4 }tem_tick = true;
! L& t/ Q! h$ M6 ?}9 b$ Z8 M; r; r# r I& Z% a
//+------------------------------------------------------------------+$ I0 G H& e: W" A$ O! i( }
//| Expert Advisor main function |7 n6 z9 [2 X, {1 N3 p9 b+ k
//+------------------------------------------------------------------+
0 Q" B; U9 j' s- E' j4 O k: N/ ]void OnTimer()
! Y, y. O9 N) c. t( @{
4 Q( [. a# }+ P" b1 {2 XMqlRates cotacao[];4 [- e3 S3 G3 g* g
return ;6 B \2 ^" x, R
if (negocios_autorizados == false) // are we outside the trading window?
& e7 t% @ W5 b& Preturn ;7 ]& L9 j3 s, s! J+ k* Y) e
//--- We are in the trading window, try to open a new position!' M& [, @$ ]. |2 k; V1 d
int sorteio = MathRand();- |4 j) v8 \9 a( s
//--- Entry rule 1.1
1 v1 ?5 p; P3 ]( _$ O. Eif(sorteio == 0 || sorteio == 32767)9 ~. Z2 Y2 g; k9 N" f2 c
return ;
8 Q" a/ w; n* t$ Jif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
, B1 [' K4 k+ g$ Q( j4 Z @) ]{$ m6 k3 e ]3 C3 o. b
negocios.Buy(info.LotsMin(), _Symbol);1 K& M& f9 W: z2 s+ i. D' q' R
}5 m" q2 {: u# J9 C& a
else // Draw rule 1.3 -- odd number - Sell" g6 B! j3 A- P8 P
{
# j5 w* ~: ~" i. _4 lnegocios.Sell(info.LotsMin(), _Symbol);- W5 }. A7 E& u1 O
}
4 G4 F/ Q0 ~' }( Z6 o- Z}
6 F) W& C: ?) m$ E) m1 u; K//--- Check if we have a new candlestick...
* F: S2 [! x5 L' g8 Bbool tem_vela_nova(const MqlRates &rate)
* C W; O# D( S6 A' _{
2 {: `8 D: i+ z1 }; N, s{
" b( S p% y6 s7 }" r5 lret = true;1 O8 d9 a5 m2 x2 I0 s6 p
close_positions = false;/ Y- _& Y; k7 U+ x- i
}
% j: J, F4 f+ uelse
+ b1 i) k: s+ l& p4 Q6 j{5 l1 j& l, g' X5 v1 Q0 [
if(mdt.hour == 16)
( {: W V" V1 F+ Wclose_positions = (mdt.min >= 30);% r' G' F/ ~* b& W% t/ S
}( O4 N% W9 ]" t+ x# U
}; Y/ f* w$ A9 Y. e; y
return ret;1 i. Z0 f- w+ C8 F3 K7 E* Y3 F
}
- @9 T6 s+ S: _' p5 ~//---
2 o) _/ f- n! [" U% ebool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
. M) L* m# D0 ^6 U. T{
7 f( l i9 v; X1 fif(PositionsTotal()) // Is there a position?
; I T$ W4 A6 c{% i5 ?( U+ h, N; F; p r- B5 k7 q( I
double offset[1] = { 0 };6 u6 J8 k6 \8 F8 c; R
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
; P2 ^+ }& k0 b; }&& PositionSelect(_Symbol)) // Select the existing position!. l, K" I$ B! H' R
{1 y- w, i8 _1 I8 Q$ s, {+ d
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE); ~' x: C6 y5 c ^+ W
double SL = PositionGetDouble(POSITION_SL);
% l, C7 u( P4 d$ c( |6 B: P3 Ndouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
9 q' B9 Z/ g9 Q8 Eif(tipo == POSITION_TYPE_BUY)
6 j. _$ w. C/ M{
! N6 ^4 k4 V5 L2 i# Q2 lif (cotacoes[1].high > cotacoes[0].high)
2 }0 X( w! s5 c, T% c2 T{
5 J& f3 {( i1 v' b) R1 b. ]6 [double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
$ P, s* C9 h0 hinfo.NormalizePrice(sl);
5 [; a6 ]' G- Aif (sl > SL). o `+ `' }+ t. B4 [
{
9 @& U$ z+ R/ Enegocios.PositionModify(_Symbol, sl, TP);% x" {3 t* C/ d( y* q
}$ u6 R& h0 C' u! `8 l3 Z4 y1 @, N
}. C) j9 M) [: u+ E
}
- M2 ~; W# D+ `/ ~& K C s& zelse // tipo == POSITION_TYPE_SELL1 d- W# _ \ W G4 h. a: E
{
; K4 U O" h C1 o+ a# U* Dif (cotacoes[1].low < cotacoes[0].low)" k6 [% f/ k5 I' E
{
5 {7 m5 `7 b V1 n1 @' P3 |6 L6 preturn true;( K2 o8 L& J$ p+ G4 f
}+ D$ T( U4 M! f3 }
// there was no position
0 [3 n& Q4 K2 N; h' zreturn false;6 F8 I2 {& w6 _9 x! s% [
}
7 {2 i6 g0 F; h P5 I6 X1 c; M我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。# h# T2 S. p3 e* c. i% Z t$ o( V
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |