MetaTrader 5 Build 1640:创建和测试自定义交易品种

现在可以在程序端创建自定义的金融品种。使用该新选项,您可以创建任何交易品种,配置其设置,导入您的价格数据到交易品种并查看其图表。

21 七月 2017

程序端

  1. 现在可以在程序端创建自定义的金融品种。使用该新选项,您可以创建任何交易品种,配置其设置,导入您的价格数据到交易品种并查看其图表。

    创建自定义交易品种
    通过“市场报价”窗口的快捷菜单打开交易品种管理窗口并点击“创建自定义交易品种”:



    大量的交易品种参数可以被配置。完整的参数列表及其描述在文档中可以查询。您可以通过复制任何类似品种的参数并修改它们来配置您的自定义交易品种。在“复制自”字段选择现有的交易品种。
    自定义交易品种的名称不可与交易商提供的交易品种名称相同。如果您连接到存在同名交易品种的服务器,那么自定义交易品种将被删除。
    这里还提供了导入和导出参数的命令。您可以在您的程序端之间轻松地分享自定义交易品种或转移交易品种。设置会被导出到JSON文本文件。

    管理自定义交易品种
    所有交易品种都显示在独立的自定义组。如果您需要更改或删除一个交易品种,请使用列表的快捷菜单:




    导入价格历史
    您可以从任何文本文件以及MetaTrader 历史文件HST和HCC导入价格数据到您的自定义交易品种。选择一个交易品种并转到“柱形图”标签。


    在导入对话框,指定到文件的路径并设置所需的参数:

    • 分隔符 — 文本文件中的元素分隔符。
    • 跳过列和行 — 导入过程中将要跳过的列数(从左向右)和行数(从上到下)。
    • 迁移 — 时间迁移小时数。导入不同时区保存的数据时使用的选项。
    • 仅使用选定 — 仅导入在行查看区域突出显示的行。您可以按住 Ctrl 或 Shift 并用您的鼠标突出标记行。

    1分钟柱文件有以下格式:日期 时间 开盘价 最高价 最低价 收盘价 报价量 交易量 点差。例如;
    2016.06.27    00:01:00    1.10024    1.10136    1.10024    1.10070    18    54000000    44
    2016.06.27    00:02:00    1.10070    1.10165    1.10070    1.10165    32    55575000    46
    2016.06.27    00:03:00    1.10166    1.10166    1.10136    1.10163    13    13000000    46
    2016.06.27    00:04:00    1.10163    1.10204    1.10155    1.10160    23    51000000    41
    您可以使用任何现有品种的数据应用于您的自定义交易品种。导出数据(该选项已添加到之前的平台版本),必要情况下进行修改再将其导回。
    价格历史以一分钟柱的形式存储在MetaTrader 5中。其他所有时间周期都基于这些柱来创建。您也可以导入较高时间周期的数据,但这种情况下较低周期的图表将会出现差别。例如,如果您导入一小时数据,按小时显示的柱形图将会出现在M1图表上。
    自定义交易品种的价格数据保存在独立的自定义目录中(不在交易服务器数据存储的目录中):
    C:\Users\[windows account]\AppData\Roaming\MetaQuotes\Terminal\[instance id]\bases\Custom

    使用自定义交易品种
    自定义交易品种的用法类似于使用交易商提供的品种。自定义交易品种显示在市场报价窗口;您可以打开这种交易品种的图表并在这里使用指标和分析对象。自定义交易品种不可以进行交易。

    测试自定义交易品种的策略
    自定义交易品种可以在策略测试中测试自动交易和指标。以此来优化交易策略,甚至包括交易商目前尚未提供的金融品种。您只需要正确导入历史数据并配置自定义交易品种的属性。





    当计算预付款和利润时,策略测试会自动使用可用的交叉汇率。假设我们在外汇预付款计算类型创建AUDCAD.custom交易品种而我们账户的货币为美元。那么,测试器会根据外汇交易品种名称按照下面顺序搜索所需的交易品种:
    1.     首先,会搜索AUDUSD.custom(计算预付款)和USDCAD.custom(计算交易利润)格式的交易品种
    2.     如果其中一些交易品种不存在,那么会搜索第一个与所需货币对名称(AUDUSD和USDCAD分别进行)相对应的交易品种。例如,找到了AUDUSD.b 和 NZDUSD.b 交易品种。这意味着可以使用它们的汇率计算预付款和利润。

    其他预付款计算类型的工具(期货和 股票交易)则需要一种货币对把工具货币兑换成入金货币。假设我们创建了一个利润和预付款货币为GBP的自定义交易品种而入金货币是CHF。这种情况下,会依照以下顺序搜索测试交易品种:
    1. 检查是否存在GBPCHF (GBP vs CHF) 对应的交易品种。
    2. 如果这种交易品种不存在,那么会搜索第一个与GBPCHF名称相对应的交易品种,例如GBPCHF.b或GBPCHF.def。

    当通过自定义工具测试应用程序时,要确保交易账户包含全部所需的货币对。否则,测试期间将无法计算金融结果和预付款需求。

    在MetaTrader 5平台未来的版本中将会提供更多的可能性
    自定义交易品种的开发尚未完成,在接下来的平台版本中将会添加更多的功能。您将可以从EA交易直接导入历史记录到自定义交易品种,以及实时放送该交易品种的数据(添加报价)。

  2. 添加通过交易量过滤成交时间&交易量功能。

    少于指定交易量的实际交易量可以从成交时间&交易量表格中隐藏。如果使用这个过滤器,那么将只有大额交易才会显示在成交时间&交易量窗口。

    双击成交时间&交易量窗口的第一行,指定最小交易量手数,然后点击市场深度的任何其他区域。交易将被过滤,而当前过滤值将会出现在交易量列的标题。



    您还可以使用成交时间&交易量的快捷菜单指定最小交易量。

  3. 添加绑定市场深度和活动图表的选项。每次您切换到金融品种的图表时,在市场深度窗口都会自动启用相同品种。所以,您无需为每个新交易品种打开市场深度窗口。





  4. 修正程序端窗口最小化和最大化后的工具栏刷新。
  5. 修正交易单和持仓单重复情况下生成的持仓交易历史。

