Разнонаправленная торговля и хеджирование позиций в MetaTrader 5 с помощью панели HedgeTerminal, часть 1

Vasiliy Sokolov | 19 января, 2015

Оглавление


Введение

В последние полтора года компанией MetaQuotes была проведена масштабная работа по объединению торговых платформ MetaTrader 4 и MetaTrader 5 в единую трейдерскую экосистему. Теперь для обеих платформ существует общий рынок программных решений - Маркет, предлагающий различные программные решения от сторонних разработчиков. Компиляторы для обеих платформ также были объединены. Теперь обе платформы имеют единый компилятор на базе MQL5 и единый язык программирования - MQL, с разным набором функций в зависимости от используемой платформы. Все общедоступные исходные коды, размещенные в базе кодов Code Base, также подверглись ревизии, а некоторые их них были скорректированы для совместимости с новым компилятором.

Однако такое глобальное объединение платформ оставило в стороне объединение их торговых частей. По-прежнему, несмотря на большую часть отныне общего торгового окружения, торговые модели MetaTrader 4 и MetaTrader 5 остались принципиально несовместимыми. MetaTrader 4 предлагает индивидуальное управление торговыми позициями через систему "ордеров", - специальных программных сущностей, делающих разнонаправленную торговлю в этом терминале простой и удобной. MetaTrader 5 ориентирован на биржевую работу, где основным представлением обязательств трейдера является его совокупная нетто-позиция, а ордера в нем являются тем, чем по сути и должны являться - приказами на покупку или продажу финансового инструмента.

Разница между торговым представлением этих платформ вызывала немало горячих споров и обсуждений. Однако споры так и остались спорами. К сожалению, за годы с момента первого релиза MetaTrader 5 так и не было продемонстрировано ни одного рабочего решения, которое доказывало бы фактом своего существование возможность представления обязательств трейдеров в виде независимых разнонаправленных позиций как в MetaTrader 4. Безусловно, на эту тему было опубликовано немало статей, где предлагались те или иные решения. Но к сожалению, эти решения были и остаются недостаточно гибкими, чтобы их можно было использовать с удобством и на более-менее массовом уровне. К тому же, ни одно из этих решений не подходит для торговли на бирже, где существует масса нюансов, которые нужно учитывать.

Эта статья должна поставить точку в спорах между любителями пятой и четвертой версий платформы MetaTrader и наконец дать универсальное решение в виде подробных спецификаций и конкретного программного решения, которое эти спецификации реализует. В этой статье речь пойдет о визуальной панели и библиотеки виртуализации HedgeTerminal, с помощью которых становиться возможным представлять свои обязательства в виде разнонаправленных позиций как в MetaTrader 4. При этом модель, заложенная в HedgeTerminal учитывает специфику биржевого исполнения торговых приказов. А значит, он с успехом может применяться как на внебиржевом рынке FOREX, так и на централизованных биржевых площадках, например, при торговле деривативами в срочной секции Московской биржи.

HedgeTerminal - это полноценный торговый терминал внутри самого терминала MetaTrader 5. Через механизм виртуализации он изменяет представление текущих позиций таким образом, что трейдер или торговый робот может управлять своими индивидуальными торговыми позициями, при этом ни количество этих позиций, ни их направление не имеют значения. Подчеркну, что речь идет о виртуализации, - специальном механизме, трансформирующим представление обязательств трейдера, но не их общую качественную характеристику.

Речь идет не об искажении результатов финансовой деятельности трейдера, а о трансформации представления этой деятельности. HedgeTerminal базируется на торговом окружении MetaTrader 5 и языке программирования MQL5, он не привносит в терминал новую торговую информацию, а лишь представляет текущее торговое окружение под другим углом зрения. Это значит, что HedgeTerminal суть MetaTrader 5, и является его родным (native) приложением, и между ними можно поставить в определенной степени знак тождества, а вернее знак включения, где HedgeTerminal является лишь небольшим и одним из многих приложений для MetaTrader 5.

Сама по себе возможность виртуализации и существование HedgeTerminal базируется на трех парадигмах:

  1. Концептуально возможна полная и гарантированная обратимость нетто-представления позиции в индивидуальные разнонаправленные торговые транзакции. Это утверждение доказывает тот факт, что в некоторых сторонних торговых платформах для трейдинга, в том числе созданных для биржевой торговли, существует возможность управлять разнонаправленными позициями;
  2. Торговая модель MetaTrader 5 на пользовательском уровне позволяет создавать односторонние ссылки ордеров друг на друга. Математические расчеты показали, что ссылки, спроектированные специальным образом, будут устойчивы к появлению коллизий. Более того, даже в случае разрушения истории или иных форс-мажорных ситуаций, разнонаправленные транзакции могут быть ретроспективно скорректированы и сведены к финансовому результату, рассчитанному при нетто-представлении;
  3. Развитые средства API в MQL5 позволяют поставить знак тождества между MQL5 и самим терминалом MetaTrader 5. Иными словами, почти все, что есть в MetaTrader 5, доступно в нем через программный интерфейс и язык программирования MQL5. Например, можно написать свою версию терминала внутри самого терминала MetaTrader 5, что и было сделано на примере HedgeTerminal.

Прочитав эту статью, вы узнаете о том, как устроена панель HedgeTerminal, и какие алгоритмы кроются за ее внешним видом. Вы подробно ознакомитесь со спецификациями и алгоритмами работы, позволяющими организовать надежную разнонаправленную торговлю. Независимо от того, решите ли вы использовать HedgeTerminal или создать свою собственную библиотеку по управлению своими торговыми алгоритмами, эта статья и ее продолжение даст вам много интересной и полезной информации.

Вы сможете прочитать эту статью, даже если вы не программист. В этой статье намерено не используется исходный код MQL. Вместо этого все исходные коды заменены более наглядными схемами, таблицами и картинками, схематично показывающими принцип работы и организацию данных. На своем опыте могу сказать, что даже разбираясь в программировании, гораздо проще увидеть общую схему работы кода, чем заниматься его анализом.

В следующей, второй части статьи, где речь пойдет об интеграции торговых экспертов с библиотекой виртуализации HedgeTerminalAPI, без программирования будет уже не обойтись. Но даже в этом случае, было сделано все, чтобы упростить восприятие кода, особенно начинающим программистам. Например, в статье сознательно не используется объектно-ориентированные конструкции, например, классы, хотя сам HedgeTerminal является объектно-ориентированным приложением.


Как читать эту статью?

Излагаемый материал получился очень объемным. С одной стороны, это хорошо, так как практически на любой вопрос в нем найдется ответ. С другой стороны, многие пользователи, не желающие вникать в дебри организации торговли, хотели бы прочитать самое главное, а потом, в случае необходимости, обратится к интересующему их разделу. Однако жанр статьи требует последовательного изложения материала. При этом сам материал должен быть изложен полностью. Подобно тому, как делается во многих книгах, мы дадим краткую аннотацию каждой главы, с помощью которой вы поймете, нужно ли вам будет ее читать.

Надеюсь что материал, изложенный в этой статье, будет достаточно интересным, чтобы вы, уважаемый читатель, прочитали его полностью.


Глава 1. Теория организации разнонаправленной торговли

1.1. Возможности MetaTrader 5 в организации разнонаправленной торговли

В статье "Основы биржевого ценообразования на примере срочной секции Московской биржи" подробно описаны нюансы биржевого ценообразования и методы расчета финансовых результатов участников рынка. В ней было показано, что ценообразование и сам расчет на Московской бирже существенно отличаются от понятий и методов расчетов, принятых при торговле на FOREX.

В целом, представление биржевой цены сложней, но при этом содержит множество существенных деталей, невидимых при торговле на форекс и в самом терминале MetaTrader 4.

Например, в 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 или сокращенно просто HT.

HedgeTerminal предоставляет из себя полноценный торговый терминал внутри самого терминала MetaTrader 5. Он использует торговое окружение MetaTrader 5, трансформирует его с помощью языка MQL5 и предоставляет в виде удобного графического интерфейса - панели HedgeTerminalUltimate и специального программного интерфейса для взаимодействия с независимыми алгоритмами (торговыми экспертами, скриптами и индикаторами) - библиотеки HedgeTerminalAPI.

Так как в MetaTrader 4 возможно использовать разнонаправленные позиции или локи, такая возможность есть и в MetaTrader 5, однако она присутствует неявно, но ее можно подключить, используя специальную программу-надстройку, чем и является HedgeTerminal по своей сути. HedgeTerminal встраивается в MetaTrader 5 и использует его окружение, собирая информацию по сделкам и ордерам в единые позиции, очень похожие на ордера в MetaTrader 4, однако при этом обладающие всеми возможностями MetaTrader 5.

Такие позиции могут быть в полном или частичном локе (когда одновременно сосуществуют активные длинные и короткие позиции). Однако возможность поддержания таких позиций не является самоцелью для HedgeTerminal. Его основная задача объединить торговую информацию в единые группы (позиции), которые было бы легко анализировать, управлять ими и получать к ним доступ. Возможность существования разнонаправленных позиций в HedgeTerminal обусловлена лишь тем, что это действительно удобно. Ведь если на одном счете торгуют несколько трейдеров, или используются несколько стратегий, вопрос разделения торговых действий все равно необходимо будет решить.

К тому же, при торговле на бирже приходится учитывать множество нюансов: например, частичное исполнение ордеров, ролловер позиций, расчет вариационной маржи, ведение статистики и многое другое. HedgeTerminal специально создавался для решения этих задач, предоставляя пользователю или торговому роботу привычный высокоуровневый интерфейс, напоминающий MetaTrader 4, но при этом корректно работающий в условиях биржевого окружения.


1.2. Связывания ордеров – основа хеджирования и статистики

Для того чтобы получить надежное управление своими торговыми техниками или алгоритмами, прежде всего, необходимо гарантированно знать, какое торговое действие какому алгоритму принадлежит.  Мною было намеренно подчеркнуто слово "гарантировано", потому что если допустить даже самую малую вероятность сбоя, крах по управлению позициями рано или поздно будет неизбежен. В свою очередь, он повлечет за собой полное разрушение статистики и в итоге приведет к неразберихе и полному фиаско идеи управления различными алгоритмами на одном счете.

Надежное разделение торговых действий базируется на двух фундаментальных возможностях:

  1. Возможности объединения или "связывания" двух торговых приказов или ордеров между собой, таким образом, чтобы всегда можно было определить, какой из этих двух ордеров является открывающим индивидуальную (виртуальную) позицию, а какой из них является закрывающим эту позицию;
  2. Алгоритм, анализирующий ордера на предмет их связывания, должен быть полностью детерминистическим и единым для всех программных модулей.

Чуть позже мы рассмотрим второе требование на детерминистичность алгоритма более подробно, а сейчас остановимся на первом из них.

Ордер – это торговый приказ на продажу или покупку. Ордер представляет из себя вполне определенную сущность, включающую в себя помимо основной информации, такой как уникальный идентификатор или номер ордера, требуемая цена и условие открытия, еще и множество других информационных "полей".

Одно из таких полей в MetaTrader 5  называется "Order Magic" - это специальное поле, служащее для того, чтобы торговый робот или эксперт мог пометить этот ордер своим индивидуальным и уникальным номером (его еще называют магическим номером эксперта). Это поле не используется при ручной торговле, однако оно очень важно для торговых алгоритмов, потому что анализируя его значения, торговый алгоритм всегда может узнать, был ли выставлен этот ордер им лично или кем-то другим.

Предположим, нам нужно открыть классическую длинную позицию, а затем, через некоторое время, закрыть ее. Для этого нам необходимо выставить два ордера: первый ордер откроет эту позицию, а второй ордер закроет ее через некоторое время:

Рис. 2. Ордера, образующие историческую нетто-позицию

Рис. 2. Ордера, образующие историческую нетто-позицию

Но что если в поле "Order Magic" второго ордера в момент его отправки на рынок записать уникальный номер первого ордера?

Позже мы сможем прочесть это поле у ордера и если его значение будет равно номеру первого ордера, то мы сможем однозначно сказать, что второй ордер относится к первому "ордеру" и является противоположенным ему ордером на закрытие позиции.

Вот как выглядело бы это связывание на условной схеме:

Рис. 3. Связывание ордеров

Рис. 3. Связывание ордеров

Условно такие ордера можно назвать связанными, так как второй ордер содержит ссылку на первый. Первый ордер, открывающий новую позицию, можно назвать инициирующим или открывающим ордером. Второй ордер назовем закрывающим.

Связку из двух таких ордеров назовем позицией. Чтобы не происходило путаницы с понятием "позиции" в MetaTrader 5, будем называть такие связанные позиции разнонаправленными, хеджирующими или позициями HedgeTerminal. Позиции в MetaTrader 5 будем называть netto-позициями или классическими позициями MetaTrader 5.

Очевидно, что количество и направление позиций HedgeTerminal, в отличие от классических позиций, может быть любым. Но что если имеется какой-либо исполненный ордер, на который не ссылается ни один другой ордер? Такой ордер можно представить в виде активной разнонаправленной позиции. В самом деле, если в будущем выставить ордер противоположенного направления, содержащий ссылку на этот ордер, то он станет ордером, который закрывает первый ордер. Такие ордера свяжутся вместе, а разнонаправленная позиция, которую они образуют, станет закрытой, так как объем двух ордеров будет одинаков, а их направление противоположенным.

Итак, дадим определение того, что подразумевает HedgeTerminal под позицией:

Если на исполненный ордер не ссылается ни один другой ордер, то HedgeTerminal считает такой ордер активной разнонаправленной позицией.

Если на исполненный ордер ссылается другой исполненный ордер, то два таких ордера образуют связь между собой и с точки зрения HedgeTerminal являются единой исторической или закрытой разнонаправленной позицией.

В реальности связывание ордеров в HedgeTerminal несколько сложней, потому что каждый ордер как минимум порождает одну сделку, а в условиях биржевой торговли таких сделок может быть множество. В общем, процесс торговли можно представить так: трейдер отправляет через терминал MetaTrader 5 ордер на открытие новой позиции. Биржа исполняет этот ордер с помощью одной или нескольких сделок.

Сделки, точно также как и ордера, содержат поля для дополнительной информации. Одно из таких полей содержит идентификатор ордера, на основании которого была совершена сделка. Прочитав это поле, можно узнать, к какому ордеру относится эта сделка. Но обратное неверно. Сам ордер не знает, какие сделки принадлежат ему. Так происходит потому, что в момент выставления ордера еще не известно, какими именно сделками он будет исполнен и будет ли исполнен вообще.

Таким образом, соблюдается причинность или детерминизм действий. Сделки ссылаются на ордера, а ордера ссылаются друг на друга. Такую структуру можно представить как односвязанный список.

Исполненные сделки открывающего ордера порождают классическую позицию в MetaTrader 5, сделки принадлежащие закрывающему ордеру, напротив, эту позицию закрывают. Полностью эти связи представлены на схеме ниже:

Рис. 4. Схема взаимосвязи ордеров, сделок и биржи

Рис. 4. Схема взаимосвязи ордеров, сделок и биржи

Мы еще вернемся к подробному анализу этой схемы, потому что направление связей в ней крайне важно для построения строго детерминированной системы учета торговых действий трейдера, которой и является HedgeTerminal.


1.3. Взаимосвязь нетто-позиций MetaTrader 5 и позиций HedgeTerminal

С точки зрения HedgeTerminal, два ордера с противоположенным направлением и равным объемом могут быть двумя разными позициями. В этом случае их суммарная нетто-позиция будет нулевой. Поэтому HedgeTerminal никаким образом не использует информацию о фактических нетто-позициях открытых в MetaTrader 5. Поэтому, позиции HedgeTerminal не связаны с позициями MetaTrader 5. Единственный момент, при котором делается проверка текущих нетто-позиций – это момент запуска HedgeTerminal. Суммарные объемы по разнонаправленным активным позициям должны в точности совпадать с величинами фактических нетто-позиций.

Если это не так, то на панели HedgeTerminal появиться предупреждающий значок в виде восклицательного знака в рамке: Позиции не равны, сигнализирующий о том, что позиции HedgeTerminal и позиции MetaTrader 5 не равны. Эта асимметрия никак не сказывается на работоспособности HT, однако для дальнейшей корректной работы ее необходимо устранить.

Большинство случаев, при которой она может возникнуть, это ошибки пользователей в редактировании файла исключенных ордеров ExcludeOrders.xml, однако разрушение истории ордеров и сделок на сервере также могут вызвать появление этого значка. В любом случае, все эти несоответствия устраняются благодаря механизму исключения, реализуемого через файл ExcludeOrders.xml.


1.4. Требования к алгоритмам, реализующим разнонаправленную торговлю

К алгоритмам, реализующим разнонаправленную торговлю, предъявлялись достаточно жесткие требования. При разработке HedgeTerminal они должны были быть выполненными. В противном случае HedgeTerminal быстро бы превратился в программу, которая работала бы время от времени. Программа была бы "еще одним решением, которое при определенных обстоятельствах могло сработать, а могло и нет".

Итак, вот некоторые требования, которые предъявлялись при его разработке:

  1. Представление разнонаправленных позиций трейдеров должно быть надежно. Любая возможность, реализованная в HedgeTerminal не должна приводить к неоднозначности или потенциальным ошибкам бизнес-логики. Если какое-то свойство или возможность не удовлетворяет этим требованиям, такая возможность не может быть использована, несмотря на свое удобство и востребованность;
  2. Все алгоритмы должны максимально базироваться на торговом окружении MetaTrader 5. Хранение дополнительной информации в файлах допускается лишь в крайних и самых необходимых случаях. Подавляющую часть информации алгоритмы виртуализации должны получать из торгового окружения. Благодаря этому свойству повышается общий уровень надежности, большинство изменений в торговом окружении передаются через сервер, а потому доступны глобально и из любой точки мира;
  3. Все действия по трансформации торгового окружения должны выполнятся за кулисами. Не должно требоваться сложной конфигурации или инициализации библиотеки API HedgeTerminal. Пользователь должен запустить приложение "из коробки" и получить ожидаемый результат;
  4. Визуальная панель HedgeTerminal должна максимально органично вписываться в общий интерфейс MetaTrader 5, давая простые и понятные визуальные инструменты работы с разнонаправленными позициями, знакомые всем пользователям MetaTrader четвертой и пятой версии. Иными словами, визуальная панель должна быть интуитивна понятна и проста для всех пользователей;
  5. Визуальная панель HedgeTerminal должна быть спроектирована с учетом высоких требований алготрейдеров. Например, панель должна поддаваться конфигурации, изменению внешнего вида и даже позволять подключать пользовательские модули расширения;
  6. Интуитивно понятный и простой программный интерфейс (API) взаимодействия со сторонними экспертами. Программная часть взаимодействия сторонних экспертов с алгоритмами HedgeTerminal должна максимально органично вписываться в существующий стандарт программного взаимодействия пользовательских экспертов с системными функциями MetaTrader 4/5. Сейчас можно сказать, что API HedgeTerminal напоминает некий гибрид между API MetaTrader 4 и API MetaTrader 5;
  7. HedgeTerminal должен надежно работать в биржевом окружении, учитывая все нюансы исполнения биржевых приказов. HedgeTerminal написан на основе канонической статьи "Основы биржевого ценообразования на примере срочной секции Московской биржи". Первоначально, эта статья была частью одного большого материала о HedgeTerminal, однако в силу слишком большого объема весь материал был разделен на несколько независимых статей. Можно сказать, что HedgeTerminal - программная реализация всех тех тезисов, которые были изложены в той работе.

Многие из этих пунктов плохо увязываются друг с другом. Например, обилие биржевой информации, которую необходимо отобразить при биржевой торговле, плохо увязывается с простотой представления этой информации.

Также сложно было создать панель, которая, с одной стороны, была бы понятна для новичков, а с другой стороны, могла бы предложить ощутимые возможности профессиональным алготрейдерам. Тем не менее, анализируя результат проделанной работы, можно с уверенностью сказать, что совместить эти взаимоисключающие свойства все же удалось.


Глава 2. Установка HedgeTerminal, первый запуск

2.1. Установка HedgeTerminal

Итак, мы уже знаем, что все исполненные ордера HedgeTerminal рассматривает как позиции. Позиции могут состоять из двух связанных между собой ордеров, и тогда они образуют закрытую историческую позицию, либо ордер будет не связан с другим ордером, и тогда такой ордер будет открытой или активной позицией.

Если на торговом счете до установки HedgeTerminal совершались какие-либо действия, и история торгов содержит множество исполненных ордеров, то с точки зрения HedgeTermianl все эти ордера будут открытыми позициями, ведь ссылки между ними не были созданы. Не страшно, если история счета содержит 2-3 исполненных ордера. Но если их тысячи, HedgeTerminal образует тысячи открытых позиций. Что с ними делать? Можно конечно "закрыть" эти ордера, выставив уже через HedgeTerminal на биржу противоположенные им ордера содержащие ссылки на инициирующие ордера, но если их к моменту установки HT будет слишком много, это может разорить трейдера, ведь потребуется платить комиссионные брокеру и нести издержки от проскальзывания.

Чтобы этого не происходило, HedgeTerminal запускает перед своей установкой специальный мастер установки, в котором предлагает варианты решений этой проблемы. Давайте и мы запустим HedgeTerminal, вызовем этот мастер, и подробно опишем его работу. Для этого скачаем и установим HedgeTerminalDemo из магазина приложений MetaTrader 5.

Как и HedgeTerminalUltimate, он выполнен в виде эксперта, и для его запуска необходимо просто перетащить его значок, доступный на вкладке "Навигатор", на какой-нибудь свободный график.

После перетаскивания возникнет стандартное окно, предлагающее запустить эксперт на графике:


Рис. 5. Окно эксперта HedgeTerminal перед запуском

На данном этапе достаточно установить флаг "Allow AutoTrading", разрешающий эксперту совершать торговые действия. HedgeTerminal, разумеется, будет руководствоваться только вашими приказами, он не обладает своей собственной торговой логикой, однако для совершения таких действий ему все равно потребуется такое разрешение.

Чтобы любой эксперт начал торговать, помимо личного разрешения на торговлю в MetaTrader 5 на панели должно быть включено общее разрешение на торговлю экспертами:

Рис. 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: "You can hide them in HedgeTerminal... To hide these orders, click 'YES' and go into the next step". Если вы выберете этот вариант и нажмете "YES", HedgeTerminal занесет их в специальный список, и в дальнейшем не будет учитывать их вклад в совокупную нетто-позицию, а также их финансовый результат. Однако занести эти ордера в список он сможет лишь в том случае, если в текущий момент времени у вас нет ни одной открытой нетто-позиции. Если у вас уже есть открытая позиция по одному или нескольким инструментам, HedgeTerminal вызовет дополнительный диалог, предлагающий закрыть существующие позиции.
  2. Оставить ордера как есть, и при желании закрыть их позже: "You can… close manually later... Click 'No' if you want close these orders manually later. In this case, you have to perform 5 trades of opposite direction". В этом случае, если вы нажмете кнопку "No", после запуска HedgeTerminal отобразит все эти ордера в виде активных позиций на своей вкладке "Active" (активные позиции). В дальнейшем эти ордера вы сможете закрыть другим ордером через панель HedgeTerminal, после чего они превратятся в закрытые позиции и перенесутся на вкладку "History" (исторические позиции). Но если таких ордеров слишком много, лучше скрыть их отображение, чем заново перезакрывать все исполненные ордера, платя комиссионные.
  3. Прервать установку: "If you are not ready continue press Cancel. In this case HedgeTerminal complete its work". Если вы выберете этот вариант и нажмете "Отмена", HedgeTerminal завершит свою работу.

Если активных позиций к моменту установки HedgeTerminal не будет, установка на этом этапе завершиться.

В случае, если вы выбрали второй вариант, и в текущий момент времени у вас имеется одна или несколько открытых позиций, HedgeTerminal вызовет дополнительный диалог, предлагающий закрыть их:


Рис. 10. Диалог, предлагающий закрыть нетто-позиции автоматически

HedgeTerminal требует закрыть все существующие позиции, т.к. ему необходимо занести все исполненные ордера в список исключенных ордеров. Если нетто-позиций не будет, то любой следующий ордер инициализирует новую нетто-позицию, направление и объем в этом случае совпадут с представлением HedgeTerminal и рассинхронизации нетто-позиций с суммой позиций HedgeTerminal не будет.

HedgeTerminal может автоматически закрыть все нетто-позиции за вас: "The HedgeTerminal can automatically close all active positions". Если вас это устроит, нажмите "OK". В этом случае он попытается закрыть позиции, и в случае успеха завершит свою работу. Если позиции по каким-то причинам ему не удастся закрыть, он перейдет к диалогу ручного закрытия позиций. Если вы выберете ручной вариант закрытия: "Click 'Cancel' if you want to close a position manually", нажмите "Cancel".

Диалог ручного закрытия позиций вызывается в случае выбора соответствующего типа закрытия в предыдущем диалоговом окне, либо в случае невозможности автоматического закрытия позиций:


Рис. 11. Диалог, предлагающий закрыть нетто-позиции вручную

На этом месте необходимо вручную закрыть все активные позиции через MetaTrader 5, либо прервать установку, нажав кнопку "Cancel". После того как все позиции будут закрыты, нажмите "Retry".


2.2. Установка в три шага. Схема установки и решение возможных проблем

Если предельно упростить весь процесс установки, то его можно свести к 3 шагам:

  1. Перед установкой HedgeTerminal закрыть все существующие активные нетто-позиции в терминале MetaTrader 5;
  2. Запустить HedgeTerminal на графике и нажать кнопку "Да" в появившемся окне мастера установки, предлагающим начать установку. HedgeTerminal в этом случае выполнит установку всех необходимых для его работы файлов;
  3. В следующем окне, если оно появиться, выбрать второй вариант и нажать кнопку "Да". В этом случае активные позиции при запуске HedgeTerminal не появятся, а информация о ранее заключенных ордерах перенесется в файл ExcludeOrders.xml автоматически, так как активных позиций, требующих закрытия, не будет.

Если установку представить еще проще, то все что нужно, это перед запуском HT закрыть все позиции, а затем нажать два раза кнопку "Да" в мастере установки HedgeTerminal.

Полная схема мастера установки представлена на графике ниже. Она поможет сориентироваться с ответами на вопросы и правильно выполнить установку:


Рис. 12. Схема мастера установки

Что делать, если установка была выполнена неверно, или требуется удалить HT с компьютера? В случае, если установка была выполнена неверно, просто удалите все установленные файлы. Для этого перейдите в папку, в которой программы для MetaTrader хранят общую для всех информацию (как правило, она находится по адресу: c:\Users\<ваше_имя_пользователя>\AppData\Roaming\MetaQuotes\Terminal\Common\Files\). Если вы хотите удалить информацию об установке HedgeTerminal полностью со всех счетов, то найдите в этой директории папку с названием "HedgeTerminal" и удалите ее. Если вы хотите удалить информацию об установке HedgeTerminal только для конкретного определенного счета, перейдите в директорию \HedgeTerminal\Brokers и выберите папку, в названии которой присутствует название вашего брокера и номер счета в формате "Название брокера – номер счета". Удалите эту папку. В следующий раз мастер установки запустится вновь при запуске HedgeTerminal на этом счете.

Установка на терминал, подключенный к счету с уже работающим с HedgeTerminal. Может возникнуть ситуация, когда потребуется установить HT на терминал, подключенный к счету, на котором уже работает HT. Как вы уже знаете, процесс установки заключается в создании и конфигурировании служебных файлов. Если эти файлы уже созданы на другом компьютере и должным образом сконфигурированы, то устанавливать HedgeTerminal не надо. Эти файлы, как правило, хранятся по адресу c:\Users\<ваше_имя_пользователя>\AppData\Roaming\MetaQuotes\Terminal\Common\Files\HedgeTerminal. Просто перенесите эту папку в аналогичное место на своем компьютере. После копировании директории запустите HedgeTerminal вновь. Мастер установки не вызовется, ведь все файлы присутствуют и сконфигурированы. Отображение активных позиций в этом случае будет идентичным с отображением на других терминалах и компьютерах.

Установка HedgeTerminalAPI и использование библиотеки в режиме тестирования. HedgeTerminal реализован как в виде визуальной панели, так и в виде библиотеки программных функций – HedgeTerminalAPI. Библиотека содержит аналогичный мастер установки, вызываемый при первом запуске HedgeTerminalAPI в реальном режиме времени. Установка файлов при использовании библиотеки аналогично. При первом вызове любой функции из эксперта появиться соответствующее окно MessageBox, предлагающее начать установку. В этом случае от пользователя требуются аналогичные действия: закрыть перед вызовом HedgeTerminalAPI все позиции и выполнить установку в три шага.

При запуске библиотеки в режиме тестирования установка HedgeTerminal не требуется. Так как в режиме тестирования эксперт каждый раз начинает работать с новым виртуальным счетом, то в скрытии ранее исполненных ордеров и установки файлов нет необходимости. Настройки, которые хранятся в файле Settings.xml, в библиотеке могут задаваться программно через вызов соответствующих функций.


2.3. Знакомство с HedgeTerminal, первый запуск

После того как HedgeTerminal произвел установку всех необходимых для его работы файлов, он запуститься на графике, отобразив свою панель:

Рис. 13. Первый запуск HedgeTerminal, внешний вид

Рис. 13. Первый запуск HedgeTerminal, внешний вид

Так как все существующие ордера скрыты, то активных позиций, которые он будет отображать, не будет. Верхняя панель содержит кнопку меню HT, располагающуюся слева и специальные значки, показывающие состояние панели. Опишем подробней значки:

Теперь, когда HedgeTerminal запущен и готов к работе, совершим несколько торговых действий и посмотрим, как он отобразит их. Если HedgeTerminal запущен на Forex, совершать торговые действия необходимо на инструменте AUDCAD. К текущему моменту у нас не должно быть открыто никаких нетто-позиций, ведь установка HedgeTerminal могла быть завершена удачно только в этом случае. Если это по каким-то причинам не так, закройте все активные позиции.

Если HT запущен на счете, подключенном к Московской бирже, совершать торговые действия необходимо на одном из фьючерсов группы VTBR*, например VTBR-13.15 или VTBR-06.15. В качестве примера, купим на forex через стандартное окно "NewOrder" 0.4 лота AUDCAD по текущей цене. Через несколько мгновений в истории ордеров терминала в режиме "Ордера и сделки" отобразиться ордер и сделка по нему:

Рис. 14. Исторический ордер и его сделка в MetaTrader 5

Рис. 14. Исторический ордер и его сделка в MetaTrader 5

Вкладка активных позиций будет содержать соответствующую длинную позицию объемом 0.4 лота:

Рис. 15. Активная нетто-позиция в MetaTrader 5

Рис. 15. Активная нетто-позиция в MetaTrader 5

В это же время HedgeTerminal представит исторический ордер в виде активной позиции:

Рис. 16. Активная разнонаправленная позиция в HedgeTerminal и ее сделка

Рис. 16. Активная разнонаправленная позиция в HedgeTerminal и ее сделка

Как видно, результаты идентичные, ведь одна позиция HT соответствует 1 нетто-позиции в MetaTrader 5.

Обратите внимание, что позиция в HT, помимо самого ордера, содержит и сделку, которая эту позицию выполнила (чтобы ее увидеть, необходимо развернуть строку позиции, нажав значок )

У активной позиции можно закрыть ее часть. Для этого достаточно ввести в поле "Vol." (Volume) новое значение объема. Новый объем должен быть меньше текущего. Разницу между текущим и новым объемом закроет новый ордер, который образует историческую позицию и перейдет на соответствующую вкладку исторических позиций. Введем в это поле значение 0.2 и нажмем Enter, через некоторое время объем активной позиции станет 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. Напомню, что для этого достаточно открыть диалоговое окно "новый ордер" и выставить соответствующую заявку по рынку. После того как новая позиция будет открыта, давайте залокируем ее противоположной позицией – продадим 0.2 лота через терминал MetaTrader 5.

На этот раз результат торговли в HedgeTerminal и в окне терминала MetaTrader 5 будет разный. HT отобразит две позиции:

Рис. 19. Противоположенные разнонаправленные позиции в HedgeTerminal (лок)

Рис. 19. Противоположенные разнонаправленные позиции в HedgeTerminal (лок)

В то время как в MetaTrader 5 их не будет вовсе:

Рис. 20. Отсутствие активной нетто-позиции в MetaTrader 5

Рис. 20. Отсутствие активной нетто-позиции в MetaTrader 5

Проанализируем получившиеся результаты. Мы совершили 4 сделки, они выделены красной рамкой на скриншоте ниже:

Рис. 21. Результат совершенных сделок в MetaTrader 5

Рис. 21. Результат совершенных сделок в MetaTrader 5

Запишем эти сделки в виде таблицы:

ТипНаправлениеЦенаОбъемПрибыль, пипсов
buy   in0,980880,2
sell   out0,980890,21
buy   in0,982070,2
sell   out0,982080,21

Таблица 1. Отображение сделок в терминале MetaTrader 5

Видно, что на 4 сделках было заработано 2 пункта. Стоимость каждого пункта приблизительно равна 0,887 доллара при торговле 1 лотом, таким образом, финансовый результат составил 0.18 доллара на позицию (0,887*0,2*1) или 34 цента на обе позиции. Колонка "Profit" показывает, что наш расчет верный. В сумме мы имеем 34 цента чистой прибыли.

Теперь посмотрим на результаты позиций в HedgeTerminal:

 Рис. 22. Результат исторических разнонаправленных позиций в HedgeTerminal

Рис. 22. Результат исторических разнонаправленных позиций в HedgeTerminal

На первый взгляд, они существенно различаются. Однако давайте посчитаем результат двух наших разнонаправленных позиций:

НаправлениеЦена входаЦена выходаПрибыль, пипсовПрибыль, $
buy0,980880,982080.0012021,28
sell0,980890,98207-0.00118-20,92

Таблица 2. Отображение позиций в HedgeTerminal

Видно, что разница между ними составила 0.34$ (21,28$ - 20,92$) что в точности соответствует полученному результату при нетто-торговле.


2.5. Торговля в один клик

В HedgeTerminal используется особенная система управления. Она базируется на прямом вводе требуемых значений прямо в строку активной позиции. Альтернативного управления нет.

Например, чтобы выставить Stop-Loss для активной позиции достаточно в поле S/L ввести необходимый уровень стоп-лосса и нажать клавишу Enter:

Рис. 23. Ввод уровня StopLoss прямо в таблицу

Рис. 23. Ввод уровня StopLoss прямо в таблицу

Аналогично можно изменить объем, поставить или поменять уровень TakeProfit, изменить исходящий комментарий.

В целом строка позиции HedgeTerminal напоминает представление позиций в MetaTrader 4/5. Колонки таблицы позиций имеют идентичные названия и значения, используемые в самих терминалах MetaTrader. Но и имеются и различия. Так, позиция HedgeTerminal имеет целых два комментария, а не один, как принято в MetaTrader. Это следует из того, что позицию в HedgeTerminal образуют два ордера, у каждого из которых есть свое поле для комментария. Так как HedgeTerminal не использует эти комментарии для хранения технической информации, то возможно создать позицию с открывающим и закрывающим комментарием.

В HedgeTerminal возможно подключить колонки, которые не отображаются по умолчанию. Например, можно подключить колонку, отображающую имя эксперта, которому принадлежит позиция. О том, как это сделать, будет написано в разделе, посвященном конфигурированию файла Settings.xml.


2.6. Установка StopLoss и TakeProfit, трейлинг стоп

HedgeTerminal позволяет закрывать позиции по уровням защитных остановок (stop-loss) и взятия прибыли (take-profit).

Чтобы посмотреть, как это происходит, введем уровни stop-loss и take-profit прямо в активную позицию, а затем дождемся, пока один из этих уровней не сработает. В нашем примере сработал уровень take-profit. Он закрыл позицию и перенес ее в список исторических транзакций:

Рис. 24. Историческая разнонаправленная позиция и ее StopLoss и TakeProfit уровни

Рис. 24. Историческая разнонаправленная позиция и ее StopLoss и TakeProfit уровни

Зеленая метка в поле T/P сигнализирует о том, что сработал take-profit и позиция была закрыта по этому уровню. Помимо уровня take-profit, позиция содержит информацию об уровне stop-loss, который также использовался, когда позиция была активна. Аналогично, если бы сработал уровень стопа, ячейка S/L с его уровнем была бы помечена розовым цветом, а T/P в этом случае был бы не окрашен.

HedgeTerminal поддерживает трейлинг стоп, а в будущих версиях появится возможность даже написать специальный пользовательский модуль, содержащий логику переноса стопа. Однако сейчас работа  трелинг-стопом в HedgeTerminal отличается от логики работы аналогичного стопа в самом терминале MetaTrader. Для того чтобы его включить, необходимо вначале ввести уровень stop-loss в ячейку S/L соответствующей позиции. Когда стоп-лосс будет выставлен, можно будет поставить флаг следования за ценой в графе, помеченной значком :

Рис. 25. Установка трейлинг стопа в форме HedgeTerminal

Рис. 25. Установка трейлинг стопа в форме HedgeTerminal

После того как флаг будет выставлен, HedgeTerminal зафиксирует расстояние между текущей ценой и stop-loss уровнем, и если оно увеличится, передвинет стоп-лосс вслед за ценой, так, чтобы это расстояние оставалось прежним. Функция трейлинг-стопа работает только при запущенном HedgeTerminal и при выходе из него сбрасывается.

В HedgeTerminal stop-loss реализуется с помощью ордеров BuyStop и SellStop. Всякий раз при установке этого уровня выставляется соответствующий ордер, чей магический номер связан с активной позицией. Если удалить этот отложенный ордер в самом терминале MetaTrader, то уровень S/L в HedgeTerminal просто исчезнет. Изменение цены отложенного ордера также вызовет изменение цены защитной остановки в HedgeTerminal.

TakeProfit работает несколько иначе. Он является виртуальным и скрывает свой уровень срабатывания от брокера. Это означает, что HedgeTerminal закрывает позицию по TakeProfit самостоятельно. Поэтому, если вы хотите чтобы ваш Take-Profit сработал, вам необходимо держать HedgeTerminal в рабочем состоянии.


2.7. Генерация отчетности

HedgeTerminal позволяет сохранять информацию о своих разнонаправленных позициях в специальные файлы, которые можно загружать в сторонние статистические программы анализа, например, в Microsoft Excel.

Сейчас, когда HT не обладает своей системой анализа и сбора статистики, такая возможность особенно важна. В настоящий момент поддерживается только один формат сохранения отчета - CSV (Comma-Separated Values). Разберемся, как он работает. Чтобы сохранить все разнонаправленные позиции в CSV файле, достаточно после запуска HT выбрать в его меню опцию "Save CSV Report":


Рис. 26. Сохранение отчета через меню "Save CSV Report"

После нажатия на этот пункт меню, HT сгенерирует два специальных файла в формате CSV. Один из них будет содержать информацию о активных позициях, другой – о исторических, завершенных позициях. Генерируются два разных файла по той причине, что каждый из них имеет разный набор колонок. К тому же, количество активных позиций может постоянно меняться, поэтому удобней анализировать их раздельно. Сгенерированные файлы доступны по относительному пути .\HedgeTerminal\Brokers\<Название брокера – номер счета> \. Получившихся файлов должно быть два: History.csv и Active.csv. Первый содержит информацию об исторических позициях, а второй – об активных позициях.

Файлы можно загрузить в статистические программы анализа. Разберем эту процедуру на примере Microsoft Excel. Запустим эту программу, в ее окне выберем "Данные" --> "Из текста". В появившемся мастере экспорта данных выберем режим с разделителями. В следующем окне в качестве разделителя выберем точку с запятой. Нажмем кнопку "далее". В следующем окне изменим общий формат представления чисел с плавающей запятой, для чего нажмем кнопку "Подробнее". В появившемся окне выберем разделитель целой и дробной части в виде точки:

Рис. 27. Экспорт CSV отчета в программу Microsoft Excel

Рис. 27. Экспорт CSV отчета в программу Microsoft Excel

Нажмем "ОК", а затем кнопку "Готово". В появившейся таблице у нас будет информация об активных позициях:

Рис. 28. Информация об активных позиция экспортированная в Excel

Рис. 28. Информация об активных позициях, экспортированная в Excel

Аналогичным образом на следующий лист можно загрузить данные об исторических позициях. Количество колонок будет соответствовать фактическому количеству колонок в HT. Если на панели в HT убрать одну из колонок, она не попадет в отчет. Это удобный способ формировать отчет только из тех данных, которые нужны пользователю.

В следующих версиях появится возможность сохранять отчет в форматах XML и HTML. При этом отчет, сохраненный в HTML, будет напоминать по своей структуре стандартный HTML-отчет в MetaTrader 5, хотя он будет полностью состоять из завершенных разнонаправленных позиций.


2.8. Представление валютных свопов

Валютный своп – это комбинация двух противоположенных конверсионных сделок на одинаковую сумму с разными датами валютирования.

Проще говоря, своп – производная операция по начислению разницы процентных ставок, уплаченных за удержание двух валют, образующих нетто-позицию.

В MetaTrader 5 нет истории нетто-позиций, вместо нее есть исторические ордера и сделки, которые образовывали и закрывали исторические нетто-позиции. Поскольку исторических позиций нет, своп приписывается к ордеру, закрывающему историческую позицию:

 Рис. 29. Валютный своп как независимая транзакция

Рис. 29. Валютный своп как независимая транзакция

Однако, более правильным было бы представлять своп отдельной производной операцией, образующейся в результате пролонгации нетто-позиции.

В текущей версии HedgeTerminal представление свопов не поддерживается, однако в следующих версиях такая поддержка появится. В нем своп будет представлен на вкладке исторических позиций как отдельная историческая транзакция. Идентификатор свопа будет соответствовать идентификатору нетто-позиции, на которую он был начислен. Также своп будет включать название валютной пары и свой финансовый результат.


2.9. Итоговая строка

Как и MetaTrader, в таблице сделок HedgeTerminal отображает итоговую строку с общими характеристиками для всего счета. Для таблицы активных и исторических позиций эти характеристики и их значения перечислены ниже:

Для корректного отображения итоговой строки требуется установить в систему дополнительный шрифт "Arial Rounded MT Bold".


2.10. Изменение внешнего вида таблиц HedgeTerminal

Как уже ранее писалось, HedgeTerminal имеет только один явный параметр в окне запуска советника - это имя файла настроек. Так сделано потому, что настройки HedgeTerminal не представляется возможным разместить в окне настроек эксперта. Их много и они слишком специфичны для такого окна. Поэтому все настройки вынесены в специальный конфигурационный файл 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> и рассмотрим ее структуру. По сути, этот раздел содержит два набора колонок: один для таблицы активных позиций на вкладке "Active", а другой для таблицы исторических позиций, размещенной на вкладке "History". Каждая колонка в одном из наборов имеет следующий вид:

<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 пикселям.

Если ширина окна вашего монитора выше, то и фактический размер колонки будет выше. Чтобы посмотреть, как работает пропорциональное масштабирование, давайте поставим ширину колонки Symbol в 240 условных пикселей: Width="240", после чего сохраним файл и перезапустим панель:

Рис. 32. Ширина колонки Symbol установлена в 240 пикселей.

Рис. 32. Ширина колонки "Symbol" установлена в 240 пикселей.

Видно, что ширина колонки символов стала значительно больше. Однако чудес не бывает и ее ширина была получена за счет более компактного размещения других колонок ("Entry ID"  и "Entry Date").

Другие колонки стали выглядеть хуже, последние значения уже не вмешаются в отведенную для них ширину и срезаются. Поэтому изменять размер колонок необходимо с осторожностью, тонко настраивая размер каждой из них. Стандартные настройки содержат выверенные значения для большинства мониторов, поэтому, как правило, изменять их размер на какой-либо другой не требуется.

Удаление колонок. Помимо изменения размера колонок и их заголовков, можно добавлять или удалять сами колонки. Например, опробуем удалить колонку "Symbol" из списка. Для этого просто закомментируем тэг этой колонки в файле Settings.xml (выделен желтым маркером):

<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"/>

Комментарием в xml служит специальный тег <!-- содержимое_комментария -->, внутри которого должна располагаться закомментированная колонка. После сохранения изменений в файле и перезапуска HedgeTerminal, его набор колонок для исторических позиций изменится, теперь он не будет содержать колонку, отображающую символ инструмента:

Рис. 33. Удаление колонки Symbol из таблицы активных позиций

Рис. 33. Удаление колонки "Symbol" из таблицы активных позиций

Удалить можно сразу несколько колонок.

Давайте закомментируем все колонки, кроме названия символа и размера прибыли, а затем перезапустим HedgeTerminal на графике:

Рис. 34. Удаление основных колонок из панели HedgeTerminal

Рис. 34. Удаление основных колонок из панели HedgeTerminal

Как видно, таблица HedgeTerminal заметно сократилась. Но с удалением колонок нужно быть осторожным, ведь в некоторые из колонок встроены элементы управления позицией, например, в нашем примере удалилась колонка, позволяющая разворачивать позиции и смотреть их сделки. Можно даже удалить колонку "Profit" из таблицы активных позиций. Но эта колонка содержит кнопку закрытия позиции. В этом случае закрыть позицию уже не получится, ведь кнопки закрытия не будет.

Добавление колонок и отображение псеводнимов экспертов. Можно не только удалять колонки путем редактирования, но и добавлять новые, если HedgeTerminal запрограммирован для работы с ними. В будущем можно будет создавать свои колонки и рассчитывать в них свои показатели. Такие колонки можно будет подключить через интерфейс внешнего индикатора iCustom и манифест взаимодействия с модулями расширения, написанный также на xml.

Сейчас такой возможности нет и приходится довольствоваться только колонками, поддерживаемыми HedgeTerminal. Единственная колонка, которая поддерживается панелью, но не отображается в настройках по умолчанию, это колонка, отображающая магический номер эксперта.

Позиция может быть открыта не только вручную, но и с помощью робота. В этом случае для каждой позиции можно отображать также и идентификатор робота, который ее выставил. Тэг колонки, включающий отображение номера эксперта, уже присутствует в файле настроек в закомментируемом виде, давайте раскомментируем его:

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

Сохраним изменения и перезапустим панель:

Рис. 35. Добавление колонки Magic в таблицу HedgeTerminal

Рис. 35. Добавление колонки "Magic" в таблицу HedgeTerminal

На рисунке выше видно, что появилась новая колонка с название "Magic", она содержит идентификатор эксперта, открывшего позицию. Позиция открыта вручную, поэтому идентификатор равен нулю. Позиция, открытая роботом, будет, как правило, содержать идентификатор, отличный от нуля. В этом случае в колонке отобразиться соответствующий магический номер эксперта.

Но гораздо удобней видеть имена экспертов, а не их номера. HedgeTerminal поддерживает такую функцию. Он берет псевдонимы (имена) экспертов, взятых из файла ExpertAliases.xml и отображает их вместо соответсвующих им магических номеров.

Например, если у вас есть эксперт с названием "ExPro 1.1" , торгующий под магическим номером 123847, достаточно в файле ExpertsAliases.xml в секции <Expert-Aliases> разместить следующий тэг:

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

Теперь, кода ваш робот откроет новую позицию, она будет помечена его именем:

Рис. 36. Отображение имени эксперта в колонке Magic

Рис. 36. Отображение имени эксперта в колонке "Magic"

Количество роботов и их псевдонимов не ограничено. Главное, чтобы все их номера различались.

Прочие настройки HedgeTerminal. Мы описали все настройки визуальной панели, доступные на текущий момент. Следующая секция <Other-Settings> содержит настройки, определяющие внутреннюю работу терминала. Необходимо заметить, что библиотека программных вызовов HedgeTerminalAPI использует эти настройки как значения по умолчанию. Однако эксперт может изменить текущие значения этих настроек с помощью специальных Set... функций. Чтобы получить значения этих настроек, эксперту достаточно вызвать специальные Get... функции. Опишем теги с настройками более подробно.

<Deviation Value="30"/>

Содержит величину предельного отклонения от запрашиваемой цены в единицах минимального изменения цены. Так, для пары EURUSD, котирующейся до пятого знака после запятой, это будет 0,0003 пункта. Для фьючерса на индекс РТС эта величина составит 300 пунктов, т.к. минимальный шаг изменения цены для него равен 10 пунктам. Если отклонение цены будет больше, команда на закрытие или изменение цены не выполнится. Это сделано для защиты от неблагоприятного проскальзывания.

<Timeout Seconds="180"/>

Этот тег содержит величину предельного ожидания ответа от сервера. Дело в том, что HedgeTerminal работает в асинхронном режиме. Это значит, что при отправке торгового приказа на сервер HedgeTerminal не дожидается ответа на него. Вместо этого HedgeTerminal контролирует приход событий, указывающих на то, что приказ прошел успешно. Событие может и не прийти вовсе. Поэтому важно задать лимит ожидания, в течении которого HT будет ждать ответа от сервера. Если в течении этого времени ответ так и не придет, выполняемая задача будет снята, HedgeTerminal разблокирует позицию и продолжит свою работу.

Предельное время ожидания можно сократить или увеличить по желанию. По умолчанию оно равно 180 секундам.

Важно понимать, что в процессе реальной торговли это ограничение практически никогда не будет достигнуто. Ответы на торговые приказы приходят быстро, большинство из них исполняются в пределах 150 – 200 миллисекунд.

Подробнее о том как работает HedgeTerminal, и о том, какие особенности существуют при работе в асинхронном режиме, написано в третьем разделе статьи: "Под капотом у HedgeTerminal".

<RefreshRates Milliseconds="200"/>

Этот тэг настраивает частоту обновления панели. Он содержит время в миллисекундах между двумя последовательными обновлениями панели. Чем меньше время, тем выше частота обновления панели, и тем больше требуется ресурсов для центрального процессора. Поэтому, если у вас не очень мощный процессор, и он не справляется с частотой обновления в 200 миллисекунд (это значение выставлено по умолчанию), вы можете увеличить его до 500 и даже 1000 миллисекунд, отредактировав этот тэг.

В этом случае загруженность ЦП резко уменьшится. Ставить значения меньше 100 миллисекунд не рекомендуется. С увеличением частоты обновления загрузка ЦП будет возрастать нелинейно. Однакоь важно понимать, что частота обновления определяет дискретность терминала. Некоторые его действия подчиняются этому таймеру и происходят только с определенной скоростью.


2.11. Нереализованные возможности в будущих версиях

HedgeTerminal обладает гибкой и расширяемой архитектурой, благодаря которой становится возможным появление новых нетривиальных возможностей в этой программе. Сейчас эти возможности не реализованы, однако они могут быть созданы в будущем, если будут востребованы. Перечислим основные из них:

Использование цветовых схем или скинов. HedgeTerminal использует свой собственный графический движок, в основе которого лежат графические примитивы наподобие прямоугольной метки или обычного текста. Графика на основе картинок не используется вовсе. Благодаря этому становится возможным менять цвет, размер, шрифт для всех отображаемых в HedgeTerminal элементов. Таким образом, не представляет затруднения создать описание шрифтов и цветовой схемы в виде скина и загружать его при запуске HedgeTerminal, меняя его внешний вид.

Подключение пользовательских модулей трейлинг стопа. Каждый эксперт, чем по сути и является HedgeTerminal, может вызывать расчет произвольного индикатора через специальный программный интерфейс (функцию iCustom()). Она позволяет вызывать расчет индикатора, который зависит от набора произвольных параметров. Трейлинг стоп - это некий алгоритм, который в зависимости от текущей цены устанавливает новый или сохраняет прежний ценовой уровень защитной остановки. Этот алгоритм и его ценовые уровни могут быть реализованы в виде индикатора. Если прийти к соглашению о передаваемых ему параметрах, HedgeTerminal может вызвать такой индикатор, и с его помощью рассчитать требуемый ценовой уровень. Всю механику по переносу стопа HT возьмет на себя. Таким образом, любой пользователь HedgeTerminal сможет написать свой (даже самый необычный) модуль управления трейлинг стопом.

Подключение новых, в т.ч. пользовательских колонок для таблицы позиций. Таблицы HedgeTerminal спроектированы таким образом, что позволяют добавлять в себя новые колонки. Поддержку новых колонок можно внедрять программно внутри самого HedgeTerminal, а можно с использованием уже знакомого механизма, реализуемого через интерфейс iCustom(). Так как каждая ячейка в строке позиции представляет какой-то параметр (например цену открытия или уровень тейк-профит), то этот параметр можно рассчитать через индикатор, а значит, можно написать неограниченное количество индикаторов, каждый из которых рассчитывал бы какой-либо параметр для позиции. Если согласовать передачу параметров для таких индикаторов, в HedgeTerminal становится возможным внедрять в таблицу неограниченное количество пользовательских колонок.

Подключение модулей расширения. Через механизм вызова кастомных индикаторов можно подключать и другие расчетные алгоритмы. Например, система отчетности включает в себя массу расчетных показателей, таких как математическое ожидание или коэффициент Шарпа. Многие из этих показателей можно получить вынеся их расчетный блок в кастомный пользовательский индикатор.

Копировщик сделок, прием и трансляция сделок с других счетов. HedgeTerminal по своей сути является менеджером по управлению позициями. На его основе можно с легкостью создать копировщик сделок, т.к. основной функционал уже реализован. Такой копировщик сделок будет обладать нетривиальными возможностями копирования разнонаправленных позиций MetaTrader 4 в терминал MetaTrader 5. С его помощью эти позиции будут представлены также как и в MetaTrader 4 – разнонаправленными с возможностью индивидуального управления каждой из позиций.

Отчетность и статистика. График Equity и вкладка “Summary". Благодаря подсчету разнонаправленных позиций становится возможным анализировать вклад в общий результат каждой отдельной стратегии или трейдера. Наряду с общим расчетом статистики, можно проводить портфельный анализ. Этот отчет может существенно отличаться от отчетности в MetaTrader 5 и дополнять его. В отчетность, размещенную на вкладке Summary, помимо общепринятых параметров, таких как математическое ожидание, максимальная просадка, профит фактор и т.д., будут входить и другие параметры, имена и значения которых могут быть получены в т.ч. из пользовательских модулей расширения. Вместо привычного графика баланса в виде картинки, можно будет использовать график Equity, изображенный в виде пользовательского свечного биржевого графика.

Сортировка столбцов. Как правило, при нажатии на заголовок таблицы происходит сортировка строк по возрастанию или убыванию (повторное нажатие). В текущей версии HedgeTerminal эта опция не поддерживается, т.к. сортировка взаимосвязана с фильтром сделок и пользовательским набором колонок, которых сейчас нет. Однако в будущих версиях такая опция появится.

Отправка торгового отчета по е-мейл, ftp. Push-уведомления. HedgeTerminal может использовать системные функции по отправки электронных писем, файлов ftp и даже push-уведомлений. Например, он может формировать html-отчет раз в сутки и высылать его списку указанных пользователей. Поскольку HedgeTerminal является менеджером экспертов и все торговые действия других экспертов ему известны, он может уведомлять пользователей о торговых действиях этих экспертов. Например, если какой-нибудь эксперт откроет новую позицию, HT может отослать push-уведомление о том, что эксперт с определенным именем совершил вход в новую позицию. HT также укажет направление входа, его дату, время и объем. Сам же эксперт конфигурировать не придется, достаточно просто внести его имя в файл псевдонимов.

Фильтрация позиций с помощью консоли регулярных выражений. Это самое мощное из планируемых нововведений. Оно выведет работу в HT на принципиально другой качественный уровень.  С помощью регулярных выражений можно фильтровать исторические или активные позиции так, чтобы отображались только те из них, которые удовлетворяли бы условиям этого фильтра. Регулярные выражения можно комбинировать и вводить в специальную строку-консоль, над таблицей активных или исторических позиций. Вот как может выглядеть эта консоль в будущих версиях HedgeTerminal:

Рис. 37. Консоль запросов в будущей версии панели HedgeTerminal

Рис. 37. Консоль запросов в будущей версии панели HedgeTerminal

С помощью регулярных выражений можно сформировать невероятно гибкие условия фильтрации позиций с последующим расчетом статистики по ним. Например, чтобы отобразить исторические позиции только по символу AUDCAD, достаточно будет ввести в ячейку консоли выражений "Symbol" значение "AUDCAD". Можно будет и комбинировать условия. Например, отобразить позиции по AUDCAD за период с 01.09.2014 по 01.10.2014, совершенные только конкретным роботом. Для этого достаточно заполнить условия в соответствующих ячейках. После того как фильтр отобразит результаты, отчет размещенный на вкладке "Summary" также измениться, учитывая новые условия фильтра.

Регулярные выражения будут состоять из небольшого количества простых операторов. Однако их совместное использование позволит создавать невероятно гибкие фильтры.

Перечислим операторы, наличие которых в консоли регулярных выражений видится необходимым и достаточным:

Корректировка и управление позициями с помощью специальных команд. Можно вводить дополнительные символы в ячейки, отображающие объем или уровни sl/tp, тем самым применять более сложное управление к своим позициям. Например, чтобы закрыть половину объема текущей позиции можно будет ввести в поле "Volume" соответствующей активной позиции значение "50%".

Вместо того, чтобы устанавливать уровни stop loss и take profit, можно будет ввести в эти ячейки, например, значение "1%". HT автоматически рассчитает уровень защитной остановки или уровень взятия прибыли таким образом, что он будет располагаться от цены входа в 1%. Также можно будет ввести в эти ячейки цифры с постфиксом "p" например "200p" будет означать приказ: "расположить уровни tp/sl в 200 пунктах от цены входа в позицию". В будущем, если ввести знак минус перед объемом в колонке "Volume", объем закроется на величину, указанную после этого знака. Например, если у нас есть позиция объемом 1.0 и мы хотим закрыть часть объема (например, 0.3), то в ячейки объема достаточно будет ввести значение "-0.3".


Глава 3. Под капотом у HedgeTerminal, спецификации и принципы работы

3.1. Понятие глобального и локального контура. Контекст, передача и хранение информации

Внешний вид HedgeTerminal и процесс торговли в нем весьма сильно напоминает хорошо знакомый терминал MetaTrader 4. Это возможно благодаря виртуализации и трансформации представления данных, когда торговая информация, доступная через MetaTrader 5, посредством панели передается в более удобном виде. В этом разделе мы опишем механизмы, благодаря которым становиться возможным создать такую виртуализацию, а также механизмы групповой обработки данных.

Как вам уже известно, HedgeTerminal представлен в нескольких разных продуктах, главных из которых два: это визуальная панель и библиотека с программным интерфейсом. Последняя позволяет внедрять управление разнонаправленными позициями в любой сторонний эксперт, она также интегрирует его в визуальную панель HT. Например, можно прямо из панели закрыть активную позицию эксперта и он узнает об этом, обработав ситуацию должным образом.

Очевидно, что при такой организации требуется групповое взаимодействие между экспертами. Панель (являющаяся экспертом) должна знать о всех торговых действиях, которые совершаются. Верно и обратно, каждый эксперт, использующий библиотеку HT, должен знать о торговых действиях, совершаемых вручную (сторонними программами или с помощью панели HT).

В основном, информация о торговых действиях может быть получена из торгового окружения. Например, если пользователь открыл новую позицию, количество ордеров изменится. Проанализировав последний ордер, можно выяснить, по какому инструменту и каким объемом была открыта позиция. Информация об ордерах и сделках хранится на сервере. Поэтому она доступна для любого терминала, подключенному к торговому счету. Такую информацию можно назвать глобальной, ведь она доступна всем и распространяется через глобальные каналы связи. Взаимодействие с торговым сервером идет в стиле "Запрос - ответ".

Таким образом, такое взаимодействие можно представить в виде глобального контура. "Контур" – понятие из теории графов. Если описать его просто, то это некая замкнутая линия, в которую встраиваются несколько узлов, которые взаимодействуют друг с другом. Возможно, это определение дано неверно, но оставим полемику на эту тему для математиков. Нам важно лишь представить процесс торговли как некоторую замкнутую последовательность действий.

Однако, не всю необходимую информацию для торговли можно передать через глобальный контур. Часть информации не передается, так как MetaTrader 5 не поддерживает такую передачу, и к тому же эта информация не существует в явном виде. Представим процесс торговли последовательно:

  1. Трейдер отдает приказ на покупку.
  2. Через некоторое время приказ исполняется.
  3. Изменяется торговое окружение. В список исторических ордеров попадает соответствующий ордер трейдера. Совокупная позиция по инструменту изменяется.
  4. Трейдер или эксперт детектирует произошедшее изменение торгового окружения и принимает следующее решение.

Между первым и четвертым действием проходит некоторое время. Оно может быть значительным. Если на счете торгует один трейдер, то он знает, какие действия совершает и будет дожидаться соответствующего его действиям ответа от сервера. Но если на счете торгует одновременно несколько трейдеров или экспертов, возможны ошибки в управлении.

Например, второй трейдер, торгующий на этом счете, может попытаться отправить приказ на закрытие еще существующей позиции в момент времени между первым и четвертым шагами. Чувствуете проблему?  В момент исполнения первого приказа будет отправлен второй. Иными словами, приказ на закрытие позиции будет отправлен дважды двумя разными трейдерами.

Такой пример кажется надуманным и маловероятным. Это действительно так, если трейдер торгует на счете самостоятельно и вручную, а также использует синхронные методы отправки приказов. Когда же на счете торгуют сразу несколько роботов, и они выполняют независимые друг от друга торговые операции, возникает существенная вероятность появления подобного рода ошибок.

Поскольку HedgeTerminal - это менеджер позиций, работающий в асинхронном режиме и обеспечивающий одновременную и параллельную работу сразу среди множества экспертов, он становится очень близок к этим ошибкам. Чтобы этого не происходило, HedgeTerminal синхронизирует действия между всеми своими запущенными копиями (будь то библиотека HedgeTerminalAPI или визуальная панель) через механизм локального контура, реализованный в виде многопоточного чтения и изменения файла ActivePositions.xml. Взаимодействие с файлом ActivePositions.xml – это ядро локального контура, важнейшая часть всего терминала HT. Поэтому этот механизм мы опишем подробно.

Если представить упрощенно, работа HedgeTerminal сводится к взаимодействию с локальным и глобальным контуром, примерно так, как написано на схеме ниже:

Рис. 38. Упрощенная схема обмена информацией между глобальным и локальным контуром

Рис. 38. Упрощенная схема обмена информацией между глобальным и локальным контуром

Любое торговое действие (метка start на диаграмме) в HedgeTerminal начинается с записи специального тега в ActivePositions.xml, который устанавливает блокирует изменяемую позицию для дальнейших изменений.

После того как блокировка позиции установлена и локальный контур успешно пройден, HedgeTerminal отправляет торговый приказ на сервер, например, встречный ордер на закрытие позиции. Через некоторое время приказ исполняется и торговое окружение меняется. HedgeTerminal обрабатывает это изменение и детектирует, что глобальный контур пройден успешно и приказ выполнен. Он снимает блокировку с позиции и возвращается в исходное состояние (метка finish на диаграмме).

Может возникнуть ситуация, когда приказ выполнить не удается. В этом случае HedgeTerminal также снимает блокировку с позиции и записывает причину неудачи в лог терминала MetaTrader 5.

В реальности схема передачи информации сложней. Как уже было сказано выше, в одном торговом терминале MetaTrader 5 может быть запущено сразу несколько копий HedgeTerminal. Они могут быть в виде библиотеки или визуальной панели. Каждая из копий может выполнять как роль слушателя, так и роль писателя. Когда HedgeTerminal совершает торговое действие – он писатель, потому что блокирует позицию для изменений с помощью записи специального xml-тега. Все остальные копии HT являются слушателями, потому что они с заданной периодичностью читают файл ActivePositions.xml, и встретив блокирующий тег, также блокируют позицию для изменений.

Этот механизм обеспечивает распространение информации между независимыми потоками. Благодаря нему становится возможной параллельная работа между несколькими панелями и экспертами, использующими библиотеку HedgeTerminalAPI.

Приближенная к реальности схема, показывающая работу HedgeTerminal в условиях многопоточного взаимодействия, показана ниже:

Рис. 39. Приближенная к фактической схема обмена информацией между экземплярами HedgeTerminal

Рис. 39. Приближенная к фактической схема обмена информацией между экземплярами HedgeTerminal

Производительность такой организации данных очень высока. Операции по чтению и записи файла ActivePositions.xml в большинстве случаев занимают менее 1 миллисекунды, в то время как прохождение глобального контура с отправкой и исполнением приказа может занимать 150-200 миллисекунд. Чтобы прочувствовать разность масштабов этих величин, изобразим эти масштабы на схеме.

Ширина зеленого прямоугольника показывает время для прохождения локального контура, а ширина голубого – время на исполнение торгового приказа:

Рис. 40. Масштаб времени между записью в файл и временем, которое необходимо для исполнения приказа

Рис. 40. Масштаб времени между записью в файл и временем, которое необходимо для исполнения приказа

Как видно, зеленый прямоугольник практически сливается в вертикальную линию. В реальности разность масштабов еще больше.

Благодаря быстрым операциям чтения-записи можно организовывать сложный обмен между советниками и создавать распределенные высокочастотные торговые системы.


3.2. Хранение локальной и глобальной информации

Условно всю торговую информацию, которую использует HedgeTerminal, можно разделить на два вида:

К глобальной информации относятся ордера, сделки и информация о счете. Эта информация доступна через специальные системные функции MetaTrader 5, вроде HistoryOrderGetInteger() или AccountInfoInteger(). HedgeTerminal в основном использует именно такую информацию. Благодаря ей HT отображает следующие данные:

Так как эти свойства глобальны, их представление едино для всех экземпляров HedgeTerminal, запущенных даже на разных компьютерах. Например, если закрыть разнонаправленную позицию в одном из терминалов, в другом терминале HedgeTermianal эта позиция также закроется, даже если этот другой терминал был запущен на другом компьютере.

Помимо глобальных данных, HedgeTerminal использует в своей работе локальную информацию. Локальная информация доступна только в пределах одного компьютера. На этой информации базируются следующие свойства HedgeTerminal:

Несработавшие уровни take-profit хранятся в файле HistoryPositions.xml. Вся остальная локальная информация хранится в файле ActivePositions.xml.

Локальное хранение данных означает, что если вы, например, выставите уровень take-profit, то он будет виден только в пределах экземпляров HedgeTerminal, запущенных на вашем компьютере. Никому другому этот уровень не будет известен.


3.3. Стоп-лосс и тейк-профит уровни, проблемы ордерной системы и OCO-ордера

В MetaTrader 5, также как и в MetaTrader 4, есть понятия стоп-лосс и тейк-профит уровней. Это защитные остановки. Как и в MetaTrader 4, они закрывают позицию в случае, если она достигла предельного уровня убытка (стоп-лосс) или прибыли (тейк-профит). Однако, в MetaTrader 4 такие остановки действуют индивидуально для каждого открытого ордера. В MetaTrader 5 эти остановки действуют сразу на всю совокупную нетто-позицию.

Проблема в том, что нетто-позиция не связана с разнонаправленными позициями экспертов и HedgeTerminal в частности, а значит, штатные уровни стоп-лосс и тейк-профитов использовать для разнонаправленных позиций нельзя. Но эти уровни можно представить как отдельные отложенные ордера. Предположим, если у нас открыта длинная позиция, то два отложенных ордера, один SellLimit, находящийся выше цены открытия этой позиции, а другой SellStop, находящийся ниже этой цены, будут эмулировать работу тейк-профита и стоп-лосса соответственно.

В самом деле, если цена после открытия достигнет SellLimit ордера, этот ордер закроет позицию c прибылью, если цена достигнет SellStop ордера, то он закроет позицию с убытком. Проблема в том, что после того как один из ордеров сработает, второй ордер все равно не перестанет существовать, и если цена после срабатывания одного из них развернется, то второй ордер может сработать вслед за первым.

Так как позиции уже не будет, срабатывание второго ордера откроет новую нетто-позицию, вместо того чтобы закрыть предыдущую.

Схема ниже иллюстрирует эту проблему на примере сопровождения защитными остановками длинной позиции:

Рис. 41. Схема эмуляции стоп-лосс и тейк-профит уровней с помощью ордеров SellStop и SellLimit

Рис. 41. Схема эмуляции стоп-лосс и тейк-профит уровней с помощью ордеров SellStop и SellLimit

Чтобы не происходило подобных накладок, в биржевой индустрии распространены так называемые OCO-ордера ("One Cancels the Other", или "один отменяет другой").

Это два отложенных ордера связанные между собой таким образом, срабатывание одного из которых отменяет второй. В нашем примере выше, после того как один ордер сработал, второй ордер отменит торговый сервер, а значит, новых позиций открываться не будет, что нам и нужно. Работа этих типов ордеров представлена на следующей схеме:

Рис. 42. OCO-ордера в качестве защитных остановок StopLoss и TakeProfit

Рис. 42. OCO-ордера в качестве защитных остановок StopLoss и TakeProfit

Однако, MetaTrader 5 не поддерживает OCO-ордера. Поэтому одновременную связку из трех ордеров использовать нельзя. Значит, использовать ордера, одновременно выполняющие роль StopLoss и TakeProfit. Но можно использовать связку из двух ордеров! Т.е. можно выбрать что-то одно: использовать или StopLoss или TakeProfit. 

В самом деле, если после исполнения ордера, инициализирующего новую разнонаправленную позицию, выставить отложенный ордер связанный с ним (например, StopLoss), то такая конструкция будет безопасной. Ведь второго отложенного ордера не будет, и он не сможет открыть новую разнонаправленную позицию. Фактически будет лишь три варианта дальнейшего развития событий:

Других вариантов быть не может. Если отложенный ордер будет отменен, это будет равносильно отмене StopLoss или TakeProfit уровня. Если отложенный ордер сработает, он закроет позицию, если ордер не сработает, то разнонаправленная позиция продолжит быть активной с установленным уровнем StopLoss.

Даже если HedgeTerminal в момент срабатывания отложенного ордера будет находится в выключенном состоянии, то позже, при запуске он сможет правильно обработать его срабатывание и понять, что произошло закрытие позиции этим ордером. Понять, что произошло закрытие по стоп-лосс или тейк-профит уровню можно в случае, если в magic-поле помимо ссылки на инициирующий ордер хранить специальную сервисную информацию, указывающую, какой именно тип имеет закрывающий ордер: обычный ордер, ордер takeprofit или stoploss. О том, как хранится ссылка и сервисная информация в поле magic, подробно объяснено в следующем разделе.

Так как использовать сразу две реальные остановки нельзя, в проектировании HedgeTerminal был принят компромисс:

Разнонаправленные позиции в HedgeTerminal защищаются реальными ордерами BuyStop и SellStop, выполняющими роль защитных остановок StopLoss. Уровни TakeProfit – виртуальные, они поддерживаются на уровне экземпляров HedgeTerminal, запущенных на одном компьютере и недоступны на уровне глобального контекста.

Выбор был сделан в пользу StopLoss уровней, т.к. в основном именно от этих уровней требуется повышенная надежность срабатывания. Если уровень прибыли не сработает, то катастрофы не произойдет, счет не закроют по маржин коллу, а вот несработавший стоп может привести к полному разорению счета.

Тем не менее, остается алгоритмическая возможность выбирать способ сопровождения позиции: реальным стоп-лосс уровнем и виртуальным тейк-профит уровнем или виртуальным стоп-лосс уровнем и реальным тейк-профит уровнем. Также уровни StopLoss и TakeProfit могут быть оба виртуальными. Сейчас такая возможность не реализована, но если она будет актуальной и востребованной, она может появиться.

Однако виртуализация TakeProfit уровня хотя и снижает его общую надежность, но незначительно. Уровни TakeProfit распространяются локально и доступны каждому из экземпляров HedgeTerminal. Достаточно иметь хотя бы один запущенный экземпляр HedgeTerminal в виде эксперта, использующего библиотеку, или панель HT, чтобы этот уровень был им исполнен. Когда запущенных экземпляров HT сразу несколько, TakeProfit исполнит только один из них – тот, кто первый сможет поставить блокирующий тэг на разнонаправленную позицию. В этом смысле экземпляры HT конкурируют друг с другом в многопоточном режиме записи-чтения данных.

Для обычного пользователя, торгующего вручную через панель HT или использующего библиотеку виртуализации в своих экспертах, работа с TakeProfit уровнем ничем не отличается от работы со StopLoss. Все фактические различия между этими уровнями спрятаны за кулисами HedgeTerminal. Трейдеру достаточно ввести в поле "TakeProfit" и "StopLoss" (уровни взятия прибыли и защитной остановки). Это уровни будут присутствовать одновременно и иметь идентичную цветовую индикацию, предупреждающую о срабатывании одного из уровней.


3.4. Решат ли OCO-ордера проблемы с защитой разнонаправленных позиций?

Благодаря OCO-ордерам можно использовать одновременную работу реальных стоп-лосс и тейк-профит уровней. Однако так ли они универсальны в организации разнонаправленной торговли? Давайте рассмотрим свойства, которыми они обладают более подробно. Итак, мы уже знаем, что OCO-ордера позволяют отменять один ордер при срабатывании другого.

Казалось бы, это полностью защитит нашу разнонаправленную позицию с обоих сторон, ведь в этом случае и Stop-Loss и Take-Profit смогут быть реальными ордерами, не требующими от HedgeTerminal быть запущенным на компьютере. Но дело в том, что в условиях биржевого исполнения приказов необходимо будет учитывать частичное исполнение заявок. Это свойство может в корне разрушить всю бизнес-логику приложения. Рассмотрим простой пример:

  1. Открылась длинная позиция объемом 10 контрактов. Мы выставили два связанных между собой OCO-ордера, реализующие StopLoss и TakeProfit уровни;
  2. При достижении уровня TakeProfit наш SellLimit ордер сработал частично. 7 из 10 контрактов были им перекрыты, оставшиеся 3 продолжили свое существовании в виде длинной позиции;
  3. SellStop ордер, реализующий уровень StopLoss отменится, т.к. связанный с ним ордер SellLimit сработал, хоть и частично.
  4. Позиция в три контракта останется без защитной остановки.

Подобный сценарий приведен на схеме ниже:

Рис. 43. Частичное исполнение защитных остановок

Рис. 43. Частичное исполнение защитных остановок

Внимательный читатель может возразить, что если спроектировать OCO-ордера таким образом, чтобы они учитывали частичное исполнение, тогда подобных сбросов защитных остановок можно будет избежать. Например, между собой может быть связан объем двух OCO-ордеров. В этом случае частичное исполнение действительно будет предусмотрено. Но это сильно усложнит и без того непростую логику ордерной системы, используемой при нетто-торговле.

Главная же проблема в том, что даже с учетом частичного исполнения, OCO-ордера не смогут дать те возможности, к которым привыкли пользователи MetaTrader 4. Например, будет проблематичным выставить отложенный ордер с защитными уровнями TakeProfit и StopLoss по нему. Причина будет в том, что два связанных между собой ордера не смогут учитывать срабатывание инициирующего ордера.

Чтобы по-настоящему сделать универсальный алгоритм, позволяющий использовать управление позициями аналогично управлению в MetaTrader 4, OCO-ордера должны обладать следующими характеристиками:

  1. Каждый связанный ордер должен корректировать свой объем в зависимости от степени срабатывания связанного с ним ордера. Например, если TakeProfit исполнил 7 из 10 контрактов, то связанный с ним StopLoss должен изменить свой объем с 10 до 3 (10 - 7 = 3);
  2. Каждый из связанных ордеров должен каким-то образом учитывать объем исполнения инициирующего ордера. Ведь если пользователь выставит отложенную заявку типа BuyLimit и защитит ее защитными остановками SL/TP в виде ордеров, то не факт, что BuyLimit сможет гарантированно исполнить весь свой объем. Эти случаи связанные ордера также должны учитывать.
  3. Связанный ордер, помимо условия на отмену, должен обладать дополнительным условием на срабатывание. Он должен срабатывать только в том случае, если дополнительно связанный с ним ордер сработал. Т.е. OCO-ордер должен обладать ссылками на целых два ордера, первая ссылка - это ордер при срабатывании которого должен активизироваться текущий ордер. Вторая ссылка - это ордер при срабатывании которого, текущий ордер должен быть отменен. Такой механизм позволит создавать позицию, чей инициализирующий ордер будет отложенным;

Подобные механизмы, даже если они появятся, будут очень сложны для восприятия рядового пользователя. Их ввод видится сомнительным. Гораздо проще использовать виртуализацию на стороне клиента, например такую, как используется сейчас в HT.

В качестве альтернативы OCO-ордерам, компания MetaQuotes могла бы рассмотреть возможность ввода специальных алгоритмических тейк-профит и стоп-лосс уровней, обеспечивающих защиту конкретной торговой заявки (ордера). Конечно, это только предложение, но возможно оно имеет рациональное зерно. Ведь такие алгоритмические уровни могут скрывать большую часть реализации и конфигурирования на стороне торгового сервера, предоставляя конечным пользователям готовый и простой механизм защиты.

Итак, подведем итог нашего небольшого логического рассуждения касательно перспектив внедрения OCO-ордеров в платформу MetaTrader 5:

В условиях частичного исполнения заявок OCO-ордера неэффективны, они не обладают достаточной надежностью и слишком сложны для восприятия рядового пользователя платформы. 


3.5. Хранение ссылок на инициализирующие ордера

В этом разделе мы подробнее опишем структуру внутреннего хранения ссылок на другие ордера и механизм связывания между ними. Как уже было сказано, поле "Order Magic" содержит идентификатор эксперта, выставившего ордер. Это значит, что любой трейдер с помощью языка программирования MQL5 может записать в это поле практически любое целочисленное значение. В таких случаях возможно появление коллизии, когда инициализирующий новую позицию ордер будет содержать идентификатор эксперта, совпадающий с идентификатором уже существующего ордера. В этом случае появится неверная ссылка на ордер.

Если трейдер в работе своих экспертов будет использовать для них числа-идентификаторы, близкие к нулю, например "1", "7" или "100", а сами номера ордеров будут существенно больше этих чисел, например "10002384732" или что-нибудь в этом роде, тогда коллизий не возникнет, совпадений номеров экспертов с номерами ордеров не будет. Но надеяться на такую сознательность трейдеров было бы наивно. Поэтому HedgeTerminal, во-первых, хранит ссылки на ордера специальным образом, снижающим вероятность появление коллизий, а во-вторых, его алгоритмы не допускают неоднозначности и устраняют коллизии в автоматическом режиме, даже если они возникли.

Поле "Order Magic", хранящее ссылку, занимает размер 64 бита. Благодаря своей ширине, это поле способно вместить невероятно большое число. В реальности, рабочий диапазон идентификаторов ордеров гораздо меньше. Благодаря этому Hedge Terminal безопасно использует старшие разряды этого поля для своих нужд, формируя ссылку на ордер специальным образом. Обратимся к схеме, показывающей, каким способом HedgeTerminal хранит ссылку на инициирующий ордер:

Рис. 44. Схема хранения ссылки на инициирующий ордер в HedgeTerminal

Рис. 44. Схема хранения ссылки на инициирующий ордер в HedgeTerminal

Старший 63 разряд поля всегда помечается единицей. Благодаря этому возможно делать очень быстрый перебор всех ордеров, ведь если этот разряд не равен единице, значит ордер заведомо не может содержать ссылку на другой ордер, и его можно пропустить. К тому же, установка старшего разряда в единицу делает число magic number очень большим, тем самым увеличивая расстояние между рабочим диапазоном идентификаторов ордеров и рабочим диапазоном ссылок HedgeTerminal, сокращая вероятность коллизии.

Следующие за ним три бита HedgeTerminal может заполнить служебной информацией. В отличии от идентификатора ордера, HT хранит в этом поле идентификаторы ордеров наизнанку, сначала заполняя старшие разряды, а потом младшие, о чем показывает направление синей стрелки direction SI (service inforamtion) на рис. 44. За счет такого хранения диапазоны сервисной информации и идентификаторов ордеров идут навстречу друг другу. А значит, в случае необходимости, их компоновку можно будет изменить или даже увеличить размер служебной информации за счет разрядов для хранения идентификатора ордера. Благодаря этой информации становиться возможным идентифицировать тип закрывающего ордера.

