启动交易模型,并构建 EA5 Y; `- Q6 d; p5 J; i+ m X
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
6 t- b' d; G5 Q- B+ Q+ G1 j为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。2 A b5 n5 P" l6 H3 Z
以下是制定这些规则的代码。
5 f+ f2 P9 F. c! x8 z//--- Indicator ATR(1) with EMA(8) used for the stop level...
_/ r: p" z5 T" sint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);" u& z+ @$ s M
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
. P: m' c7 |: n, E4 a; r4 W//--- Define a variable that indicates that we have a deal...2 W U( t) O3 S9 J
bool tem_tick = false;
/ Z; Y4 B- [* G s: i7 O9 b//--- An auxiliary variable for opening a position3 B# S( O( ]- T' r! [& G
#include<Trade/Trade.mqh>' @6 R/ s i, g
#include<Trade/SymbolInfo.mqh>+ J4 w+ S% r. z& M% G. N4 z! \$ g
CTrade negocios;8 Z8 Q6 \7 @0 X3 x% {. h
CSymbolInfo info;0 g. ^" i$ X. M6 ^
//--- Define in OnInit() the use of the timer every second7 G' V4 t; ?5 h+ ?, {2 [
//--- and start CTrade
4 t* U6 ^7 F* {1 mint OnInit()
% g/ i- @6 _$ U( L{
) G: ^* C! S; Y& x3 |* z//--- Set the fill type to keep a pending order
9 T2 x7 c& F, F* c//--- until it is fully filled6 r& R: L' e4 \
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
. t* s8 z. S! N6 v7 r+ k//--- Leave the fixed deviation at it is not used on B3 exchange
! q# o' d: \- o, q/ c1 k+ f1 I4 Onegocios.SetDeviationInPoints(5);
3 n0 |4 E( r% G* Z) b//--- Define the symbol in CSymbolInfo...
+ G3 n0 i4 w0 T! C2 \# Q$ }info.Name(_Symbol);
4 {- e$ v0 r: _! r& P* c- o//--- Set the timer...
& T' U& l5 J) z1 ~3 H/ b3 \EventSetTimer(1);0 F: h* {" T& r4 j
//--- Set the base of the random number to have equal tests...! d6 m6 o: D, z9 w! J
MathSrand(0xDEAD);% N( S; z$ R- p/ y. \3 S( ~ P
return(INIT_SUCCEEDED);
- `8 {' x( y1 o; O; Y% Z6 U3 F% S}8 {6 i% u, J3 Z; S
//--- Since we set a timer, we need to destroy it in OnDeInit().
4 v& S- t3 B) Evoid OnDeinit(const int reason)! V( O! `' W; V" ~) D) o
{
) r3 a$ W% h# F( O; }# R1 _( nEventKillTimer();
& k7 |5 @) Q1 W8 Y" Y7 w& ]: [" ?' G}5 h1 f( n( A: @" T8 h
//--- The OnTick function only informs us that we have a new deal" V* m: i4 d7 D1 I0 F
void OnTick(); \$ H `8 d) g& m- a$ |: i
{
. B1 b% v- o) Ctem_tick = true;2 g8 g. }$ X# V! U; G/ S
}1 B4 o# f! i; `, x
//+------------------------------------------------------------------+
( n g8 e. g" o: l//| Expert Advisor main function |9 M* g4 t" B/ T, e
//+------------------------------------------------------------------+ S& f: a1 {! _" i8 X
void OnTimer() @" T2 `; p. ?# c4 f
{. H2 W: L6 z8 V2 u2 M
MqlRates cotacao[];
; X Q$ \) }+ c# yreturn ;. M, H Z$ c) o+ ^4 U2 N' \
if (negocios_autorizados == false) // are we outside the trading window?
4 B$ |# p% e- nreturn ;
' l/ y3 Y; L9 j2 d P//--- We are in the trading window, try to open a new position!
3 @) `% p2 N& S6 {7 o' z! ^, oint sorteio = MathRand();4 l( M+ e+ j3 z4 f' ~, K
//--- Entry rule 1.1 P' N5 r; B, r6 o
if(sorteio == 0 || sorteio == 32767)* a. E; X3 l' j& Q4 S& `
return ;; C& n/ n5 a6 K+ P
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy
( j8 v, Y I/ w4 @6 D6 J{
+ ~6 h- |0 ? G$ Snegocios.Buy(info.LotsMin(), _Symbol);
g! x3 b1 m; B+ O# `/ P0 o}/ z+ \" s V/ n p
else // Draw rule 1.3 -- odd number - Sell: J: e0 U @7 h
{
- ?4 X3 A: i1 Ynegocios.Sell(info.LotsMin(), _Symbol);$ h( X J# i7 Q" [
}, E+ {6 ~) v o: h$ f( {" A& e b
}
; b8 e0 L u. O9 Z G8 x1 S//--- Check if we have a new candlestick...
+ t# i$ l4 b( cbool tem_vela_nova(const MqlRates &rate)# v6 O0 Y; D0 y
{. i! [6 P2 I! z0 F, d* h8 d
{/ T* A9 |- p6 }& x# w" h$ U+ v
ret = true;7 C* B( Z5 l A+ N# r6 P- R
close_positions = false;& O \: y/ m, I1 ]2 F+ q) y
}1 P; y( _$ H# E( w5 N+ D7 h
else: u* t1 H) \! M3 i( ~: s: _# [
{
8 t0 [" v( w* Q/ d! |- F+ \) a% q6 Cif(mdt.hour == 16)
% q; q2 }: T/ a8 c& jclose_positions = (mdt.min >= 30);
0 i6 B; Q% N& s}! J! v1 h. x3 ~5 @+ A
}; B r5 ^7 W& ^( z; }+ G8 I
return ret;9 V3 G. y- l& ^
}
) h! S3 x3 _) L( Z//---, R- H3 d3 E: [6 o$ R
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])& R. K/ @! v1 N1 Y* [' D8 c: K7 @# _% v
{
6 G, o, H1 h0 Z2 D3 _' `if(PositionsTotal()) // Is there a position?" B$ ~4 x( w M" F* I
{
! X1 N: Q- Z! [2 ~0 R: v1 j, Odouble offset[1] = { 0 };
x4 W% L9 \$ e# x9 q6 fif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?' v2 X( L9 x8 K
&& PositionSelect(_Symbol)) // Select the existing position!4 i, F% R1 F% b! B& e% h. p
{( x. g! {, _ y% i" I, Z# @
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
3 O1 O& R3 K; U% U9 y- D3 Rdouble SL = PositionGetDouble(POSITION_SL);
; z$ |. ?( a$ w1 Sdouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));) `& o2 z" i2 O
if(tipo == POSITION_TYPE_BUY)
8 E1 W% L) e3 u* }{
$ B5 H1 R$ i7 }4 mif (cotacoes[1].high > cotacoes[0].high)
5 ^5 O8 n( |, W5 G! U9 ?{8 B! O6 ~: I( ^
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
2 Y$ i6 N" G. L6 \* d0 H2 v9 Oinfo.NormalizePrice(sl);$ B9 H- k. S2 _ u' c3 W
if (sl > SL)
- L, L9 R( G" ~( w' G9 c# H I{* K4 h4 ~6 o: ^) T8 h
negocios.PositionModify(_Symbol, sl, TP);4 B! B2 B0 u4 y# B! V, k
}9 i+ a; }3 L6 l
}
# Q. R% K6 L* _! h" z1 k8 v5 s5 a4 s8 G}
% s4 Y+ l q9 Oelse // tipo == POSITION_TYPE_SELL
3 V. ?( P b# B8 S& v{
* C2 i( y) E6 H" lif (cotacoes[1].low < cotacoes[0].low)5 R) e2 E# @6 p/ |. |# U( ^
{
I% @; ]: D1 j# m% f+ xreturn true;
Q! Y) J; m% Z2 N+ f5 e% Q0 I/ }: `6 T}
0 [* p0 m' a$ N// there was no position& v1 Q8 v& @! _) i) h' v
return false;% q- x) t: B1 d# ], `
}7 X0 x/ o% P3 T
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
; s- w! ]6 K7 U到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |