启动交易模型,并构建 EA/ [8 v' @7 q2 k t5 X7 J U
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。) f+ ?" B+ L7 n7 h! a& h8 f+ w- g
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
. U" t4 z' N2 `$ J3 s$ `/ j以下是制定这些规则的代码。. n4 [6 y( A+ k+ N4 f
//--- Indicator ATR(1) with EMA(8) used for the stop level...
: x+ \2 F) V' b& v) Pint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);, O1 T% D6 o1 P' { q
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
4 y( f8 o4 x8 X o0 X* N* o//--- Define a variable that indicates that we have a deal..." F& E; I& O6 z9 h9 C* M
bool tem_tick = false;/ q' ~% t( m2 l7 R
//--- An auxiliary variable for opening a position
, Z+ m7 q2 q% J# T: F1 q#include<Trade/Trade.mqh>
+ V1 Z A( H+ }. E#include<Trade/SymbolInfo.mqh>
3 F a: V0 s8 s# @: H; I4 aCTrade negocios;' x5 L* F7 \3 v
CSymbolInfo info;
6 w0 F3 d1 b4 `//--- Define in OnInit() the use of the timer every second
5 d3 r% N5 h \: s: f# N* ~//--- and start CTrade* e7 ?+ {; Q2 [2 x$ t1 _. W
int OnInit()
0 ?# [# F5 b0 M! `* S6 G# L& V, @{
+ E; ^. h% E5 R; q* [: ?//--- Set the fill type to keep a pending order
0 Q- }9 |' c* w# r) M1 E; g//--- until it is fully filled
5 `+ o; k0 ^( d5 _negocios.SetTypeFilling(ORDER_FILLING_RETURN);3 |6 q' C% s8 ]5 n$ V1 ?
//--- Leave the fixed deviation at it is not used on B3 exchange
/ h# d" I9 C2 rnegocios.SetDeviationInPoints(5);
4 l, `& u7 W5 A7 j//--- Define the symbol in CSymbolInfo...
; u, Q/ M5 q% R$ cinfo.Name(_Symbol);7 W B4 o: }9 w! @3 [! E. a# `1 M2 ~
//--- Set the timer...! l0 y( z! o; Z c
EventSetTimer(1);
. _5 l% D* W7 ^1 d; f! n) R/ b//--- Set the base of the random number to have equal tests...3 o4 r. m+ D$ i& n
MathSrand(0xDEAD);6 z- C" Z8 \, C' d0 H* F X2 Y
return(INIT_SUCCEEDED);
0 E1 R. I* B5 j1 H; [& s8 x( r' M}$ W$ s4 T% ^; s/ F- p$ P
//--- Since we set a timer, we need to destroy it in OnDeInit().
# U1 c& }" E+ Q; U2 Bvoid OnDeinit(const int reason)
8 Y7 T- M$ y2 y# V" }$ D{" |# O6 ~! j N0 z2 p; `. N5 }
EventKillTimer();
9 P& A& r) {/ Y0 D8 c6 ~& x}/ J6 e0 P/ o. e, e
//--- The OnTick function only informs us that we have a new deal
" r( I& @+ {1 J- S. O0 @void OnTick()
" T/ R" t# e& K/ F" X* y{
3 c Q8 [0 C/ K2 Mtem_tick = true;
' d' N0 x2 J( {8 }}
; x% `, @! N, ]1 S7 N: N//+------------------------------------------------------------------+
& c) s; n( Q9 D( }//| Expert Advisor main function |! x9 W" S$ q" v8 [
//+------------------------------------------------------------------+
+ [8 O* j( {2 l7 f+ I6 J5 t$ `void OnTimer()8 H: _) t ^' T: G* k; S0 ]
{$ {6 D# K2 P- I0 P" N
MqlRates cotacao[];+ ?2 _; J* g" R
return ;* z- b+ L0 Q! C! _, |$ {! z" C7 v
if (negocios_autorizados == false) // are we outside the trading window?5 F+ [5 H" Y7 ?# L6 a
return ;7 o3 X9 {( ? [6 x7 g. S
//--- We are in the trading window, try to open a new position! I, P3 A- F0 C) v! S1 {$ E
int sorteio = MathRand();8 S: i3 [: A* S, j
//--- Entry rule 1.1
G( g. q# F7 H, x7 M7 _if(sorteio == 0 || sorteio == 32767)1 T4 f' h8 T1 y* b$ y2 k
return ;
7 I) t7 i Q7 z% }if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy% D _0 u+ V: e' B; G! c6 b5 C
{% X- @: B7 c8 @7 b) g" s, [
negocios.Buy(info.LotsMin(), _Symbol);
( |% K6 v( D( _4 B7 l2 j! \}
5 q7 x/ M! F& R* belse // Draw rule 1.3 -- odd number - Sell
A8 M% A8 {: f. M7 _5 Y7 n{
$ D. y( Y! q) T& z9 d+ p! `8 A* Nnegocios.Sell(info.LotsMin(), _Symbol);* o- Q0 j# Y2 e, T- |: V
}* V' ~, J# f9 T/ Q4 B! k$ e0 H0 k
}- G6 A9 [# [4 f9 ?% q" N$ V" |
//--- Check if we have a new candlestick...
- s7 m& s) G4 ], F+ V8 z+ y) wbool tem_vela_nova(const MqlRates &rate)- R$ K( Q- x1 K# F
{
% ~. q7 v- f* v/ d* G$ D' L/ J- z6 [* h{2 M; ~2 Q; Z# C+ y6 s6 g
ret = true;" q8 h( V" v6 c7 l
close_positions = false;9 p; Y* F0 P, A: E. h
}
0 R* A* _" w& P7 l! s; i$ {- w* belse
3 @' n* J. V2 J3 R; U) @# J: A{
: Q. [9 k( }0 ~, a5 @, ^if(mdt.hour == 16)
/ L+ g: t3 l: T+ O% N! Z7 F+ eclose_positions = (mdt.min >= 30);% ^) |0 A- T1 U
}# u* X: r! _4 I
}
9 q+ L- |, G+ H; b/ T5 ]4 xreturn ret;7 k; z% Q' I5 F( C* s, c
}/ ]! N, g: p" U5 F5 R
//---
+ z: V2 I" r9 i4 Kbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
! t- Q4 u) p% {8 f9 Q{
/ L1 s! a5 j7 k& |" X/ Kif(PositionsTotal()) // Is there a position? c# q) U' |9 b q8 Y" m; R5 t
{6 }+ o; Y9 P5 X
double offset[1] = { 0 };( I' M, Y/ m- g- \# o
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?# o; t0 v6 d1 d( e z& G4 P
&& PositionSelect(_Symbol)) // Select the existing position!# @# \/ _$ V; y4 \& O9 {3 ?. B2 n
{
9 \! N. Z: I/ |3 B$ JENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);0 r4 G4 H! L( i: k' x |. |
double SL = PositionGetDouble(POSITION_SL);# y( u5 t! W! a, u& V* B
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
( F' ^) g' ~8 ?" xif(tipo == POSITION_TYPE_BUY)5 L! N+ o* g' X! G- L
{1 H1 |( q% R! {( X+ x5 Q
if (cotacoes[1].high > cotacoes[0].high) I5 S4 w4 ?6 j( f& u- @% @9 ]
{
\+ o- q- q- J7 m: p& odouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];. ~3 i/ s' m- d; f5 [) h/ ?: _4 X
info.NormalizePrice(sl);! q8 Z% L1 z/ ?. E: I: |
if (sl > SL)
/ Z9 i, z2 N6 v7 v4 ^. U4 c" ^{* c1 j$ a. @4 z! {
negocios.PositionModify(_Symbol, sl, TP);
y) M: B: |4 S0 [4 d}$ t8 k" R$ X& g- @1 B) E4 \# P
}9 X% K. d3 y6 b8 h7 k
}
3 Z$ c) K4 F6 v+ Delse // tipo == POSITION_TYPE_SELL7 P/ c4 w% ~, g; T3 r. G: \( Y5 z# P
{/ q* z, S3 C; l! S4 F* N
if (cotacoes[1].low < cotacoes[0].low)( |5 h" j' F5 w' r: l
{; @5 x) ~# a- N5 h
return true;
. L7 n" o4 a- M6 p( K2 Y5 e( B! X}
" N; R# L& ~% x5 T: Q) {// there was no position' \0 g1 e3 o* b$ [
return false;
9 M$ c o; I+ ~" P* V, ^! a, Z}
2 K: F/ r/ p y, q7 l# `6 u% Z0 d! n我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。% F7 t8 E9 M4 B* k- E. i. s: s
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |