请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3364712 新帖:0

MQL5:在 MetaTrader 5 中分析和处理商品期货交易委员会 (CFTC) 报告

爱汇小王子发表于:5 月 13 日 19:00回复(1)

简介

作为交易人员的工具之一的由 MetaQuotes Software Corp. 开发的 MetaTrader 5 交易终端,包含支持面向对象编程的 MQL5 编程语言。一方面,MQL5 和前一版本的 MQL4 并不兼容;另一方面,它具有全功能 面向对象语言的大量新的可能性。因此,那些已经驾驭 MQL4 的交易人员,不得不学习这一(事实上的)新的语言,而他们正是本文的目标读者。

在本文中,我将给出下述问题的解决方案:有必要开发交易人员工具,以获得和分析商品期货交易委员会 (CFTC) 报告的不同数据。本主题已在 Meta COT 项目 - MetaTrader 4 CFTC 报告分析的新视野一文中进行讨论,因此我假设读者已熟知基本概念,而我们将讨论在文章中未涉及的详细信息。

理念如下:开发可从委员会提供的文件获取数据而无需中间处理和转换的单一指标。此外,该指标可用于不同目的:作为指标绘制数据;作为其他指标的数据源、在脚本中用于自动分析、在开发交易策略时用于“EA 交易”。


1.COT 报告类型

有三种类型的报告:旧式报告 (COT)、补充商品指数 (CIT) 和新式分类报告 (DCOT),它们之间的差异如表 1 所示。

说明
旧式报告 补充商品指数 新式分类报告
短名称 COT CIT DCOT
 参考 标题
旧式报告
补充商品指数
新式分类报告
最近的数据文件引用

deacot2010.zip

dea_cit_txt_2010.zip

fut_disagg_txt_2010.zip

报告中出现的交易人员组别
非商业持仓
商业持仓
非报告持仓
非商业持仓
商业持仓
非报告持仓
指数型交易人员
生产商/贸易商/加工企业/用户
互换交易商
管理基金
其他报告持仓
非报告持仓

表 1. 交易人员持仓类型报告  

有关交易人员、哪些人应在期货市场报告他们的持仓、分类原则和报告周期的信息可在 "Trade Stocks and Commodities With the Insiders:Secrets of the COT Report"(与业内人士交易股票和商品:COT 报告的秘密)一书和 Meta COT 项目 - MetaTrader 4 CFTC 报告分析的新视野一文中找到。

我将讨论两种未在以上材料中述及的报告。

首字母缩略词 CIT 表示 交易员承诺指数。此报告自 2007 年起发布。最新 CIT 报告网页的网址为 http://cftc.gov/dea/options/deaviewcit.htm。指数型交易人员属于套期保值者和投机者之外的组别。

补充报告的描述可在 http://www.cftc.gov/MarketReports/CommitmentsofTraders/AbouttheCOTReports/index.htm 找到。所有这些指数型交易人员经常在市场上建立买入持仓并在合约间操作。

自 2009 年起,委员会开始发布“交易人员持仓分类报告”,相关说明可在 注释说明中找到。

COT 分类报告把交易人员分为下述四种类别,相比 COT 旧式报告具有更高的透明性:生产商/贸易商/加工企业/用户;互换交易商;管理基金;以及其他报告持仓。

  • 生产商/贸易商/加工企业/用户。 “生产商/贸易商/加工企业/用户”是主要从事生产、加工、包装或处理实体商品以及使用期货市场管理或套期保值与上述行为相关的风险的实体。
  • 互换交易商。 “互换交易商”是主要从事商品互换以及使用期货市场管理或套期保值与那些掉期交易相关的风险的实体。互换交易商的对手方可能是投机商,比如对冲基金,或在实体商品中管理来自交易的风险的传统商业客户。
  • 基金经理。 对于本报告而言,“基金经理”是指注册商品交易顾问 (CTA)、注册商品基金经理 (CPO) 或由 CFTC 确定的未注册的基金。这些交易人员代表客户管理和进行有组织的期货交易。
  • 其他报告持仓。 不属于其他三个类别的每个报告持仓交易人员都归于“其他报告持仓”类别。

报告工具的完整列表在附录 2 中给出。还有一些列显示了在 CIT 和 DCOT 报告中存在特殊工具。


2. 编写使用来自 CSV 文件的外部数据的 COT 指标

指标将按照如下所述的方式工作。报告类型(表 1 中列示的一种)、数据类型和交易人员组别在指标的输入参数中进行定义。

数据的类型可以是下述类型中的任一种:

  • 净长仓
  • 未平仓合约中的净长仓比率
  • 威廉指标,计算净长仓
  • 未平仓合约

可能的数据类型列表并不完整,它可轻松扩展以将我使用的最基本的数据包括在内。对于当前交易品种,需要从数据文件获取指定的数据(下载及解压缩方式在下文中说明)。 我们将 CCFTCReport 用于数据访问,并从这些文件中下载数据。

指标具有如下所述的结构:

2.1. 常量

要定义常量,需要使用 enum 数据类型。指标支持的报告类型如下所示:
enum cot_type_report // 报告类型
{ 
  COT, DCOT, CIT
};

交易人员群组:

enum cot_type_traders // 交易者类型
{
  noncommercial,      // 非商业 
  commercial,         // 商业
  nonreportable,      // 无需报告
  index,              // 指数交易者
  producer,           // 生产商
  swapdealers,        // 掉期交易者
  managedmoney,       // 基金
  otherreportables    // 其他须报告交易者 
};

可在指标中使用的数据类型:

enum cot_type_data    // COT数据类型
{   
  netlongs,           // 净买入
  netlongsrate,       // 未平仓合约中的净买入比率
  willams_index,      // Williams指数
  openinterest        // 未平仓合约
}; 

2.2. 类

要在单一变量中存储不同的对象,可以使用结构和类。然而,分配两个结构类型的变量是不可能的,如果它们包含动态数组或字符串类型的值的话。这是我们使用类而不是结构来存储 COT 记录以及数据分配方法的原因之所在。

class cot_record                                // 用于COT报告数据记录的类
  {
public:
   datetime          COT_DATE;                  //日期 
   double            COT_OPENINTEREST;          //未平仓合约 
   double            COT_LONGNONCOM;            //非商业交易者的买入
   double            COT_SHORTNONCOM;           //非商业交易者的卖出
   double            COT_LONGCOM;               //商业交易者的买入
   double            COT_SHORTCOM;              //商业交易者的卖出
   double            COT_LONGNONREPORTABLE;     //其他非报告交易者的买入
   double            COT_SHORTNONREPORTABLE;    //其他非报告交易者的卖出
   double            COT_LONGINDEX;             //指数交易者的买入
   double            COT_SHORTINDEX;            //指数交易者的卖出
   double            COT_LONGPRODUCER;          //生产商/贸易商/加工企业/用户的买入
   double            COT_SHORTPRODUCER;         //生产商/贸易商/加工企业/用户的卖出
   double            COT_LONGSWAPDEALERS;       //掉期交易者的买入
   double            COT_SHORTSWAPDEALERS;      //掉期交易者的卖出
   double            COT_LONGMANAGEDMONEY;      //基金交易者的买入
   double            COT_SHORTMANAGEDMONEY;     //基金交易者的卖出
   double            COT_LONGOTHERREPORTABLES;  //其他需报告者
   double            COT_SHORTOTHERREPORTABLES;
   string            COT_ID;                    //交易品种标识符
   string            COT_NAME;                  //交易品种名称 

   void copyvar(const cot_record &from)         // 从一个类中复制内容(变量值)到另一个类中
     {
      COT_ID                    = from.COT_ID;
      COT_NAME                  = from.COT_NAME;
      COT_DATE                  = from.COT_DATE;
      COT_OPENINTEREST          = from.COT_OPENINTEREST;
      COT_LONGNONCOM            = from.COT_LONGNONCOM;
      COT_SHORTNONCOM           = from.COT_SHORTNONCOM;
      COT_LONGCOM               = from.COT_LONGCOM;
      COT_SHORTCOM              = from.COT_SHORTCOM;
      COT_LONGNONREPORTABLE     = from.COT_LONGNONREPORTABLE;
      COT_SHORTNONREPORTABLE    = from.COT_SHORTNONREPORTABLE;
      COT_LONGINDEX             = from.COT_LONGINDEX;
      COT_SHORTINDEX            = from.COT_SHORTINDEX;
      COT_LONGPRODUCER          = from.COT_LONGPRODUCER;
      COT_SHORTPRODUCER         = from.COT_SHORTPRODUCER;
      COT_LONGSWAPDEALERS       = from.COT_LONGSWAPDEALERS;
      COT_SHORTSWAPDEALERS      = from.COT_SHORTSWAPDEALERS;
      COT_LONGMANAGEDMONEY      = from.COT_LONGMANAGEDMONEY;
      COT_SHORTMANAGEDMONEY     = from.COT_SHORTMANAGEDMONEY;
      COT_LONGOTHERREPORTABLES  = from.COT_LONGOTHERREPORTABLES;
      COT_SHORTOTHERREPORTABLES = from.COT_SHORTOTHERREPORTABLES;
     };
  };

从现在开始,我假设读者熟悉 CSV 格式的 COT 报告,这在 Meta COT 项目 - MetaTrader 4 CFTC 报告分析的新视野一文中业已讨论。该类型的类实例将被用于存储 COT 报告的单线。这些类实例的数组可使用它们存储和方便地访问 COT 记录的字段。CCFTCReport 类已被开发用于数据存储和访问:

class CCFTCReport                    //COT 报告
  {
private:
   cot_type_report   type;           //当前报告的类型 
   cot_record        data[];         //cot报告数据
   int               sizedata;       //当前报告的记录数目
   string            idsymbol;       //持仓报告中的交易品种标识符,在字段"CFTC Contract Market Code"中 )
   string            terminalsymbol; //客户端中的交易品种名称
public:
   void ~CCFTCReport(){ sizedata=0; };  
   bool              Init( cot_type_report passedtype, string sym="" ); //类实例的初始化
   bool              LoadFile( string filename );                       //从文件中加载数据
   string            Name();                                            //返回报告的简短名称
   bool              Type(cot_type_report passedtype);                  //设置报告类型
   cot_type_report Type(){return(type);};                               //返回报告类型
   bool              TestGroup( cot_type_traders type_trader );         //检查特定交易者是否出现
   bool              DefineIdSymbol();                                  //持仓报告中id的定义
   bool              GetString( int handle, cot_record& arr );          //从csv文件中获取字符串(记录)
   string            GetFieldCommaDelimited(string &str);               //从csv字符串中获取字段
   double            At(datetime time,cot_type_traders type_trader,cot_type_data typedata=netlongs); //从报告中获取数据
  };

CCFTCReport 类的实例包含单一交易品种的整个报告,报告类型可以是 COT、CIT 或 DCOT。枚举和类在 "cot.mqh" 包含文件中列出。

2.3. 输入参数

输入参数由输入变量定义。这些参数可用于指定交易人员组别、数据类型和必要的 COT 报告类型:

input cot_type_traders type_trader = noncommercial;  //交易者类型
input cot_type_data    type_data   = netlongs;       //指标类型
input cot_type_report  type_report = COT;            //报告的类型

2.4. OnInit 函数

指标具有 OnInit 函数,该函数用于以下目的:从报告文件下载数据、检查输入参数、分配指标的缓冲区。

通过 INDICATOR_DATA 属性初始化的缓冲区包含要在图表上绘制的数据。通过 INDICATOR_CALCULATIONS 属性初始化的缓冲区包含中间计算。

SetIndexBuffer( 0, BufferData, INDICATOR_DATA );
IndicatorSetString(INDICATOR_SHORTNAME,indname);
SetIndexBuffer( 1, BufferCalculations, INDICATOR_CALCULATIONS );

2.5. OnCalculate 函

该函数用于选择必要数据、计算请求的数据及其绘图。

让我们来具体讨论它的工作。我们使用第二种形式的调用:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &Time[],
                const double &Open[],
                const double &High[],
                const double &Low[],
                const double &Close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[]){

让我们确定待计算和绘图的柱。

int pos=rates_total-prev_calculated-1;
if( pos >= rates_total-1 )pos--;

我们指定元素必须按时序编排索引。

ArraySetAsSeries(Time, true);
ArraySetAsSeries(BufferData, true);
ArraySetAsSeries(BufferCalculations, true);

经过一系列尝试,我发现最好将时序索引用于所有与指标的缓冲区相关的数组。这对于作为参数传递至 OnCalculate 函数的数组而言同样是方便的,最后(最近)的元素索引等于 0。

计算循环如下所示:

for(int i=pos;i>=0;i--)
{
    cot_type_data passed = type_data;
    if(type_data==netlongs || type_data==netlongsrate || type_data==willams_index)
    {
      // 数据类型:净买入,净买入率,威廉指数) 返回净买入 
      // 进一步的计算都基于这些数据。
      passed = netlongs;
    
}
    double res = Report.At(Time[i], type_trader, type_data ); //从报告中获取数据
    BufferCalculations[i] = res;
    BufferData[i]         = CalcData( type_data, i, Time );
  
}

BufferCalculations 数组用于存储从 COT 报告中选择的原始数据。

BufferData 数组包含在图表上绘制就绪的数据。数据可能是报告的值(净长仓、未平仓合约)以及计算的值(净长仓比率、威廉指标)。我想指出下述问题,该问题我尚未找出妥善的解决方案。传递至 OnCalculate 函数的数组,可能在后续水平中被要求,且数组仅当在这些调用中传递时我们才可以访问它们,因此我认为这样会使代码变得杂乱无章。

CalcData 函数调用

BufferData[i]         = CalcData( type_data, i, Time );

CalcData 函数调用 CalcIndex 函数

double CalcData( cot_type_data type_data, int i, const datetime& Time[] )
{
  // 未平仓合约中的净买入比率
  if( type_data == netlongsrate ) return( BufferCalculations[ i ] / Report.At( Time[i], type_trader, openinterest ));
  // 威廉指数
  if( type_data == willams_index )return( CalcIndex( i, Time, BufferCalculations ) );

  return(BufferCalculations[i]);        

}

我需要在 CalcIndex 函数内部访问时间数组,所以我不得不按照调用层次将其传递。想象一下,如果我们需要使用全部的 8 个数组,代码会变成什么样子。


3. 下载数据文件

所有文件链接均已在表 1 中给出。每年会有单独的文件发布,出版年号位于文件名中。例如,http://www.cftc.gov/files/dea/history/deacot2010.zip 文件包含 2010 年的报告,http://www.cftc.gov/files/dea/history/deacot2009.zip 文件包含 2009 年的报告等。

需要下载所有这些文件并将它们解压缩至客户端安装目录的 \MQL5\files\ 文件夹中。每年需要为其创建名为 deacotXXXX 的单独文件夹,其中 XXXX 对应于年号。如此一来,我们会得到下述文件夹结构:

图 1. 报告的文件夹结构。

我们可以简化数据准备的过程。所有下述操作(检查 CFTC 网站的更新、下载和解压缩至相应文件夹)均由 "Cotdownloader" 脚本执行。脚本内核(数据下载)基于 WININET_TEST 脚本。我使用 CProgressBar ,该类在价格直方图(市场概况)及其在 MQL5 中的实施一文中发布外部应用程序使用 Windows API 执行,相关说明请见实际交易中的交易机器人自动优化一文

使用脚本十分简单:只要将其附加至任意图表即可。工作时,它通过图表上进度条的形式以及 EA 交易选项卡上文本消息的形式报告数据下载信息。


图 2. 数据下载过程。


4. 使用示例

要运行指标,需要将指标附加至所选交易品种的图表并指定输入参数。

图 3 COT 指标的输入参数

请注意,现在您可以指定用户友好的表示法来取代变量名和枚举数据类型的值。操作方法如下:要取代变量名,您应在声明一个输入变量时指定一则注释:

input cot_type_traders type_trader = noncommercial;  //交易者类型
input cot_type_data    type_data   = netlongs;       //指标类型
input cot_type_report  type_report = COT;            //报告的类型

对于值同样如此 - 当声明枚举值时,需要在注释中指定说明:

enum cot_type_data    // 数据类型
{   
  netlongs,           // 净买入
  netlongsrate,       // 未平仓合约中的净买入比率
  willams_index,      // Williams指数
  openinterest        // 未平仓合约
};

如果输入参数已正确指定且文件已下载和解压缩,指标将在单独窗口中出现:

图 4 COT 指标

如果发生错误,错误将在 "Toolbox"(工具箱)窗口的 "Experts"(EA 交易程序)选项卡中列出。

图 5 错误消息


5. 发行说明

该指标并非定位为全功能的成品。这只是说明如何获得结果的示例,还可以通过编写简单的代码进一步使用。例如,我们没有开发模块,以允许使用由特定经纪人提供的客户端设置自定义 COT 报告数据的类型。该功能在 DefineIdSymbol 函数的内部实施。下面是最初的几行代码:

bool CCFTCReport::DefineIdSymbol()
  {
   idsymbol="";
   if(terminalsymbol=="USDLFX" || terminalsymbol=="DX_CONT" || StringFind(terminalsymbol,"DX")==0)idsymbol="098662";
   //U.S. 美元指数 - 美国CE期货
   if( terminalsymbol == "FC_CONT" || StringFind( terminalsymbol, "FC")== 0)idsymbol = "061641";  //肉牛 
   if( terminalsymbol == "LC_CONT" || StringFind( terminalsymbol, "LC")== 0)idsymbol = "057642";  //活牛 
   if( terminalsymbol == "QM_CONT" || StringFind( terminalsymbol, "QM")== 0)idsymbol = "067651";
   //原油,轻质原油 - 纽约商品交易所

如果您需要从报告分配交易品种至客户端交易品种,您应通过修改这些代码来手动完成这项工作。我使用的是 BrocoTrader4 终端的设置。在本文的示例中,我使用的是在 Metaquotes-Demo 和 Alpari-Demo 服务器上设立的演示帐户。仅有 2 个工具可用于 DCOT 报告:XAUUSD (gold)、XAGUSD (silver)。

目前还不支持 CIT 报告,因为这些服务器上没有任何金融工具。当有金融工具时,可通过取消注释和修改部分代码很容易地获得它们的支持。


6. 如何通过 iCustom 使用 COT 指标

我没有使用图 3 中所示形式的指标。使用 iCustom 函数,MQL5 语言可重复使用自定义指标。

6.1. 创建新指标

有多种方式用于 COT 报告直观分析。直方图正是其中之一,使用不同颜色显示不同交易人员群组的持仓情况。

我们讨论以下任务:创建 COTnet 指标,将不同交易人员群组(COT 报告中的商业持仓和非商业持仓)的持仓情况绘制成直方图。用户必须能够选择数据类型:净长仓、净长仓比率、威廉指标。

此过程可通过“MQL5 向导”进行简化,详情已在 “MQL5:创建自己的指标”一文中讨论。因此,指标(绘图风格由“MQL5 向导”创建)代码如下所示:

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//---- 绘制非商业的
#property indicator_label1  "Noncommercial"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  5
//---- 绘制商业的
#property indicator_label2  "Commercial"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  5
//--- 指标缓存
输入变量、全局变量以及用于包含带类的库的预处理程序指令如下所示:
#include <cot.mqh>
input cot_type_data    type_data   = netlongs;  // 指标类型
double         NoncommercialBuffer[];
double         CommercialBuffer[];
//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
int handlecomm, handlenoncomm;

OnInit 函数的代码如下所示:

int OnInit()
{
   SetIndexBuffer(0,NoncommercialBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,CommercialBuffer,INDICATOR_DATA);
   cot_type_traders td = commercial;
   cot_type_report  tr = COT; 
   handlecomm = iCustom(NULL, 0, "cot", td, type_data, tr );
   td = noncommercial;
   handlenoncomm = iCustom(NULL, 0, "cot", td, type_data, tr );
   return(0);

}
让我们考虑一下如何使用自定义指标(以非商业持仓交易人员为例)。在首次调用 iCustom 函数后,下述参数(是我们的报告所必需的)被传递至函数:
  • NULL – 客户端中的当前交易品种
  • 0 – 当前时间表
  • "cot" – 自定义指标的文件名(请注意,指定为无扩展名)
  •  td = 商业持仓(我们需要的交易人员组别)
  •  type_data = 指标类型,在输入参数中指定
  •  tr = COT – 报告类型

结果,我们得到一个句柄,它将用于进一步获取指标的数据。

从指标获取数据通过函数 OnCalculate 完成:
  if(BarsCalculated(handlecomm)<rates_total || BarsCalculated(handlenoncomm)<rates_total) return(0);
  int to_copy = clctocopy(rates_total, prev_calculated );
  if( !copycotbuf(handlecomm, CommercialBuffer, to_copy ) )
  {
    Print("Error in data of commercial traders");
    return( 0 );
  
}

  if( !copycotbuf(handlenoncomm, NoncommercialBuffer, to_copy ) )
  {
    Print("Error in data of non-commercial traders");
    return( 0 );
  
}
  return(rates_total);

我们花费一些时间,编写了一小段代码并获得如下所示的结果:

图 6 cotnet 指标

6.2. iCustom 也可用于脚本

我们讨论以下任务:创建 cotsignals 脚本以计算统计估计。

使用 COT 报告的不同数据,我们看看我们会获得什么样的统计优势。最简单的方法是估计正确确定每周烛形颜色的概率。考虑下述假设:
  • 非商业持仓交易人员的净长仓的符号与烛形颜色一致:如果符号为正,周趋势为上涨;如果符号为负,周趋势为下跌。
  • 烛形颜色(白色/黑色)与非商业持仓交易人员的净长仓的增多/减少直接相关。
  • 烛形颜色为黑色或白色取决于基于非商业持仓交易人员的净长仓计算出的威廉指标值。如果为超买(超过 75%),烛形颜色为黑色;如果为超卖(不足 25%),烛形颜色为白色。

我们将使用来自 COT 报告的数据。您可以使用这些示例来开发您自己的 COT 数据解释方法并充分利用它的优势。在您的案例中,我们将检查对应于 3 年时长的 150 个周柱的历史数据。在编写脚本前,我们必须定义必要的数据类型和类:

统计数据可能类型的枚举为:

enum cot_type_statistics   //用于计算的统计 类型 
{  
  speculantsign,           //非商业交易者的净买入的标志
  speculantchange,         //非商业交易者买入仓量的变化
  willamszones             //威廉指标的超买/超卖区
};

为获取指定交易品种的统计数据,我们创建特殊类:

class CCOTStatistic
{
  private:
    
    int bars ;                            // 交易品种历史周线的数量 
    string symbol;                        // 客户端中交易品种的名称
    double netlongsspeculantsdata[];      // 投机者的净买入数据 
    double willamsindexspeculantsdata[];  // 投机者净买入的威廉指标数据
    cot_type_statistics liststatistic[];  // 统计列表
  public:
    //初始化和初始设置
    void Init( string symbol_passed, cot_type_statistics& listpassed[] );
    //获取方向的预报 
    int GetCotSignalDirection( int ibar, cot_type_statistics type_stat   );
    bool Get( double& probably[] );       // 返回统计数据
};

请求的统计数据通过 Get 方法返回,让我们来说明一下它是如何工作的。首先,必要数组使用自定义指标填充数据。我们需要非商业持仓(投机者)交易人员的净长仓值和威廉指标值:

if (!LoadDataFromCOTIndicator(symbol, PERIOD_W1, noncommercial, netlongs, COT, netlongsspeculantsdata, bars))
   return(false);
  //获取到相关数据 -  投机者 的净买入
if (!LoadDataFromCOTIndicator(symbol, PERIOD_W1, noncommercial, willams_index, COT, willamsindexspeculantsdata, bars))
   return(false);
  //获取到数据 -  投机者的威廉指数 

统计数据计算(我们只有一个参数需要计算 - 它是每周烛形颜色的预测概率)的代码如下所示:

for(int istat = 0; istat < ArraySize(liststatistic); istat++)
  {
   int cntsignals = 0;
   int cntsucsess = 0;
   for(int i=bars-1; i>=0; i--)
     {
      double colorcandle=iClose(symbol,PERIOD_W1,i)-iOpen(symbol,PERIOD_W1,i);
      if(symbol=="USDCHF" || symbol=="USDCAD" || symbol=="USDJPY") colorcandle=-colorcandle;
      double cotdirection=GetCotSignalDirection(i,liststatistic[istat]);
      if(cotdirection==0)continue;                 //无信号
      cntsignals++;
      if(cotdirection*colorcandle>0) cntsucsess++; //颜色和方向一致
     
}

   if(cntsignals!=0) probably[istat]=1.*cntsucsess/cntsignals;

   Print("Calculation complete for ",symbol,GetStringTypeStatistic(liststatistic[istat]),
                 " the correct forecast probability=",DoubleToString(probably[istat],2));
   Print("Total signals:",cntsignals,"success:",cntsucsess);
  
}
LoadDataFromCOTIndicator 函数十分复杂,因为它需要执行数量庞大的检查以从指标获取数据,因此让我们对它进行详细讨论:
bool LoadDataFromCOTIndicator( string           symbol,        //交易品种名称
                               ENUM_TIMEFRAMES  timeframe,     //时间框架
                               cot_type_traders type_trader,   //交易者群组的 类型
                               cot_type_data    type_data  ,   //指标 类型 
                               cot_type_report  type_report,   //报告 类型
                               double&          loadto[],      //输出数据 数组
                               int              nbars   )      //需要的柱形数量
{     
  
  int cothandle;
  nbars+=10 ; //用于反向
  cothandle = iCustom( symbol , timeframe, "cot", type_trader, type_data, type_report );

在最后一行,我们获得自定义指标的句柄,该句柄可用于从缓冲器获取数据。

我们必须检查指标是否已成功创建:

  if( cothandle == INVALID_HANDLE ){
    Print("Error in indicator creation for symbol ", symbol );
    return(false);
  
}

检查历史数据,我们需要:

int n = BarsSinh( symbol, timeframe );
  if(  n < nbars    )
{ 

如果没有足够的历史数据,我们可自己载入:

Print("Loading history for ", symbol ); //, " 始于 ", loadtm  
    CheckLoadHistory( symbol ,timeframe,   loadtm );
    n = BarsSinh( symbol, timeframe );
    if( n < nbars )
    {
      Print("Not enough history for the "+symbol, " total ", n, "bars");
      return(false);
    
}
  
}

BarsSinh(返回指定交易品种和时间表的可用柱数)和 CheckLoadHistory(下载历史数据)函数基于来自 script代码,该代码来自 MQL5 Reference。

在使用来自指标缓冲区的数据前,我们必须检查数据是否已准备就绪,因为仅凭句柄存在并不能保证计算已经完成。

如果计算已经完成,下一个调用执行检查并等待:

if( !WaitForCalculcateIndicator( cothandle ) ){
    Print("Timeout for the COT indicator calculation");
    return(false);
  
}

数据已就绪,我们需要复制数据:

int res = CopyBuffer(cothandle, 0, 0, nbars, loadto );

接下来,我们检查数据是否已成功复制:

if( res != nbars ){
    Print("Error in obtaining the data, ", MyErrorDescription(_LastError) );
    return(false);
  
}

最后:

return(true);

我们获得数据,并通过函数参数传递将数据返回至数组中。

结果统计数据将打印为 CSV 文件,为此我们创建 CCOTOutFile 类:

class CCOTOutFile
{
  private:
   string  filename;
   int     handle; 
  public:
    bool Init( string passedname );
    void PutString( string symbol, double& probably[] );
    void PutHeader( cot_type_statistics& arrheaders[] ) ;
    void ~CCOTOutFile(){       FileClose(handle);    }
};

它创建含输出数据的文件,以 .csv 格式编写字符串,在销毁类实例时生成头文件和关闭文件。

脚本的代码会比较短,因为所有必要的库已编写。

输入参数和包含库:

input int      NBars =150; //历史数据深度 W1
#include <common.mqh>
#include <cot.mqh>

用于分析的交易品种列表:

string listsymbols[] = {"EURUSD", "GBPUSD", "USDCHF", "USDCAD", "USDJPY", "AUDUSD", "XAUUSD"};

对象初始化:

void OnStart()
{
  CCOTOutFile outfile;  //结果文件
  if( !outfile.Init("cotw1signals.csv") )return;

待计算的统计数据列表:

  cot_type_statistics list_statistic[]= // 统计类型列表
  { speculantsign, speculantchange, willamszones };

编写 CSV 文件头:

outfile.PutHeader( list_statistic ); //向.csv文件写入头

在主循环中,我们获得每个交易品种和信号的统计数据,并将结果写入文件:

  for( int i = 0; i < ArraySize(listsymbols); i++  ) //列表中的所有交易品种
 {  
    Print( "Analysis for "+listsymbols[i] );
    CCOTStatistic stat;
    stat.Init( listsymbols[i ], list_statistic );
    double probably[];                               //一个信号的概率
    if( !stat.Get( probably ) )
    {
      Print( "Error in statistics calculation for the symbol ", listsymbols[i] );
      return;
    
}  
    outfile.PutString( listsymbols[i], probably );   //向.csv 文件写入字符串
  
}
  Print("Calculation complete.");

}

脚本已在 Alpari-Demo 服务器上测试。如果您在 MetaQuotes-Demo 服务器上运行脚本,服务器将打印消息 "Error in statistics calculation for the XAUUSD symbol"(XAUUSD 交易品种的统计数据计算发生错误),因为该交易品种目前尚不可用。

执行脚本后,我们将获得文件,如下所示:


为了让它更加清楚,我们用 Excel 打开,计算平均值并创建概率直方图:

图 8 预测概率

所有交易品种的预测结果都相同。不同信号类型的正确预测概率的平均值为:
  • 0.54 – 非商业持仓交易人员符号;
  • 0.50 – 非商业持仓交易人员的净长仓量改变;
  • 0.48 – 威廉指标的超买/超卖区域。

正如我们所见,非商业持仓交易人员的净长仓获得了最佳的预测结果。最差的结果来自威廉指标区域。值 0.48 表示白色烛形的概率为 0.52,即使威廉指标为超买,如果是超卖则为黑色。因此,它通过威廉指标表示的使用形式是不合理的。也许,使用较大的时间表会使结果得到改善:月或更大时间表。我们使用了演示服务器和 COT 报告中所有可用的交易品种。


总结

MQL5 是一款工具,允许您为开发交易系统必需任务的整个周期编程:
  • 具有复杂算法的指标被用于访问外部数据源;
  • 它在其他指标、脚本和“EA 交易”中重复使用;
  • 统计和数量分析自身算法的实施。
优点:
  • 面向对象编程极大地节约了调试时间。
  • 调试程序。
  • 很容易从 MQL4 迁移到 MQL5。
  • 面向对象模型成功实施,易于使用。
  • 文档组织有序。
  • Windows API 的集成扩展了平台,例如可使用网页。

缺点:

我的主要问题是访问历史数据: 
  • 缺乏必要的原生函数来访问时间序列(如 MQL4 中的 Time[]、Open[]、Close[] 及其他)
  • 访问数据时,需要执行数目繁多的数据可访问性检查,需要了解数据的详细信息。

虽然有调试程序,但没有提供多少有用的功能:没有指标调试,也无法执行复杂对象的检查,比如数组和类。列表并不完整,我仅仅是列出在本文成文过程中碰到的优缺点。


附录 1.文件表

所有文件均位于客户端文件夹中。从 sources.zip 将文件解压缩至客户端文件夹。

 №文件名
说明
 1 MQL5\Files\unzip.exe
 解压缩 .zip 档案的 Windows 应用程序
 2 MQL5\Include\Cdownloader.mqh
 从网络下载 CFTC 档案的类
 3 MQL5\Include\ClassProgressBar.mqh
 用于在图表窗口中显示下载过程的类 CProgressBar
 4 MQL5\Include\common.mqh
用于所有指标和脚本的通用函数和常量
 5 MQL5\Include\cot.mqh
 用于从 COT 报告选择数据的类 CCFTCReport
 6 MQL5\Include\ErrorDescription.mqh
 错误描述库
 7 MQL5\Indicators\cot.mq5
 基础指标 cot
 8 MQL5\Indicators\cotnet.mq5
指标 cotnet,将 cot.mq5 用作自定义用户指标的简单示例
 9 MQL5\Scripts\cotdownloader.mq5
脚本 cotdownloader,用于从互联网下载档案文件
 10 MQL5\Scripts\cotsignals.mq5
 脚本 cotsignals,COT 报告统计分析的示例


表 2. 文件列表


附录 2. COT 报告中的可用交易品种列表


交易品种名称
交易所 ID 客户端 ID 出现于 CIT 中 出现于 DCOT 中
 1 小麦 - 芝加哥交易所 001602 ZW x x
 2 小麦 - 堪萨斯城交易所 001612   x x
 3 小麦 - 明尼阿波利斯谷物交易所 001626     x
 4 玉米 - 芝加哥交易所 002602 ZC x x
 5 燕麦 - 芝加哥交易所 004603 ZO   x
 6 黄豆 - 芝加哥交易所 005602 ZS x x
 7 大豆 - 芝加哥交易所 005603     x
 8 硫金融工具 - 芝加哥气候期货交易所 006261     x
 9 碳金融工具 - 芝加哥气候期货交易所 006268     x
 10 RGGI 二氧化碳配额 2009 - 芝加哥气候期货交易所  00626U      x
 11 黄豆油 - 芝加哥交易所 007601 ZL x x
 12 美国国库债券 - 芝加哥交易所 020601 ZB    
 13 美国国库长期债券 - 芝加哥交易所 020604      
 14 GULF # 6 燃料 3.0% 硫交换 - 纽约商品交易所 02165A      x
 15 NY RES 燃料 1.0% 硫交换 - 纽约商品交易所  02165B      x
 16 EUR 1% 燃油 NWE CAL 交换 - 纽约商品交易所  02165C      x
 17 EUR 3.5% 燃油 RTD CAL 交换 - 纽约商品交易所  02165E      x
 18 SING 燃油 180 CAL 交换 - 纽约商品交易所  02165G      x
 19 东西燃油 SPR 交换 - 纽约商品交易所  02165I      x
 20 NY 1% V GULF 3% 燃油 SPR - 纽约商品交易所  02165T      x
 21 2 号热燃油 022651     x
 22 SING 汽油交换 - 纽约商品交易所  02265J      x
 23 SING 汽油/RDAM 汽油交换 - 纽约商品交易所  02265T      x
 24 NYMEX 热燃油/RDAM 汽油 - 纽约商品交易所  02265U      x
 25 汽油 (ICE) 交换 - 纽约商品交易所  02265V      x
 26 上下 GC ULSD VS HO SPR 交换 - 纽约商品交易所  022A13      x
 27 SING 汽油 BALMO 交换 - 纽约商品交易所  022A22      x
 28 天然气 ICE 亨利港 - ICE OTC  023391     x
 29 天然气 - 纽约商品交易所  023651 QG   x
 30 MICHCON 基差交换 - 纽约商品交易所  02365A      x
 31 M-3 基差交换 - 纽约商品交易所  02365C      x
 32 TCO 基差交换 - 纽约商品交易所  02365D       
 33 NGPL TEXOK 基差交换 - 纽约商品交易所  02365G      x
 34 NGPL MIDCON 基差交换 - 纽约商品交易所  02365K      x
 35 WAHA 基差交换 - 纽约商品交易所  02365O      x
 36 休斯敦航道利率交换 - 纽约商品交易所  023A10      x
 37 CBT 乙醇 - 芝加哥交易所 025601     x
 38 芝加哥乙醇交换 - 纽约商品交易所  025651     x
 39 黄豆粉 - 芝加哥交易所 026603 ZM   x
 40 日本 C&F NAPTHA 交换 - 纽约商品交易所  03265C      x
 41 2 号棉花 - ICE 美国期货交易所  033661 CT x x
 42 亨利港基差交换 - 纽约商品交易所  035652     x
 43 休斯敦航道基差交换 - 纽约商品交易所  035653     x
 44 NW PIPE ROCKIES 基差交换 - 纽约商品交易所  035654     x
 45 PANHANDLE 基差交换 - 纽约商品交易所  035655     x
 46 亨利港交换 - 纽约商品交易所  03565B       
 47 亨利港天然气倒数第二个工作日期满掉期 - 纽约商品交易所  03565C      x
 48 稻谷 - 芝加哥交易所 039601 ZR   x
 49 冻橙汁 - ICE 美国期货交易所  040701 JO   x
 50 美国两年债券 - 芝加哥交易所 042601      
 51 美国十年债券 - 芝加哥交易所 043602 ZN    
 52 美国五年债券 - 芝加哥交易所 044601      
 53 30 天联邦基金 - 芝加哥交易所 045601 ZQ    
 54 连续月第三级牛奶 - 芝加哥商品交易所 052641     x
 55 瘦肉猪 - 芝加哥商品交易所 054642 HE x x
 56 活牛 - 芝加哥商品交易所 057642 LC x x
 57 任意长度木材 - 芝加哥商品交易所 058643 LB   x
 58 肉牛 - 芝加哥商品交易所 061641 FC x x
 59 PJM 月度电价 - 纽约商品交易所  064657     x
 60 ISO NEW ENGLAND LMP 交换 - 纽约商品交易所  06465H      x
 61 PJM CAL 月度离峰 LMP 交换 - 纽约商品交易所  06465M      x
 62 ISO NEW ENG 离峰 LMP 交换 - 纽约商品交易所  06465S      x
 63 CINERGY CAL 月度 LMP 交换 - 纽约商品交易所  064A01      x
 64 CINERGY 离峰 LMP 交换 - 纽约商品交易所  064A02       
 65 PJM N ILL 日前峰值 - 纽约商品交易所  064A34      x
 66 PJM JCPL 日前峰值 - 纽约商品交易所  064A48      x
 67 PJM PEPCO 日前峰值 - 纽约商品交易所  064A50      x
 68 PJM PSEG 日前峰值 - 纽约商品交易所  064A54      x
 69 PJM WESTERN 日前峰值 - 纽约商品交易所  064A56       
 70 PJM WESTERN 实时峰值 - 纽约商品交易所  064A58      x
 71 PJM WESTERN 实时离峰 - 纽约商品交易所  064A59      x
 72 ISO NEW ENG INT HUB 峰值交换 - 纽约商品交易所  064A60      x
 73 MW IND TRANS 峰值交换 - 纽约商品交易所  064A62      x
 74 NYISO ZONE 5 MW 峰值交换 - 纽约商品交易所  064A66       
 75 ISO NEW ENG HUB 离峰交换 - 纽约商品交易所  064A78       
 76 MT BELVIEU 丙烷 5 DEC 交换 - 纽约商品交易所  06665O       
 77 MT BELVIEU 乙烷 5 DEC 交换 - 纽约商品交易所  06665P      x
 78 MT BELV 标准丁烷 5 DEC 交换 - 纽约商品交易所  06665Q      x
 79 MT BELV 天然汽油 5 DEC 交换 - 纽约商品交易所  06665R      x
 80 低硫轻质原油 - ICE 欧洲期货交易所   轻质原油 - ICE 欧洲期货交易所  067411     x
 81 低硫轻质原油 - 纽约商品交易所 067651 QM   x
 82 WTI 原油日历交换 - 纽约商品交易所  06765A      x
 83 迪拜原油日历交换 - 纽约商品交易所  06765G      x
 84 WTI 原油金融工具 - 纽约商品交易所  06765I      x
 85 布伦特金融工具 - 纽约商品交易所  06765J      x
 86 布伦特 (ICE) 日历交换 - 纽约商品交易所  06765N      x
 87 布伦特-迪拜交换 - 纽约商品交易所  06765O      x
 88 可可 - ICE 美国期货交易所 073732 CC x x
 89 钯金 - 纽约商品交易所  075651 PA   x
 90 白金 - 纽约商品交易所  076651 PL   x
 91 11 号糖 - ICE 美国期货交易所  080732 SB x x
 92 咖啡 C - ICE 美国期货交易所 083731 KC x x
 93 白银 - 商品交易所  084691 SI,XAGUSD,ZI   x
 94 高级铜 - 商品交易所 085692 HG   x
 95 黄金 - 商品交易所  088691 GC,GOLD,XAUUSD   x
 96 俄罗斯卢布 - 芝加哥商品交易所  089741 USDRUB,USDRUR    
 97 加拿大元 - 芝加哥商品交易所 090741 6C,USDCAD    
 98 瑞士法郎 - 芝加哥商品交易所 092741 6S,USDCHF    
 99 墨西哥比索 - 芝加哥商品交易所 095741      
 100 英镑 - 芝加哥商品交易所 096742 6B,GBPUSD    
 101 日元 - 芝加哥商品交易所 097741 6J,USDJPY    
 102 美元指数 - ICE 美国期货交易所 098662 DX    
 103 欧元 - 芝加哥商品交易所 099741 6E,EURUSD    
 104 汽油搀配油 (RBOB) - 纽约商品交易所  111659 XRB   x
 105 RBOB 日历交换 - 纽约商品交易所  11165K      x
 106 新西兰元 - 芝加哥商品交易所 112741 6N,NZDUSD    
 107 VIX 期货 - 芝加哥期货交易所 011700      
 108 道琼斯工业平均指数 - 芝加哥交易所 124601      
 109 3 月期欧洲美元期货 - 芝加哥商品交易所 132741      
 110 标普 500 指数 - 芝加哥商品交易所  138741      
 111 电子迷你标普 500 指数 - 芝加哥商品交易所  13874A  ES,SPX    
 112 纳斯达克 100 指数 - 芝加哥商品交易所  209741 NQ    
 113 迷你纳斯达克 100 指数 - 芝加哥商品交易所  209742      
 114 道琼斯瑞银额外回报 - 芝加哥交易所 221602      
 115 澳元 - 芝加哥商品交易所 232741 6A,AUDUSD    
 116 罗素 2000 迷你指数期货 - ICE 美国期货交易所  23977A       
 117 日经股价指数 - 芝加哥商品交易所 240741      
 118 日经股价指数 YEN DENOM - 芝加哥商品交易所 240743      
 119 电子迷你 MSCI EAFE - 芝加哥商品交易所  244741      
 120 电子迷你 MSCI 新兴市场 - 芝加哥商品交易所  244742      
 121 10 年期利率交换 - 芝加哥交易所 246602      
 122 5 年期利率交换 - 芝加哥交易所 247602      
 123 标普 GSCI 商品指数 - 芝加哥商品交易所  256741      
 124 SING JET KERO 交换 - 纽约商品交易所  26265D       
 125 电子迷你标普 400 指数 - 芝加哥商品交易所  33874A       
 126 GULF JET NY 热燃油 SPR 交换 - 纽约商品交易所  86465A      x
 127 SING JET KERO 汽油 SPR 交换 - 纽约商品交易所  86465C      x
 128 JET CIF NWE/汽油期货 - 纽约商品交易所  86465D      x
 129 GULF # 6 燃油裂解交换 - 纽约商品交易所 86565A      x
 130 3.5% 燃油 RDAM 裂解价差 - 纽约商品交易所  86565C      x
 131 石脑油裂解价差交换 - 纽约商品交易所  86665A      x
 132 汽油裂解价差交换 - 纽约商品交易所  86765C      x


表 3. COT 报告中的可用交易品种列表


全部回复

0/140

达人推荐

量化课程

    移动端课程