启动交易模型,并构建 EA) h9 a% A( N( D4 s. K. p
在解决系统品质因数之前,有必要创建一个能在测试中使用的基本系统。 我们选择了一个简单的系统:我们先选择一个随机数字,若它是偶数,我们就开仓做多;否则,我们开仓做空,因为数字是奇数。* V% B8 R6 \0 q! l
为了保持随机抽取,我们调用 MathRand() 函数,它提供一个介于 0(零)至 32767 之间的数字。 此外,为了令系统更加平衡,我们将添加两条互补规则。 有了这三条规则,我们将努力确保系统更加可靠。" F6 v: k; \; ~# R Z' f
以下是制定这些规则的代码。
7 ]( |6 g5 d. b//--- Indicator ATR(1) with EMA(8) used for the stop level...
9 k% X8 c* t' Q8 Bint ind_atr = iATR(_Symbol, PERIOD_CURRENT, 1);
, ?; K9 V4 g. P) K6 ?- \, P9 r& hint ind_ema = iMA(_Symbol, PERIOD_CURRENT, 8, 0, MODE_EMA, ind_atr);
1 X- p: C& m5 g9 X/ t8 a! U//--- Define a variable that indicates that we have a deal.../ P. V. u4 d1 \: ]* L
bool tem_tick = false;
- V4 x; r" S' L# O/ Q) k& @//--- An auxiliary variable for opening a position
7 C4 f) K" R; Z; R1 V2 T#include<Trade/Trade.mqh>. _! F" W; Z, f+ M: C. J3 g
#include<Trade/SymbolInfo.mqh>
2 F5 h7 Q. |& x, o+ s- qCTrade negocios;
E9 q9 P, V- \! T3 J; vCSymbolInfo info;
; V9 K5 U$ X' V4 a! P//--- Define in OnInit() the use of the timer every second3 o6 e2 s- Q5 M g: S' m
//--- and start CTrade! T/ w6 T3 a# ~# {- Y% M
int OnInit() y! {7 U4 {6 h% e
{8 r8 {8 V1 ]$ v0 D3 Z$ m6 q
//--- Set the fill type to keep a pending order
' E7 ^" Y( j! G( S+ f//--- until it is fully filled1 g0 z- _- b+ K7 o
negocios.SetTypeFilling(ORDER_FILLING_RETURN);# a% |3 q n8 l7 L
//--- Leave the fixed deviation at it is not used on B3 exchange, c( v) [. X8 c {: y, s
negocios.SetDeviationInPoints(5);
" i4 c# O2 s& D4 u/ {! E8 P//--- Define the symbol in CSymbolInfo.../ Y- _7 I/ \( n4 W: a+ q
info.Name(_Symbol);
- [0 A; v8 i1 d9 q//--- Set the timer...& Q3 c7 j l) w$ Y0 O+ q$ B
EventSetTimer(1);: U. S2 i' t2 M6 h
//--- Set the base of the random number to have equal tests...) `- \3 ~$ w) F; r; p/ D; N
MathSrand(0xDEAD);
; S/ e3 H; C3 b4 e% {return(INIT_SUCCEEDED);
/ h4 ~- o/ B2 f9 c}
4 R) ]4 w) C' j6 ]//--- Since we set a timer, we need to destroy it in OnDeInit().# p- i" g2 d7 \% w, I
void OnDeinit(const int reason)
. l7 Q6 V) x( o) C2 ?! h{/ {2 P' @% M8 z
EventKillTimer();! T: k' P! K1 s7 g) h
}7 N2 k" X! _6 o/ S1 f
//--- The OnTick function only informs us that we have a new deal0 ^6 {: o$ B0 w- Z$ l% P0 R- @
void OnTick()
% T* F7 z- V6 ?2 n0 H2 q( u3 C{3 j) v# \/ M- @6 C" X4 \) V* t
tem_tick = true;/ }$ G8 \, g& w s
}& ~5 O7 A& ]2 ?. y' D% @
//+------------------------------------------------------------------+* @: n& t, j5 Q6 i- `7 P
//| Expert Advisor main function |! _4 K. L$ x' Q# m& K* H7 C0 {4 X& J; X
//+------------------------------------------------------------------+$ I' x3 ?) ]6 Q" l
void OnTimer()
. \* } G( ]; w8 {6 p6 A1 e( N{
) j+ @ `8 @9 s CMqlRates cotacao[];# X8 J, k2 U5 N( l# t2 s6 W, d$ w$ ^
return ;6 ~" i3 h5 v, ~* J( n5 W
if (negocios_autorizados == false) // are we outside the trading window?1 D: x/ S$ V% n9 o- _2 N% n( x" u
return ;
+ x1 A+ O0 R! N+ k. k//--- We are in the trading window, try to open a new position!
3 B6 o" c. P( \, t6 ?0 Wint sorteio = MathRand();
8 I! V' j! {: }# O A//--- Entry rule 1.1
: F# |5 R! i7 Aif(sorteio == 0 || sorteio == 32767)+ D) d' U1 ?$ y" ]1 p
return ;) n6 Q0 g6 E- ~8 X- G" G5 N
if(MathMod(sorteio, 2) == 0) // Draw rule 1.2 -- even number - Buy# s. l P9 N5 F3 j) s ^
{4 n, R4 ~% B; f1 t% E* C) ^. A, R
negocios.Buy(info.LotsMin(), _Symbol);
& R8 O% h7 s/ Y}4 {7 W: ^" {4 r; d1 v$ g% F
else // Draw rule 1.3 -- odd number - Sell
9 d8 k. |) G3 } x6 {9 ]6 p |{
6 S! x5 }7 ~! `- r, F1 cnegocios.Sell(info.LotsMin(), _Symbol);
* _7 X6 Q" Y0 q3 w}
( t6 g: k5 ]& G l0 ?, i$ g" Q}
0 p2 w3 a5 ]" k# i+ L; {! [ y//--- Check if we have a new candlestick...
9 {' o0 P, h7 h# Lbool tem_vela_nova(const MqlRates &rate)1 o) ?+ {) [* d
{
+ X; S x- U7 g{
/ T6 y1 j. e; }2 w; Uret = true;
9 F: Q) h5 s d. }. dclose_positions = false;
$ U! h& m0 R( q5 n! H, V4 t8 z}
L4 L7 x8 E) W* V1 nelse7 y, e9 J& |) q. _
{- a4 b9 M0 n: n
if(mdt.hour == 16)
0 r7 F/ j7 v( {. Eclose_positions = (mdt.min >= 30);, M }, P$ I5 Z& m/ b
}
1 u5 p: x7 `1 g' T7 q' H}8 Q! d4 T' o; }! O; g' j; O$ X1 ?$ P
return ret;
, I6 k+ z- H7 q( D8 a1 s4 c}. r; @4 V4 q- X. @5 p3 n
//---
+ ], O- c( p$ ~% @' K. M Nbool arruma_stop_em_posicoes(const MqlRates &cotacoes[])- O) m, S3 Z7 h" \
{( ]9 [0 J6 D3 J% F% v, T3 V9 F7 L
if(PositionsTotal()) // Is there a position?
6 x, L- E& L9 @* m{
2 C$ m7 u! A" O3 D3 `+ I& W4 Cdouble offset[1] = { 0 };
2 f4 m# D' S2 h- P( J. xif(CopyBuffer(ind_ema, 0, 1, 1, offset) == 1 // EMA successfully copied?% r/ G$ D7 B0 | L9 y3 I/ i
&& PositionSelect(_Symbol)) // Select the existing position!
, P# C9 g7 l; i8 I% h{! N; I6 u, g1 e% I1 A
ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
) M1 n3 V! p: kdouble SL = PositionGetDouble(POSITION_SL);! a i9 ^& Y2 w8 P# H
double TP = info.NormalizePrice(PositionGetDouble(POSITION_TP));
4 |* U) z& Z7 W$ [if(tipo == POSITION_TYPE_BUY)
' {; _2 w! x% X{
3 n# D5 U6 D3 @! s) E' Vif (cotacoes[1].high > cotacoes[0].high)
5 ~6 \& Q! b# Q+ S* `1 a{ n, }2 k% u4 \$ A, r$ I! W% i
double sl = MathMin(cotacoes[0].low, cotacoes[1].low) - offset[0];5 X8 F* Q7 }3 K' @4 Q
info.NormalizePrice(sl);! R# [, M; `, X' d" d1 D8 q! S
if (sl > SL)
% l: ?, _) w% ~( D- C8 c. Y{
, S$ v1 O( ?- X0 S. I7 Nnegocios.PositionModify(_Symbol, sl, TP);9 n( M% J; g) y: S
}
# D* {# p3 k, a}
4 I5 g: G9 d. t4 E3 B* z/ D5 }# e}
& y7 v0 ]$ b- V. L3 aelse // tipo == POSITION_TYPE_SELL4 {; N ^4 i) \+ x6 M% s2 S
{
6 ?: z/ u% B& W5 ]2 ~3 \! n3 D; qif (cotacoes[1].low < cotacoes[0].low)
4 T2 W. R: j# K* v+ {# S' C{
1 `# S7 J5 p3 i: J1 Mreturn true;4 Y3 `% Z1 b# e; w P: y- h9 V9 B
}
/ ?7 a7 G A5 x. w/ C9 S. c6 g// there was no position' L. f7 o$ e, \
return false;( @2 t: o1 I5 S( X9 ` T# x% J" R
}
' g, H* n% G/ r我们简略研究一下上面的代码。 我们将经均化计算的 ATR 值来判定止损步长,即我们发现当前烛条超过前一根时,将止损价位放置在烛条的边界。 这是在函数 arruma_stop_em_posicoes 中完成的。 当其返回 true 时,已有设置,且我们无需在 OnTimer 的主代码中前进。 我使用该函数取代 OnTick,因为我不需要针对每笔执行的交易运行一遍大函数。 函数应该在所定义周期的每根新烛条建立时执行。 在 OnTick 中,设置 true 值表示前一笔交易。 这是必要的;否则,在休市期间,策略测试器将引入暂停,因为即使没有前一笔的交易,它也会执行该函数。7 q. P D9 Z/ x- B9 u/ G
到该处为止,一切都严格按照定义好的计划进行,包括两个指定的窗口。 第一个是开仓交易的窗口,在 11:00 到 4:00 之间。 第二个是管理窗口,它允许算法管理持仓,移动其止损价位,直至 16:30 — 此时它应该把当天的所有交易了结。 |