MQL5

  1. 添加在价格历史分析MQL5程序的选项。该选项无需等候新报价就可以检查程序性能。

    当基于真实数据进行分析时,可以在程序端标准图表中启用程序。许多程序,尤其是指标,只有在收到新报价(OnTickOnCalculate)时才会执行计算。因此,若要评估程序表现,您必须等候实时新报价。如果您使用历史数据测试程序,您可以立即提供所需的负载。分析在策略测试中以可视化模式启动,您可以一次性接收许多新报价事件。



  2. 添加支持union。Union是一种特殊的数据类型,由几个共享相同内存区的变量组成。因此,union提供了以两种(或更多)不同的方式讲解相同位序列的能力。Union声明从'union'关键字开始。
    union LongDouble
    {
      long   long_value;
      double double_value;
    };
    与结构不同,不同的union成员属于同一个内存区。在该示例中,LongDouble函数的union是通过共享同一个内存区的long和double类型值来声明。请注意,由于long_value 和 double_value 变量重复(在内存中),所以union不可以同时存储long整型值和double真实型值(不同于结构)。 换句话说,MQL5程序随时都可以将union的数据处理为整型(long)或真实型(double)值。因此,union允许接收表示相同数据序列的两种(或更多种)选项。

    union声明期间,编译器会自动分配足够的内存区以便在变量union存储最大的类型(交易量)。同样的语法也用于访问关于结构的union元素,例如,点操作符
    union LongDouble
    {
      long   long_value;
      double double_value;
    };
    //+------------------------------------------------------------------+
    //| 脚本程序起始函数                                                        |
    //+------------------------------------------------------------------+
    void OnStart()
      {
    //---
       LongDouble lb;
    //--- 获得并显示无效 -nan(ind) 数字
       lb.double_value=MathArcsin(2.0);
       printf("1.  double=%f                integer=%I64X",lb.double_value,lb.long_value);
    //--- 最大的标准化数值 (DBL_MAX)
       lb.long_value=0x7FEFFFFFFFFFFFFF;
       printf("2.  double=%.16e  integer=%I64X",lb.double_value,lb.long_value);
    //--- 最小的正标准化 (DBL_MIN)
       lb.long_value=0x0010000000000000;    
       printf("3.  double=%.16e  integer=%.16I64X",lb.double_value,lb.long_value);
      }
    /*  Execution result
        1.  double=-nan(ind)                integer=FFF8000000000000
        2.  double=1.7976931348623157e+308  integer=7FEFFFFFFFFFFFFF
        3.  double=2.2250738585072014e-308  integer=0010000000000000
    */

  3. 为结构和类对象添加自动生成隐式复制操作符。现在,编译器可以自动创建复制操作符,它可以为对象编写简单的条目,例如b=a:
    class Foo
      {
       int               value;
    public:
       string Description(void){return IntegerToString(value);};
       //--- 默认构造函数
                         Foo(void){value=-1;};
       //--- 参数化构造函数   
                         Foo(int v){value=v;};
      };
    //+------------------------------------------------------------------+
    //|  包括 Foo 类型对象的结构                           |
    //+------------------------------------------------------------------+
    struct MyStruct
      {
       string            s;
       Foo               foo;
      };
    //+------------------------------------------------------------------+
    //| 脚本程序起始函数                                    |
    //+------------------------------------------------------------------+
    void OnStart()
      {
    //---
       MyStruct a,b;
       Foo an_foo(5);
       a.s="test";
       a.foo=an_foo;
       Print("a.s=",a.s," a.foo.Description()=",a.foo.Description());
       Print("b.s=",b.s," b.foo.Description()=",b.foo.Description());
    //---
       Print("b=a");
       b=a;
    //---
       Print("a.s=",a.s," a.foo.Description()=",a.foo.Description());
       Print("b.s=",b.s," b.foo.Description()=",b.foo.Description());
    /*
       Execution result;
       a.s=test a.foo.Description()=5
       b.s= b.foo.Description()=-1
       b=a
       a.s=test a.foo.Description()=5
       b.s=test b.foo.Description()=5
    */
      }
    在隐式操作符中执行对象的成员逐一复制。

    • 如果成员是一个对象,那么该对象对应的复制操作符将会被调用。
    • 如果成员是一个对象数组,那么调用每个元素对应的复制操作符之前就会使用ArrayResize增加或减少接收数组到所需的大小。
    • 如果成员是简单类型数组,ArrayCopy函数将用于复制。
    • 如果成员是一个对象指针,那么将会复制指针而不是它指向的对象。

    必要的情况下,您可以使用重载覆盖这个行为然后创建您自己的选项来替代隐式复制操作符。

  4. 当使用Copy* 函数访问来自EA交易的价格历史时,优化内存使用。当处理大量数据将会大幅降低内存消耗。

  5. 现在,TimeToStruct函数返回一个布尔值,允许检查datetime到MqlDateTime转换的成功率。
  6. 添加禁止在结构使用FileWriteStructFileReadStruct函数的禁令,包括字符串,动态数组,对象和指针。
  7. 已添加以下返回代码:

    • TRADE_RETCODE_REJECT_CANCEL — 激活挂单的请求被拒绝,订单被取消
    • TRADE_RETCODE_LONG_ONLY — 由于交易品种设置了“仅允许买入持仓”的规则,所以请求被拒绝
    • TRADE_RETCODE_SHORT_ONLY — 由于交易品种设置了“仅允许卖出持仓”的规则,所以请求被拒绝
    • TRADE_RETCODE_CLOSE_ONLY — 由于交易品种设置了“仅允许关闭现有持仓”的规则,所以请求被拒绝

  8. 通过SYMBOL_ORDER_MODE参数添加SymbolInfoInteger函数的新返回值。SYMBOL_ORDER_CLOSEBY — Close By操作的权限,例如,通过反向持仓来平仓。
  9. SYMBOL_CUSTOM布尔属性已添加到ENUM_SYMBOL_INFO_INTEGER枚举。该属性可以了解交易品种是否为自定义。使用SymbolInfoInteger函数来获得属性。
  10. 现在有可能获得创建一个订单,交易或持仓的原因。

    新属性


    订单,交易和持仓的创建原因
    已添加三个变量用来获得创建交易操作的原因:

    ENUM_POSITION_REASON ENUM_DEAL_REASON ENUM_ORDER_REASON 原因描述
    POSITION_REASON_CLIENT DEAL_REASON_CLIENT ORDER_REASON_CLIENT 激活从桌面程序端下单的订单而执行该操作
    POSITION_REASON_MOBILE DEAL_REASON_MOBILE ORDER_REASON_MOBILE 激活从手机应用下单的订单而执行该操作
    POSITION_REASON_WEB DEAL_REASON_WEB ORDER_REASON_WEB 激活从网页平台下单的订单而执行该操作
    POSITION_REASON_EXPERT DEAL_REASON_EXPERT ORDER_REASON_EXPERT 激活从MQL5程序下单的订单而执行该操作,例如EA交易或脚本
    - DEAL_REASON_SL ORDER_REASON_SL 激活止损而执行该操作
    - DEAL_REASON_TP ORDER_REASON_TP 激活止赢而执行该操作
    - DEAL_REASON_SO ORDER_REASON_SO 由于Stop out 事件而执行该操作
    - DEAL_REASON_ROLLOVER - 由于展期交割而执行交易
    - DEAL_REASON_VMARGIN - 收取变动预付款后执行交易
    - DEAL_REASON_SPLIT - 股票或其他资产分割(价格减少)后执行交易,宣布分割期间拥有持仓

  11. 优化同步和访问报价历史。
  12. CopyTicksRange函数中,修正返回报价到统计数组。在早期版本中,这种情况下经常返回0报价。
  13. 模糊逻辑库完成了多种修正。

信号

  1. 修正无交易账户连接的情况下从网站打开的信号。

Tester

  1. 优化并加速处理订单和交易历史。当处理大量数据时(数万条历史条目)将大幅度提高操作速度。
  2. 修正测试报告中计算的持仓时间。

MetaEditor

  1. 修正了调试程序中静态类成员数组的显示内容。
  2. 在调试程序中添加了一个断点列表。该列表可以使用Debug标签的快捷菜单来打开:



    若要跳转到断点,请双击它。
更新文档。