启动交易模型,并构建 EA
3 B, x; w0 f1 @& K: p在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。. f; o) k5 h, F, d: l9 C
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
+ x$ W5 ~0 o% y# n; j以下是制定这些规则的代码。+ _( Z8 @2 S* I6 c* H4 j
//--- Indicator ATR(1) with EMA(8) used for the stop level...
- c; R$ d( E$ [7 G2 o. Vint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);. x; Y: i, h/ Z4 T
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
9 {3 s. w& {8 L. ~6 W% b! v$ B, [# F//--- Define a variable that indicates that we have a deal...
! G4 j1 S# p$ B+ R" ibool tem_tick = false;' w V* U( `; g( J) S4 p. K; m! F- A
//--- An auxiliary variable for opening a position( |6 k3 d5 u6 j x( y# P# x r
#include<Trade/Trade.mqh> ?4 b" w' x( z) Z' b- q6 T' y; Z
#include<Trade/SymbolInfo.mqh>
2 b$ R& K. l! k: Y- F; X) ?2 r9 LCTrade negocios;
9 L# D8 y: e3 a! q4 v* K6 DCSymbolInfo info;8 q! e# Y% y$ G' y1 j( Q1 K
//--- Define in OnInit() the use of the timer every second$ ]+ t8 z3 D0 i' Y8 \) P
//--- and start CTrade
! j6 }8 R6 j; |, P) I9 d; Kint OnInit()/ S, a5 E$ X% ~- s- `/ b8 K
{
Q, ]4 S- @ q1 z* [7 M//--- Set the fill type to keep a pending order6 ~. I; i5 H% _; {& z
//--- until it is fully filled
8 m7 J2 B/ f5 C1 i; Vnegocios.SetTypeFilling(ORDER_FILLING_RETURN);* a( ^% ]" T% o+ N, u2 c
//--- Leave the fixed deviation at it is not used on B3 exchange) ]5 B% A. G" [$ f
negocios.SetDeviationInPoints(5);
: L3 F$ M! Q# J9 r8 O//--- Define the symbol in CSymbolInfo...
* r5 y$ p, {2 ~* m1 ainfo.Name(_Symbol);
+ s/ s% |* x% b" T//--- Set the timer...
+ J5 r4 Q4 {5 |2 S( l' QEventSetTimer(1);4 f1 B" N; ], L1 |
//--- Set the base of the random number to have equal tests...
6 j3 l3 X1 N# vMathSrand(0xDEAD);
. V+ Q5 d7 m/ dreturn(INIT_SUCCEEDED);
@0 r8 q5 n7 l0 l% C}
% h/ }* J% o9 E& A. |//--- Since we set a timer, we need to destroy it in OnDeInit().
' L+ X" F, Q' r; e, O6 Qvoid OnDeinit(const int reason)
2 f/ Y0 U# w4 V7 k{
$ o- Z; Q3 T6 IEventKillTimer();
7 H5 l1 B. |& `}
, ?7 u) O0 M* ~' ^# r) S, O//--- The OnTick function only informs us that we have a new deal
) G: D$ `# x3 ?8 dvoid OnTick(), F' S1 N3 c; F% _1 U4 |
{/ L |8 y; V y5 |2 [
tem_tick = true;( Q$ v( D9 v" J# ^- R+ \$ b
}
1 B A9 o6 u+ L9 Z+ |* y# N1 ?6 z( a//+------------------------------------------------------------------+8 E! \; u) ~4 A; G7 x+ [; B
//| Expert Advisor main function |
4 A9 H0 E; [$ b6 v$ O1 ]3 [//+------------------------------------------------------------------+
+ Y1 S e# L/ X: C7 a' I- }void OnTimer()0 u) o" c/ m7 l r9 [
{% R% p' q: L# z7 t+ J; x0 c$ A
MqlRates cotacao[];
s. G" _! E) Q, }0 ^3 kreturn ;" O4 A/ X1 f, N) z; C/ F) w
if (negocios_autorizados == false) // are we outside the trading window?) A- q6 Q. ^* w1 M2 o o9 N, M
return ;. a, H) c5 U2 O, M) o, b0 y
//--- We are in the trading window, try to open a new position!
( Q8 m" V9 \# ~6 d6 E- Kint sorteio = MathRand();
! U8 P, L, s, u0 I7 {, n//--- Entry rule 1.1/ p# S7 h& f# A+ m B# s6 r
if(sorteio == 0 || sorteio == 32767). D# h0 b) o: m. S: f- m6 w
return ;
4 V1 S' T$ K/ X2 [7 tif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy: i- m2 S9 J# p7 R6 E; H, |
{
3 q2 B1 k+ z0 e! t3 I8 L8 n" C, Nnegocios.Buy(info.LotsMin(), _Symbol);
5 I0 ]8 ?$ e B; J% D}! G( T5 Q! K H; {6 y' b! Z( Q
else // Draw rule 1.3 -- odd number - Sell7 ]' A% {( U. i9 [8 }
{
, {4 B7 I1 P: J1 G1 q$ Tnegocios.Sell(info.LotsMin(), _Symbol);
5 i! E, Z( p4 T: G+ Z}
5 {/ k- I' @: L: W/ j I2 t}
0 v" E3 H9 Q( }8 ]. p7 j//--- Check if we have a new candlestick...
9 t' l) y% c* t3 o! Ebool tem_vela_nova(const MqlRates &rate)' z' M7 z/ [& W
{
5 G4 }( g8 E: x, j{* P. ~3 {* E J1 i& w* \$ r. G
ret = true;
4 V7 O# \- I( |: bclose_positions = false;
2 A. @' j; L3 i# E}
+ D: r/ ]) c# ]& ?, j& `else
- G: E9 P# Y9 i- I3 [{
+ t# _+ K5 P6 ]' E: G$ Mif(mdt.hour == 16)
+ k, W) F* b" N4 w! g4 j& d0 R! O( c3 wclose_positions = (mdt.min >= 30);1 G+ r- r$ A. {! W' c
}
t9 h' g2 Q$ ?/ z& ?% m0 l}( b: O+ O4 J0 v* r
return ret;( M7 e- m3 f1 n8 _( S
}
, F* C. g W; B: Z$ |//---
1 g# v1 U% F2 `- W& b# i0 Sbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])" T/ z. n4 a2 J
{
. t, [& V) ~* u; l! o: M. Y+ Eif(PositionsTotal()) // Is there a position?' Y5 M0 A8 M9 ~/ S2 L- r
{% T( Z1 t" n, A, |9 E) Q6 ^3 C5 I
double offset[1] = { 0 };
; U) ]- K2 U9 H, J9 B1 fif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?5 i+ C0 q9 t6 O" e7 \* f: V
&& PositionSelect(_Symbol)) // Select the existing position!
7 K; ~: v( h0 N5 H; h$ r# p" o{ `% g+ u0 M- D2 q, O. H
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);) r# @; R& x9 d' A$ B
double SL = PositionGetDouble(POSITION_SL);! ~" w! G* [: L' x
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
. n/ u0 e; `5 F% R3 I0 J& c; Mif(tipo == POSITION_TYPE_BUY)
X* \: A5 @! E% D- G g/ X{( B% f: W/ L" E8 E
if (cotacoes[1].high > cotacoes[0].high)3 U* q; @6 [+ ~) x* a) ^# t
{
+ a" ~, J( }2 t L7 `" S7 n. Rdouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];
3 H* m# {9 {+ [0 o0 P- ainfo.NormalizePrice(sl);8 T- k' I- n$ L6 a) m5 n
if (sl > SL)
0 z. L0 r) b" g8 P$ ^/ d# T{
4 Y5 s `8 g; m) F& l, t$ ?' [negocios.PositionModify(_Symbol, sl, TP);* Y9 F! }8 X& T8 h8 ]/ r
}! p9 |, a. j1 z& o
}& F& d" R+ o* J- ^1 p
}
S" r8 y. ^8 @else // tipo == POSITION_TYPE_SELL2 E' o( x B6 A$ }9 u! m/ w5 a5 y
{" F5 U% z: i1 t' }
if (cotacoes[1].low < cotacoes[0].low)
# W& j# @: F% B5 T' E{
0 m5 e5 d5 I# ~$ r+ H0 _0 Greturn true;
/ C+ J# z' P! f6 r2 Z3 Q}3 d$ X8 d5 z" ~* o: l+ P
// there was no position! H+ n) x$ V S7 K. \; e% }
return false;
7 T- l( c2 b2 y# N n}
) |$ ^- |" y7 r6 F" B: w( E我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。. F, x) S( A2 G$ V/ W1 C
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |