Эксперт Online

«D`» №6 (93) /26 марта 2010
Константин Ивайловский

Вкалывают роботы, а не человек

Пишем торгового робота в Excel. Специальные навыки не требуются

Тенденция в разработке ПО для трейдинга сейчас такова: идет борьба за упрощение программ для построения торговых роботов. Популярность набирают такие программы, которые позволяют обойтись без знания языка программирования. То есть составить алгоритм можно с помощью набора блок-схем, а программа превратит его в полноценный код, написанный на языке C#. Среди лидеров в этой области на Западе выступает Wealth-Lab. А совсем недавно в РФ появился свой аналог — TSlab, который адаптирован под российские торговые площадки и может использоваться в качестве торгового терминала. (Основные функции этих программ были подробно разобраны в предыдущих номерах D'.)

Раздумывая над реализацией своей торговой идеи, многие игроки отказываются от использования знакомых всем нам офисных приложений, так как считают, что это слишком сложно, к тому же технология прошлого века. Но это не так, и, чтобы доказать обратное, мы разберем простейший пример. Покажем, какие этапы нужно пройти, чтобы создать робота в MS Excel и системе интернет-трейдинга NetInvestor, который выставляет заявки по стратегии на основе осциллятора Momentum.

Начнем с базовой технологии NetInvestor API, которая позволяет работать с рыночными данными и отправлять приказы напрямую из MS Excel.

Схематично NIAPI (NetInvestor Application Programming Interface) можно описать как универсальный набор логики, позволяющий взаимодействовать с различными программами и алгоритмами. Иными словами, это связующее звено, с помощью которого можно работать напрямую с сервером брокера, используя при этом свою любимую программу для теханализа или готовый код на языках C++, C#, VB и других. Клиентская часть системы NetInvestor в данном случае не используется.

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

Стратегия победителя

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

Для соединения MS Excel с сервером NetInvestor нужно скачать специальную библиотеку Regsvr32 NiApi.dll с сайта разработчиков www.netinvestor.ru [1]. Она распространяется создателями бесплатно и содержит набор из десяти классов, обеспечивающих работу с сервером. В основе взаимодействия лежит механизм обмена данными с таблицами сервера, с полным списком которых можно подробно ознакомиться на сайте.

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

  1. Соединение Excel с сервером NetInvestor.
  2. Получение рыночных данных.
  3. Анализ рыночных данных.
  4. Выставление заявки на торги.
  5. Получение информации о выставленной заявке.

Теперь необходимо открыть окно редактора макросов и скриптов VBA в MS Excel с помощью команды Alt + F11 и объявить нужные нам переменные, классов которые понадобятся:

Public WithEvents NISession As NiApiLib.SrvrSession — соединение с сервером
Public WithEvents TableFu As NiApiLib.Table — таблица заявок
Public NIFilterFutures As NiApiLib.Filter — ограничение трафика только по одной ценной бумаге
Public Row As NiApiLib.DataRow — здесь содержатся данные
Public DataPos As Long, PrevMinute As Date — служебные переменные
Public O As Double, H As Double, L As Double, C As Double — сохранение цены в формате OHLC (Open, High, Low, Close)
Dim FuturesValueList() As String — в массиве будут указаны время, цена в формате OHLC и индикатор Momentum

Классы NIAPI для программирования

ISrvrSession — реализация коммуникации и протокольной части, поддерживает работу через прокси-службы, протокольное сжатие, бинарный протокол, передачу и прием защищенных сообщений (ЭЦП и шифрование).
IStructure — интерфейс для работы с описанием структур таблиц и форматов транзакций.
IDataRow — для доступа к «полям записи» таблиц и данным транзакций.
IDataRowSet — для доступа к коллекциям IDataRow. IFilter — для доступа к коллекциям фильтров для получения исторических данных по таблицам.
ITable — для работы с серверными таблицами, поддерживает описание структуры таблиц, запросы историй, срезов, запросы на вставку, модификацию и удаление записей, управление подпиской на обновления.
ITransaction — для работы с серверными транзакциями, поддерживает описание структуры транзакции и запросы на выполнение транзакций.

Материалы

Схема 1
NetInvestor Application Programming Interface
Схема 2
Робот в Excel
1. Соединение с сервером NetInvestor

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

Private Sub ConnectButton_Click() — соединение с сервером
Set NISession = CreateObject(«NiApi.SrvrSession»)
Set TableFu = CreateObject(«NiApi.Table»)
Set NIFilterFutures = CreateObject(«NiApi.Filter»)
Set Row = CreateObject(«NiApi.DataRow»)
NISession.HostAddr = Cells(1, 2) — протестируем на демо-сервере nidemo.mfd.ru
NISession.HostPort = Cells(2, 2) — порт брокера 2900
NISession.Name = Cells(3, 2) — ввести логин
NISession.Password = Cells(4, 2) — ввести пароль
NISession.Connect
End Sub

Запрос на соединение с сервером отправлен, но необходимо обработать ответ от сервера о подключении и других сообщениях. Регистрация обработчиков очень проста, нужно к названию сессии добавить _OnConnectionLost и _OnLogin

Private Sub NISession_OnConnectionLost() — проверка соединения
MsgBox («Соединение потеряно») — сообщение пользователю
End Sub

 

Public Sub NISession_OnLogin(ByVal LoginResult As Long)
MsgBox («Соединение установлено»)
End Sub

Подключение к серверу на этом завершено. Чтобы прервать соединение, нужно лишь вызвать команду NISession.Disconnect.

2. Получение рыночных данных

Получение рыночных данных осуществляется из таблицы всех сделок на рынке FORTS: ALL_TRADES_PSFU (если брать данные с биржи ММВБ, то используем ALL_TRADES). Чтобы ограничить данные только по одному инструменту, что снизит нагрузку на робота, воспользуемся объявленным раньше фильтром и откроем таблицу на получение данных:

Private Sub GetStartedButton_Click() — открытие таблицы
Call TableFu.Open(NISession, «ALL_TRADES_PSFU», tabNoneAddr)
NIFilterFutures.Structure = TableFu.Structure NIFilterFutures.Add «I_NAME», conEqual, Cells(11, 2) Call TableFu.AddUpdateFilter(0, ELogicalOperation.logAnd, «I_NAME», conEqual, Cells(11, 2))
— устанавливаем фильтр, чтобы Excel работал быстро и данные приходили только по этому инструменту
TableFu.SetOnlineUpdates subEnabled — режим включенного обновления данных
TableFu.GetData NIFilterFutures — команда получения данных
End Sub

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

Private Sub TableFu_OnInsert(ByVal NiDataRow As Object, ByVal TableName As String) — обработка поступивших обновлений
Dim CurMinute As Date, momValue As Double, tmpLast As Double
CurMinute = TimeValue(NiDataRow.Item(«I_TIME»))
— получаем время сделки
tmpLast = NiDataRow.Item(«I_LAST») — цена сделки
 

Записываем данные в массив в формате время, OHLC, Momentum:

If tmpLast < H Then
H = tmpLast
End If
If tmpLast > L Then
L = tmpLast
End If
If Minute(CurMinute) >< Minute(PrevMinute) Then
C = tmpLast
PrevMinute = TimeValue(NiDataRow.Item(«I_TIME»))
ShiftFuturesValues
FuturesValueList(Period, 0) = NiDataRow.Item(«I_TIME»)
FuturesValueList(Period, 1) = O
FuturesValueList(Period, 2) = H
FuturesValueList(Period, 3) = L
FuturesValueList(Period, 4) = C
momValue = Momentum(5)
FuturesValueList(Period, 5) = momValue
O = tmpLast
H = tmpLast
L = tmpLast
C = tmpLast

Вызов стратегии:
Strategy
Вывод данных в Excel для построения графика:
WritePrices
End If
End Sub

3. Анализ рыночных данных

Функция Strategy содержит код, который анализирует данные и отправляет заявки на биржу. Разработчик робота может добавить для себя другие индикаторы или фильтры. Чтобы написать более сложную стратегию, мы для простоты ограничимся одним индикатором.

Private Sub Strategy()
If FuturesValueList(Period — 1, MOMENTUM_INDEX) >< «» Then
If FuturesValueList(Period — 1, MOMENTUM_INDEX) > -50 And FuturesValueList(Period, MOMENTUM_INDEX) < -50 Then
Call SendOrder(PriceHigh, 1, «B»)
End If
If FuturesValueList(Period — 1, MOMENTUM_INDEX) < 250 And FuturesValueList(Period, MOMENTUM_INDEX) > 250 Then
Call SendOrder(PriceLow, 1, «S»)
End If
End If
End Sub

4. Выставление заявки на торги

Отправка заявки или выполнение любой транзакции осуществляется созданием объекта ITransaction с названием транзакции и передачей ей параметров. Транзакция исполнится в рамках сессии подключения к серверу, поэтому достаточно трех объектов: сессия, транзакция и строка со значениями.

Private Sub SendOrder(Price As Double, Qty As Integer, Direction As String)
Dim oTransaction As NiApiLib.Transaction, oRow As NiApiLib.DataRow
Set oRow = CreateObject(«NiApi.DataRow»)
Set oTransaction = CreateObject(«NiApi.Transaction»)
oTransaction.Open NISession, «FutAddOrder», 0
oRow.Structure = oTransaction.Structure
oRow.Item(«I_SECCODE») = Cells(11, 2)
— ценная бумага
oRow.Item(«I_BUYSELL») = Direction — указать тип операции: B — для покупки, S — для продажи
oRow.Item(«I_QUANTITY») = Qty — размер позиции
oRow.Item(«I_PRICE») = Price — цена позиции
oRow.Item(«I_MKTLIMIT») = «M» — для лимитированной заявки
oRow.Item(«I_BROKERREF») = «780» — идентификатор клиента
oRow.Item(«I_SECBOARD») = «PSFU» — идентификатор рынка
oRow.Item(«I_ACCOUNT») = «AC1» — счет
If MsgBox(«Send order: » & Price & " " & Qty & " " & Direction, vbOKCancel) = vbOK Then
Call oTransaction.Execute(oRow)
End If
End Sub

5. Получение информации о выставленной заявке

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

В итоге мы получили полноценный торговый клиент на базе MS Excel. На практике робот может вести торговлю параллельно с человеком. То есть на одном торговом счете. Трейдер может смотреть и корректировать позиции робота через торговый терминал NetInvestor. Для этого просто создаются дополнительные логин и пароль.

Математический аппарат Excel может быть полезен опционщикам. Например, человек открывает какую-либо позицию по фьючерсам, а робот считает дельта-нейтральную стратегию или параметры офсетной сделки. При этом используется тот же протокол, что и у терминала. Это означает, что скорость обработки и получения информации по сравнению с терминалом будет одинаковая. Но если терминал обрабатывает много информации, то робот может запрашивать не всю, а только ту, которая ему нужна. Обработка меньшего количества данных дает некоторую прибавку к скорости. Если сравнивать, что работает быстрее по одной и той же библиотеке, то код на С# будет чуть быстрее. С более подробным описанием возможностей NIAPI, а также с вариантами применения можно ознакомиться на сайте разработчика www.netinvestor.ru/manuals.aspx#niapi.

Файл MS Excel с приведенным примером robot.xls вы можете скачать по ссылкам fincake.ru/ Robot_NIAPI_Momentum.xls или netinvestor.ru/robot.xls.