Дело в том, что в MetaTrader 4 активные ордера могут быть закрыты по TakeProfit или StopLoss уровням – это специальные ценовые отметки, на уровне которых происходит закрытие ордера с фиксацией прибыли или убытка соответственно. В MetaTrader 5 уровни TakeProfit и StopLoss можно применять только к нетто-позициям и они не подходят для связанных ордеров. Однако обычные отложенные ордера могут выполнять роль TakeProfit и StopLoss ордеров.

Такие ордера HedgeTerminal помечает специальными идентификаторами, указывающие на то, каким именно типом является ордер: TakeProfit или StopLoss ордером. Так как magic number храниться на торговом сервере, сервисная информация становится доступной для всех трейдеров, подключенных к торговому счету. Таким образом, даже несколько HT терминалов, запущенных на разных компьютерах, будут в курсе о типах сработавших ордеров и корректно отобразят информацию по закрытым позициям.

В диапазоне с 0 по 59 разряд хранится собственно информация об идентификаторе ордера, на который и ведет ссылка. Она хранится в стандартном направлении, занимая разряды справа налево, о чем указывает синяя стрелка direction order id. Для того чтобы оценить величину отведенного для хранения места, давайте рассчитаем, сколько места требуется для хранения диапазона всех ордеров, поступивших на Московскую биржу в течении года.

В отчете моего брокера за 13.06.2013 значится ордер с идентификатором 10 789 965 471. Это число занимает 33.3297 бит информации  (log2(10 789 965 471)) или 34  из 64 разрядов. Идентификатор одного из ордеров, выставленных на момент 25.09.2014 равен 13 400 775 716. Это число занимает 33.6416 бит информации. Таким образом за 1 год и 4 месяца было выставлено 2.6 миллиардов ордеров (!), однако размер идентификатора увеличился лишь на 0.31263 бита что гораздо меньше даже одного разряда. Я не могу утверждать, что наше Солнце погаснет прежде, чем размер идентификатора ордера подойдет к 59 разряду, но на то, что эти два события произойдут не раньше, чем через несколько миллионов лет, я бы поспорил.

HedgeTerminal не хранит ссылку в открытом виде. Для этого он шифрует поле OrderMagic, оставляя самый старший разряд нетронутым. Шифр HedgeTerminal основан на обратимой перестановке разрядов, которую реализует специальная функция шифрования, работающая на переменном ключе. После такого шифрования служебная информация и идентификатор ордера оказываются перемешены друг с другом и скрыты под специальной маской таким образом, что на выходе они представляют из себя равномерное распределение из нулей и единиц. Шифрование проводится по двум соображениям. Во-первых, перестановка разрядов снижает вероятность перекрытия рабочих диапазонов ссылок и идентификаторов ордеров, а во-вторых, это защищает внутренние алгоритмы HT от внешнего целенаправленного или случайного воздействия.

Эта процедура полностью безопасна, обратима и не подвержена коллизиям. Благодаря этому внешний пользователь может быть уверен в том, что какие бы действия он не совершал с помощью своих экспертов, это не повлияет на надежность внутренних алгоритмов HT. Это крайне важно, ведь в реальности управление этими ссылками невозможно без специальных и довольно сложных алгоритмов.

Однако если ограничиться контролированием ссылок, крах бизнес-логики будет неизбежен. Почему это так, читатели смогут понять, изучив следующие разделы, посвященные подробному описанию этих алгоритмов. Шифрование используется в том числе для того, чтобы этого краха не произошло. Обратной стороной медали этого ограничения является то, что управлять позициями HedgeTerminal можно только с его помощью и никак иначе.


3.6. Ограничения при работе с HedgeTerminal

Из особенности структуры хранения ссылки можно сделать вывод, что HedgeTerminal хранит ссылки на ордера равномерно занимая числа от 9223372036854775808 до 18446744073709551615. Если 64-рязрядное поле представить как число со знаком типа long, то это будут отрицательные значения. Из этого появляются три ограничения на работу с HedgeTerminal.

Первое ограничение касается торгового робота, работающего с HedgeTerminal, оно нестрогое и может рассматриваться как рекомендация:

Торговый робот или советник, работающий с HedgeTerminal, должен иметь идентификатор (магический номер эксперта) не превышающий значение 9223372036854775808.

В реальности с таким ограничением обычные эксперты никогда не столкнутся, потому что редко когда используют идентификаторы больше 5-6 знаков (самым распространенным идентификатором для экспертов является "12345" или что-нибудь в этом роде). Единственные, кто может столкнутся с этим ограничением, это роботы, хранящие в magic номерах служебную информацию, например, такие же ссылки на другие ордера. HedgeTerminal не совместим с такими экспертами и не может использоваться с ними совместно.

Если по каким-то причинам все равно использовались или используются номера больше указанного ограничения, то возникает ненулевая вероятность коллизии. Она мала, потому что получить совпадение на таком диапазоне сложно. Но даже в этом случае 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. При дальнейшем переборе находится еще один ордер, ссылающийся на ордер, описанный в первом пункте. Происходит поиск ордера, на который он ссылается в разделе активных ордеров. Однако поиск завершится неудачей, ведь требуемый ордер был уже перенесен из этого раздела в раздел завершенных транзакций. Раз ордер (ссылка на который содержится в текущем ордере) не найден, значит, текущий ордер, несмотря на свою ссылку, является активным ордером и переносится в раздел активных позиций!

Так как идентификаторы ордеров заполняются последовательно, а сам их список отсортирован по времени, то гарантированно можно выполнить их последовательный перебор. Следовательно, сколько бы одинаковых ссылок не содержалось на инициирующий ордер, он всегда будет закрыт только самым первым ордером, у которого обнаружится ссылка на него. Все остальные ордера, ссылающиеся на него, перейдут в разряд активных инициирующих позиций.

Алгоритм, выполняющий такой перебор, как уже писалось ранее, должен быть полностью детерминистичным или последовательным. Именно такой алгоритм перебора и использует HedgeTerminal в своей работе. Фактически это не просто перебор, а повторение всех торговых действий, которые были совершены с момента первой сделки. Фактически при каждом запуске HedgeTerminal последовательно выстраивает всю цепочку торговых действий с самого начала до текущего момента. Благодаря этому, его текущее представление позиций является результатом его ретроспективной торговли в момент запуска.

Так как перебор всех ордеров на истории осуществляется последовательно, необходимо также последовательно совершать и торговые действия. Это накладывает определенную специфику на исполнение приказов в HedgeTerminal. Предположим, что нам необходимо закрыть активную разнонаправленную позицию в HedgeTerminal защищенную стоп-лоссом. Мы уже знаем, что такая разнонаправленная позиция фактически будет состоять из двух ордеров: исполнившегося ордера, инициирующего активную позицию, и отложенного ордера buy-stop или sell-stop, исполняющего функции stop-loss ордера. Чтобы закрыть такую позицию, необходимо удалить отложенный ордер и закрыть активную разнонаправленную позицию встречным ордером аналогичным объемом. Фактически необходимо совершить два торговых действия. Все торговые приказы HedgeTerminal выполняет асинхронно.

При этом виде исполнения приказы можно исполнять параллельно: т.е. одновременно отослать первый приказ на отмену отложенного ордера, и второй на исполнение встречного ордера, который закроет нашу позицию. Однако HedgeTerminal не может этого сделать, потому что в этом случае будет нарушен детерминизм действий. Если по каким-то причинам удаление отложенного ордера не удастся, а закрытие позиции встречным ордером произойдет, то возникнет неопределенность, позиция будет закрыта, но ее стоп-лосс не перестанет существовать. В итоге ордер, реализующий стоп-лосс, может сработать и породить новую разнонаправленную позицию, а этого быть не должно. Поэтому HedgeTerminal вначале отменит стоп-ордер, и уже после успешной отмены выставит ордер встречного направления. Конечно, на втором шаге встречный ордер может также не исполниться или исполнится частично. Однако в этом случае неопределенности не будет, т.к. даже частично исполнившейся встречный ордер закроет часть активной позиции. А это вполне штатная ситуация.

Есть и более сложная последовательность действий, выполняемая HedgeTerminal. Рассмотрим пример, похожий на предыдущий, только на этот раз попытаемся закрыть часть позиции. Это будет означать, что программе HedgeTerminal понадобится выполнить сразу три действия:

  1. Удалить отложенный ордер, выполняющий функцию стоп-лосс ордера;
  2. Исполнить ордер встречного направления, закрывающего часть объема разнонаправленной позиции;
  3. Поставить новый стоп-ордер с новым объемом, защищающий оставшуюся часть активной позиции.

Все эти действия будут выполнены последовательно чтобы не нарушать детерминизм действий. Конечно, хотелось бы, чтобы за счет параллельной отправки приказов, скорость приказов была бы быстрее, однако в этом случае невозможно гарантировать последовательное исполнение торговых операций, а значит, возможно появление неопределенностей. В последовательной обработки приказов неопределенностей быть не может.


3.8. Разбиение и сведение сделок – основа ордерной арифметики

Последовательной обработки ордеров недостаточно. Помимо этого, необходимо учитывать два момента:

Исполнение ордера может быть выполнено сразу несколькими сделками, а также ордер может исполниться частично. Если вы не знаете, почему так может произойти, обратитесь к статье, посвященной описанию биржевого ценообразования: "Основы биржевого ценообразования на примере срочной секции Московской биржи". Наибольший интерес вызывает именно второй тонкий момент: почему объем закрывающего ордера может быть не равен объему открывающего? Что делать в этом случае?

На самом деле их объемы могут быть неравны, если представить возможность частичного закрытия активной позиции. В самом деле, если открыть активную позицию объемом 50 контрактов, а через некоторое время закрыть часть позиции встречным ордером с объемом 20 контрактов, то активная позиция как бы раздвоится надвое: первая часть образует с встречным ордером новую историческую позицию с объемом 20 контрактов, а вторая часть продолжит существовать, но ее объем уменьшится и будет уже 30 контрактов.

Именно такой алгоритм частичного закрытия позиций и реализован в HedgeTerminal. Если в поле "Volume" панели HT ввести новый объем, который будет меньше текущего, то произойдет частичное закрытие. На вкладке "History" образуется новая позиция, а объем текущей позиции станет равен введенному новому значению. Но HedgeTerminal может обработать ситуацию даже тогда, когда объем закрывающего ордера больше объема инициирующего! Такая ситуация может произойти в том случае, если по каким-то причинам HT выставит неправильный объем закрывающего ордера или брокер ретроспективно отменит несколько сделок, входящие в инициирующий ордер, тем самым изменит его исполненный объем на меньший.

Чтобы учитывать потенциальную разницу в объемах, необходимо использовать универсальный алгоритм, основанный на подсчете совокупного объема всех сделок, относящихся к ордеру. В этом случае на первом месте выступают именно сделки, а не ордера. Объем ордера – это объем его сделок. Цена исполнившегося ордера – это средневзвешенная цена его сделок.

HedgeTerminal использует алгоритм, который объединяет ордера друг с другом, или наоборот, разделяет их. Он основан именно на сложении и вычитании сделок. Вся его работа заключается в объединении сделок между инициирующим и закрывающим ордером с последующим образованием исторической позиции.

Чтобы понять как работает этот алгоритм, давайте поэкспериментируем и предположим, что нам необходимо связать два ордера друг с другом, образовав историческую позицию. Количество сделок у двух ордеров, и их исполненный объем будет одинаковый. Номера сделок для простоты будут трехзначными:

Order #1 (in order)Volume (10/10)
deal #2833
deal #2882
deal #2945

Таблица 3. Ордер №1 и его сделки


Order #2 (out order)Volume (10/10)
deal #8711
deal #8823
deal #9216

Таблица 4. Ордер №2 и его сделки

Сопоставим их сделки с объемами друг напротив друга:

Таблица 5. Сопоставление ордеров друг с другом

Таблица 5. Сопоставление ордеров друг с другом

Выберем две последние сделки из каждого столбца: №294 и №921. В общем случае они могут не быть на одном уровне друг с другом (как в данном примере).

Выберем из них сделку с наименьшим объемом. Эта сделка №294 с объемом 5. Разделим противоположенную ей сделку №921 на две: первая сделка будет равна объему сделки №294 (5 контрактов), вторая сделка будет содержать оставшийся объем: 1 контракт (6 контрактов – 5 контрактов = 1 контракт). Объединим сделку #294 с объемом 5 с первой частью сделки №921 с аналогичным объемом:

Таблица 6. Вычитание объемов

Таблица 6. Вычитание объемов

Перенесем эту объединенную часть в новую колонку, содержащую сделки исторической позиции.

Она отображена зеленым цветом. Оставшуюся вторую часть сделки #921 с объемом 1 оставим в нашей первоначальной колонке активной позиции, она отображена серым цветом:

Таблица 7. Сплит и перенос сделок

Таблица 7. Сплит и перенос сделок

Мы совершили первый шаг по объединению сделок двух ордеров и их переносу в историческую позицию. Отобразим нашу последовательность действий в более краткой форме:

Таблица 8. Сплит и перенос сделок. Шаг 1

Таблица 8. Сплит и перенос сделок. Шаг 1

Объем сделки №294 был полностью перенесен в секцию исторической позиции. Можно сказать, что эта сделка полностью аннигилировалась. Или произошел сплит (разбиение) сделки с последующим ее переносом в секцию исторических сделок. Поэтому на следующем шаге можно перейти к следующей за ней сделке №288 с объемом 2. Сделка №921 еще присутствует, и ее объем равен оставшейся второй части сделки. В следующем шаге этот объем будет взаимодействовать с объемом сделки №288.

