启动交易模型,并构建 EA( ]% u6 P7 ~+ q2 w( W# K! |# y
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。# E( q- X4 @" o+ E5 {
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。: i) u4 o' N" ~2 h. ^4 \, B
以下是制定这些规则的代码。$ C! {# y8 J8 e# T( S, |# {
//--- Indicator ATR(1) with EMA(8) used for the stop level...; [5 C* x8 C; @, {8 \
int ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
& D R; ^& l* }. {/ P3 ~" T9 }5 xint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
8 f9 V" x: j: P5 q' {//--- Define a variable that indicates that we have a deal...
' F+ N8 j3 d4 ?% @+ k! ibool tem_tick = false;
( |; O# G4 g" w& i, v; R3 o! b//--- An auxiliary variable for opening a position2 v2 Y( P; ~6 Z1 R
#include<Trade/Trade.mqh>& a8 l! k7 ?3 V' `7 k) g& x' h
#include<Trade/SymbolInfo.mqh>
1 C/ e) I$ _! u1 D5 zCTrade negocios;
/ ?8 Z& u; p8 k: u1 nCSymbolInfo info;
% L5 A% i: {; U6 }% I//--- Define in OnInit() the use of the timer every second! U% t. t! O; {$ S7 d0 ]
//--- and start CTrade. W' S/ c) e5 G8 K8 x3 \- T7 `
int OnInit()$ k% t( R; [# R3 Q; A
{
1 {# ?: {$ i }. U1 z4 R F//--- Set the fill type to keep a pending order: W3 i" T9 U* _, y5 j5 |. C5 e
//--- until it is fully filled
4 x% B! r, `# A7 H/ Z" Fnegocios.SetTypeFilling(ORDER_FILLING_RETURN);
8 y2 k. Y' X3 {' H8 h! w$ Q b//--- Leave the fixed deviation at it is not used on B3 exchange
: v9 T7 }/ \ D; L+ ^3 d0 Anegocios.SetDeviationInPoints(5);0 @$ C( j% O& {) J
//--- Define the symbol in CSymbolInfo...9 P$ l( k ]# A5 D* J
info.Name(_Symbol);. S# |& v8 P4 q9 g0 P$ i; _
//--- Set the timer...
9 R, d* b7 ~* _) u# e) T+ REventSetTimer(1);0 l* q) @, j* Y# e7 e8 s j3 U V
//--- Set the base of the random number to have equal tests...
8 W1 j! |/ r* h8 jMathSrand(0xDEAD);+ q/ b. _9 G' M6 }
return(INIT_SUCCEEDED);# d* @. S, y( ~# O% K1 o
}( B2 I) u# K+ {1 ?# s' j; `7 i
//--- Since we set a timer, we need to destroy it in OnDeInit().
* R1 Z, Q/ Y- G! A) K0 U+ Zvoid OnDeinit(const int reason)
1 b7 K( p* H; \2 E{
( H0 U' f ? B1 z. SEventKillTimer();# Z0 a _1 K" |: |
}7 l) p' @# g& w6 o4 X
//--- The OnTick function only informs us that we have a new deal
. J3 T5 P$ s! O: t! vvoid OnTick()
- W6 d: s4 E! g% w3 v5 C{$ D' @" A% G9 I
tem_tick = true;
/ n) f) F+ _& D8 c}& Z2 C6 V7 K; _/ w6 P7 S
//+------------------------------------------------------------------+2 C0 L. B' m, {# z, T7 B& m
//| Expert Advisor main function |
* \, N, T7 Y2 N, f+ q9 n//+------------------------------------------------------------------+
9 @% N. _/ _6 p' b3 ~void OnTimer()* k( o% b, a' {5 Q6 j$ W- R5 f
{
9 w6 I3 h' f+ W! M1 JMqlRates cotacao[];
1 E. w, ^5 H& @5 wreturn ;
2 G) a, @) v% T& k% Iif (negocios_autorizados == false) // are we outside the trading window?
( }( H" A/ Y3 K1 P; ^# K- ^ Wreturn ;. d* ~. ~+ L2 o9 D
//--- We are in the trading window, try to open a new position!
9 L3 s3 s$ f& D) w$ iint sorteio = MathRand();/ D$ p2 Y, i9 n4 H4 H
//--- Entry rule 1.18 \# z1 S& F A) e! a/ ~0 \" p
if(sorteio == 0 || sorteio == 32767)3 y! e! i# t5 X* ]* A" l$ R2 l
return ;
1 H% d6 t* W" E( W: c) Mif(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy$ U+ t7 T. N/ J2 M1 o" X+ X
{
4 G) b& Q, [# i- h* ?1 ]1 G! Gnegocios.Buy(info.LotsMin(), _Symbol);2 ]* `8 o# y T F/ X! Y
}2 [3 @+ Z5 F2 a6 [8 z" R
else // Draw rule 1.3 -- odd number - Sell
) E; Q5 X8 z9 ]7 V{
5 c+ i+ E" l( c) c& Xnegocios.Sell(info.LotsMin(), _Symbol);
! b0 }/ s! C& c5 q& u) I0 q' ^}* O I9 l2 T" R% o0 G
}
2 H6 i6 N1 h+ q, Q O/ f//--- Check if we have a new candlestick...
( y4 u" q" K/ A& O2 o0 N* Sbool tem_vela_nova(const MqlRates &rate), k2 [, C. a" x( a
{
/ e }! u0 h- U5 w{& S. N v2 ` r* n) O! K. R N
ret = true;7 L7 {% W+ q& z! {3 Y
close_positions = false;; F+ O* {9 A0 y! T3 x1 w
}
, A" _1 W" v/ U5 E8 Uelse
0 A7 c2 A) ]/ H7 e{ t+ n2 y; x0 }
if(mdt.hour == 16). Z& B, P) k% ?) j) ^3 @
close_positions = (mdt.min >= 30);" N: E" L0 j' l" x S, m7 X
}
7 [8 F- g, G E5 x8 |5 p/ K}
+ J1 `* a$ ?1 S Lreturn ret;
) O! H2 }, C2 U* m A( v# n}' K8 T+ I. Y6 G; E3 [) U/ Z
//---
9 v$ M9 i; v$ F3 U5 _bool arruma_stop_em_posicoes(const MqlRates &cotacoes[])
( n# x! w: X+ U0 v4 p+ E) R6 L* g{; C$ g2 Z+ k' M% a/ W5 [
if(PositionsTotal()) // Is there a position?
: d7 w4 d* Q8 g: Y1 N2 b, K{
: n. `% u3 G* h. N5 d8 odouble offset[1] = { 0 };
. h% F! n* R: n; F( d: p6 m9 gif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?
l3 W( U/ O% R2 U( A&& PositionSelect(_Symbol)) // Select the existing position!
: Y& J" l* Q; c, t8 ^- O' ~9 E/ R{; f: k9 q3 t+ H
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
, L* l" I/ P2 P( W, ~double SL = PositionGetDouble(POSITION_SL);9 s9 X/ g( A$ w6 f/ l4 n% {
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
, v+ I& U9 {$ u# ]! Lif(tipo == POSITION_TYPE_BUY)
6 \( r; y: s' \$ e: ~{5 p; o) u" ^* \1 Z. ?
if (cotacoes[1].high > cotacoes[0].high)$ a" _8 |+ y1 c+ M; @9 \& ~
{0 m/ h% S0 ]( [2 c5 W
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];* @/ }5 u4 N% N) e6 S* e/ V6 t$ V- D
info.NormalizePrice(sl);
, q% j1 L3 j4 ]( ]if (sl > SL)' J0 X/ g# J3 }* ]: ]
{; D2 B5 r+ `% I1 @4 e1 H5 T
negocios.PositionModify(_Symbol, sl, TP);
6 t) A0 ^+ s- J6 Z) A$ G3 K}
. L }! _$ O1 g# X8 N% v' I- A}& _' v+ P+ u/ V) q) y4 X5 v4 i7 |
}
8 t; S* o/ d0 q" @" o. f9 N9 Xelse // tipo == POSITION_TYPE_SELL0 R$ p1 z c" @ @% H
{
. Z. V6 n8 v- B* A# ]2 Dif (cotacoes[1].low < cotacoes[0].low)
7 ~9 ]; P0 p, ^0 [{6 i. [$ c' ^6 ?; E
return true;% j L+ {' b: W+ t2 z7 ]
}
' P: u$ a3 V. R8 T4 m// there was no position) Q7 j, N2 O) P9 r
return false;
9 u2 H) `1 z8 P) ~}
1 y3 I" S3 }/ ]$ E. d我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。 A7 s" _' j: ^
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |