启动交易模型,并构建 EA
0 e. j1 M" b1 V" | W在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
: D4 X& Y2 Z2 {& `7 _+ a4 \为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。* O7 b6 s8 C2 T) a( x" {
以下是制定这些规则的代码。1 Y5 p8 {6 P7 x e; Y
//--- Indicator ATR(1) with EMA(8) used for the stop level...
8 y+ v$ T( v% @0 r& Bint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);' T% Z) E8 z% ?, X. w
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
6 N0 B9 H4 l: B4 j5 }' `' b//--- Define a variable that indicates that we have a deal...
\+ [- {8 a& d: i6 Mbool tem_tick = false;
9 J( L, X: _3 C7 l6 F//--- An auxiliary variable for opening a position% P/ s$ e. ]2 G: ]
#include<Trade/Trade.mqh> f- _2 H0 x! y. ?" R' p5 e
#include<Trade/SymbolInfo.mqh>
4 j, H1 c& F: |1 {! H) J% DCTrade negocios;
7 q6 c5 x9 a/ u1 O4 XCSymbolInfo info;+ g% c; W% m, V- q
//--- Define in OnInit() the use of the timer every second! B. M8 G! t! O' i8 [; ^8 ~) B8 N! J
//--- and start CTrade
4 L8 A1 u; m3 e1 `/ V* |int OnInit()
) H( v) ]: m6 t) e3 u$ a) `3 C0 U$ E{1 C0 H/ I! n& D6 M: I* }
//--- Set the fill type to keep a pending order0 d) ^0 K Y5 L, S5 A5 P
//--- until it is fully filled
A) J* d" V6 _* K5 k7 V1 U. G6 U& onegocios.SetTypeFilling(ORDER_FILLING_RETURN);
4 C9 b- s& K1 I/ L9 y4 z2 _//--- Leave the fixed deviation at it is not used on B3 exchange* V) A p5 R# X
negocios.SetDeviationInPoints(5);
; e1 Q* B; i, x8 m) e' \0 _! _# z//--- Define the symbol in CSymbolInfo...
$ D, e2 q1 f) R. X& E% vinfo.Name(_Symbol);
$ @, S( L; p( X/ k3 i2 Y//--- Set the timer...; [) V( M9 E; [+ v3 g
EventSetTimer(1);
/ k' g6 \' H; T- s- D/ }! E//--- Set the base of the random number to have equal tests...
2 K( T/ R+ i3 T6 X$ u3 tMathSrand(0xDEAD);; w: t7 g1 ?, g. U) b$ A
return(INIT_SUCCEEDED);1 S: S5 E" \5 q" b. V6 k
}( {0 \# d8 q, `& Y
//--- Since we set a timer, we need to destroy it in OnDeInit(). j7 |$ s3 a! ]' T4 {5 `
void OnDeinit(const int reason)
% n3 O0 y! V( I& i{) o8 D. g7 s- g9 i2 v& E
EventKillTimer();
# r- u4 H5 n: P/ j1 F# R0 g4 B}
( H( P$ n2 f1 a//--- The OnTick function only informs us that we have a new deal
3 m$ F3 l% v7 f' V8 Dvoid OnTick()) @3 S8 Q1 a& f4 g, r2 Y3 U
{7 k4 a7 E) a1 X+ l7 F
tem_tick = true;& O% l3 Q! j5 r* r9 b" O! C
}- I. L0 g" W) |: r, y, S7 V- Z
//+------------------------------------------------------------------+
+ L' m$ B: E7 w6 c- G1 b* c//| Expert Advisor main function |: {+ M7 p1 D, ~$ E0 q9 i
//+------------------------------------------------------------------+
9 {& Q! x3 a4 `! S. ovoid OnTimer() {1 z6 }5 A. H. W+ F
{
% n3 y& Y/ V0 J- |( C, h9 K0 A" ?MqlRates cotacao[];
$ P& E1 \4 q; D. p3 h" b( ireturn ;; G" C1 z! Q" Y; g4 g* s
if (negocios_autorizados == false) // are we outside the trading window?! M& E% h3 v) E# `3 J0 y/ J
return ;
, d7 P1 n4 s4 B7 D0 D9 J//--- We are in the trading window, try to open a new position!
) u0 i* C$ n* d( X( V8 Aint sorteio = MathRand();% k/ F1 C8 f, q' v
//--- Entry rule 1.1
: ~0 C+ @) D6 vif(sorteio == 0 || sorteio == 32767)
1 m x! A' R; n7 A7 O% @3 breturn ;
$ e. ~* Z0 |9 L/ Y. _% Cif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy% X. x( M* Y4 p! k4 G3 w% z# N
{
7 _# W6 k% o# Vnegocios.Buy(info.LotsMin(), _Symbol);7 I# I" q5 v1 w1 T" b. e
}
9 v) W/ X U, d' X# zelse // Draw rule 1.3 -- odd number - Sell
% A* K/ a1 R+ O* m, J{
5 A; t5 L- V2 T. onegocios.Sell(info.LotsMin(), _Symbol);; S: P5 S5 l, _6 _9 t) l
}
3 G5 B, i/ [6 F2 O/ R}* A' j" I. p; v* C2 A# ?3 j
//--- Check if we have a new candlestick...
7 Z& n) a' R" m0 [6 E5 K' U1 dbool tem_vela_nova(const MqlRates &rate)/ d G; R; p* Z+ T& S
{0 D( f; ~( |5 x5 n
{
0 ]: i N( w6 Uret = true;1 Q. K& @. w4 c6 K) M: m
close_positions = false;
: N8 r! |8 R! @/ q3 E2 z9 e}2 U+ t% R6 j' r: x9 f/ s4 e
else- R- Q( n5 A) z% \
{0 X+ c! ^* P3 J/ H
if(mdt.hour == 16)
7 ?' ~* B! d" R3 }close_positions = (mdt.min >= 30);
: s5 ]" _0 q; F M% G5 V+ d}5 `6 k7 q6 g8 ?# R
}7 z( B. V8 M: @8 q: \; A. |
return ret;
* d4 ?& d3 E: u}
( x E ]+ Y- a4 G) R9 L9 S8 [//---
; \0 n& w. N A7 y! W* M0 Q. Nbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])- @9 t) }' j" x a, k7 z7 P: d
{
, k- A) [8 p; r8 Aif(PositionsTotal()) // Is there a position?
/ x* `# r5 Y/ ^{9 u( Q: N3 G. [, F
double offset[1] = { 0 };6 r9 E9 y* O- ^) t* v
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?6 R/ u3 p8 M: E7 ^
&& PositionSelect(_Symbol)) // Select the existing position!
$ A7 a n( d6 G. c1 Z{' ~( \6 |7 d, y/ t
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);' j. C! H7 c# l: k" e) l9 n
double SL = PositionGetDouble(POSITION_SL);+ e7 Z& X/ x1 H; P1 X0 t l; L
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
; N7 i4 N7 p) Vif(tipo == POSITION_TYPE_BUY)5 F5 M& h$ E. Y! n2 @- C
{2 A' h/ v/ }3 S! e; w
if (cotacoes[1].high > cotacoes[0].high)$ c* T/ Y3 ]0 \* m! k: c- f5 Y1 G3 j7 Z
{
3 y, {) B! C! q# xdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];; _+ J/ M5 {6 {7 k' n9 T: D
info.NormalizePrice(sl);
& k+ R1 h, \/ L) @; @' vif (sl > SL)
* o& [$ N) }- G5 Z7 Y( w{6 q. t% Y6 ~" q# C `
negocios.PositionModify(_Symbol, sl, TP);
' I# [( J$ F/ W" m}# U `/ ?0 M1 r) x3 d: U
}, V& G3 ~' h0 c, D+ o
}
, d1 O3 R3 E3 W4 H% T! l1 [else // tipo == POSITION_TYPE_SELL- A" U4 R0 x: a% t8 I4 p
{
: T0 i: g+ e& h. N2 Nif (cotacoes[1].low < cotacoes[0].low)5 K, }: O9 R, E
{
& }$ z" {0 v: ^& L dreturn true;
9 M; A4 l9 G: s! _+ `' A' G2 H4 l}
: M; k/ n8 r3 b2 K6 O- y// there was no position
' B' Q' m% P' l8 g/ B9 M$ Areturn false;1 i$ a0 s; g6 x# a, H5 H9 ^
}
& z! X' s7 |4 i+ |6 J; ~我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。! j& n9 Z) O5 I$ }
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |