基于大众交易系统和交易机器人优化点金术的 Expert Advisor(续)

Nikolay Kositsin | 17 三月, 2016

简介

在之前的第 2 篇和第 3 篇文章中,我介绍了回溯测试的基本知识。我认为,当 EA 参数不时变化时,回溯测试的主要目的是定性分析 EA 在某个时间段的行为。在此过程中使用优化结果的策略类似于一项严格的规则,用于从收到作为每个优化的结果的所有变体中选择参数。例如,具有最高收益率和最低亏损的变体。

此类变体是在单独优化的各种变体中选择出来,与我们之前的优化内容无关。如果你发现此类策略在某些时间段具有盈利性,而在某些时间段在保本位附近,我们可以得出以下结论:利用此类使用已优化参数的策略,你的交易系统很可能会在将来某个时段获得盈利。

这是一个完美的例子。但是,如果在半数的回溯测试情况中,EA 使用了看似很合理的操作逻辑,但却出现了无可救药的亏损,我们应该怎么做?实际上,基于分别在每个优化中选择 EA 参数的策略并不是唯一可行的方法。进行统计分析并比较不同优化中的 EA 参数,更为有意思。

而且,在回溯测试中,优化会占用大量时间,仅对回溯测试本身进行这些优化是不合理的。例如,我们可以将所有可获利的优化操作的结果连同优化一起以表格形式保存在同一个文件中,此文件可通过诸如 Microsoft Excel 等程序中的表格统计分析方式轻松处理。MetaTrader 4 终端提供以 HTML 表格形式保存优化结果的可能性:

可轻松上传至 Microsoft Excel。但对于处理而言,仅每个优化操作的最终报告以表格形式呈现。Expert Advisor 的外部参数未包括在此表格中:

而且,它仅是一个优化的结果。为了进行分析,我们需要将所有优化的结果记录中同一个文件中。事实上,可通过 MQL4 方式实现所有这一切,因此在本文中,我想提供自己的方案。



以 HTML 表格形式将 EA 优化结果记录在同一个文件中

为了记录到文件中,我编写了以下函数:

void Write_Param_htm
(
bool ToResolveWrite_Up, int Timeframe_Up, string ExtrVarblsNemes_Up, string ExtrVarblsVelues_Up, 
bool ToResolveWrite_Dn, int Timeframe_Dn, string ExtrVarblsNemes_Dn, string ExtrVarblsVelues_Dn
)

此函数能够记录针对一个货币对在一个时间范围以及一个交易方向上执行的所有可获利优化操作的结果。此函数的调用放在 EA 去初始化块中(位于 deinit() 函数内部):

int deinit()
{
//----+
//---- Recording EA parameters into a text file
if (IsOptimization())
{ 
//---- +------------------------------------------+
//Here is the code of external variables initialization of the Write_Param_htm() function
//---- +------------------------------------------+
//---- RECORDING STRINGS INTO A HTML FILE
Write_Param_htm(Test_Up, Timeframe_Up, ExtVarNemes_Up, ExtVarVelues_Up, Test_Dn, Timeframe_Dn, 
ExtVarNemes_Dn, ExtVarVelues_Dn);
//----+ +-------------------------------------------------------+
}
//---- End of the EA deinitialzation
return(0);
//----+ 
}

此函数在 C:\ 目录中写入三个文件:两个优化结果文件(分别对应多头和空头仓位)和一个日志文件 (MetaTraderTester.log),这两个文件的路径和名称写入日志文件。这两个文件的名称类似于 (OptReport_Exp_5_2_GBPUSD_240_Long.htm):

Write_Param_htm() 函数通过以下指令包括在文件中:

#include <TestReport.mqh>

此操作在声明 EA 外部变量之前完成应更好。除此函数以外,TestReport.mqh 文件还包含在函数 Write_Param_htm() 代码中使用的其他函数;我稍后将会介绍它们的含义。此文件还包含用于进行回溯测试的带外部变量的已知函数 IsBackTestingTime()(上一篇文章已介绍此函数)。此函数调用应放在 start() 函数块中:

//----+ Execution of backtesting conditions
if (!IsBackTestingTime())
return(0);

因此,TestReport.mqh 文件的最简单的使用完全类似于上一篇文章的 IsBackTestingTime.mqh 的使用,但在此例中,EA 编译过程中未使用任何其他 EA 函数。Write_Param_htm() 函数使用了 8 个变量,用作为外部参数。这些变量可分为两组:用于将以 _Up 结尾的多头仓位的 EA 优化结果记录在一个文件中,以及用于将以 _Dn 结尾的空头仓位的 EA 优化结果记录到一个文件中。

我们分析其中一个组,另一个组与之类似。ToResolveWrite_Up 参数将允许或禁止记录到文件传递给此函数。ToResolveWrite_Up 参数传递 EA 的多头算法所使用的时间范围。ExtrVarblsNemes_Up 参数将包含多头仓位的 EA 外部参数名称的字符串传递给此函数。ExtrVarblsVelues_Up 参数用于传递包含多头仓位的 EA 外部参数值的字符串的方式完全相同。

我们来讨论后面两个变量的初始化。假设,我们有针对多头仓位的以下外部变量:

n_ExternParam_1, n_ExternParam_2, d_ExternParam_3, n_ExternParam_4, b_ExternParam_5, d_ExternParam_6, 
d_ExternParam_7, n_ExternParam_8

前缀“n_”表示参数属于整数类型,“d_”表示参数属于双精度类型,“b_”表示布尔类型。在ExtrVarblsNemes_Up 和 ExtrVarblsVelues_Up 进行初始化之前,应声明一对额外的字符串变量,并且应由 html 代码部分对此对变量进行初始化:

string n_Width = "</td><td><center>";
string d_Width = "</td><td class=mspt><center>";

之后,我们可以组合所需的字符串。对于外部变量 ExtrVarblsNames_Up,代码将如下所示:

ExtVarNames_Up =
StringConcatenate
(
n_Width, "n_ExternParam_1", 
n_Width, "n_ExternParam_2", 
n_Width, "d_ExternParam_3", 
n_Width, "n_ExternParam_4", 
n_Width, "b_ExternParam_5", 
n_Width, "d_ExternParam_6", 
n_Width, "d_ExternParam_7", 
n_Width, "n_ExternParam_8"
);

外部变量 ExtVarValues_Up 的初始化稍微困难点:

ExtVarValues_Up = 
StringConcatenate
(
n_Width, n_ExternParam_1, 
n_Width, n_ExternParam_2, 
d_Width, d_ExternParam_3, 
n_Width, n_ExternParam_4, 
n_Width, b_ExternParam_5, 
d_Width, d_ExternParam_6, 
d_Width, d_ExternParam_7, 
n_Width, n_ExternParam_8
);

在此代码中,在外部 EA 参数之前,始终先放置 d_Width 变量,然后再写入所有其他参数 n_Width。在这样的最后一个字符串安排中,所有双精度类型的参数将被传递给 Write_Param_htm() 函数,且小数点后有四个符号。如果需要其他数量的符号,使用以下函数:

DoubleToStr( double value, int digits)

请注意,这些字符串不能包含 255 个以上的符号。如果超过此长度,将忽略超过的符号,同时编译器将显示一个相应的提醒。在这种情况下只有唯一一种解决方案:在 ExtVarNemes_Up 中,应缩短外部变量的名称,在 ExtVarVelues_Up 中,应删减进行字符串组合的变量数量。但对于大多数任务,255 个符号绰绰有余>

下面是以 Exp_5_2.mq4 为例实现记录到 HTML 文件的形式:

//+==================================================================+
//| expert deinitialization function |
//+==================================================================+ 
int deinit()
{
//----+
//---- Recording EA parameters into a text file
if (IsOptimization())
{
string ExtVarNemes_Up, ExtVarVelues_Up;
string ExtVarNemes_Dn, ExtVarVelues_Dn, n_Width, d_Width;

//---- INITIALIZATION OF STRINGS FOR THE Write_Param_htm FUNCTION
//----+ +-------------------------------------------------------+ 
n_Width = "</td><td><center>";
d_Width = "</td><td class=mspt><center>";
//---- 
ExtVarNemes_Up =
StringConcatenate( 
n_Width, "IndLevel_Up",
n_Width, "FastEMA_Up",
n_Width, "SlowEMA_Up",
n_Width, "SignalSMA_Up",
n_Width, "STOPLOSS_Up",
n_Width, "TAKEPROFIT_Up",
n_Width, "TRAILINGSTOP_Up",
n_Width, "PriceLevel_Up",
n_Width, "ClosePos_Up");

ExtVarVelues_Up = 
StringConcatenate(
d_Width, DoubleToStr(IndLevel_Up, Digits), // 9
n_Width, FastEMA_Up, // 10
n_Width, SlowEMA_Up, // 11
n_Width, SignalSMA_Up, // 12
n_Width, STOPLOSS_Up, // 13
n_Width, TAKEPROFIT_Up, // 14
n_Width, TRAILINGSTOP_Up, // 15
n_Width, PriceLevel_Up, // 16
n_Width, ClosePos_Up); // 17 
//----+ +-------------------------------------------------------+
ExtVarNemes_Dn =
StringConcatenate( 
n_Width, "IndLevel_Dn",
n_Width, "FastEMA_Dn",
n_Width, "SlowEMA_Dn",
n_Width, "SignalSMA_Dn",
n_Width, "STOPLOSS_Dn",
n_Width, "TAKEPROFIT_Dn",
n_Width, "TRAILINGSTOP_Dn",
n_Width, "PriceLevel_Dn",
n_Width, "ClosePos_Dn"); 

ExtVarVelues_Dn = 
StringConcatenate(
d_Width, DoubleToStr(IndLevel_Dn, Digits), // 9
n_Width, FastEMA_Dn, // 10
n_Width, SlowEMA_Dn, // 11
n_Width, SignalSMA_Dn, // 12
n_Width, STOPLOSS_Dn, // 13
n_Width, TAKEPROFIT_Dn, // 14
n_Width, TRAILINGSTOP_Dn, // 15
n_Width, PriceLevel_Dn, // 16
n_Width, ClosePos_Dn); // 17 

//---- RECORDING STRINGS INTO HTML FILE
Write_Param_htm
(Test_Up, Timeframe_Up, ExtVarNemes_Up, ExtVarVelues_Up, 
Test_Dn, Timeframe_Dn, ExtVarNemes_Dn, ExtVarVelues_Dn);
//----+ +-------------------------------------------------------+
}
//---- End of the EA deinitialization
return(0);
//----+ 
}

下面是在 Microsoft Excel 中打开的针对此 EA 生成的 HTML 参数表:


此表包含所有执行的优化的结果。此表本身具有以下形式(前八列包含 EA 交易结果):

请注意,参数 Drawdown $ 和 Drawdown % 是仅针对关闭交易计算的,这就是为什么它们不同于与策略测试程序中的其他参数的原因。还应考虑,“获利因子”参数仅在至少有一个亏损交易时才有意义,如果根本没有亏损交易则毫无意义。最初,此表不包含任何亏损交易,这就是我为什么在没有亏损的情况下将此参数设置为零的原因。

在 EA 交易结果的右侧,有已优化的 EA 参数:

因此,我们用表格的形式同时显示每个优化操作的所有必要值和所有优化。这样可以给测试程序和终端留有一段时间,使用有关表格内容的最新程序分析器中非常有效的方法,基于一个 html 文件中包含的信息进行统计分析。

还有一点。以这种方式记录的上述 html 文件将拥有不完整的 html 代码,原因是不断将数据添加到文件里去。如果你不打算稍后将数据添加此文件中,应在 html 代码的结尾处写入以下行(在某个文本编辑器中打开此代码):

</table>
</body></html>


有关 TestReport.mqh 内容的一些解释

我使用此文件编写导出数据到 HTML 表格的 MQL4 代码,此文件包含很多通用的用户自定义函数。这些函数都是现成的,它们对于任何 EA 编写者都很有帮助,因此我想详细地讨论这些函数:

此文件的开头部分是上一篇文章中介绍的回溯测试和 IsBackTestingTime() 的外部变量的声明。之后是一个特殊的 CountTime() 函数的声明,此文件的一些函数会使用到此函数,但读者很少会用到。

指令

#include <Read_Write_File.mqh>

将 Read_Write_File.mqh 文件的内容纳入 TestReport.mqh 文件中:导入用于在操作系统 Windows 的模块的任何目录下记录和读取文件的函数。

#include <WinUser32.mqh>
#import "kernel32.dll"
int _lopen (string path, int of);
int _lcreat (string path, int attrib);
int _llseek (int handle, int offset, int origin);
int _lread (int handle, int& buffer[], int bytes);
int _lwrite (int handle, string buffer, int bytes);
int _lclose (int handle);
#import

可从此文件中包含的四个用户自定义通用函数的代码理解此函数的使用含义:

int _FileSize
(
string path
)

bool WriteFile 
(
string path, string buffer
) 

bool ReadFile
(
string path, string&amp;amp; StrBuffer[]
)

SpellFile
(
string path, string&amp; SpellBuffer[]
)

这些函数包含用于将包含路径的字符串引入到文本文件的可变路径及其名称。

_FileSize() 函数返回文件大小(单位:字节)。

WriteFile() 函数将“buffer”字符串的内容记录到文件末尾处。如果你希望每个字符串换到新的一行写入,则在每行末尾处添加“\n”:

buffer = buffer + "\n";

ReadFile() 函数更改字符串缓冲区 StrBuffer[] 的大小,并通过字符串将文件内容上传到其中,其中四个字母包括在一个缓冲区单元格中。

SpellFile() 函数更改字符串缓冲区的大小并逐个字母地上传文件内容。

在 TestReport.mqh 文件中,#include <Read_Write_File.mqh> 指令的后面有一组通用的用户定义函数,这些函数用于计算所谓的优化参数,

CountProfit(int cmd) 
CountMaxDrawdownPrs(int cmd) 
CountMaxDrawdown(int cmd) 
CountAbsDrawdown(int cmd) 
CountProfitFactor(int cmd) 
CountProfitTrades(int cmd) 
CountTotalTrades(int cmd) 
CountExpectedPayoff(int cmd)

它们与策略测试程序中的“优化结果”选项卡中显示的函数相类似。这些函数仅基于关闭交易的数据进行计算,这就是为什么函数CountMaxDrawdownPrs(),CountMaxDrawdown(),CountAbsDrawdown()返回的值与在策略测试程序中获得的值不同的原因。如果“cmd”变量接受了值 OP_BUY,则所有函数仅针对已关闭的多头仓位进行计算,如果接受了 OP_SELL,则所有函数仅针对已关闭的空头仓位进行计算。此变量的任何其他值提供对所有已关闭交易操作的计算。

在这些函数之后,文件还声明了其他四个函数 - 用于将优化结果和已优化参数记录到文件中:

void Write_Param_htm
(
bool ToResolveWrite_Up, int Timeframe_Up, string ExtrVarblsNemes_Up, string ExtrVarblsVelues_Up, 
bool ToResolveWrite_Dn, int Timeframe_Dn, string ExtrVarblsNemes_Dn, string ExtrVarblsVelues_Dn
)

void Write_Param_1htm
(
int Timeframe, string ExtrVarblsNemes, string ExtrVarblsVelues
)

void Write_Param_txt
(
bool ToResolveWrite_Up, int Timeframe_Up, string ExtrVarblsVelues_Up,
bool ToResolveWrite_Dn, int Timeframe_Dn, string ExtrVarblsVelues_Dn
)

void Write_Param_1txt
(
int Timeframe, string ExtrVarblsVelues
)

对于 Write_Param_htm(),上文已经进行了介绍。

Write_Param_1htm() 函数与上一函数完全相似,但它是针对 Expert Advisor 创建的,在此函数中,未针对多头和空头仓位划分外部参数。这里不需要 ToResolveWrite 函数,这就是为什么删除了它的原因。

Write_Param_txt() 函数与 Write_Param_htm() 类似,它记录相同的数据,但没有 html 指示。另一个用于组合包含优化结果和已优化参数的字符串的变量按照以下方式进行初始化:

Width = " ";

每个新的字符串使用新的一行记录到文件中,在文本文件中,在每个字符串的末尾处写入“;”。在文本文件中,在一个字符串的外部变量的值之间输入空格。

Write_Param_1txt() 函数与 Write_Param_txt() 函数完全相似,但它是针对 Expert Advisor 创建的,在此函数中,未针对多头和空头仓位划分外部参数。

最后两个函数

void Write_Param_htm_B
(
bool ToResolveWrite_Up, int Timeframe_Up, string ExtrVarblsNemes_Up, string ExtrVarblsVelues_Up, 
bool ToResolveWrite_Dn, int Timeframe_Dn, string ExtrVarblsNemes_Dn, string ExtrVarblsVelues_Dn
)

void Write_Param_1htm_B
(
int Timeframe, string ExtrVarblsNemes, string ExtrVarblsVelues
)

完全类似于 Write_Param_htm() 和 Write_Param_1htm(),但在它们的帮助下收到的 html 文件具有相反颜色。下面是示例:

很可能会有人喜欢处理这类文件。我个人喜欢这种信息呈现方式。



抛物线交易系统

此系统的工作指标包含在外汇和股票市场中运行的所有常见交易平台中。

我在这里介绍一个包含 BuyLimit 和 SellLimit 类型挂单的系统。

下面是 BuyLimit 的算法实现方式:

SellLimit 订单的算法方式相类似:

下面是 Expert Advisor 的程序代码的实现:

//+==================================================================+
//|                                                        Exp_8.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up = true;//filter of trade calculations direction
extern int    Timeframe_Up = 240;
extern double Money_Management_Up = 0.1;
extern double Step_Up = 0.02; 
extern double Maximum_Up = 0.2;
extern int    STOPLOSS_Up = 50;  // stop loss
extern int    TAKEPROFIT_Up = 100; // take profit
extern int    TRAILINGSTOP_Up = 0; // trailing stop
extern int    PriceLevel_Up =40; // difference between the current price and
                          // pending order triggering price
extern bool   ClosePos_Up = true; // forced position closing 
                                              //is allowed
//----+ +------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn = true;//filter of trade calculations direction
extern int    Timeframe_Dn = 240;
extern double Money_Management_Dn = 0.1;
extern double Step_Dn = 0.02; 
extern double Maximum_Dn = 0.2;
extern int    STOPLOSS_Dn = 50;  // stop loss
extern int    TAKEPROFIT_Dn = 100; // take profit
extern int    TRAILINGSTOP_Dn = 0; // trailing stop
extern int    PriceLevel_Dn = 40; // difference between the current price and 
                          // pending order triggering price
extern bool   ClosePos_Dn = true; // forced position closing
                                              //is allowed
//----+ +------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up, MinBar_Dn;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up variable value
   TimeframeCheck("Timeframe_Up", Timeframe_Up);                                                          
//---- Checking the correctness of Timeframe_Dn variable value 
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn);  
//---- Initialization of variables             
   MinBar_Up  = 5;
   MinBar_Dn  = 5;                               
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of the EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring local variables
   double SAR1, SAR2, CLOSE1, CLOSE2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static datetime StopTime_Up, StopTime_Dn; 
   static int LastBars_Up, LastBars_Dn;
   static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Initialization of variables 
           BUY_Sign = false;
           BUY_Stop = false;
           LastBars_Up = IBARS_Up;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                           + 60 * Timeframe_Up;
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS                                        
           SAR1 = iSAR(NULL, Timeframe_Up, Step_Up, Maximum_Up, 1);         
           SAR2 = iSAR(NULL, Timeframe_Up, Step_Up, Maximum_Up, 2);
           //---
           CLOSE1 = iClose(NULL, Timeframe_Up, 1);
           CLOSE2 = iClose(NULL, Timeframe_Up, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (SAR2 > CLOSE2)
             if (SAR1 < CLOSE1)
                          BUY_Sign = true;
                          
           if (SAR1 > CLOSE1)
                          BUY_Stop = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (PriceLevel_Up == 0)
           {           
            if (!OpenBuyOrder1(BUY_Sign, 1, 
                Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up))
                                                                return(-1);
           }
          else
           {           
            if (!OpenBuyLimitOrder1(BUY_Sign, 1, 
                Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime_Up))
                                                                return(-1);
           }
           
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Initialization of variables 
           SELL_Sign = false;
           SELL_Stop = false;
           LastBars_Dn = IBARS_Dn;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0)
                                           + 60 * Timeframe_Dn;
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS                                        
           SAR1 = iSAR(NULL, Timeframe_Dn, Step_Dn, Maximum_Dn, 1);         
           SAR2 = iSAR(NULL, Timeframe_Dn, Step_Dn, Maximum_Dn, 2);
           //---
           CLOSE1 = iClose(NULL, Timeframe_Dn, 1);
           CLOSE2 = iClose(NULL, Timeframe_Dn, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (SAR2 < CLOSE2)
             if (SAR1 > CLOSE1)
                          SELL_Sign = true;
                          
           if (SAR1 < CLOSE1)
                          SELL_Stop = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (PriceLevel_Dn == 0)
           {           
            if (!OpenSellOrder1(SELL_Sign, 2, 
                Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn))
                                                                return(-1);
           }
          else
           {           
            if (!OpenSellLimitOrder1(SELL_Sign, 2, 
                Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime_Dn))
                                                                return(-1);
           }
           
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Dn))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

在此 EA 中,交易执行块更加复杂。在这里,用于进入市场的函数 OpenBuyOrder1() 与 OpenSellOrder1() 和用于下挂单的函数 OpenBuyLimitOrder1() 与 OpenSellLimitOrder1() 一起使用。针对外部变量 PriceLevel_Up 和 PriceLevel_Dn 等于零的情况,执行此操作。在这种情况下,EA 将从市场建立交易,而仅处理挂单的 EA 将在距离市场最近的位置下挂单。



突破交易系统

关于基于突破位的交易系统,有许许多多的此类交易系统,你始终可以再开发一个突破系统。在本文中,我将介绍一个系统,在此系统中,由基于移动构建的通道的两侧定义突破位:

将在封闭的柱上定义突破。此外,我将使用在突破后出现反弹的突破交易系统。下面是此类带 BuyLimit 订单的交易系统形式:

SellLimit 订单也是如此:

EA 代码没有任何架构特点,这就是我为什么在本文中包含此代码的原因。你会发现 EA 已附上此代码 (Exp_9.mq4)。EA 中没有强制平仓。新的全局变量在 EA 初始化块中进行初始化。

dMovLevel_Up = MovLevel_Up * Point;
dMovLevel_Dn = MovLevel_Dn * Point;

这些变量用于计算 UpMovLeve1 位和 DownMovLevel1 位的值。



基于新闻进行交易

