启动交易模型,并构建 EA
+ I/ }0 E1 k: ^. X在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
2 ^3 ]3 s( q! ?为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
* X) d9 D+ h* V! y以下是制定这些规则的代码。( _0 R. ?+ {. f0 I. s/ N9 W4 {1 Y- |
//--- Indicator ATR(1) with EMA(8) used for the stop level...
$ g- T2 A) z! I& N [int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
8 O+ E. y9 ?+ B5 n0 vint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);( W4 X% V7 D, U3 r2 ~4 {' {
//--- Define a variable that indicates that we have a deal...* q) W' V8 j$ h7 B
bool tem_tick = false;
0 f) N0 [( n$ Z( y6 z//--- An auxiliary variable for opening a position5 v( i7 a9 \' X( }# `
#include<Trade/Trade.mqh>
4 \/ \% j% l7 O! N! B9 r1 @2 b) P: i#include<Trade/SymbolInfo.mqh>
; j1 {5 ?, \9 @/ h& s. MCTrade negocios;
; u4 t d4 {6 ~3 B/ h: I7 rCSymbolInfo info;
) z: P/ I3 `- S% J- m//--- Define in OnInit() the use of the timer every second
; W4 J" E' E2 c. v) c. _# @//--- and start CTrade' R4 d1 D/ g8 r4 E
int OnInit() F) f; k) j, c. m
{
$ H+ s, h$ p) V0 t3 @7 v" o//--- Set the fill type to keep a pending order# m. p% H0 E. {/ ^0 i
//--- until it is fully filled. C* F R7 y6 r+ }, G3 l/ d. M
negocios.SetTypeFilling(ORDER_FILLING_RETURN);
' n. R8 g- W w: ~3 G//--- Leave the fixed deviation at it is not used on B3 exchange2 G7 j: z( K/ }0 N5 L+ \" {2 i
negocios.SetDeviationInPoints(5);
* H3 a7 l" L, o& v; @, I% e//--- Define the symbol in CSymbolInfo...
8 w) b D. f- V2 O/ b+ T. c( rinfo.Name(_Symbol);
- J1 Z0 V/ a" r. J" u+ f//--- Set the timer...
- M; n5 Y; W. YEventSetTimer(1);7 i) E. K$ A& D: j
//--- Set the base of the random number to have equal tests...
" c- E" o2 e$ F, l( f6 HMathSrand(0xDEAD);+ Q/ \0 x: h, V# k8 }
return(INIT_SUCCEEDED);
6 n$ A4 n! i8 k6 L: L: ]0 w}
( e$ D" h* ?, D: f" v! j//--- Since we set a timer, we need to destroy it in OnDeInit().% _1 e7 @+ L, I) g7 [
void OnDeinit(const int reason)+ G! {3 H4 s2 U
{
9 k u! q+ X3 L! h/ @# [' iEventKillTimer();; h& M5 m9 S9 U i
}
/ C* Y- z' r( V( l//--- The OnTick function only informs us that we have a new deal7 U" A7 n( X8 N7 o" a$ I
void OnTick()
1 R: N. ^8 p) @{/ i: j s* q( @9 l* v% I) g, t
tem_tick = true;
2 O( w* y \, P s2 S$ s}
7 X" K' y b" b//+------------------------------------------------------------------+
r& T/ r3 {! T. ~! U+ j9 `//| Expert Advisor main function |
2 Z5 V: f/ u8 k3 J//+------------------------------------------------------------------+6 b! E4 d& B3 j" F9 @8 r: I
void OnTimer()
" _5 L3 i; d1 H- K) d# P- m* A{/ M* i7 ]! J; p/ e t% M+ T
MqlRates cotacao[];
; e: i- }+ l4 g5 ~; W7 p5 i2 E Areturn ;0 S+ W. d/ A9 V4 N: w' ^
if (negocios_autorizados == false) // are we outside the trading window?
* o0 s* b% f1 ^1 N1 qreturn ;
9 Q k" r" w* V* P' t! \. B- q//--- We are in the trading window, try to open a new position!
$ E9 P2 p' I2 F6 s4 z" I. w1 Nint sorteio = MathRand();
. Y7 l- k' C% u; b4 l' a" [//--- Entry rule 1.1" k6 m, c8 ?) y6 u/ Y: x6 n
if(sorteio == 0 || sorteio == 32767)( n2 I4 d: `# r
return ;
0 P$ Z. T0 t; z! mif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy2 l' P& A0 W% K# x
{
2 j+ D6 z4 H1 u5 W' {2 Vnegocios.Buy(info.LotsMin(), _Symbol);
# @5 T$ q" ]2 }# ?- }! k5 z0 l}
p8 [ h" j3 V3 Z" r8 oelse // Draw rule 1.3 -- odd number - Sell% t9 }# u* N+ q6 Z/ W3 X w( ]1 E
{
# e5 J3 K/ f A+ ?1 }" i/ unegocios.Sell(info.LotsMin(), _Symbol);
# o+ k/ K5 ^# I! a$ t$ J/ |}
# B2 Z A+ R3 q0 A}3 o) ^/ M0 g: ^- O+ g
//--- Check if we have a new candlestick...6 u; F/ ~! X# ?$ ]/ V
bool tem_vela_nova(const MqlRates &rate)
" |" J6 ^- ~0 s7 Y1 m6 P{
) [$ Y+ V8 \, U# K{
1 \1 w5 I* `, W" a6 E: k% K/ sret = true;5 R: E: c% a2 T1 T9 _+ o
close_positions = false;) W) |1 t" B4 m& A. z
}* v6 V w5 B# V7 t& [; h3 \
else7 V7 w: x" h! j2 u( T. S
{: ~' U0 d0 U& W8 g$ P
if(mdt.hour == 16)6 l$ \2 Y: ?; u! |2 s# p. X
close_positions = (mdt.min >= 30);
4 F O* ?, d9 J, U% r}
: ~8 B# [/ M% F; q; ~}$ a6 j) g9 W, w& R
return ret;
/ P6 I( a n' ?4 g8 h/ G" v}
( w, Q# S+ {, k//---% F& f& R* n' G! r: h! Y+ P* t6 H- U
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
# g" L* ^# h; h- n{% x7 {% C/ b; c* p6 p
if(PositionsTotal()) // Is there a position?
9 Q2 }7 i3 v6 X' T6 E3 _( |{
. Z5 N) e4 H6 n- f2 Fdouble offset[1] = { 0 };
8 \( ]5 W4 M$ [0 x) l% j3 D) Gif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?8 B: n3 n5 Z$ w# j4 e
&& PositionSelect(_Symbol)) // Select the existing position!" x: U1 ~& n0 t) o! o9 f& h
{( g+ v5 ?. l7 j0 C4 [
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
# `0 _( p6 [9 ^* |double SL = PositionGetDouble(POSITION_SL);
" I- p5 W3 ^- u; ]: Y: {1 X, Ldouble TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
O+ x: G% A. d8 H. U* ?% n9 pif(tipo == POSITION_TYPE_BUY)
+ Y5 `5 j# A, o; ^' E- m3 z{
. I* W+ I3 m) _8 f0 R, Cif (cotacoes[1].high > cotacoes[0].high)
6 \0 P' S0 ?3 [7 O{
) @" P% A6 ?8 S7 ~* m( V6 @double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
1 y0 B. q* T b6 G; dinfo.NormalizePrice(sl);
, `! N- p( Q2 ]if (sl > SL)" r0 U9 n$ B2 I8 `/ e
{
8 V' c. T: t: z% y4 V% Gnegocios.PositionModify(_Symbol, sl, TP);
' z3 Q# m! g! m: x2 N}. p7 h2 |; P0 U+ j2 `3 M' {6 [
}
$ A9 m: R r# z% {& X}- i) F/ Z% O) L1 z1 x! ^
else // tipo == POSITION_TYPE_SELL
( f$ E% z' W& `0 N* D4 s' _{- k) {( C' ]3 R" W4 H
if (cotacoes[1].low < cotacoes[0].low)
' m# e) I x p8 F6 X, T- `{
9 L- {" u. F) }! g/ h- I5 [return true;
% _" {! c$ c1 t0 {}
6 ?" p/ G- ^$ [% F" F; l* V) h6 O// there was no position9 c" [, I! s: H3 Z O
return false;
1 S, O+ |2 t& [}
8 q, f' J$ i: a9 p1 N# V( I我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。
@5 G% z2 z8 I, l) B到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |