English Русский Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
在 MetaTrader 5 里使用 HedgeTerminal (对冲终端) 面板进行双向交易和仓位对冲, 第一部分

在 MetaTrader 5 里使用 HedgeTerminal (对冲终端) 面板进行双向交易和仓位对冲, 第一部分

MetaTrader 5交易 | 11 六月 2015, 12:11
4 030 0
Vasiliy Sokolov
Vasiliy Sokolov

内容目录


介绍

在过去的 18 个月里,MetaQuotes 为了将 MetaTrader 4 和 MetaTrader 5 平台整合到统一的生态系统,进行了广泛坚实的工作。现在,这两个平台可以共享一个解决方案的统一市场 - MetaTrader市场,可由外部开发者提供不同的产品。用于两个平台的编译器也已经统一。其结果是这两个平台都拥有基于 MQL5 的通用编译器,和一种编程语言 - MQL 依据所使用的平台,具有不同函数集合。所有发布于 代码库 的源代码也已修改,并且它们当中的一些经过调整也可与新编译器兼容。

平台的这次重大统一,搁置了交易部分的统一。MetaTrader 4 和 MetaTrader 5 的交易模型依然不兼容,尽管事实上,交易环境的主要部分是共通的。MetaTrader 4 通过系统订单,有助于独立管理交易仓位 - 特殊程序实体使得终端里的双向交易十分简单容易。MetaTrader 5 的目标在于交易所交易,其中交易者契约的主要体现是总体净持仓。在 MetaTrader 5 中订单只是简单地买卖金融工具的指令。

这两个平台之间交易执行的差异,导致了很多热烈的讨论和辩论。不过,讨论归讨论。不幸的是,自从 MetaTrader 5 发布,如同 MetaTrader 4 那样展现交易者契约双向仓位的解决方案不止发布了一款。尽管发表了许多文章,提出了各种方案,只是它们都不具备足够地灵活性,以便大规模应用。另外,这些决定中没有能适合交易所交易的,它涉及了大量必须考虑的细节。

本文要解决 MetaTrader 平台第四版、第五版的爱好者之间的争议。这将提供一种通用方案来形成编程规范,以及精确按照规范实现的程序。本文讨论一款可视化的面板和虚拟化函数库 HedgeTerminal, 其允许交易员像使用 MetaTrader 4 那样展现双向仓位。同时,HedgeTerminal 底层模型亦考虑了交易订单执行的特性。这意味着它可以在场外市场 FOREX 和集中式交易所两者间成功地实现,例如,在莫斯科交易所的衍生品分部交易衍生证券。

HedgeTerminal 是一款内置于 MetaTrader 5 的全功能交易终端。通过虚拟化 机制,它改变了当前仓位的表现,所以交易员或交易机器人可以管理他们的独立交易仓位。无论仓位数量,甚或它们的方向都不重要。我想强调的是,我们正在谈论虚拟化 - 一个具体地转换交易者契约展现的机制,而不是它们的量化特征。

这并非与扭曲交易者财务活动的结果有关,但与转换这种活动的重现有关。HedgeTerminal 基于 MetaTrader 5 交易环境和 MQL5 编程语言。它并未给终端带来新的交易信息,它只是简单地从不同角度观察当前的交易环境。这意味着,HedgeTerminal 基于 MetaTrader 5,且是其本机应用。虽然,我们在它们之间发放一个标识符,但包容符更合适,因为 HedgeTerminal 仅是众多小型 MetaTrader 5 应用之一。

虚拟化可行性以及 HedgeTerminal 的存在基于三个范例:

  1. 从概念上讲,将一个完整且保证可转换的仓位,表示为独立的双向交易事务是可行的。此陈述证明的事实是,在一些外部交易平台,包括那些设计用于交易所交易的平台,有管理双向仓位的手段;
  2. MetaTrader 5 的交易模型在用户级别可以在订单之间创建单向连接。计算表明,以某种方式设计的链接将抵御冲突。此外,即使在某些情况下,如历史数据受损或不可抗力情况,双向事务可以追溯修正,并在净值重现时作为财会结果计算;
  3. 在 MQL5 中的高级 API 允许在 MQL5 和 MetaTrader 5 终端之间放置标识符。换句话说,在 MetaTrader5 里可以通过程序界面和 MQL5 编程语言访问几乎所有东西。例如,您可以编写自己的终端版本,就像 MetaTrader 5 终端内的 HedgeTerminal。

本文讨论底层算法,以及 HedgeTerminal 是如何工作的。此规范和算法确保与本文中详细讨论的双向交易一致。无论您是否决定使用 HedgeTerminal,或创建您自己的函数库来管理自己的交易算法,您都会发现这篇文章以及它延续的有用信息。

本文不针对具体的程序员。如果您不具备任何编程经验,您也可以理解它。在本文里刻意未包含 MQL 的源代码。所有源代码置换为更具说明性的图表,表格和图片,有规划地表达操作原理和数据的组织。我可以用经验告诉大家,即使掌握良好的编程原理,观看一段代码的通用范式也比对其进行分析更容易。

在这篇文章的第二部分,我们要讨论 EA 与 HedgeTerminalAPI 可视化库的集成,然后涉及编程。不过,即使在这种情况下,一切所为都是为了简化代码的感知,尤其是对程序员新手。举例,虽然 HedgeTerminal 是面向对象的应用程序,但诸如类这种面向对象的构造,没有在程序里使用。


如何阅读本文

本文相当长。一方面,这很好,因为几乎所有关于该主题的问题,都可以在这里找到答案。另一方面,许多用户宁愿只阅读最重要的信息,而在必要时返回到相关的章节。本文以完整连贯的表述,覆盖了全部材料。与实体书类似,我们将会在每章给出简短总结,所以您可以看到您是否需要阅读。

  • 第 1 章, 第 1 部分. 双向交易组织的原理。 这章包括 HedgeTerminal 的主要思路。如果您不想深入了解双向交易的组织的信息,这章足以获得 HedgeTerminal 操作的一般原理的思路。这章建议所有读者阅读。

  • 第 2 章, 第 1 部分. 安装 HedgeTerminal, 首次启动。 这章描述 HedgeTerminal 的可视化面板的设置与启动。如果您不打算使用 HedgeTerminal 的可视化面板, 那么您可以跳过此章节。如果您将要使用 HedgeTerminalAPI 函数库, 您需要浏览本文的 2.1 和 2.2 节。它们专述 HedgeTerminal 的安装程序。安装程序是所有 HedgeTerminal 产品的通用组件。

  • 第 3 章, 第 1 部分. 在 HedgeTerminal 的礼帽之下。规范和操作原则。 本章强调 HedgeTerminal 的内部结构,它的算法和内部数据组织。那些对双向交易感兴趣的,可在本章搜索信息。自行开发虚拟化函数库,且并发使用大量机器人的专业算法交易者,可以发现本章非常有用。

  • 第 1 章, 第 2 部分. EA 与 HedgeTerminal 及其面板的通信。本章将得到那些探索这方面的人,以及专业算法交易者的赞赏。它描述了 HedgeTerminal 函数库与交易机器人架构配合工作的一般原则。

  • 第 2 章, 第 2 部分. HedgeTerminalAPI 的文档。 包含 HedgeTerminalAPI 函数库的函数文档。本章是文档清单,将会被不时参考。此处没有无用的讨论以及滥竽充数的文本。本章只包括函数原型,结构和枚举也只有用法的简短例程。

  • 第 3 章, 第 2 部分. 异步交易操作基础。 HedgeTerminal 在自身工作时使用异步操作。本章包括使用它们的经验。本文里包括的这一章,所有读者,不管是否计划在他们的工作里使用 HedgeTerminal,都可以找到一些有用的信息。

  • 第 4 章, 第 2 部分. 在 MetaTrader 环境里的多线程编程基础。 本章解释了什么是多线程,如何分配它,以及什么样的数据组织形式可以使用。就像第 3 章,与所有的 MetaTrader 用户共享多线程应用开发的经验。

我希望这篇文章足够有趣,可令您从头读到尾。


第一章. 双向交易的组织原理

1.1. MetaTrader 5 组织双向交易的机会

文章 "莫斯科交易所衍生产品市场为例的交易定价原则" 仔细描述了交易价格形成的细微差别,以及市场参与者计算财会业绩的方法。它概述了莫斯科交易所的价格计算,与外汇交易接受的计算方法之间概念上的显著不同。

总体上,交易价格的形成是比较复杂的,包含了很多在 MetaTrader 终端上进行外汇交易时隐藏的明显细节。

例如,在 MetaTrader 4 上交易者的订单执行细节被隐藏,而在 MetaTrader 5 上这些细节可见。另一方面,在 MetaTrader 5 上的详细交易信息并非一直需要。它也许令一个没有经验的用户或者程序员新手工作困难,以及造成误解。例如,在 MetaTrader 4 里,找出订单的执行价格,您需要简单地在“价格”栏查找对应的数值。在 MQL4 编程语言里,调用 OrderOpenPrice() 函数就足够了。在 MetaTrader 5 里,它需要查找所有订单执行的成交细节,审查它们并计算它们的加权均价。这个可变的价格是订单执行的价格。

还有其它一些情况,在 MetaTrader 5 中,交易环境的扩展重现需要额外的努力来分析这些信息。提示逻辑问题:

在 MetaTrader 5 上有没有如同 MetaTrader 4 一样简单、清晰的交易方式,并可保持便利地访问所有交易细节?使用 MetaTrader 5 是否有如同 MetaTrader 4 一样分配双向交易的方式?- 这些问题的答案是: "是的, 这就是"!

让我们来参照 MetaTrader 4 和 MetaTrader 5 终端的能力图例来理解这种可能:

图例. 1 MetaTrader 4 和 MetaTrader 5 的能力图例

图例. 1. MetaTrader 4 和 MetaTrader 5 的能力图例

正如我们所看到的, "MetaTrader 5" 的集合包含了 "MetaTrader 4" 子集。这意味着 MetaTrader 4 的所有事情均可在 MetaTrader 5 上完成,但反之则为假。MetaTrader 5 的能力不可避免地增加了交易信息呈现的数量和复杂性。可以将这个困难委派给工作于 MetaTrader 5 环境里的特殊助理程序。这些程序可以处理这些复杂性,从而使终端性能在同一水平。一款这样的程序 HedgeTerminal 就是本章的焦点。

HedgeTerminal 是一款能够运行在 MetaTrader 5 内部的羽翼丰满的交易终端。它利用 MetaTrader 5 交易环境, 以 MQL5 语言转换并以便利的图形界面呈现 - HedgeTerminalUltimate 面板以及用于独立算法 (EA,脚本,指标) 交互的 HedgeTerminalAPI 特殊接口。

MetaTrader 4 的特性使之可以使用 双向仓位锁单。在 MetaTrader 5 里也有这种能力,但它不很明确。这可以使用一个特定的附加程序启动,实质上就是 HedgeTerminal。HedgeTerminal 内建于 MetaTrader 5,并利用其环境, 收集订单和成交信息,将之与仓位集成,看上去与 MetaTrader 4 类似,且拥有 MetaTrader 5 的所有能力。

此类仓位可以全部或部分锁单 (当同时存在多头和空头持仓时)。维护此类仓位的机会并非 HedgeTerminal 本身的目标。其主要目标是将交易信息统一到群 (仓位),这将便于分析,管理和访问。双向仓位只能在 HedgeTerminal 里存在,因为这很方便。若干交易者在同一账户里进行交易的情况下, 或许使用多个策略, 必须安排交易动作的拆分。

此外,在外汇交易时一些细微之处都必须考虑到,如部分订单执行,仓位翻转,保证金变动的计算,统计和其它许多事情。开发 HedgeTerminal 就是为了应对这些挑战。它为用户或 EA 提供了与 MetaTrader 4 类似,规范且高水准的界面,能够同时在交易所环境里正确工作。


1.2. 配对订单 - 对冲和统计的基础

为了能够管理交易技术和算法的一致性, 有必要了解 明确 何种交易动作属于何种算法。我强调 "明确" 这个词,因为即使失败的概率很小,仓位管理迟早崩溃是必然的。反之, 结果将是统计损坏,以及破坏在同一账户里用不同算法进行管理的想法。

可靠拆分交易活动基于两个基本的可行性:

  1. 将两笔交易订单 合并 或 "配对" 在一起的可行性,因此它总可以定义为两个订单独立开仓 (虚拟) 和平仓。
  2. 分析订单配对的算法必须完全确定,并在所有程序模块里统一。

确定性算法的第二个要求将在下面加以详细研究。现在,我们将重点放在第一条。

一笔订单就是一个买入或卖出指令。一笔订单是一条定义好的实例,其中包括众多信息的 "字段",主要信息之外还有像魔幻数和订单号,请求价格和开单条件。

在 MetaTrader 5 里此类字段之一称为 "订单魔幻数"。这是用于交易机器人或 EA 的特殊字段,能够用自己独有的数字标记订单,所以也称为 "魔幻数字"。这个字段在人工交易时未使用,但它对交易算法十分重要,因为交易算法分析该字段的值,它可以随时查看每笔订单是否由它或任何其它算法放置的。

让我们来看一个例子。让我们假设,我们需要打开一个经典的多头仓位,然后在一段时间后,平掉它。为此,我们必须放置两笔订单。第一笔订单会打开这个仓位,第二笔则将其平仓:

图例. 2. 所有订单形成了历史净持仓

图例. 2. 所有订单形成了历史净持仓

如果我们在向市场发送第二笔订单时将第一笔订单的魔幻数字填写在 "订单魔幻数" 字段里会怎样呢?

之后,订单的字段可以被读取,如果数值等于第一笔订单的数值,则我们可以确定地说第二笔订单与第一笔相关,且是它的反向,即平仓单。

在图示上这个对应看起来像:

图例. 3. 订单配对

图例. 3. 订单配对

名义上此类订单可以被称为配对,因为第二笔订单包含到第一笔订单的链接。第一笔订单开新仓,称之为 初始 或 开仓 订单。第二笔订单称之为 平仓

如此配对的订单称之为 仓位。为了避免与 MetaTrader 5 中的"仓位"概念混淆,我们将如此配对的仓位称作 双向, 对冲HedgeTerminal 仓位。仓位在 MetaTrader 5 里将被称为 净持仓 或 MetaTrader 5 经典持仓。

显然,不同于经典的那样,HedgeTerminal 的仓位数量和其方向,可以任意。如果有一笔执行的订单没有被其它任何订单引用会怎样?这样的订单可以被表述为一个活动的双向持仓。事实上,如果一个放置的反向订单包含至此订单的链接,则这个订单是第一笔订单的平仓单。此类订单将会配对,并且 已平仓 双向仓位的成交量相等,方向相反。

所以, 让我们来定义在 HedgeTerminal 里仓位的含义:

如果一笔执行的订单没有被其它任何订单引用, 则 HedgeTerminal 处理此类订单作为 一个活动双向持仓

如果一笔执行的订单被其它订单引用, 则两笔订单配对,HedgeTerminal 将之处理作为合并的 历史已平仓 双向仓位。

在现实中,在 HedgeTerminal 里配对的订单是比较复杂的,因为每笔订单最少生成一笔成交,而在外汇交易里可以有很多这样的成交。一般情况下,交易过程可以概述如下: 一位交易者通过 MetaTrader 5 终端下订单来开新仓。交易所执行这个订单时会有一笔或若干笔成交。

成交,与订单类似,包含更多附加信息的字段。一个这样的字段包含订单 id,即建立在成交执行的基础上。该字段包含一个有关此成交属于哪笔订单的信息。反之为假。该命令自身并不知道哪笔成交属于它。它的发生,在于放置订单时,它并不清楚此订单的成交如何执行,以及此订单以后会否执行。

如此一来,动作的因果关系或判断可被观察到。成交将会引用订单,且订单会引用其它。这样的结构可以表述一个 单向链表

开单执行成交后在 MetaTrader 5 里生成经典持仓,且成交属于一笔平仓订单,反之,平仓。这些配对在以下图例中呈现:

图例. 4. 订单, 成交和交易之间的关系图例

图例. 4. 订单, 成交和交易之间的关系图例

我们将会返回到这个图例来详细分析,因为方向对于建立一个严格判断交易者动作记录的系统是非常重要的,而这就是 HedgeTerminal。


1.3. MetaTrader 5 的净持仓和 HedgeTerminal 仓位的关系

从 HedgeTerminal 的角度来看,两笔带有相同交易量的相反订单可以是两笔不同的仓位。在这种情况下,它们的净持仓为零。这就是为什么 HedgeTerminal 不使用在 MetaTrader 5 里的有关实际净持仓的信息。所以, 在 HedgeTerminal 里的仓位未与 MetaTrader 5 里的仓位关联。当前净持仓仅在 HedgeTerminal 启动的时刻验证一次。反向活动持仓的总成交量必须与实际净持仓数值一致。

如果不是这种情况, 则在 HedgeTerminal 上出现警告惊叹号, 持仓不相等表示在 HedgeTerminal 里的持仓与在 MetaTrader 5 里的不相等。这种非对称不影响 HedgeTerminal 的效率,然而为了进一步的正确工作,它必须被消除。

在大多数情况下, 它会出现在用户错误编辑排除订单文件 ExcludeOrders.xml 时, 不过服务器上的损毁订单和成交纪录也可能导致这种现象。在所有情况下,这些差异可由 ExcludeOrders.xml 文件实现的排除机制移除。


1.4. 实现双向交易算法的需求

实现双向交易算法的时候需要强加严格限制。在开发 HedgeTerminal 时,它们必须要符合。否则, HedgeTerminal 将迅速变成一个随机工作程序。此程序将是 "可操作或失败的概率等同"

下面是开发它的一些要求规范:

  1. 交易者的双向持仓的表达必须要可靠。在 HedgeTerminal 里实现的任何想法,不能引起歧义或潜在的业务逻辑错误。如果某些属性或条件不符合这些要求,那么也不能图省事而使用这种想法。
  2. 所有算法必须尽可能的基于 MetaTrader 5 的交易环境。在绝对必要时,允许将附加信息保存在文件中。虚拟算法必须接收来自交易环境信息的主要部分。因为大部分变化都是通过服务器传送,因此这个属性增强了可靠性的总水平,并能从全世界的任何地方访问。
  3. 转换交易环境上的所有动作必须在幕后进行。HedgeTerminal 的 API 库无需复杂的配置和初始化。用户启动应用程序应该可以 "开箱即用",并得到 期望的 结果;
  4. HedgeTerminal 的可视化面板必须尽可能的与正常的 MetaTrader 5 界面相配, 对于熟悉 MetaTrader 4 和 5 的所有用户都应该是简单易懂的可视化工具。换句话说,可视化面板必须对所有用户都 清晰直观且简洁;
  5. HedgeTerminal 可视化面板的设计必须考虑到算法交易者的高要求。例如,面板必须可配置,用户必须能够改变其外观,甚至添加自定义模块;
  6. 它必须提供直观简单的程序接口 (API) 与外部 EA 交互。EA 与 HedgeTerminal 之间交互的算法程序部分,必须符合现有 MetaTrader 4/5 系统功能与定制 EA 之间交互程序的标准。实际上,HedgeTerminal API 表现为 MetaTrader 4 和 MetaTrader 5 的 API 的混合体;
  7. HedgeTerminal 必须保证在交易环境里可靠工作,要考虑到交易订单执行的所有细节。HedgeTerminal 基于典籍 以莫斯科交易所衍生品市场为例的交易价格原理" 编写。最初, 那篇文章是关于 HedgeTerminal 的长篇文章的一部分, 之后出于篇幅考虑,被切分为若干独立的文章。可以说,HedgeTerminal 是实现本文所述想法的程序。

这里的许多想法,彼此间无法明确共通。例如, 在交易中反馈的信息容量, 很难与信息表达的简洁化共通。

另一个难点是,要为交易新手创建一个操作简单的面板,同时要为专业算法交易者提供广泛的机动性。尽管如此, 评估的结果, 这些显然矛盾的性质在 HedgeTerminal 里被成功实现。


第二章. 安装 HedgeTerminal,首次启动

2.1. 安装 HedgeTerminal

我们知道,在 HedgeTerminal 里执行的所有订单均视为仓位。仓位可由两种配对的订单组成, 历史仓位平仓,或开仓的未绑定订单。

如果在 HedgeTerminal 安装之前, 账户里已经有一些动作和历史交易订单存在, 则从 HedgeTerminal 的观点来看,所有这些彼此间没有连接关系的订单都是开仓单。如果账户历史里包含 2-3 笔已执行订单,这个不要紧。如果有几千笔,HedgeTerminal 产生数以千计的仓位。针对它们能做什么?在 HedgeTerminal 里,这些订单可以通过包含链接到初始订单的反向订单"平仓"。虽然,这有一个缺点。如果按照安装 HedgeTerminal 的时间,则订单太多,已支付的经纪商佣金和点差费用可令交易者崩溃。

为了避免这种情况,HedgeTerminal 在安装时启动一个专用的安装向导,针对该问题建议不同的解决方案。让我们启动 HedgeTerminal,调用向导,并详细介绍其工作。可以从 MetaTrader 5 市场下载并安装 HedgeTerminal 演示版

HedgeTerminal 终极版类似, 它以 EA 形式启动, 将其图标从 "导航" 栏拖拽到可用的图表即可。

拖动该图标会在图表上弹出一个标准的窗口来启动 EA:


图例. 5. HedgeTerminal 启动前的窗口

在这个步骤设定标记 "允许自动交易" 就足够了,允许 EA 执行交易动作。HedgeTerminal 将跟踪您的订单,由于它们没有自己的交易逻辑,但交易执行依然需要您的准许。

为了能让 EA 开始交易, 在 MetaTrader 5 中必须要在个人权限面板里授权 EA 交易许可。

图例. 6. 启用自动交易

图例. 6. 启用自动交易

HedgeTerminal 的设计可避免用户进行冗长复杂的配置。

这就是为什么所有可用的设置均包括在一个特殊的 XML 文件里。对于 HedgeTerminal,唯一明确的参数就是设置文件的文件名:

图例. 7. HedgeTerminal 面板的设置窗口

图例. 7. HedgeTerminal 面板的设置窗口

这些设置的性质,以及修改它们的方式将在稍后讨论。

在按下 "OK" 之后, HedgeTerminal 安装向导提示安装过程开始。安装过程在 MetaTrader 4 和 MetaTrader 5 终端的标准共享目录下创建若干文件。

HedgeTerminal 在安装这些文件时需要权限:


图例. 8. 安装开始对话框

如果您不打算某些文件在您的计算机上安装,按“取消”。在这种情况下 HedgeTerminal 将完成工作。要继续安装,点击 "OK"。

以下对话框的外观将依据您启动 HedgeTerminal 的账户。如果在交易账户里没有执行的交易, 则 HedgeTerminal 将完成它的工作。

如果已经有一些执行的交易, HedgeTerminal 将显示以下对话框:


图例. 9. HedgeTerminal 首次启动的检测对话框

在上图中,HedgeTerminal 确定 5 个有效订单。在您的情况下它们的数量会有所不同(可能很大,等于帐户生存期的执行订单的总数)。这些订单不能与平仓单配对,因此从 HedgeTerminal 的观点来看,它们是活动持仓。

HedgeTerminal 推荐了几种选择。

  1. 从 HedgeTerminal 里排除这些订单: "您在 HedgeTerminal 里可以隐藏它们... 要隐藏这些订单, 点击 'YES' 并进入下一步"。如果您选择此项并按 "YES", HedgeTerminal 将它们放进特殊列表, 此后将停止计算它们在净持仓里的贡献和财会结果。这些订单仅在当前没有净持仓时放进列表里。如果您有一个或若干品种的持仓,HedgeTerminal 将弹出附加对话框来建议将存在的持仓平仓。
  2. 如果需要,保留订单将在稍后平仓: "您可以… 稍后手工平仓... 点击 'No' 如果您打算稍后手工平仓。在此情况下, 您要执行 5 笔反向交易"。在此情况下, 如果您按 "No", HedgeTerminal 将启动后在 "活动" 栏里反映 (即作为活动持仓)。稍后这些订单可以通过 HedgeTerminal 面板的其它订单平仓。之后,它们将变为平仓单,将被转移到 "历史" 栏 (历史仓位)。如果这些订单数量庞大,则最好隐藏它们,而不是再次将所有执行订单平仓并支付经纪商费用。
  3. 您可以停止安装: "如果您不准备继续按取消。在此情况下 HedgeTerminal 完成它的工作"。如果您选择此项并按 "取消", HedgeTerminal 将停止它的工作。

如果在安装 HedgeTerminal 时没有活动持仓, 安装将在此阶段终止。

如果您选择第二个选项,且您现在有一笔或几笔已开持仓,HedgeTerminal 将调用另一个对话框提示关闭它们:


图例. 10. 建议自动平仓对话框

HedgeTerminal 需要将所有已执行订单平仓,因为所有执行订单都被放入排除订单列表。如果没有净持仓,那么以下任何订单将初始一笔新的净持仓。在这种情况下,方向和交易量在 HedgeTerminal 里相同,并确保避免与 HedgeTerminal 里的净持仓总量不同步。

HedgeTerminal 可以自动为您将所有净持仓平仓: "HedgeTerminal 可以自动将所有活动持仓平仓"。如果您能接受, 按 "OK"。在此情况下它尝试平仓,若成功则完成工作。如果持仓出于某些原因不能平仓,它会进入手动平仓对话框。如果您选择手工平仓, "点击 '取消' 如果您打算手工平仓", 按 "取消"

当在之前的对话框里选择手工平仓或不可能自动平仓时, 手工平仓对话框被调用。


图例. 11. 建议选择手工平仓对话框

在此处所有活动持仓不得不通过 MetaTrader 5 手工平仓,或通过按下 "取消" 终止安装。所有持仓已平, 按下 "重试"


2.2. 安装的三个步骤。安装图示,以及可能出现的问题的解决方案

如果我们尽可能简化安装过程,它可以缩减到三个步骤:

  1. 在安装 HedgeTerminal 之前,在 MetaTrader 5 终端里将所有当前活动的净持仓平仓;
  2. 在图表里启动 HedgeTerminal,并在独立的安装窗口里按下 "Yes" 开始安装。HedgeTerminal 此时将安装所有操作中所需的文件;
  3. 如果出现,下一个窗口里,选择第二项并按下 "Yes"。在这种情况下,活动持仓不会在 HedgeTerminal 启动时出现,并且有关之前执行的订单信息将会被自动转移到 ExcludeOrders.xml 文件里,因为没有活动持仓需要平仓。

最简单的描述方式如下: 在启动 HedgeTerminal 时将所有持仓平仓,并在 HedgeTerminal 安装向导里按两次 "Yes"

安装向导的完整形态呈现在下面的图表上。它将有助于回答这个问题,并正确执行安装:


图例. 12. 安装向导

如果 HedgeTerminal 安装未能正确执行或需要从电脑中删除该做哪些动作?在这种安装不正常的情况下,只需删除所有已安装的文件。为此, 到 MetaTrader 共享数据的文件夹 (按照规则, 其位于: c:\Users\<您的用户名>\AppData\Roaming\MetaQuotes\Terminal\Common\Files\)。如果您打算从所有账户里删除有关 HedgeTerminal 安装的信息, 在此目录里搜索 "HedgeTerminal" 文件夹并删除它。如果您打算只从确定账户里删除有关 HedgeTerminal 安装的信息, 到 \HedgeTerminal\Brokers 目录, 并选择包含您的经济商名字和您的账户号码的文件夹, 比如像是 "经纪商名 - 账户号码"。删除此文件夹。下一次,当 HedgeTerminal 在此帐户开始时,安装向导将再次启动。

在终端上安装并连接到账户后,已经有 HedgeTerminal 在工作。这可能发生在打算将 HedgeTerminal 安装于已经有对冲终端在工作的账户里。正如您已经知道,安装过程由创建和配置系统文件构成。如果所有这些文件已经在另一台计算机上创建并正确配置,那么就没有必要安装 HedgeTerminal。按照规则, 这些文件保存在 c:\Users\<您的用户名>\AppData\Roaming\MetaQuotes\Terminal\Common\Files\HedgeTerminal。简单地将此文件夹复制到您的电脑相同位置。目录复制后,再次启动 HedgeTerminal。因为所有文件都存在并已配置,安装向导将不会被调用。在这种情况下,活动持仓的显示与其它终端和电脑上类似。

安装 HedgeTerminalAPI 并在测试模式使用该库。HedgeTerminal 的实现,即可作为可视化面板,也可作为程序的函数库, - HedgeTerminalAPI。该函数库包含一个类似的安装向导,会在实时状态下首次启动 HedgeTerminal 时调用。使用该函数库时的安装文件是相似的。首次调用任意函数时,EA 会弹出一个相关消息框提示开始安装。在这种情况下,用户必须做同样的事情 - 在调用 HedgeTerminalAPI 之前将所有持仓平仓,并执行三个安装步骤。

在测试模式启动该库时,不需要安装 HedgeTerminal。因为在测试模式下,EA 每次都用一个新的虚拟账户的开始工作,没有必要隐藏先前执行的订单并安装文件。设置保存在文件 Settings.xml, 在函数库中, 可以通过调用相关功能语法定义。


2.3. HedgeTerminal 入门,首次启动

在 HedgeTerminal 安装所有工作所需文件之后, 将在图表上启动并显示它的面板:

图例. 13. HedgeTerminal 首次启动, 外观

图例. 13. HedgeTerminal 首次启动, 外观

由于所有现有订单均被隐藏,此处没有显示活动持仓。面板上部左手边包含 HedgeTerminal 的菜单按钮和显示终端状态的专用图标。按钮有以下功能:

  •  - 表明面板的演示版已经启动。它不支持实盘账户的交易,且仅显示 AUDCAD 和 VTBR* 品种的持仓。在此模式下,仓位历史也限制在最后 10 笔已平仓位。
  •  - 表明在 HedgeTerminal 里的持仓与 MetaTrader 5 里的净持仓不符。这不是一个严重的错误,但它需要被消除。如果 HedgeTerminal 安装正确,请参阅本文描述如何消除错误的部分。
  •  - 此图标表示不可交易。将鼠标悬停在此图标上,然后从弹出的提示里发现问题的出处。可能的原因: 与服务器断线; EA 被禁止交易; 在 MetaTrader 5 里没有允许 EA 进行交易。
  • - 此图标表示允许交易; HedgeTerminal 可以执行任何交易动作。

现在,HedgeTerminal 已经启动并准备工作,进行若干笔交易,看看它们是如何显示的。如果 HedgeTerminal 已在 Forex 上启动,针对 AUDCAD 品种的交易动作可以被执行。在这种情况下,仅当如同 HedgeTerminal 安装时那样没有任何已开净持仓时,方能成功。如果出于某种原因不是这样的话,将所有活动持仓平仓。

如果 HedgeTerminal 在联到莫斯科交易所的账户里启动, 只能针对期货品种 VTBR* 的组进行交易, 例如 VTBR-13.15 或 VTBR-06.15。作为说明, 通过标准窗口 "新订单", 按现价买入 0.4 手的 AUDCAD。片刻之后,订单和已执行成交将会出现在终端的订单历史中:

图例. 14. 在 MetaTrader 5 中的历史订单和它的成交

图例. 14. 在 MetaTrader 5 中的历史订单和它的成交

活动持仓栏将含有一笔相应的 0.4 手多头持仓:

图例. 15. 在 MetaTrader 5 中的活动持仓

图例. 15. 在 MetaTrader 5 中的活动持仓

与此同时,HedgeTerminal 将显示历史仓位作为活动持仓:

图例. 16. 在 HedgeTerminal 里的活动双向持仓和它的成交

图例. 16. 在 HedgeTerminal 里的活动双向持仓和它的成交

正如我们所看到的,结果都是一样的,在 HedgeTerminal 里一笔持仓对应于 MetaTrader 5 里的一笔净持仓。

请注意,如果加仓,在 HedgeTerminal 里的仓位包含一笔此仓位的已执行成交 (为了能看到它, 可最大化持仓, 通过按下 )

一部分活动持仓可以被隐藏。为此,简单地在 "Vol." (交易量) 字段输入新的交易量数值。新的交易量应小于当前的数值。当前与新交易量之间的差异将通过新的订单来补充,形成一笔历史仓位,且被显示在相应的历史仓位中。在此字段里输入值 0.2,然后按下回车键。经短暂时间后活动持仓的交易量升至 0.2,而历史仓位栏将采用首笔历史事务的交易量 0.2 手 (0.4 - 0.2 = 0.2):

图例. 17. 在 HedgeTerminal 里的双向历史仓位

图例. 17. 在 HedgeTerminal 里的双向历史仓位


换句话说,我们将一半的活动持仓平仓了。历史和活动仓位的通用财务结果与终端里的结果将是相同的。

现在,我们要将剩余的活动持仓平仓。为此按下 HedgeTerminal 里的平仓按钮 :

图例. 18. 在 HedgeTerminal 里的双向持仓平仓按钮

图例. 18. 在 HedgeTerminal 里的双向持仓平仓按钮

这个按钮被按下后,剩余持仓必须通过反向订单被平仓,并转移到历史仓位栏。活动持仓将以这种方式 (无论在 MetaTrader 5 里还是在 HedgeTerminal 里) 被平仓。


2.4. 对冲和操作的计算

在本节中,我们将介绍几种与 HedgeTerminal 一起工作的方法,使用若干双向持仓作为例子。

目前我们没有任何活动持仓。开一笔 0.2 手的 AUDCAD 多头仓位。为此, 打开 "新订单" 对话窗口并下一笔相应订单就行了。在开仓之后, 通过反向持仓 锁定 它 - 通过 MetaTrader 5 终端卖出 0.2 手。

此刻在 HedgeTerminal 和 MetaTrader 5 终端窗口里的结果是不同的。HedgeTerminal 显示两笔持仓:

图例. 19. 在 HedgeTerminal 里的相反的双向持仓 (锁仓)

图例. 19. 在 HedgeTerminal 里的相反的双向持仓 (锁仓)

在 MetaTrader 5 里则没有任何表示:

图例. 20. 在 MetaTrader 5 里少了一笔活动的净持仓

图例. 20. 在 MetaTrader 5 里少了一笔活动的净持仓

让我们来评估结果。执行了 4 笔成交。它们在下图的红色框里:

图例. 21. 在 MetaTrader 5 中的成交执行结果

图例. 21. 在 MetaTrader 5 中的成交执行结果

将这些成交放入表格:

类型方向价格交易量盈利, 点数
   in0,980880,2
   out0,980890,21
   in0,982070,2
   out0,982080,21

表.1。在 MetaTrader 5 终端里显示的成交

很明显,4 笔交易赚了 2 点。每点的价值大约是每手 0 .887 美元。所以, 财务结算是每单 0.18 美元 (0,887*0,2*1) 或两单 34 美分。"盈利" 这列显示这个结果是正确的。净盈利是 34 美分

现在看看在 HedgeTerminal 里的结果:

 图例. 22. 在 HedgeTerminal 里的双向仓位历史结果

图例. 22. 在 HedgeTerminal 里的双向仓位历史结果

起初,它们似乎明显不同。让我们来计算我们的两个双向仓位的结果:

方向入场价位出场价位盈利, 点数盈利, $
0,980880,982080.0012021,28
0,980890,98207-0.00118-20,92

表格 2. 在 HedgeTerminal 里显示的仓位

它们之间的差异是 0.34$ (21,28$ - 20,92$), 这与净交易所获结果完全一致。


2.5. 一键交易

HedgeTerminal 采用了一套独特的管理系统。这是基于在活动仓位的字段里直接输入所需数值。此处没有替代管理。

例如, 给活动仓位设置止损, 在止损字段里简单地输入所需数值并按下回车:

图例. 23. 直接在表格里输入止损位

图例. 23. 直接在表格里输入止损位

同样,交易者可以通过这种方式修改交易量,设置或修改止盈位,改变初始注释

一般情况下, 在 HedgeTerminal 里的仓位行与在 MetaTrader 4/5 里显示的仓位类似。该仓位表格的每一列所用标识名和数值与 MetaTrader 终端使用的相同。这里也有不同之处。所以, 在 HedgeTerminal 里的仓位有两条注释, 而在 MetaTrader 里每笔仓位只有一条注释。这意味着,在 HedgeTerminal 里一笔仓位由两笔订单形成,并且它们都有自己的注释字段。由于 HedgeTerminal 不使用这些注释保存技术信息, 所以它可以用来创建开仓和平仓的注释。

HedgeTerminal 提供机会来添加省缺时没有的列。例如, 能够反映出开仓 EA 名称的列。专述 Settings.xml 文件配置的章节描述了如何做到这一点。


2.6. 设置止损和止盈, 尾随终止

HedgeTerminal 允许按照止损或止盈位来平仓。

来看看它是如何发生的,为活动仓位设置止损和止盈位,然后等待这些价位中的一个被触发。在我们的案例中止盈位被触发。它平仓并将其移到历史事务清单里。

图例. 24. 双向仓位历史以及它们的止损和止盈位

图例. 24. 双向仓位历史以及它们的止损和止盈位

在止盈位的绿色标记表示该仓位是由止盈位触发而平仓的。除了止盈,还包含了当仓位处于活动时可用的止损位信息。类似地,如果止损位被触发,则止损位单元格将以粉色加亮,而止盈位不会被着色。

HedgeTerminal 支持尾随停止,且在未来版本中允许编写特殊的包含携带止损逻辑的自定义模块。当前在 HedgeTerminal 里的尾随停止与 MetaTrader 终端里的尾随停止不同。要启用它,需要在相应持仓的止损单元格中输入止损价位。当止损位设置后, 在单元格里可以用符号来标记以下价格选项 :

图例. 25. 在 HedgeTerminal 里设置止损

图例. 25. 在 HedgeTerminal 里设置止损

在标记之后, HedgeTerminal 修复当前价格和止损位之间的距离。如果增加, 止损位将跟随价格,所以距离保持相同。尾随停止仅当 HedgeTerminal 正在运行直至离场时工作。

在 HedgeTerminal 里, 止损也在 BuyStop 和 SellStop 类型的订单上实现。每次设置止损时, 同时放置一笔与活动持仓连接的带有魔幻数字的信使订单。如果这笔挂单在 MetaTrader 终端里被删除, 则在 HedgeTerminal 里止损位消失。更改挂单的价位将触发 HedgeTerminal 里止损的变化。

止盈的工作稍有不同。这是 虚拟的 且它对经纪商隐藏了触发位。意味着 HedgeTerminal 能自动按照止盈位平仓。所以, 如果您想用止盈触发, 您的 HedgeTerminal 要保持工作。


2.7. 生成报告

HedgeTerminal 可以保存有关它的双向仓位信息至设计好的文件, 它可以通过第三方统计程序加载并分析, 例如微软的 Excel。

由于 HedgeTerminal 当前没有分析和统计收集系统, 这个功能尤为重要。此刻, 仅有支持一种报告格式 - CSV (逗号分隔数值)。让我们看看它如何工作。为在 CSV 文件里保存双向仓位信息, 启动 HedgeTerminal 后在菜单里选择 "保存 CSV 报告" 选项:


图例. 26. 通过 "保存 CSV 报告" 菜单保存一份报告

在菜单中选择这些点后,HedgeTerminal 会生成两个 CSV 格式的文件。其一将包括有关活动持仓信息,另一个则有关于历史,已完成的。为什么会生成两个不同的文件,原因在于它们有不同的列组合。此外,活动持仓的数量可以持续变化,因此分别分析它们更方便。生成的文件保存在相对路径 .\HedgeTerminal\Brokers\<经纪名称上 - 帐户号码> \ 此处须有两个文件: History.csvActive.csv。第一个包含了历史仓位,第二个有关活动持仓的信息。

这些文件可以加载到统计程序用于分析。让我们来看看使用微软 Excel 为例的过程。启动程序并选择 "数据" --> "来自文本"。在出现数据导出向导时选择分隔符的模式。在随后的窗口中,选择分号作为分隔符。按下 "下一步"。在随后的窗口中修改浮点数的一般表示格式。为此, 按下 "详情"。在出现的窗口中选择周期字符作为整数和小数部分的分隔符:

图例. 27. 导出 CSV 报告至微软 Excel

图例. 27. 导出 CSV 报告至微软 Excel

按下 "ОК", 然后 "完成"。在出现的表格里将包含有关活动持仓的信息:

图例. 28. 导出有关活动持仓的信息到 Excel

图例. 28. 导出有关活动持仓的信息到 Excel

历史仓位的数据可用相同的方式加载到下一页。列数将与 HedgeTerminal 中的实际列数相对应。如果某一列被从 HedgeTerminal 面板上删除,它将不被包括在报告中。这种方式便于形成仅基于所需数据的报告。

程序的后续版本将允许保存 XML 和 HTML格式的报告。添加之后, 保存 HTML 格式的报告将类似于 MetaTrader 5 的一个标准 HTML 报告, 不过它包括完整的双向仓位。


2.8. 货币掉期演示

货币掉期 是两个双向转换交易的组合, 总和相同但估值日期不同。

简单地说, 掉期是衍生操作, 当持有两种货币形成的净持仓时支付的累积利息

在 MetaTrader 5 中没有净持仓的历史。由历史订单和成交,形成替代的历史平仓。由于没有历史仓位, 掉期被分配到历史已平仓的订单上。

 图例. 29. 货币掉期作为独立的事务

图例. 29. 货币掉期作为独立的事务

这将更准确的表现出,掉期作为一个独立的衍生操作出现,是净持仓延期的结果。

HedgeTerminal 的当前版本不支持掉期重现,不过以后的版本将采用这样的选项。掉期将在历史仓位栏单独显示。掉期标识符将对应于累计的净持仓的标识符。掉期将包括货币对的名称和它的财会结果。


2.9. 底行

与 MetaTrader 类似,HedgeTerminal 在成交表格的最后一行显示整个帐户的常规属性。对于活动和历史仓位表格,这些属性和它们的值如下所示:

    Balance – 总余额。等于 MetaTrader 里活动持仓窗口中的类似数值 "盈利"。这不考虑来自未平持仓的浮动盈亏。
    Floating P/L – 浮动盈亏。这等于所有当前活动持仓的利润总和。
    Margin – 包含质押资金与账户余额的百分比。可以从 0% 到 100% 变化。表示一定程度的资金负载。
    Total P/L – 包含了所有平仓的利润和亏损总和。
    Pos.:# - 显示的历史仓位的数量。

为了正确显示底行,需要在系统里添加 "Arial Rounded MT Bold" 字体。


2.10. 更改 HedgeTerminal 表格的外观

如前所述,HedgeTerminal 在 EA 的启动窗口里只有一个显式参数。就是设置文件的名称。这是因为 HedgeTerminal 的设置不能放在 EA 的设置窗口里。它们太多了, 且对于这个窗口它们太特别。这就是为什么所有设置放于设计好的配置文件里 Settings.xml 。每一个启动的 HedgeTerminal,都可以有自己的设置文件。这样就有机会,为每一个启动的 HedgeTerminal 版本进行单独配置。

HedgeTerminal 目前不允许通过可视设置窗口编辑这个文件。因此,改变 HedgeTerminal 行为的唯一方法是手工编辑文件。设置文件省缺以最佳方式配置,因此,大部分的时间没有必要修改其内容。在需要编辑时,可能有这种情况。微调和定制面板外观有必要进行这样的编辑。例如, 当文件被编辑, 删除不必要的列, 或是与此相反, 可以添加省缺情况下不显示的列。

让我们看看这个文件的内容,以及如何进行定制。为此,在 HedgeTerminal 的安装目录里找到这个文件。这个目录, 如前所述, 位于地址 c:\Users\<您的用户名>\AppData\Roaming\MetaQuotes\Terminal\Common\Files\HedgeTerminal。文件 Settings.xml 应该位于其中。用任意的文本编辑器打开它:

<!--This settings valid for HedgeTerminal only. For settings HedgeTerminalAPI using API function and special parameters.-->
<Hedge-Terminal-Settings>
        <!--This section defines what columns will be showed on the panel.-->
        <Show-Columns>
                <!--You can change the order of columns or comment not using columns.-->
                <!--You can change the value of 'Width' for a better scaling of visual table.-->
                <!--You can change the value of 'Name' to install your column name.-->
                
                <!--This columns for tab 'Active'-->
                <Active-Position>       
                        <Column ID="CollapsePosition" Name="CollapsePos." Width="20"/>
                        <!-- Unset this comment if you want auto trading and want see name of your expert:
                        <Column ID="Magic" Name="Magic" Width="100"/>-->
                        <Column ID="Symbol" Name="Symbol" Width="70"/>
                        <Column ID="EntryID" Name="Entry ID" Width="80"/>
                        <Column ID="EntryDate" Name="Entry Date" Width="110"/>
                        <Column ID="Type" Name="Type" Width="80"/>
                        <Column ID="Volume" Name="Vol." Width="30"/>
                        <Column ID="EntryPrice" Name="EntryPrice" Width="50"/>
                        <Column ID="TralStopLoss" Name="TralSL" Width="20"/>
                        <Column ID="StopLoss" Name="S/L" Width="50"/>
                        <Column ID="TakeProfit" Name="T/P" Width="50"/>
                        <Column ID="CurrentPrice" Name="Price" Width="50"/>
                        <Column ID="Commission" Name="Comm." Width="40"/>
                        <Column ID="Profit" Name="Profit" Width="60"/>
                        <Column ID="EntryComment" Name="Entry Comment" Width="100"/>
                        <Column ID="ExitComment" Name="Exit Comment" Width="100"/>
                </Active-Position>
                <!--This columns for tab 'History'-->
                <History-Position>
                        <Column ID="CollapsePosition" Name="CollapsePos." Width="20"/>
                        <!-- Unset this comment if you want auto trading and want see name of your expert:
                        <Column ID="Magic" Name="Magic" Width="100"/>-->
                        <Column ID="Symbol" Name="Symbol" Width="70"/>
                        <Column ID="EntryID" Name="Entry ID" Width="80"/>
                        <Column ID="EntryDate" Name="Entry Date" Width="110"/>
                        <Column ID="Type" Name="Type" Width="40"/>
                        <Column ID="EntryPrice" Name="Entry Price" Width="50"/>
                        <Column ID="Volume" Name="Vol." Width="30"/>
                        <Column ID="ExitPrice" Name="Exit Price" Width="50"/>
                        <Column ID="ExitDate" Name="Exit Date" Width="110"/>
                        <Column ID="ExitID" Name="Exit ID" Width="80"/>
                        <Column ID="StopLoss" Name="S/L" Width="50"/>
                        <Column ID="TakeProfit" Name="T/P" Width="50"/>
                        <Column ID="Commission" Name="Comm." Width="40"/>
                        <Column ID="Profit" Name="Profit" Width="50"/>
                        <Column ID="EntryComment" Name="Entry Comment" Width="90"/>
                        <Column ID="ExitComment" Name="Exit Comment" Width="90"/>
                </History-Position>
        </Show-Columns>
        <Other-Settings>
                <Deviation Value="30"/>
                <Timeout Seconds="180"/>
                <!-- If your computer is not fast enough - set a value 'Milliseconds' greater than 200, such as 500 or 1000. -->
                <RefreshRates Milliseconds="200"/>
        </Other-Settings>
</Hedge-Terminal-Settings>

此文件包含一份用 xml 标记语言 书写的特殊文档, 描述了 HedgeTerminal 的行为和外观。

编辑开始之前的主要事情就是创建一个备份,防止意外的偶然破坏。该文件具有分层结构,由彼此嵌入的几个部分构成。主要部分称为 <Hedge-Terminal-Settings> , 它包含两个主要分部: <Show-Columns><Other-Settings>。按照它们的名称, 第一部分调整显示列和它们的条件宽度, 第二部分设置面板自身和 HedgeTerminalAPI 函数库。

改变尺寸和列名。让我们参考 <Show-Columns> 部分并考虑它的结构。基本上, 这部分包含两组列: 其一用于在 "活动" 栏的活动持仓表格, 以及另一个 "历史" 栏的历史仓位表格。每一组的列如下所见:

<Column ID="Symbol" Name="Symbol" Width="70"/>

列必须包含一个识别符 (ID="Symbol"), 列名 (Name="Symbol") 和条件宽度 (Width="70").

标识符包含独有的内部列名称。它提示 HedgeTerminal 如何显示此列,以及在里面放什么数值。标识符不能被改变,且它应该能够被 HedgeTerminal 支持。

列名定义将在表格里显示的列名。如果名称被修改为其它, 像: Name="Currency Pair", 则在下次启动 HedgeTerminal 时, 将显示修改后的符号:


图例. 30. 在 HedgeTerminal 面板里修改列名

这个变化属性允许创建本地化版本的面板, 即列名将用首选的语言显示, 例如俄语:

 图例. 31. 本地化 HedgeTerminal

图例. 31. 本地化 HedgeTerminal

下一个标签包含列的条件宽度。在面板启动后, 图形引擎自动根据窗口宽度对齐表格的大小。较宽的窗口的每一列也比较宽。不可能精确地设置列宽度, 但比例可通过设置列的基本宽度来指定。基本宽度是当窗口宽度为 1280 像素时,以像素为单位的列宽。

如果您的显示器较宽,则列的实际大小就越大。为了解统一缩放如何工作, 设置品名的列宽为 240 条件像素: Width="240"。然后保存文件并重启面板:

图例. 32. 品名列宽被设置为 240 像素。

图例. 32. 品名列宽被设置为 240 像素。

品名列宽明显增加。不过,应该指出的是,它获得的宽度是以其它列宽为代价 ("Entry ID"  "Entry Date")。

其它列看上去很糟糕, 最后的数值不符合允许的宽度。列的尺寸要仔细修改, 找到每列的最佳尺寸。标准设置对于主要显示器已经是精确数值, 一般情况下无需改变。

删除列。除了改变列的尺寸和它们的列标题,还可以添加或删除列。例如, 让我们尝试从列表里删除 "品名" 列。为此, 简单地在 Settings.xml 文件里注释掉列标签 (黄色加亮):

<Column ID="CollapsePosition" Name="CollapsePos." Width="20"/>
<!-- 如果您要自动交易并查看 EA 名称, 则取消注释:
<Column ID="Magic" Name="Magic" Width="100"/>-->
<!--<Column ID="Symbol" Name="Symbol" Width="70"/>-->
<Column ID="EntryID" Name="Entry ID" Width="80"/>

在 xml 特殊标签 <!-- 注释内容 --> 具有注释的作用。注释掉的列必须位于标签内。修改文件并保存,重启 HedgeTerminal 后,其列集合的历史仓位将发生变化。它将不包含显示品名的列:

图例. 33. 从活动持仓表格里删除品名列

图例. 33. 从活动持仓表格里删除品名列

可以一次删除若干列。

让我们注释掉除了品名和盈利大小之外的所有列,然后在图表上重启 HedgeTerminal:

图例. 34. 从 HedgeTerminal 面板上删除主要列

图例. 34. 从 HedgeTerminal 面板上删除主要列

正如我们所看到的,HedgeTerminal 的表格显著缩水。每一列的删除都应该小心,在某些情况下,它们含有仓位管理的要素。在我们的案例中,允许反转持仓,并查看它们的成交列已被删除。虽然 "盈利" 列可以从活动持仓表格里删除。但此列, 包含一个平仓按钮。在此情况下, 平仓按钮消失将令持仓无法平仓。

添加列并显示 EA 的别名。 如果 HedgeTerminal 与它们一起编程工作, 可以通过删除和编辑列。在将来,用户可以创建他们自己的列,并计算自己的参数。这些列可以通过外部接口指标 iCustom 连接,以及 XML 编写的扩展模块交互。

目前还没有这样的功能,并且只有 HedgeTerminal 可以支持这些列。可由面板支持,但在设置里省缺不显示的列,包括 EA 的魔幻数字。

不仅可以由手工开仓,也可以通过机器人开仓。在这种情况下,可以显示每笔仓位的开单机器人标识符。注释掉列的标签,包括已经出现在设置文件里的 EA 的号码。让我们取消注释:

<Column ID="Magic" Name="Magic" Width="100"/>

保存改变并重启面板:

图例. 35. 在 HedgeTerminal 表格里添加魔幻数字

图例. 35. 在 HedgeTerminal 表格里添加魔幻数字

正如我们在上图中看到的那样, 一个名为 "Magic" 的列出现。这是开仓 EA 的标识符。仓位由手工开仓,所以标识符为零。作为规则,由机器人打开的仓位包含一个不等于零的标识符。在这种情况下,与 EA 对应的魔幻数字将被显示在列中。

代替号码,看到 EA 的名字显然更方便。HedgeTerminal 有此选项。从 ExpertAliases.xml 文件里取出 EA 的别名并替代相应的数字显示。

举例来说, 如果您的 EA 称为 "ExPro 1.1" 且魔幻数字为 123847, 在 ExpertsAliases.xml 文件的 <Expert-Aliases> 标签部分放置它就够了:

<Expert Magic="123847" Name="ExPro 1.1"></Expert>

从现在起,当您的机器人开笔新仓,这将有它的名字:

图例. 36. 在 Magic 列显示 EA 的名字

图例. 36. 在 Magic 列显示 EA 的名字

机器人的数字和它们的名字没有限制。此处唯一条件是它们的数字是不同的。

HedgeTerminal 的其它设置。我们已经描述了当前可视面板所有可用的设置。下一部分 <Other-Settings> 包含定义终端内部工作的设置。请注意,程序使用这些省缺设置调用 HedgeTerminalAPI 库。EA 可以通过特别的 Set... 函数改变这些设置的当前值。要获取这些设置的值,EA 只需要调用特别的 Get... 函数。我们将描述设置标签的更多细节。

<Deviation Value="30"/>

包含自当前价位的极端偏离,单位是最小价格变化。所以, 对于五位报价的 EURUSD 货币对, 它是 0,0003 点。对于 RTS 期货指数此数值是 300 点, 最小价格变化步长是 10 点。如果价格偏离较大,则平仓或价格改变将不会被执行。这在不利的滑点时用于保护。

<Timeout Seconds="180"/>

标签包含来自服务器允许的最大响应值。HedgeTerminal 工作在异步模式。这意味着,HedgeTerminal 发送交易信号到服务器,而不必等待接收后者的响应。代之,HedgeTerminal 控制事件序列,指向已成功放置的订单。该事件可能不会发生。这就是为什么设置等待超时时间是如此重要的原因,在此期间,HedgeTerminal 将等待服务器响应。如果在这段时间没有响应,任务将被取消,HedgeTerminal 将仓位解锁并进行工作。

等待超时时间可以被缩短或延长。省缺是 180 秒。

重要的是要了解,在真实交易中,这种限制从未触及。交易信号的响应很快返回, 它们中的大多数执行时间在 150 – 200 毫秒以内。

更多有关 HedgeTerminal 工作的细节,以及有关在异步模式下工作的特殊性,可以在本文的第三部分找到: "在 HedgeTerminal 的礼帽之下"

<RefreshRates Milliseconds="200"/>

该标签设置面板更新的频率。它包含面板两次更新之间的以毫秒为单位的时间。数值较低, 面板的更新频率较高, 使用更多的 CPU 资源。如果您的处理器不太强劲, 且它不能应付 200 毫秒的更新频率 (省缺值), 您可以通过编辑标签将它增加到 500 甚或 1000 毫秒。

在这种情况下,CPU 的负荷将显著下降。不建议数值小于 100 毫秒。增加更新频率时,CPU 负荷将非线性增加。重要的是要了解,该更新频率定义了终端的离散。它的一些动作由计时器定义,并按照一定的速度发生。


2.11. 计划但未实现功能

由于此程序非凡的能力,使得 HedgeTerminal 具有灵活和非凡的构架变得可行。今天,这些功能还尚未得到实现,不过如果有需求,它们可能会在将来出现。下面是些主要的:

使用配色方案和皮肤。 HedgeTerminal 使用自己的图形引擎。这是基于原生图形,像是矩形标签或通常的文本。基于图片的图形不再使用。这提供了一个机会来,在 HedgeTerminal 里改变所有显示的元素,颜色、大小和字体。这种方式很容易创建字体描述和配色方案来形成皮肤,并在启动 HedgeTerminal 时将其加载,改变它的外观。

连接自定义尾随停止模块。 每款 EA, 包括 HedgeTerminal 的本质也是 EA, 可以通过一个特定的程序接口计算任意指标 (函数 iCustom())。它允许调用指标计算,这取决于任意参数集合。尾随止损是一种算法,根据当前价格设置新价位或保持旧有价位。此算法和它的价位可以作为一个指标来实现。如果传递的参数都认可,HedgeTerminal 可以调用这些指标,并计算所需的价位。HedgeTerminal 可以留意传送尾随停止机制。这样一来,任何 HedgeTerminal 用户可以编写自己的(即使是最不寻常的一个)管理尾随停止的模块。

在仓位表格里添加新列。这包括自定义列。 HedgeTerminal 的表格设计允许添加新列。在 HedgeTerminal 内部可通过编程支持新列,并通过与 iCustom() 接口类似的方式实现。每行仓位的每个单元格代表一个参数(例如,开盘价或止盈位)。此参数可以由一个指标来计算,这意味着,可以编写无限数量的指标,每个计算仓位的某些参数。如果协调传递到这些指标里的参数,那么在 HedgeTerminal 里,在表中添加无限数量的自定义列将成为可能。

连接扩展模块。 其它算法可以通过自定义指标调用机制来计算。例如, 报告系统包含了大量的计算参数,比如预期收益和锋锐比率。许多此类参数可以通过将它们的计算块移动至自定义指标来接收。

复制交易,接收和传输来自其它帐户的交易。 HedgeTerminal 本质上是一个仓位管理员。它很容易成为一个交易拷贝机的基础,因为主要功能都已经实现。如此这样的拷贝机将有非凡的能力,可以复制双向 MetaTrader 4 持仓至 MetaTrader 5 终端。拷贝机将按照双向显示这些仓位,可以单独管理每一个仓位,就像在 MetaTrader 4 里一样。

报告与统计。净值图表和 "摘要" 栏。 双向仓位计数可以分析每一个策略或交易者的结果,以及相应的贡献。除了统计,一个也可以进行组合投资分析。此报告明显与 MetaTrader 5 的报告不同,它里面添加了许多东西。在摘要栏的报告中,除了像预期收益,最大回撤,盈利因子等普遍接受的参数,还包含许多其它参数。后者的名称和数值可以从自定义扩展模块来获得。替代图片上类似的余额图表, 可以使用自定义的蜡烛条来形成净值图表.

列排序。 通常,当按表头时,该行可按照升序或降序(第二次按)排序。当前版本的 HedgeTerminal 不支持此选项,因为排序要连接成交过滤器和自定义列,而此刻还未提供。后续版本将采用这个选项。

通过邮件和 FTP 发送交易报告。推送通知。 HedgeTerminal 可以使用系统功能来发送邮件, ftp 文件甚至推送通知。例如它可以每天形成一个 HTML 报告,并将之发送给列表里的用户。由于 HedgeTerminal 是 EA 管理员,它知道其它 EA 的所有交易动作,它可以通知用户有关的其它 EA 的交易动作。举例来说,如果 EA 之一,开一笔新仓,HedgeTerminal 可以发送推送通知,告知某个 EA 入场开新仓了。HedgeTerminal 也可以指明入场方向, 日期, 时间和交易量。而 EA 本身不需要配置,将其名称添加到别名文件中足以。

用正则表达式控制台过滤仓位。 这是最强烈的开发规划。它将 HedgeTerminal 的工作提升到一个全新的水平。正则表达式可用于过滤的历史和活动仓位,从而只有那些满足该过滤器的要求被显示。正则表达式可以组合,并通过位于活动和历史仓位表格之上的专用控制台输入。这就是控制台在 HedgeTerminal 的未来版本里的可能样子:

图例. 37. 在 HedgeTerminal 未来版本中的请求控制台

图例. 37. 在 HedgeTerminal 未来版本中的请求控制台

正则表达式可以形成非常灵活的过滤条件,并在统计计算之后过滤仓位。例如,仅显示 AUDCAD 品种的历史仓位,在单元格 "Symbol" 里输入"AUDCAD" 品名就够了。条件可以组合。例如,可以显示从 01.09.2014 直至 01.10.2014 期间,由特别机器人执行的 AUDUSD 仓位。您需要做的所有事情就是在对应的单元格里输入条件。在过滤器显示结果之后,“摘要”栏中的报告将按照新的过滤条件变化。

正则表达式将由少量简单的运算符构成。然而,当一起使用时,它们将能够创建非常灵活的过滤器。

下面示意的操作符,在控制台里充分且必要:

    Operator = - 全等。如果从 "Symbol" 字段得到单词 AUDСAD, 则所有品名包含此字符串, 例如 AUDCAD_m1 或 AUDCAD_1, 将会被发现。这意味着,将使用一个隐式的插入操作符。全等 "=" 需要一个表达式完整匹配,因此,除了 AUDCAD 所有的品名将被排除。AUDCAD_m1 或 EURUSD 将被排除。

    Operator > - 只显示数值大于指定值。

    Operator < - 只显示数值小于指定值。

    Operator ! – 逻辑否定。仅返回不等于指定值的那些数值。

    Operator | - 逻辑 "或"。允许在同一时间指定两个或多个条件。在同一时刻,为满足判据,只需至少满足一个条件即可。例如, 在表达式控制台的单元格里 "Entry Order" 输入表达式 "> 10106825|=10106833" 将显示所有订单标识符大于 10106825 或等于 10106833 的仓位。 

    Operator & - 逻辑 "与"。允许在一行里指定两个或多个条件,在同一时间它们必须满足每一个条件。在单元格里 "Entry Order" 输入表达式 ">10106825&<10105939" 显示所有订单标识符大于 10106825 或小于 10105939 的仓位。标识符在两个数字之间的仓位, 例如 10106320, 将被过滤掉。

使用特殊命令校正和管理仓位。 可以在单元格里输入附加品名来返回交易量或止损位和止盈位。这使得更复杂的仓位管理成为可能。例如, 将当前持仓交易量平仓一半, 在相应的活动持仓的 "Volume" 字段里输入数值 "50%"。

替代设置止损位和止盈位,可在这些单元格里输入数值,例如 "1%"。HedgeTerminal 能自动计算止损位和止盈位,并在距入场价位 1% 的位置设置止损位和止盈位。带有后缀 "P" 的数字可在这些单元格中被输入。例如, "200p" 意即订单: "在持仓入场价位的 200 点处设置止损位和止盈位"。在将来, 如果在 "Volume" 列内的交易量之前添加一个减号, 该交易量由符号之后的指定数值平仓。举例来说,如果您有一笔交易量为 1.0 的持仓,我们打算将部分交易量平仓(例如 0.3),那么在交易量单元格中输入“-0.3”即可。


第 3 章. 在 HedgeTerminal 的礼帽之下。操作规范和原则

3.1. 全局和局部轮廓。上下文,转移和信息的存储

HedgeTerminal 的外观和交易过程, 类似于大家熟悉的 MetaTrader 4。这种可能, 出于 虚拟化 和数据显示的变换, 从 MetaTrader 5 得到的可用交易信息能够在面板上以更方便的方式显示出来。本章介绍了创建此类虚拟化的机制, 和数据分组处理机制。

如您所知,HedgeTerminal 在若干不同的产品里出现。它们主要是可视面板和程序接口库。后者允许在任何外部 EA里实现双向的仓位管理, 且也能将之集成到 HedgeTerminal 可视面板中。例如,属于某个 EA 的活动持仓,可以直接从面板平仓。EA 将得到信息,并进行相应的处理。

显然,这样的结构需要 EA 之间的群体互动。此面板,本质上是一款 EA,必须了解所有发生的交易动作。反之, 使用 HedgeTerminal 库的所有 EA 必须了解所有手动操作的交易动作 (通过第三方程序或使用 HedgeTerminal 面板)。

在一般情况下,关于交易动作的信息可从交易环境里接收。例如,当用户开新仓时,订单的数量改变。最后的订单可以告之哪个品种开仓了,它的交易量有多少。关于订单和成交的信息存储在服务器上。这就是为什么它可用于所有连接到交易账户的终端。这些信息可以被称为 全局化 因为它通过全局渠道分发,且提供给所有人。与交易服务器之间的通信具有“请求 - 回应”的格式。

因此这样的通信可以呈现为一个 全局轮廓"轮廓" 是来自图论的一个概念。简单的说,一个轮廓是几个节点彼此交互的封闭线。这个定义可能不足,但是我们将精确留给数学家。对我们来说,重要的是当前交易过程中的一些平仓动作顺序。

不是所有需要的信息都可以通过全局轮廓被传递。一部分信息不能被传递,因为 MetaTrader 5 不支持传递这些并没有明确存在的信息。交易动作的顺序是:

  1. 交易者下订单买入。
  2. 订单在某些时候被执行。
  3. 交易环境改变。已执行的订单进入历史订单列表。品种的持仓总和变化。
  4. 交易者或 EA 在交易环境里检测到这个变化并做出下一步决策。

在第一和第四动作之间需要经历一定时间。很明显,如果只有一位交易者在账户上进行交易,他们知道采取哪个动作,并等待来自服务器的适当响应。如果有若干交易者或 EA 同时在账户上进行交易,很可能会发生管理错误。

例如,第二位交易者可以在第一和第四步之间的时间内将现有持仓平仓。您能否看到其中潜在的问题?当地一笔订单在执行的时候,第二笔订单来了。换句话说, 一笔平仓订单被发送了两次。

如果交易者独自在帐户里手动交易,以及使用同步方法下单,这个例子似乎是遥不可及的,不可能发生。而有若干机器人在帐户里执行独立的交易操作,发生这种错误的概率很高。

所以 HedgeTerminal 是一个仓位管理员,在异步模式下工作,确保数个 EA 的并发工作,与这些错误非常接近。为了避免这种情况, HedgeTerminal 在所有启动的副本之间通过实现的 本地轮廓 机制进行动作同步 (无论是 HedgeTerminalAPI 库或是可视面板), 利用多线程读取并修改 ActivePositions.xml 文件。与 ActivePositions.xml 文件交互是本地轮廓的核心, 是 HedgeTerminal 最重要的部分。此机制在以下详述。

用一个简单的方法,HedgeTerminal 降低工作与本地和全局轮廓合作,就像下图:

图例. 38. 全局和本地轮廓之间的信息交换的简化方案

图例. 38. 全局和本地轮廓之间的信息交换的简化方案

在 HedgeTerminal 里的所有交易动作 (图例上的标签 start ) 开始在 ActivePositions.xml 中书写一个特殊标签, 此处是将来被修改仓位的变更部分。

在仓位块被设置,且本地轮廓成功传递之后, HedgeTerminal 发送交易订单至服务器。举例,一笔反向订单将其平仓。片刻之后,订单得到执行,且交易环境也得到改变。HedgeTerminal 处理这种变化, 检测全局轮廓顺利通过,且订单已执行。它解锁持仓,并返回到初始状态 (图例上的标签 finish)。

有一种情况是当订单未能执行。在这种情况下 HedgeTerminal 也解锁持仓并在 MetaTrader 5 终端的日志里记录失败原因。

在现实中信息沟通的模式更为复杂。正如我们已经提及的,在一个 MetaTrader 5 终端上可以运行数个 HedgeTerminal 副本。它们可以是库或可视面板。每个副本均可以充当一个 监听器书写器。当 HedgeTerminal 执行一个交易动作, 这是一个书写器, 因为它使用设计好的 xml 标签来阻塞持仓的改变。所有其它的 HedgeTerminal 副本都是监听器, 因为它们周期性读取文件 ActivePositions.xml 并根据阻塞标签来阻塞持仓的改变。

这种机制确保独立线程之间信息的散布。这有利于那些使用 HedgeTerminalAPI 库的面板和 EA 之间的并行工作。

一个实际的图例, 示意多线程条件下 HedgeTerminal 的协调工作:

图例. 39. 近乎自然形态的 HedgeTerminal 副本之间的信息交换

图例. 39. 近乎自然形态的 HedgeTerminal 副本之间的信息交换

这样组织数据,效率是非常高的。读取和写入 ActivePositions.xml 文件的操作一般用不到 1 毫秒, 而经过全局轮廓, 连带订单发送和执行可能要花费 150-200 毫秒。观察图例来了解这些数据尺度之间的差异。

绿色长方形的宽度示意经过本地轮廓的时间, 蓝色是交易订单执行的时间:

图例. 40. 在文件里做记录和订单执行耗时的时间尺度

图例. 40. 在文件里做记录和订单执行耗时的时间尺度

正如您所看到的,绿色的矩形看起来更像是一条垂直线。在现实中尺度之间的差别更大。

读取和记录的快速操作,有利于 EA 之间复杂数据的交换,以及创建分布式高频交易系统。


3.2. 保存全局和局部信息

常规上, 所有使用 HedgeTerminal 的交易信息可以被切分为两个部分:

  • 本地信息。 这些被存储在计算机中的文件,仅通过本地轮廓传送;
  • 全局信息。 这些信息被保存在交易服务器上。它是通过全局轮廓传递,并且对于所有连接到此帐户的终端都可用。

订单, 成交和有关账户的信息属于全局信息。这些信息可通过 MetaTrader 5 的特殊函数获取, 像是 HistoryOrderGetInteger()AccountInfoInteger()。HedgeTerminal 主要使用这些信息。有鉴于此,HedgeTerminal 显示下列数据:

  • HedgeTerminal 的活动和历史仓位;
  • 活动止损位和历史订单;
  • 历史仓位的触发止盈位;
  • 活动持仓的内嵌注释, 历史仓位的内嵌和外嵌注释;
  • 活动和历史仓位的所有其它属性未纳入本地信息列表。

由于所有这些属性都是全局性的,运行在不同计算机上的所有 HedgeTerminal 副本,它们的显示均唯一。例如,如果一个双向持仓在某终端上被平仓,即使另一台计算机上启动的 HedgeTerminal 副本,该仓位也将平仓。

除了全局数据,HedgeTerminal 也在其工作时使用本地信息。本地信息只能在一台电脑上可用。这个信息是以下属性的基础:

  • 活动持仓的止盈位;
  • 历史仓位的未触及止盈位;
  • 活动持仓的外嵌注释;
  • 阻塞双向仓位变化的服务标志。

未触及止盈位保存在 HistoryPositions.xml 文件里。本地信息的其余部分存储在 ActivePositions.xml 文件里。

本地数据存储意味着,如果您设置一个止赢位,只有在您运行 HedgeTerminal 副本的计算机上才可见。除了您没有人会知道这个价位。


3.3. 止损和止盈位。订单系统问题和 OCO 订单

在 MetaTrader 5 以及 MetaTrader 4 中, 有止损和止盈位的概念。这些都是保护性停止。与 MetaTrader 4 类似,当持仓到达确定的亏损 (止损) 或盈利 (止盈) 的情况下,将会平仓。在 MetaTrader 4 中, 每笔订单都有独立的停止位。在 MetaTrader 5 里这些停止位对整体净持仓起作用。

这里的问题是,净持仓不与 EA 的双向持仓,以及 HedgeTerminal 关联。这就意味着,常规的止损和止盈位不能用于双向持仓,不过,这些价位可以表示为单独的挂单。如果您已有多头持仓,则有两笔挂单来分别模拟止盈和止损的工作。其一是置于此持仓开仓价之上的 SellLimit,另一个是置于低于开仓价之下的 SellStop。

事实上,如果开仓后价格到达 SellLimit 订单,这个订单将盈利平仓,如果价格到达 SellStop 订单,它会止损平仓。唯一的缺点是,一单触发后,如果价格再改变方向,第二单将不会停止现有持仓,而是在第一单触发后第二单也被触发。

由于此刻没有持仓,触发第二笔订单将开新仓,而不是将之前的持仓平仓。

下图描绘了使用保护性停止的多头持仓例中的问题:

图例. 41.  模拟止损和止赢使用 SellStop 和 SellLimit 订单

图例. 41. 模拟止损和止赢使用 SellStop 和 SellLimit 订单

为了避免这种矛盾, 在交易所的交易使用 OCO 订单 ("多则一")。

这是两笔挂单彼此关联,触发其一则取消其它。在我们的例子中,一笔订单触发,另一笔订单由交易服务器取消,因此将不会开新仓,这正是我们所期待的。这种订单类型的工作示意在下面的图表上:

图例. 42. OCO 订单作为止损和止盈

图例. 42. OCO 订单作为止损和止盈

MetaTrader 5 不支持 OCO 订单。由于不能将三笔订单绑定,订单同时充当止损和止盈是不适合的。两笔订单作为一对可以使用! 所以它既是止损亦或止盈。 

事实上, 如果放置一笔与已执行订单相关的挂单来初始化一笔新的双向持仓 (例如止损), 那么这个结构是安全的。此处不会有第二笔挂单,且它将无法形成一个新的双向持仓。实际上,这里只有三种情况:

  • 挂单因某种原因被经纪商或用户取消;
  • 挂单被触发;
  • 挂单未被触发。

没有其它情况。如果挂单被取消,这等同于取消止损或止赢。如果挂单触发,它将平仓。如果订单未触发,则双向持仓将保持活动并带有止损。

即使孤单触发时 HedgeTerminal 被禁用, 那么之后当它启动时, 它也能够处理触发并了解持仓以被该订单平仓。如果在魔幻数字字段包含特殊服务信息,就有可能明示某个已平仓位是由常规订单、止损或止盈平仓的。链接和服务信息在魔幻数字字段的储存方式,将在下个部分详细说明。

由于不能在同一时间使用两个真实的保护性停止,在设计 HedgeTerminal 时做出了折衷:

在 HedgeTerminal 里的双向持仓由真实的 BuyStop 和 SellStop 订单保护,扮演止损的角色。止盈位是虚拟的,仅在运行 HedgeTerminal 副本的电脑这一级别上支持,在全局级别不可用。

选择止损位,因为这些价位需要可靠触发更高价位。如果止盈不能工作, 它不会导致灾难, 且帐户不会因追加保证金而被关闭, 而止损未被触发可导致帐户爆仓。

然而,有机会选择持仓尾随方式的算法。您可以在真实止损和虚拟止盈之间,或是虚拟止损和真实止盈之间进行选择。止损和止盈位,也可以是虚拟的。此刻该功能尚未实现,但如果有需求,它可以出现。

止盈位的虚拟化降低其总体的可靠性,但不明显。止盈位分布在本地,且可用于 HedgeTerminal 的所有副本。对于执行止盈,运行至少一个使用 HedgeTerminal 库的 EA,或 HedgeTerminal 面板的副本就可以了。当有运行多个 HedgeTerminal 副本,只有其一将执行止盈。它会第一个将一个阻塞标签放在双向持仓上。在这个意义上,在多线程模式下,HedgeTerminal 的实例相互竞争读写数据。

对于用户,通过 HedgeTerminal 面板手动交易,或使用 EA 里的虚拟库,止盈和止损的工作没有区别。这些级别之间的所有实际差异,被隐藏在 HedgeTerminal 的幕后。对于交易者而言,输入 "止盈" 和 "止损" 就足够了。这些价位将并发呈现,且用相同颜色来表示警告:有关价位中的一个被触发。


3.4. OCO 订单可以解决双向仓位的保护问题吗?

OCO 订单令并发使用真实的止损和止盈位成为可能。在组织双向交易中,难道它们真的多才多艺?下面是它们的特点。我们已经知道,OCO 订单允许触发一笔订单的同时取消另一个。

好像这能从两方面保护我们的双向仓位,因为在这种情况下,止损和止盈可以是真实的订单,因而无需 HedgeTerminal 在计算机上运行。问题是,在订单执行时必须考虑 部分订单执行。这个性质可以破坏应用程序的业务逻辑。让我们考虑一个简单的例子:

  1. 开一笔 10 份合约交易量的多头仓位。两笔链接 OCO 订单实现止损和止盈位的设置;
  2. 当止盈位到达,SellLimit 订单得到部分执行。十分之七的合约平仓,还剩 3 份合约的多头持仓;
  3. SellStop 订单实现的止损位, 由于 SellLimit 订单已经部分执行而被取消。
  4. 三 份合约的持仓不再有保护性停止。

此场景在下图呈现:

图例. 43. 保护性停止部分执行

图例. 43. 保护性停止部分执行

设计 OCO 订单时考虑部分执行,并避免清除保护性停止,这可能有些异议。两笔 OCO 订单的交易量可以相互关联。这种部分执行的情况肯定会被预见。不过, 这将导致订单系统的逻辑更趋复杂。

这里的主要问题是 ,即使考虑到部分执行,OCO 订单也不能提供如同 MetaTrader4 中的同样机会。举例,放置带有止盈和止损位的挂单将是困难的。原因在于,两个相互关联订单的无法考虑初始订单的触发。

编写一段真实的通用算法, 如同 MetaTrader 4 那样管理仓位, OCO 订单必须具有以下特征:

  1. 每笔链接订单必须根据所链接的订单执行程度来调整交易量。举例, 如果止盈执行了十分之七的合约, 则其链接的止损必须修改其交易量从10 到 3 (10 - 7 = 3);
  2. 每笔链接订单,必须考虑初始订单执行的交易量。一位交易员放置一笔 BuyLimit 类型的订单,并在形成的订单里以止损和止盈保护它的情况下,这并不意味着 BuyLimit 能够保证执行整个交易量。这些情况也必须由成对的订单满足。
  3. 针对取消的附加条件, 是一对订单必须有额外的触发条件。仅当与它连接的额外订单触发时,它才可以触发。这意味着,一笔 OCO 订单必须链接到两笔订单。第一笔链接指向激活当前订单的那笔触发订单。第而笔链接指向取消当前订单的那笔触发订单。这种机制将允许创建一笔带有初始挂单的仓位;

这种机制,即使它们出现,对于经验有限的用户也很复杂。其适用性值得怀疑。在客户端一侧的虚拟化,就像目前在 HedgeTerminal 中使用的,更容易使用。

作为一种 OCO 订单的替代品,MetaQuotes 考虑引入特殊的止盈和止损位算法的可能性,来确实保护某些交易订单。当然,这只是一种理论,虽然它具有合理的内核。这种算法可以将其实现和配置的重要组成部分隐藏在交易服务器端,并提供给最终用户一个简单的、现成的保护机制。

综上,我们稍微论述了一些有关在 MetaTrader 5 平台上集成 OCO 订单的观点。

当订单部分执行时,OCO 订单是无效的,对于平台的正常用户来说它们不十分可靠,而且太复杂。 


3.5. 存储初始订单的链接

本节研究连接到其它订单的内部存储,以及它们之间绑定机制的详细描述。正如前面提到的,字段 "订单魔幻" 包含下单 EA 的标识符。这意味着,任何交易者可以使用 MQL5 编程语言在此字段中输入任意整数值。在这种情况下 冲突 是有可能的, 当订单初始一个新仓位时将包含一个 EA 标识符, 与现有订单的标识符匹配。在这种情况下,将出现一个错误的订单链接。

如果一位交易者使用的 EA 标识符接近零, 像 "1", "7""100", 且订单号明显大于这些数字, 像是 "10002384732", 则这些冲突可以避免。宁愿天真的相信,交易者会记住这一点。这就是为什么 HedgeTerminal 以特殊的方式存储到订单的链接,以便降低冲突的概率,并且它的算法不允许歧义,如果它们出现则自动消除冲突。

字段 "Order Magic" 保存的链接是 64 比特位。由于它的宽度,这个字段可以容纳很长的数字。在现实中,订单标识符的工作范围则小了很多。为了安全需要,HedgeTerminal 允许这个字段使用更高的位数,以特殊方式形成订单链接。让我们参考策划,显示 HedgeTerminal 如何保存初始订单链接:

图例. 44. 在 HedgeTerminal 里存储初始订单链接的形态

图例. 44. 在 HedgeTerminal 里存储初始订单链接的形态

字段的顶部比特位 (63) 永远标记为 1。这样可以非常快速地迭代所有订单。显然,如果下一个比特位不等于 1,则该订单未包含到另一笔订单的链接,它可以被跳过。此外,给最高比特位分配数值 1,使魔幻数非常大,而且增加了订单标识符的工作范围,以及 HedgeTerminal 中链接的工作范围,能够最小化冲突的概率。

HedgeTerminal 可以用服务信息填写以下三个比特位。不像订单标识符,HedgeTerminal 在此字段存储的订单标识符由内而外。首先它填充最高比特位之后是较低比特位, 在图例.44. 中以蓝色箭头指示 direction SI (服务信息)。这种存储方式,令服务信息和订单标识符的范围各满足一半。如果有必要时,它们的组合可以改变。服务信息的大小可以通过存储订单标识符的比特位来增加。此信息可以识别 平仓单类型

关键是,在 MetaTrader 4 中活动订单可通过止赢或止损来平仓。这是确定的价位,即订单以固定的利润或亏损平仓。在 MetaTrader 5, 止盈和止损只能用于净持仓, 且它们不适合配对的订单。只有普通挂单可以扮演止赢和止损的角色。

在 HedgeTerminal 中此类订单被分配特殊的标识符,指明其是否为止赢或止损订单。由于魔幻数字被保存在交易服务器上, 服务信息对于所有访问此账户的交易者都可用。这样一来,甚至在不同计算机上运行的若干 HedgeTerminal 副本都拥有关于触发订单类型的信息,并可以正确地显示已平仓位的信息。

有关订单标识符的参考信息存储范围从 059 比特位。它按照标准方向存储, 自右向左排位, 以蓝色箭头指示 direction order id。 为了评估所分配的存储空间大小, 让我们来计算一年内发送到莫斯科交易所的所有订单所需要的存储范围的额度。

我的经纪商截至 13.06.2013 的报告里包含 10 789 965 471 笔订单的标识符。这些数字需用 33.3297 比特位  (log2(10 789 965 471)) 或 64 比特位之中的 34 比特位。一笔在 25.09.2014 下的订单其标识符是 13 400 775 716。此数字使用 33.6416 比特位。虽然在一年四个月的时间里有 26 亿笔订单, 标识符的大小仅增加了 0.31263 比特位, 这甚至小于一个数量级。我不认为太阳会在订单标识符的大小达到第 59 位之前毁灭,但我非常有信心,这个发生时间不会早于数百万年。

HedgeTerminal 不存储公开的链接。为此, 它加密 OrderMagic 字段,保留高位数字不变。HedgeTerminal 的代码基于数字可逆重排,由工作在可变长度密钥的特殊加密函数实现。如此加密后,服务信息和订单标识符彼此混合,并用一个特殊的掩码隐藏,以便最终它们表现为均匀分布的一和零。采用加密的原因有两个。首先,数位重排降低链接和订单标识符重叠的概率,然后保护 HedgeTerminal 的内部算法抵御外部恶意或随机的影响。

此过程是绝对安全的,可逆的,不容易出现冲突。它保证无论交易者使用 EA 执行何种操作,都不会影响 HedgeTerminal 内部算法的可靠性。这很重要,因为在实际情况中,不采用复杂的专用算法来管理这些链接是不可能的。

与此同时,如果我们将自己局限在控制链接,业务逻辑的失败是必然的。以下章节将解释这是为什么,它们专门对这些算法进行详细描述。加密也可用于避免这种失败。此限制好比硬币的反面,除此之外没有其它办法来管理 HedgeTerminal 的仓位。


3.6. HedgeTerminal 的工作限制

链接存储结构的特殊性表明 HedgeTerminal 存储的订单链接,使用的数字一般从 9223372036854775808 18446744073709551615。如果一个 64 比特位的字段表示一个带符号的长整数类型, 则其为负数。这样 HedgeTerminal 的工作就出现三个限制。

第一个限制涉及与 HedgeTerminal 工作的交易机器人。这个不太严格,它可以被视作一个建议:

一个交易机器人或 EA 与 HedgeTerminal 工作时必须有一个标识符 (EA 的魔幻数字), 它不能超过数值 9223372036854775808

现实中,通常 EA 永远不会遇到这种限制,因为使用的标识符很少超过 5-6 个数字。最常见的 EA 标识符是 "12345" 或诸如此类)。此限制可能适用于存储服务信息的机器人,像是在魔幻数字里链接到其它订单。HedgeTerminal 与这些 EA 不兼容,且无法与它们协同工作。

如果由于某种原因,提到的限制被超越,则出现冲突的概率为零。后者只是极小的巧合,在如此范围里可能性极小。即使在这种情况下 HedgeTerminal 将使用它的算法来解决这一冲突。解译一个链接将令工作减缓,链接和现有订单的比较,分析这笔订单是否与另一笔订单适合配对将需要额外的时间。因此,为了避免这种情况,最好不用带负号的长整数。

第二个限制很强硬,但它仅涉及 HedgeTerminal 将要连接的经纪商和交易所:

订单标识符的数字必须使用从 0 到 2^59 或 576 460 752 303 423 488。

显而易见,因为只有 59 位能用于存储订单标识符,而不是 64 位。如果您的经纪商使用的标识符大于这个值,您不能在工作中使用 Hedge Terminal。

第三个限制来自仓位表示的方式:

HedgeTerminal 不与任何其它仓位管理系统兼容。它不能与具有平仓功能的外部交易面板兼容,并且它们不能一起使用。


3.7. 订单配对和动作判断机制

我们已经研究了 HedgeTerminal 中仓位表现的详情,以及它的链接结构。我们不打算继续讨论管理边界订单的算法描述。举例来说,我们从一些其它订单里选择两笔订单,并将它们链接。如果我们不依赖订单链接必须是唯一的,只能由一个订单所拥有的规则,那么所有可能的情况,可分为三组:

  1. 订单未被任何其它订单引用;
  2. 订单被另一个订单引用;
  3. 订单由两个或以上的订单引用。

第一组不会造成困难,这种订单可认定为开仓。第三组也可以非常直截的认定为完成平仓的配对订单。针对第三组的情况我们怎么办?为什么一笔订单会被另外两笔订单引用?它们中的哪一个应该与第一笔链接,并且第二笔订单会发生什么?如果我们将配对过程作为一个序列来表述,这个问题很容易解答:

  1. 我们遇到一笔订单未在其它订单里包含其链接。它被转移到活动订单的部分(持仓),之后持续迭代订单;
  2. 然后,我们遇到了另一笔订单,引用了第一笔订单。那么,在活动订单部分搜索被引用的订单。如果引用的订单在此部分中,则将它与当前订单配对,它们全部转移到历史仓位形成的已完成事务的部分。
  3. 在进一步的迭代中,我们遇到更多订单,其中包含第 1 点中描述的订单链接。那么,在活动订单部分搜索被引用的订单。这次的搜索将不会成功,因为目标订单已经从这部分结转到完成事务的部分。由于依照当前订单未发现订单引用,那么,当前订单的链接是活动的订单,并转移到活动持仓部分。

由于订单标识符的填充是一致的,且它们的列表按照时间进行排序,那么它们可以执行顺序迭代。因此,初始订单将与第一个包含其链接的订单配对,不管其它含有相同链接的订单数量。含有链接到初始订单的所有其它订单,将被纳入活动持仓列表。

正如我们已经提到的,该算法执行这种迭代必须完全确定且一致。HedgeTerminal 在其工作时使用此类迭代算法。事实上,这不是一个简单地迭代,而是自第一笔成交那刻起,所有执行的交易动作的循回。实际上,在每次启动 HedgeTerminal 时始终会构建一个从开始到当前时刻的交易动作链表。有鉴于此, 当前仓位的表现实际上是启动时刻交易回顾的结果。

由于迭代会遍历所有历史订单被,它也需要顺序执行交易动作。这决定了在 HedgeTerminal 中订单执行的方式。举例来说,在 HedgeTerminal 里一笔由止损来保护的活动双向仓位需要平仓。我们知道,此类双向仓位主要由两笔订单组成:活动持仓的已执行初始订单,以及作为止损单的 BuyStop 或 SellStop 挂单。若要平仓,需要删除挂单并通过一笔同等交易量的反向订单将双向持仓平仓。。所以,两笔交易动作都必须执行。HedgeTerminal 异步执行所有交易订单。

这种方式订单可以并发执行,即第一笔订单用来取消挂单,第二笔订单执行向订单,这将平仓。然而,这将打乱动作的确定性,而且 HedgeTerminal 不能执行。如果出于某种原因,挂单没有被取消,且持仓未能通过反向单平仓,则将产生歧义,因为仓位已平,但其止损依然存在。在结束时,实现止损的订单可以触发并生成一个新的双向持仓。这不应该发生。这就是为什么 HedgeTerminal 将取消止损,并在成功取消后会放置一笔反向订单。有一种可能性,即,反向订单不被执行,或在第二步中部分地执行。在这种情况下,歧义将被消除,因为一笔部分执行的反向订单将活动持仓的一部分平仓。这是一个普遍情况。

还有一个更复杂的由 HedgeTerminal 实现的动作顺序。让我们用类似前一个的例子,但这次我们只将部分持仓平仓。这意味着 HedgeTerminal 将展开三个动作:

  1. 删除充当止损的挂单;
  2. 执行方向订单将双向持仓的一部分交易量平仓;
  3. 用新交易量设置新止损来保护活动持仓的剩余部分。

所有这些动作将连续执行,以避免破坏行动的确定性。期望增加订单执行速度是很自然的事,因为同时下单的情况下,不能保证交易操作顺序执行,很可能会产生歧义。连续订单处理并非暗含任何歧义。


3.8. 切分和链接成交 - 订单运算基础

按连续订单处理是不够的。这里应该指出两件事情:

  • 一笔订单可能包括几笔成交。这些成交的数量可能是随机的;
  • 同样重要的是要考虑到的部分订单执行,以及一个更常见的情况,即一个平仓订单的交易量不等于初始订单的交易量;

此订单可在同时由几笔成交执行,而且它也可以被部分地执行。如果您不了解为什么它会发生, 请参阅专门论述交易定价的文章 "以莫斯科交易所衍生品市场为例的交易价格原理"。这个问题 "为什么平仓交易量不等于开仓交易量?" 需要一个答案。在这种情况下我们可以做些什么?

事实上,如果我们假定有机会将一笔活动持仓 部分 平仓,那么交易量不会相等。如果我们开仓时交易量为 50 份合约,并以反向订单部分平仓时交易量为 20 份合约,则活动持仓被分为两部分。第一部分交易量为 20 份合约的反向订单成为新的历史仓位,第二部分将仍然持有,尽管其交易量将减至 30 份合约。

该部分平仓算法已在 HedgeTerminal 中实现。如果在 HedgeTerminal 面板的 "Volume" 字段里输入新的交易量数值,则将进行部分平仓。在 "历史" 文件夹将出现一笔新仓位,当前持仓的交易量将等于新数值。HedgeTerminal 可以处理这种情况,即使当平仓订单的交易量大于初始订单的交易量!这种情况发生在 HedgeTerminal 由于某种原因放置的一笔错误交易量的平仓单,或经纪商反手取消的若干笔成交中包括初始订单,此时交易量将以较小的为准执行。

考虑到可能的交易量差异,它需要采用计算与此订单相关的所有成交总交易量的通用算法。在这种情况下,它是成交,而不是订单决定一切。订单的交易量是其成交的交易量。一笔已执行订单的价格是它的成交均价。

HedgeTerminal 使用订单彼此链接或切分它们的算法。它基于这些成交的叠加和抵消。它的工作基于初始单和形成历史仓位的平仓单之间的所有成交的统合。

要理解这种算法的工作原理,让我们假设有两笔订单需要配对,变为历史仓位。两笔订单有相同数量的成交且它们的执行交易量也相同。为简单起见,成交单号定为三位数:

订单 #1 (进仓订单)交易量 (10/10)
成交 #2833
成交 #2882
成交 #2945

表 3. 订单 #1 和它的成交


订单 #2 (出仓订单)交易量 (10/10)
成交 #8711
成交 #8823
成交 #9216

表 4. 订单 #2 和它的成交

让我们将它们的交易量放到一起:

表 5. 将订单放到一起

表 5. 将订单放到一起

从每列选择最后两笔订单: #294 和 #921。通常它们彼此不在同一级别 (就像此例)。

选择交易量最小的成交。这笔成交是 #294 交易量为 5。切分反向成交 #921 为两笔。第一笔等于成交 #294 的交易量 (5 份合约), 第二笔包含剩余的交易量 1 份合约 (6 份合约 – 5 份合约 = 1 份合约)。统合成交 #294 与 #921 的第一部分,交易量相似都是 5:

表 6. 交易量相减

表 6. 交易量相减

转移统合的部分到包含历史仓位成交的新列。

它以 绿色 加亮。在活动持仓的初始列保留成交 #921 的剩余部分交易量 1 。它以 灰色 加亮:

表 7. 切分和结转成交

表 7. 切分和结转成交

我们在第一步已经将两笔成交订单统合,并结转至历史仓位。让我们简要回顾动作序列:

表 8. 切分和结转成交步骤 1

表 8. 切分和结转成交步骤 1

成交 #294 被完整结转至历史仓位部分。这笔成交已彻底 了结。因此这笔成交被 切分 并结转到历史仓位部分。这就是为什么在随后的步骤,我们可以如下用交易量 2 来处理成交 #288。成交 #921 依然出现,且它的交易量与成交第二部分的相等。在随后的步骤中,该交易量将与成交 #288 的交易量相动。

在第二步重复成交 #288 和 #921 的过程。这次成交 #921 剩余的交易量 (1 份合约) 与成交 #288 的交易量统合之后进入历史订单的行列。成交 #288 的剩余交易量等于 1 份合约,且将保留在活动持仓的行列:

 表 9. 切分和结转成交步骤 1-2

表 9. 切分和结转成交步骤 1-2

重复成交 #288 和 #882 的相同动作:

表 10. 切分和结转成交步骤 1-3

表 10. 切分和结转成交步骤 1-3

按照相同的方式执行步骤四和五:

表 11. 切分和结转成交步骤 1-5

表 11. 切分和结转成交步骤 1-5

第五步之后, 平仓单的交易量将与开仓单的交易量绝对相等。结转到历史仓位行列的成交构成一笔完整的历史事务。活动持仓的剩余部分作为新的活动持仓。在这种情况下,没有交易保留在活动持仓的行列。这意味着,这样的统合之后,活动持仓将不复存在。一笔新的历史仓位将会出现,包括活动持仓的所有交易。

成交结转后,它们之中的一些会被切分成几部分,并占据若干行。为了避免这种情况,在统合/切分成交的算法里面加入收集成交的选项。简单地统合相同标识符的成交的交易量:

表 12. 在同一级统合成交

表 12. 在同一级统合成交

统合之后,成交数量和它们的交易量完全匹配初始成交和其交易量。发生这种情况,不过是因为它们的交易量与初始匹配。如果它们的交易量不同,那么统合的过程之后,这些成交将有不同的交易量。

这个算法是通用的,因为它不要求初始单和平仓单的成交数量相同。我们来看看另一个基于此性质的例子:

表 13. 统合不同成交数量的订单

表 13. 统合不同成交数量的订单

正如我们所看到的,统合订单为一笔历史仓位成功。尽管有不同数量的成交,它们的成交量再度匹配。

现在, 想象平仓单的交易量总和 (12 份合约) 小于初始单的成交量 (22 份合约)。这种情况下如何来统合?

表 14. 统合不同成交量的订单

表 14. 统合不同成交量的订单

正如我们所看到的, 在第二个步骤, 平仓单的交易量等于零, 而初始单包含两笔成交, 交易量为 4 的 #321 和 交易量 6 的 #344。这超出了活动订单。这样,超出的将作为一笔活动的双向持仓存在。此处,历史仓位的成交结转到绿色列中。其初始和出场的交易量 12 份合约再次匹配。

在平仓单的交易量大于其初始单的情况下,在平仓单一侧也有一笔超出:

表 15. 统合不同成交量的订单

表 15. 统合不同成交量的订单

正如我们看到的,初始单交易量为 4,平仓单交易量为 6,变成两笔仓位。第一笔是交易量为 4 的历史仓位,初始单的成交 #625,而平仓单的成交 #720。第二比仓位是超出配对订单成交的部分。它包括交易量为 2 的成交 #719。这笔成交在 HedgeTerminal 面板的“活动”栏中生成一笔活动持仓。

成交和订单能够通过算法切分为历史和活动的仓位。交易量可以不同。最主要的是,该算法可以将初始单和平仓的交易量一起统计,形成一笔入场和出场交易量相等的历史仓位。它可确保因交易量不相等和仓位重现错误引起的仓位不对称的情况不会发生。

我们假设在第一个例子中,经纪商取消一笔在平仓单里包含的成交:

表 16. 从历史记录中删除成交的模拟

表 16. 从历史记录中删除成交的模拟

新的净持仓交易量为 6 份合约。这等于被取消成交的交易量。让我们来看看 HedgeTerminal 的算法在这种情况下如何工作:

表 17. 还原完整性重现

表 17. 还原完整性重现

正如我们所看到的, 在第二步有超出的 6 份合约 (3+2+1)。这些超出将变成一笔活动持仓,而且双向持仓的交易量和方向等于净持仓。

综上,我们可以说,统合成交的算法保证了在历史仓位中初始和平仓单的交易量的平等,尽管有过多的未绑定成交。这超出的成交成为活动的双向持仓,即在 MetaTrader 5 中的净持仓等于 HedgeTerminal 中所有活动净持仓。

这种机制在回顾和实时两种模式下均可工作,这意味着,无论经纪商是否进行取消成交的动作,HedgeTerminal 的净持仓总能与 MetaTrader 5 中的精持仓对应。净持仓和取消成交的变化组合,不会导致终端与 HedgeTerminal 之间净持仓的不对称。

部分平仓机制,基于该算法合并不同交易量的能力。这个算法是 HedgeTerminal 的最重要部分之一,确保其作为一个自适应系统,无需设置即可稳定工作。


3.9. 订单与成交虚拟化

在 HedgeTerminal 中每笔订单和成交有一个带有通讯标识符的真实原型。尽管如此,从 HedgeTerminal 的角度来看,一笔订单可以作为一笔活动持仓,同时也是历史的一部分。在 MetaTrader 5 里的成交和订单是不可分割的实体。在平台中,订单即可待决也可执行。一笔成交也有一个恒定的交易量且始终是一笔已执行事务。

在 HedgeTerminal 中同样的订单和成交可以表现为不同的双向仓位。相同的成交或订单可以是活动的或是历史仓位。换句话说,订单和成交在 HedgeTerminal 中被切分为若干个虚拟部分。这种数据重现与 MetaTrader 5 的数据重现有极大不同。然而,这种重现可以很灵活,并能适应交易信息的变化追溯,以及能将订单和成交结为一体。


3.10. 隐藏订单机制

我们在描述 HedgeTerminal 的安装的章节提到隐藏订单的机制。HedgeTerminal 可以忽略一些订单。对于 HedgeTerminal,一笔订单或成交终止存在,将其标识符输入指定的文件 ExcludeOrders.xml 就可以了。

让我们假设我们有几笔已执行的某品种的卖单或买单。卖单的总交易量等于买盘总交易量。这样一来,无论我们有多少订单,其仓位总计等于零。如果这些订单的标识符不在 ExcludeOrders.xml 文件里, HedgeTerminal 将它们视为双向持仓。其总持仓依然为零。因此,在 MetaTrader 5 中如果净持仓为零,那么这个订单集合对于净持仓的贡献可以被简单地忽略。

现在,让我们假设此刻 t 我们持有的 S 品种净持仓为零,且该品种的订单集合 N 此时执行。因为该品种尚无净持仓,订单集合 N 的总交易量是微不足道的。事实上,订单的数量和它们的交易量都无关紧要,因为 因为没有持仓,这些订单对总体净持仓没有贡献。这意味着,此类订单可以简单地被忽略,也没有必要将它们表示为双向仓位。

这就是 HedgeTerminal 当前在其安装时采用的非常机制。在安装时 t 如果没有一个净持仓, HedgeTerminal 将订单集合 N 纳入异常列表。因为没有净持仓,它们的总交易量和数量无关紧要。如果在安装 HedgeTerminal 时存在净持仓,则简单得很,它根本不会被安装,直到净持仓平仓。安装完成后,新订单将改变净持仓的状态。这个状态将在 HedgeTerminal 里与双向仓位的净交易量一起被同步。

看似,我们可以摆脱 HedgeTerminal 将已执行订单放入异常列表中。在安装的同一时刻,可能有大量订单的情况发生,从 HedgeTerminal 的角度来看,它们将全部变成双向持仓,且它们的总交易量可能与 MetaTrader 5 中的不同。

这种隐藏订单的机制可有效抵御账户历史崩溃。这是它如何工作。让我们假设有一些订单的历史记录。当 HedgeTerminal 在此帐户启动时,它会遍历所有的订单并建立基于它们的双向仓位。如果所有的订单,自开单时间的数据都完好,这些订单的净持仓将与 MetaTrader 5 中的净持仓对应。显然,在 HedgeTerminal 中的净持仓将等于这些订单的总和。这在下面的图例上说明:

图例. 45. 整体历史图例

图例. 45. 整体历史图例

历史的一部分可能会丢失或有关订单的信息是不正确的。

如果只有一笔或几笔订单丢失这并不重要,并且如果帐户历史记录信息从开头或中间缺失,这也无关紧要。在这种帐户上运行的 HedgeTerminal,其净持仓等于所有可用订单的净持仓。因为历史数据部分缺失,订单的净持仓不等于终端里的实际净持仓。这些情况展现在图例 B:

图例. 46. 部分历史数据损失

图例. 46. 部分历史数据损失

要在 HedgeTerminal 的净持仓,与 MetaTrader 5 的实际净头寸之间同步,我们无需了解订单是否消失或损坏。所有我们需要的是计算这些净持仓的差额。在上面的例子中,在 MetaTrader 5 终端里以 5 份合约的交易量开多头仓位。在 HedgeTerminal 中它将对应总量 8 份合约的多头持仓。这两个仓位之间的差额为 3 份合约,因为 8 BUY – 5 BUY = 3 BUY

计算合约差额之后,需要放置一个对应的相同交易量的多头或空头定单。在我们的例子中,需要放置 3 份合约的多头订单。当订单被执行,HedgeTerminal 会在活动持仓栏显示它,其净持仓总量增加 3 份合约,共等于 11 份合约的多头。

在 MetaTrader 5 中的持仓也将增加,将变成 8 份合约。这个订单的识别符将进入 ExcludeOrders.xml 列表, 之后终端需要重启。因此,如果我们的订单标识符等于 101162513,则以下标签应该被写入文件中:

<Orders-Exclude>
        ...
        <Order AccountID="10052699" ID="101162513"></Order>
</Orders-Exclude>

重新启动 HedgeTerminal 后,这个双向仓位将消失。这样,在 MetaTrader 5 中的净持仓将匹配 HedgeTerminal 中的一笔净持仓,并产生 5 份多头合约。动作顺序的描述表示在下图:

图例. 47. 数据完整性还原图例

图例. 47. 数据完整性还原图例

消失仓位的财会结果将不会在 HedgeTerminal 的统计里记录。不幸的是,隐藏双向仓位并不能作为交易统计数据的一部分。

在现实中,历史数据的一部分不可用或损坏的情况,发生的可能性极低。虽然大多数的 MetaTrader 5 用户将永远不会遇到这种情况,但如果他们需要使用它,这种机制必须到位。HedgeTerminal 的程序出错的可能性并未完全排除。即使在这种情况下,应该有解决这些错误的可靠手段。


3.11. 适应机制

我们已经研究了通过 HedgeTerminal 来重现 MetaTrader 5 中净持仓的双向仓位的机制。有三种机制:

  1. 成交的顺序迭代;
  2. 成交的切分与统合机制;
  3. 隐藏订单机制。

这些机制的每一种均定位于它们的问题,并可以在它们的级别上避免歧义和错误。让我们把这些问题及其解决方案带进表格。第一列包含的问题与可能的错误绑定,第二列是解决这些问题的机制:

问题, 错误, 在双向交易组织里引起的歧义错误校正机制
指向开单的连接错误; 连接冲突; EA 的过长魔幻数字; 从历史记录里删除订单; 交易操作的执行错误。定单顺序迭代。动作判断。
交易量错误; 不同交易量订单匹配错误; 订单部分执行; 从历史数据里删除成交; 转换较小交易量至较大的。成交切分与匹配机制。
在拥有大量已执行订单的帐户上安装 HedgeTerminal; 历史数据损坏; HedgeTerminal 处理订单时的缺陷。隐藏订单机制。

表 18. 可能的错误及其消除机制

所有三种机制连同存储连接的系统,确保稳定的数据重现。本质上,这些机制覆盖了所有不可预见的故障,并保证 HedgeTerminal 中的净持仓与 MetaTrader 5 的净持仓匹配。


3.12. 性能和内存使用

HedgeTerminal 本质上是一个面向对象的应用程序。由于面向对象原则的底层架构,该终端高效率且对于存储需求很低。唯一消耗资源的任务是在图表上启动终端时,它要提取订单和成交的历史数据至计算机内存。

一旦所有需要事务提取到存储器中,该终端将打印一条消息,通报有关操作花费的时间和内存使用情况。在一台处理器为 Intel i7 的电脑上,账户包含超过 20000 笔成交,启动 HedgeTerminal 面板所需花费时间小于 30 秒,所需内存为 118 MB。

2014.11.20 16:26:19.785 hedgeterminalultimate (EURUSD,H1)       We begin. Parsing of history deals (22156) and orders (22237) completed for 28.080 sec. 118MB RAM used.

因为不需要用图形重现事务,HedgeTerminalAPI 库工作得更快,且占用更少的内存。下面是同一帐户的启动结果:

2014.11.20 16:21:46.183 TestHedgeTerminalAPI (EURUSD,H1)        We are begin. Parsing of history deals (22156) and orders (22237) completed for 22.792 sec. 44MB RAM used.

简单的计算表明,提取一笔仓位,根据程序类型需花费 1 至1.26 毫秒。存储一笔事务占用: (22156 成交 + 22237 订单) / 44 MB = 1 K 内存。存储附加事务图形重现占用大约: (118 MB – 44 MB) * 1024 / (22 156 成交 + 22237 订单) = 1.71 KB 内存。

代码分析表明,时间花费的主要部分只在订单分析一块。后者的主要部分则是系统函数调用。在未来的版本中,此块将被优化,这可以在启动时提高 10-15% 的效率。


结论

我们已经研究了 HedgeTerminal 可视面板的工作要点。这是一个良好的例子,创建面板的新类,可以进行灵活配置。

规划和规范给出了双向交易组织原则的深度思路。如果您正在创建自己的虚拟化函数库,这篇文章的第二章将帮助您设计这种函数库。

交易执行的特征,作为双向持仓来重现成交和订单的过程中需要考虑的关键点。这篇文章表明,若没有成交和订单的虚拟化,这种重现是不可能的。虚拟化是一种将已执行交易的交易量 "断开" 并克隆实际订单的机制, 使某一笔订单可以作为若干事务的一部分。

这些依靠交易环境的操作相当勇敢,不过虚拟化所需信息的主要部分存储在交易服务器上,有基于此重现可以被视为可靠。


本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1297

关于策略优化的一些简单想法 关于策略优化的一些简单想法
即使你借助MQL5的云计算网络来进行优化工作,仍就需要消耗大量的计算机资源。本文由我对MetaTrader 5策略测试器一些简单的改进想所法组成。这些想法来自于MQL社区的相关技术文档、论坛和文章。
物美价廉的神经网络 - 链接 NeuroPro 与 MetaTrader 5 物美价廉的神经网络 - 链接 NeuroPro 与 MetaTrader 5
是否用于交易的特殊神经网络程序好似很昂贵和复杂,或是与此相反,太简单?来试试 NeuroPro。它是免费的,并且包含针对业余爱好者的最佳功能集合。这篇文章将告诉您如何结合 MetaTrader 5 来使用它。
选择交易信号进行订阅的技巧。循序渐进的操作手册 选择交易信号进行订阅的技巧。循序渐进的操作手册
本文提供一种在信号服务中搜寻交易信号的系统性方法,寻找能够平衡获利、风险、交易欲望,并且能适用于各类交易帐户及交易对象的交易信号。
MQL5.com 自由职业: 开发者的收入来源 (信息图) MQL5.com 自由职业: 开发者的收入来源 (信息图)
值此 MQL5 自由职业服务的第四个生日, 我们准备了一幅信息图来展示其自创生来的整体服务成果。让数据本身说话: 迄今已总计执行了超过 10000 笔订单, 价值约 $600,000, 有 3000 余客户和 300 余开发者已经在使用此服务。