在市场上,经常会出现同一时刻发生多个剧烈变动的情况。很难事先确定将朝哪个方向变动。但可以事先说明会发生此类变动。例如,公布非农就业数据会导致此类剧烈变动。很多交易者喜欢抓住此类剧烈变动。检查此类交易系统是否合理是一件很有趣的事情。此系统的思路包括下两个 BuyStop 和 SellStop 类型的挂单,等到发生剧烈变动时,其中一个挂单建立交易并在到达获利位时进行关闭:

突破系统还有一种形式。在程序代码中实现此类系统并不是很困难:

//+==================================================================+
//|                                                       Exp_10.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR PLACING PENDING ORDERS
extern int    NewsWeekDay = 5;  // Weekday for news release
// if parameter is less than 1 or more than 5 any working day is used
extern int    NewsHour = 15;  // hour of news release
extern int    NewsMinute = 0;  // minute of news release
extern int    OrderLife = 30;  // Number of minutes of pending order validity
//----+ +------------------------------------------------------------+
//---- ea INPUT PARAMETERS FOR CLOSING POSITIONS
extern int    PosLife = 120;  // Number of minutes of an opened position validity
                                              //from news release time
//----+ +------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up = true;//filter of trade calculations direction
extern double Money_Management_Up = 0.1;
extern int    STOPLOSS_Up = 50;  // stop loss
extern int    TAKEPROFIT_Up = 100; // take profit
extern int    TRAILINGSTOP_Up = 0; // trailing stop
extern int    PriceLevel_Up =40; // difference between the current price and
                          // the price of pending order triggering
extern bool   ClosePos_Up = true; // forced position closing
                                              //is allowed
//----+ +------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn = true;//filter of trade calculations direction
extern double Money_Management_Dn = 0.1;
extern int    STOPLOSS_Dn = 50;  // stop loss
extern int    TAKEPROFIT_Dn = 100; // take profit
extern int    TRAILINGSTOP_Dn = 0; // trailing stop
extern int    PriceLevel_Dn = 40; // difference between the current price and 
                          // the price of pending order triggering
extern bool   ClosePos_Dn = true; // forced position closing
                                              //is allowed
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- 
    if (NewsHour > 23) 
             NewsHour = 23;
    if (NewsMinute > 59)
           NewsMinute = 59;                               
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of the EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static datetime StopTime, PosStopTime; 
   static bool BUY_Sign, SELL_Sign, BUY_Stop, SELL_Stop;
   //----+ +---------------------------------------------------------------+
   
   //----+ DEFINING SIGNALS FOR TRADES 
   if (DayOfWeek() == NewsWeekDay || NewsWeekDay < 1 || NewsWeekDay > 5)
     if (Hour() == NewsHour)
        if (Minute() == NewsMinute)
    {
     StopTime = TimeCurrent() + OrderLife * 60;
     PosStopTime = TimeCurrent() + PosLife * 60;
     BUY_Sign = true;
     SELL_Sign = true;
    }
    
    
    
   //----+ +---------------------------------------------------------------+ 
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up) 
    {
      //----+ EXECUTION OF TRADES          
      if (!OpenBuyStopOrder1(BUY_Sign, 1, 
                Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime))
                                                                return(-1);
      if (TimeCurrent() >= PosStopTime)                                                                    
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                           return(-1);
                                        
      if (!Make_TreilingStop(1, TRAILINGSTOP_Up))
                                           return(-1);
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn) 
     {
      //----+ EXECUTION OF TRADES
      if (!OpenSellStopOrder1(SELL_Sign, 2, 
                Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime))
                                                                return(-1);
      if (TimeCurrent() >= PosStopTime)            
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                           return(-1);
                                        
      if (!Make_TreilingStop(2, TRAILINGSTOP_Dn))
                                           return(-1);
     }
   //----+ +---------------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+


总结

在本文中,我提供了一个将有关优化结果的各种信息导出为电子表格方式的通用方法,为深入分析此类信息和显著改进 Expert Advisor 在自动交易中使用的交易结果提供了大量的机会。我希望我的方法对任何 EA 编写者都有用。