На втором шаге повторим процедуру с сделками №288 и №921. На этот раз оставшийся объем сделки №921 (1 контракт) объединится с объемом сделки №288, перейдя в колонку исторических позиций. Оставшийся объем сделки №288 будет равен 1 контракту и останется в колонке активной позиции:

 Таблица 9. Сплит и перенос сделок. Шаги 1-2

Таблица 9. Сплит и перенос сделок. Шаги 1-2

Повторим аналогичную процедуру с сделками №288 и №882:

Таблица 10. Сплит и перенос сделок. Шаги 1-3

Таблица 10. Сплит и перенос сделок. Шаги 1-3

Выполним шаги IV и V аналогичным образом:

Таблица 11. Сплит и перенос сделок. Шаги 1-5

Таблица 11. Сплит и перенос сделок. Шаги 1-5

После шага V объем сделок закрывающего ордера в точности будет равен объему сделок открывающего ордера. Сделки, перешедшие в колонку исторической позиции, образуют законченную историческую транзакцию. Оставшиеся сделки из активной позиции образуют активную позицию. В данном случае сделок в колонке активной позиции не осталось. Это значит, что после такого объединения активная позиция перестанет существовать, а вместо нее образуется новая историческая позиция, которая включит в себя полностью все сделки из активной позиции.

После переноса сделок многие из них будут разбиты на несколько частей, занимая при этом несколько строк. Чтобы этого не происходило, в алгоритм объединения/разбиения сделок можно ввести дополнительную опцию по сбору сделок. Просто объединим объемы сделок с одинаковыми идентификаторами в единые уровни:

Таблица 12. Объединение сделок в один уровень

Таблица 12. Объединение сделок в один уровень

Очевидно, что после объединения количество сделок и их объем в точности соответствуют первоначальным сделкам и объемам. Но это так лишь потому, что их объемы изначально совпадали. Если бы объемы были разными, то после процедуры объеденения эти сделки имели бы другие объемы.

Алгоритм универсален, поэтому ему не требуется одинакового количества сделок для инициирующего и закрывающего ордера. Разберем еще один пример, основанный на этом свойстве пошагово:

Таблица 13. Объединение ордеров с разным количеством сделок

Таблица 13. Объединение ордеров с разным количеством сделок

Как видно, объединение двух ордеров в единую историческую позицию снова прошло успешно. Несмотря на разное количество сделок, их объем снова совпал.

Теперь представим, что суммарный объем сделок закрывающего ордера (12 контрактов) меньше объема сделок инициирующего ордера (22 контракта). Как пройдет объединение в этом случае?

Таблица 14. Объединение ордеров с разным объемом

Таблица 14. Объединение ордеров с разным объемом

Видно, что на втором шаге объем сделок закрывающего ордера сравнялся с нулем, в то время как инициирующий ордер содержит еще две сделки №321 с объемом 4 и №344 с объемом 6. Таким образом, образовался остаток из сделок активного ордера. Этот остаток продолжит существовать в виде активной разнонаправленной позиции. Однако образовалась и историческая позиция с сделками, перенесенными в зеленую колонку. Ее входящий и исходящий объем снова совпал и составил 12 контрактов.

Осталось разобрать третий вариант, когда объем закрывающего ордера больше инициирующего. По аналогии с предыдущим примером, образуется остаток, но уже со стороны закрывающего ордера:

Таблица 15. Объединение ордеров с разным объемом

Таблица 15. Объединение ордеров с разным объемом

Как видно, входящий ордер с объемом 4 и закрывающий ордер с объемом 6 образовали две позиции. Первая – это историческая позиция с объемом 4 и сделками №625 входящего ордера, и №719, №720 исходящего ордера. Вторая позиция получилась как остаток от слияния сделок этих ордеров. Она содержит сделку №719 с объемом 2. Эта сделка и ордер, на основе которого она выполнена, образует активную позицию на вкладке "Active" панели HedgeTerminal.

Сделки и ордера будут разбиты алгоритмом на исторические и активные транзакции. Эти объемы могут быть разными. Главное, алгоритм позволяет гарантированно свести объемы инициирующего и закрывающего ордера друг с другом, образовав историческую позицию с равным объемом входа и выхода. Благодаря этому, ситуация, когда эти объемы не будут равны, невозможна, следовательно, невозможны и ошибки представления позиций, вызывающие ассиметрию позиции.

Представим, что в самом первом примере брокер отменил одну из сделок, входящую в закрывающий ордер:

Таблица 16. Имитация удаления сделки из истории

Таблица 16. Имитация удаления сделки из истории

Образуется новая нетто-позиция объемом 6 контрактов. Она будет равна объему отмененных сделок. Давайте посмотрим, как отработает алгоритм Hedge Terminal в этом случае:

Таблица 17. Восстановление целостности представления

Таблица 17. Восстановление целостности представления

Как видно, на втором шаге образуется остаток в размере 6 контрактов (3+2+1). Этот остаток превратится в активную позицию, и тем самым объем и направление разнонаправленной позиции совпадет с нетто-позицией.

Резюмируя, можно сказать, что алгоритм объединения сделок гарантирует равенство объемов инициирующего и закрывающего ордера в исторической позиции за счет образования остатка в виде необъединенных сделок. Этот остаток из сделок образует активную разнонаправленную позицию, которая уравнивает нетто-позицию MetaTrader 5 с нетто-позицией всех активных позиций HedgeTerminal.

Этот механизм работает как ретроспективно, так и в режиме реального времени, а значит, он будет уравнивать нетто-позиции Hedge Terminal с нетто-позицией MetaTrader 5 независимо от действий брокера по отмене торговых действий. Комбинации по изменению нетто-позиции и отмене сделок могут быть любыми, ассиметрии между нетто-позицией терминала и нетто-позицией HT все равно не будет.

Механизм частичного закрытия позиции основан именно на возможности этого алгоритма сводить разные объемы друг с другом. Этот алгоритм одна из важнейших частей HT, обеспечивающая его устойчивую работу без настроек как самоадаптирующуюся систему.


3.9. Виртуализация ордеров и сделок

Каждому ордеру и сделки в HT соответствует его реальный прототип с аналогичным идентификатором. Тем не менее, один и тот же ордер с точки зрения HT может образовывать активную позицию и при этом быть частью исторической позиции. Сделки и ордера в 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 в список исключения. Их совокупный объем и количество не имеет значение, так как нет нетто-позиции. Если нетто-позиция в момент установки HT все-таки существует, то он просто откажется устанавливаться на компьютер, пока она не будет закрыта. После установки новые ордера изменят состояние нетто-позиции. Однако это состояние будет синхронизированно с нетто-объемом разнонаправленных позиций HT.

Конечно, исполненные ордера к моменту установки HedgeTerminal можно было бы не заносить в список исключений, но во-первых, их к моменту установки может быть уже очень много, и с точки зрения HT они все станут разнонаправленными позициями, а во-вторых, их совокупный объем по каким-либо причинам может отличаться от нетто-объема в MetaTrader 5.

Механизм скрытия ордеров позволяет эффективно противостоять даже разрушению истории счета. Вот как это работает. Представим, что у нас имеется некая история ордеров. Когда HedgeTerminal запустится на этом счете, он переберет все ордера и построит на их основе разнонаправленные позиции. Если на счете доступны все ордера с момента его открытия и данные об этих ордерах не нарушены, нетто-позиция этих ордеров будет соответствовать нетто-позиции в MetaTrader 5. Очевидно, что нетто-позиция HedgeTerminal также будет равна сумме всех этих ордеров. Этот вариант показан на условной схеме ниже:

Рис. 45. Схема целостной истории

Рис. 45. Схема целостной истории

По каким-то причинам часть истории может отсутствовать или предоставляемая информация об ордерах не будет корректной.

Неважно, отсутствует один ордер или сразу несколько, также неважно где находятся отсутствующие ордера: с самого начала истории счета или в середине. Нетто-позиция HedgeTerminal, запущенного на таком счете, будет равна нетто-позиции всех доступных ордеров. Однако, сама нетто-позиция ордеров не будет равна фактической нетто-позиции терминала из-за недостающей части истории. Такая ситуация отмечена на следующей схеме B:

Рис. 46. Схема частично разрушенной истории

Рис. 46. Схема частично разрушенной истории

Для синхронизации нетто-позиции HedgeTerminal с фактической нетто-позицией MetaTrader 5 нам не требуется знать, какие именно ордера исчезли или повреждены, нам лишь требуется рассчитать разницу между этими нетто-позициями. В приведенном выше примере в терминале MetaTrader 5 открыта позиция на покупку в размере 5 контрактов. В терминале HT при этом будет отображаться совокупная длинная позиция на 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>

После перезагрузки HT разнонаправленная позиция, образуемая этим ордером, исчезнет. Таким образом, нетто-позиция MetaTrader 5 совпадет с нетто-позицией HedgeTerminal, и в обоих случаях составит 5 контрактов на покупку (buy). Описанная последовательность действий представлена на диаграмме ниже:

Рис. 47. Схема восстановления целостности данных

Рис. 47. Схема восстановления целостности данных

Финансовый результат исчезнувшей позиции также пропадет из статистики HedgeTerminal. К сожалению, скрытые разнонаправленные позиции не участвуют в торговой статистике.

В реальности ситуация, когда часть истории недоступна или разрушена, крайне маловероятна. Подавляющее число пользователей MetaTrader 5 никогда с ней не встретятся, однако подобный механизм все равно необходим. В конце концов, не исключены программные ошибки самого HedgeTerminal. Даже в этом случае необходим надежный инструмент разрешения этих ошибок.


3.11. Механизмы адаптации

Мы подробно рассмотрели механизмы, позволяющие HedgeTerminal надежно представлять разнонаправленные позиции в нетто-окружении MetaTrader 5. Этих механизмов три:

  1. Последовательный перебор сделок;
  2. Механизм разбиения и сведения сделок;
  3. Механизм скрытия ордеров.

Каждый из этих механизмов решает свои задачи и позволяет избежать неопределенностей и ошибок на своем уровне. Представим в виде таблицы эти проблемы и способы их решения. В первой колонке будут обозначены проблемы и возможные ошибки связывания, а во второй – механизмы, которые их решают:

Проблемы, ошибки, неоднозначности возникающие при организации разнонаправленной торговлиМеханизмы разрешения ошибок
Ошибки в ссылках на открывающие ордера; Коллизия ссылок; Использование экспертами больших magic-номеров; удаление ордеров из истории; Ошибки выполнения торговых операций.Последовательный перебор ордеров. Детерминизм действий.
Ошибки в объемах; Сведение ордеров с разными объемами; частичное исполнение ордеров; удаление сделок из истории; Закрытие меньшего объема большим.Механизм разбиения и сведения сделок.
Установка HedgeTerminal на счет с большим числом исполненных ордеров; Разрушение истории; Баги HedgeTerminal в работе с ордерами.Механизм скрытия ордеров.

Таблица 18. Возможные ошибки и механизмы их устранения

Эти три механизма совместно с системой хранения ссылок обеспечивают устойчивое представление данных. Фактически эти механизмы покрывают все возможные случаи непредвиденных сбоев, а значит, HedgeTerminal может гарантированно свести свою нетто-позицию с нетто-позицией MetaTrader 5.


3.12. Производительность и использование памяти

HedgeTerminal представляет из себя объектно-ориентированное приложение. Благодаря ООП-принципам, заложенным в его архитектуру, терминал обладает высокой производительностью и низкими требованиями к занимаемой памяти. Основной ресурсоемкой задачей является развертывание истории сделок и ордеров в памяти компьютера в момент запуска терминала на графике.

После развертывания всех необходимых транзакций в памяти, терминал выводит сообщение, говорящее о времени, затраченном на эту операцию а также использовании оперативной памяти. Панель HedgeTerminal, запущенная на счете, содержащим более 20 000 сделок на компьютере с процессором Intel i7, запустилась менее чем за 30 секунд, при этом потребовалось 118 Мб оперативной памяти:

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 миллисекунд в зависимости от типа программы. На хранение одной транзакции уходит: (22 156 сделок + 22237 ордеров) / 44 Мб = 1 Кб оперативной памяти. На хранение дополнительного графического представления одной транзакции уходит примерно: (118 Мб – 44 Мб) * 1024 / (22 156 сделок + 22237 ордеров) = 1.71 Кбайт памяти.

Профилирование кода показывает, что большую часть времени забирает один единственный блок разбора ордеров, существенную часть которого занимает вызов системных функций. Оптимизация этого блока в будущих версиях позволит поднять производительность в момент запуска еще на 10-15%.


Заключение

Мы рассмотрели основные моменты работы с визуальной панелью HedgeTerminal. На ее примере была показана возможность создания нового класса панелей, обладающих возможностью гибкого конфигурирования.

На примере схем и спецификаций мы подробно познакомились с принципами организации разнонаправленной торговли. Если вы создаете свои библиотеки виртуализации, вторая глава данной статьи окажет вам неоценимую помощь в проектировании такой библиотеки.

Было показано, что специфика биржевого исполнения требует учитывать важные моменты в процессе представления сделок и ордеров в виде разнонаправленных позиций. Было продемонстрировано, что такое представление невозможно без виртуализации сделок и ордеров - механизма, позволяющего "дробить" объем совершенных сделок, а также клонировать реальные ордера таким образом, чтобы один и тот же ордер мог входить сразу в несколько транзакций.

Все это довольно смелые манипуляции с торговым окружением, однако, благодаря тому, что большая часть необходимой информации при виртуализации хранится именно на торговом сервере, такой вид представления можно рассматривать как надежный.