启动交易模型,并构建 EA
6 f2 ?. O( t- j+ r在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。
3 u2 [& v8 U. G; D" G1 }. e% d为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。
0 S# _2 ]- ~- e* D' s以下是制定这些规则的代码。
: i$ A# |: b: J: O//--- Indicator ATR(1) with EMA(8) used for the stop level...
2 {: {6 y$ k+ o# K+ T1 ^int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);* i: g7 K5 n# W8 b; O
int ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);' e( k+ Z8 D% P5 N4 q8 u' Z) i
//--- Define a variable that indicates that we have a deal...
. i* ?; V$ e' g! v, cbool tem_tick = false;$ v# M" T1 w3 S1 K9 e7 E4 r' U+ l
//--- An auxiliary variable for opening a position
' q" Z, Y$ N: j0 N7 z, ]: v#include<Trade/Trade.mqh>$ f( v* J# o3 t! Y: T" E6 U7 {
#include<Trade/SymbolInfo.mqh>% A" F' z. C7 H3 b4 d' S
CTrade negocios;
4 |0 E9 J6 c/ g+ t. n6 n0 ACSymbolInfo info;
$ [1 W+ A$ ~- O& [3 J//--- Define in OnInit() the use of the timer every second1 l. Q- H0 W1 x3 Y9 ?
//--- and start CTrade
% V; K" { a! h: x- o$ S2 t9 ^! gint OnInit()1 E) |+ E, t: B. Q! Q; W7 K
{
2 o5 u8 w6 w5 f+ s6 @0 _+ Q//--- Set the fill type to keep a pending order
. ?0 \3 _5 U" y( R//--- until it is fully filled
% F# x8 M1 I+ j1 N: f' anegocios.SetTypeFilling(ORDER_FILLING_RETURN);: Q# f4 l* V$ _
//--- Leave the fixed deviation at it is not used on B3 exchange7 G0 |1 z6 O5 r
negocios.SetDeviationInPoints(5);
. F, N& ^! |9 y5 J//--- Define the symbol in CSymbolInfo...
. K6 X6 c7 e" O9 z. V- K; L7 [info.Name(_Symbol);9 P- V% L) A" L2 z( x. T y; w
//--- Set the timer...6 @6 G/ u8 h$ H8 t0 @
EventSetTimer(1);
0 ~) e8 m& G6 _2 k! i//--- Set the base of the random number to have equal tests...
; ?) y+ V: Y5 ~; {7 p. [, m" x8 ~MathSrand(0xDEAD);2 Z" a. b# P& N% V; D) L3 i
return(INIT_SUCCEEDED);
+ U& U3 `. F) y, b8 }4 j# v}6 n8 y& I* W) C# u& Y; \3 }
//--- Since we set a timer, we need to destroy it in OnDeInit().0 M% e# P, v0 S3 F
void OnDeinit(const int reason)
" t1 q. |, E2 r( H{: W9 T/ U8 m7 G# i
EventKillTimer();
3 w2 [' M& d6 n0 a r; ?' O}
' H8 H6 ` `" m- v; Z* e/ r//--- The OnTick function only informs us that we have a new deal7 K8 t5 O# Y' V/ e
void OnTick()- Y1 N7 T: D7 {; i! v( }2 S
{; t- C2 ]) {9 m4 D8 s4 U: X& [
tem_tick = true;& }; Y7 N- G F! y
}
0 e5 d0 a: S3 k8 G) D' L8 |/ m//+------------------------------------------------------------------+
2 G1 K* k) i& e+ a+ f: ~//| Expert Advisor main function |! O$ o+ G' q& |; t
//+------------------------------------------------------------------+- _) u. {8 I+ S+ Z* R& O+ y
void OnTimer()
- b3 o9 P, L& m! r{# Z& u5 E! B0 i# f. |; b
MqlRates cotacao[];
; T6 w: W8 y: \! o5 {$ ureturn ;% u+ p* M5 z, s. j B
if (negocios_autorizados == false) // are we outside the trading window?3 n/ Y- s! x! _* A% ^9 Y; M& Q* w
return ;- ^$ L3 R; M. i& B* ?: j" H
//--- We are in the trading window, try to open a new position!
0 U1 U$ e$ b5 }1 ^/ [& {% `, K+ e3 Fint sorteio = MathRand();
4 d9 S9 o. L3 M) H' `* E//--- Entry rule 1.1
' D5 _, N. ~, c* Q# lif(sorteio == 0 || sorteio == 32767)
$ ^+ g A2 u F# J/ z- |9 zreturn ;$ @' f( A6 c/ M0 b$ W! V
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy- ?2 ]. E7 ~5 P/ u& g: H
{
0 B! b' F- {, ]) `2 \1 S9 Snegocios.Buy(info.LotsMin(), _Symbol);" k2 b0 v2 R1 E4 {: u0 p: w; K' ]( w; q5 l
}
4 X4 }& s% \2 Lelse // Draw rule 1.3 -- odd number - Sell
3 ^0 y% j/ o9 O# E% H5 n7 c{9 |, X) J( E# ?
negocios.Sell(info.LotsMin(), _Symbol);
+ }7 k6 L; p) X# }, v}
. q* a9 ^ O. _# E; j' P# W}
9 P1 o8 E/ M3 Q# ~( Z//--- Check if we have a new candlestick...: ~) ~, }( h- [+ \7 h
bool tem_vela_nova(const MqlRates &rate): m; {* O# A6 a h3 Q! z0 a. Q7 a' ^
{
8 R( V# a; |/ K3 l{ I5 X: x2 \7 N E
ret = true;3 N2 F+ m- G" e. I: q6 m% R9 I
close_positions = false;9 t) j- }$ v- y8 N5 P& f. B
}) e) t8 X, [" q1 w. O) P& T1 g
else" C8 V8 v% B/ v+ ^ u
{
, O, b' i! ~+ L* `! cif(mdt.hour == 16)4 o& i; y. j' V
close_positions = (mdt.min >= 30);
9 M4 ]. w) `* o: `5 \ \}
% N5 k2 I& \) N0 M. v- h}
0 Y% e- H8 s5 n5 X. l: h7 mreturn ret;# f( p" k" O' @1 o) k0 A
}% w3 c% ~+ b2 P4 I" n* K
//---2 C1 t+ P J$ E: \/ c: c8 b
bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])/ c4 e. m* P* {9 k! V! S4 U
{
$ \" w8 {2 n. I: o D0 dif(PositionsTotal()) // Is there a position?
- Y n I* o+ S2 v* Q. F{) ~6 a( `( \, P* q" ?
double offset[1] = { 0 };( a/ z3 d3 r0 M% q1 V- Q+ B: }
if(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?" n, o1 a; L V) ]0 P
&& PositionSelect(_Symbol)) // Select the existing position!$ O) U% I8 M r& n' ]! M
{
6 f) v( |' q1 Y& YENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);5 U/ k, A( _( b3 Q, }' s
double SL = PositionGetDouble(POSITION_SL);& e, b% }0 y# ~( H; `! A7 Q( I: o
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
. F: [' B- e f5 R0 lif(tipo == POSITION_TYPE_BUY)
8 f1 x9 n2 ]+ K7 H2 u9 C. l{
4 R, r# j9 G" d) p. L3 P$ y" \if (cotacoes[1].high > cotacoes[0].high) q) k- n% n/ L7 r- i
{
9 x+ A. d1 p& Odouble sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];: _4 C0 V0 T, C L' v: a: m; B
info.NormalizePrice(sl);
! h# q1 j) P7 |* F, v: U `if (sl > SL)
1 [. I j1 @% r/ w. x9 n{
% j O, ?% R! q* Q+ b6 P" g% enegocios.PositionModify(_Symbol, sl, TP);
4 [$ Z3 o5 e8 A' @; H}
" ~4 o& B3 r- ~8 o, c; Q}, L# w7 [ s; s1 ?" ]
}
0 O2 x' R) y! P% b8 ?& D" i# H) Velse // tipo == POSITION_TYPE_SELL/ K- [. F. e& j, t7 _! W' c
{
+ W6 v5 `/ g' V+ p4 @ `if (cotacoes[1].low < cotacoes[0].low)) F$ Y0 W2 y8 P! z- U
{2 a) Q2 m' S; g8 }9 o
return true;
2 S" z. }1 A( h. S! _}
$ h; C" N/ D- R( H9 ^& D8 K// there was no position
9 a+ M' \) r/ }. |7 M1 Treturn false;
. r) B$ s8 Q: U/ w* J' O}6 u# |% d" i* R! G7 s
我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。6 _3 U, A! A* E4 W* F
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |