OLE интерфейс к таблицам quik

Опубликовано в Утилиты

Как получить во внешней программе, написанной,к примеру, на языке С++, содержимое таблиц рабочего места quik? Алгоритм вроде очевиден. Создаём таблицы вручную, добавляем в них все инструменты и все параметры, которые могут понадобиться роботу. Настраиваем экспорт по DDE и в своей программе создаём DDE сервер. Либо экспортируем данные протоколом ODBC в какую-нибудь базу данных и учим программу с этой базой работать. При этом постоянно что-то не складывается, отсоединяется, лапы ноют и хвост отваливается... При рестарте терминала нужно каждый раз руками или программно (автогеном) инициировать старт экспорта. Не забывать добавлять вручную в таблицу текущих параметров каждый раз новые фьючерсы после экспирации старых. В общем, насколько бы ни был качественно написан сам алгоритм, удобство и надежность робота оставляют желать много лучшего из-за "удобств", предлагаемым самим терминалом.

Моя лень долго боролась со всей этой заливной рыбой, но рыба взяла измором.

Итак, задача. Написать на qlua программный интерфейс, позволяющий получать любые данные из терминала quik без каких-либо дополнительных пассов руками, из любого языка программирования в реальном времени. То есть заменить собой протокол DDE.

Результат должен выглядеть как-то так:

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

 

Как это все работает?

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

 

 

 

AmiSharp автоматически запустится.

 

 

Теперь из внешней программы можно инициировать создание любой таблицы quik и читать ее как любой com-объект.

Как это выглядит во внешней программе?

 

Для наглядности будем использовать какой-нибудь простенький язык. Например, мою любимый для такого рода целей AutoIt. Ровно то же самое можно сделать и на С++, и на дельфи, и на Visual Basic. Да и вообще на любом языке, поддерживающем OLE-технологию. А других, считай, и не существует Улыбаюсь.

В качестве COM сервера возьмем старый добрый AmiSharp. Можно использовать и Excel, но у старичка ожирение и симптомы тугодумия. Итак, приступаем.

 

Сначала подключимся к AmiSharp.

;~ Создаём объект AmiSharp
$amisharp = ObjCreate("Amisharp.Mutant")
;~ $amisharp.Tracelog("e:\a.log")

;~ Имя таблицы приказов. В нее пишем запросы для LuaSharp
;~ Строка. Состоит из двух частей: пути к терминалу quik и фиксированной строки "LuaSharp Command Table"
$cmd = "C:\Program Files\QUIK-Junior:LuaSharp Command Table"

;~ Проверим, запущен ли LuaSharp в терминале
If $amisharp.IsTableExists($cmd) == "0" Then
      MsgBox(16,"Test LuaSharp","Не обнаружена командная таблица " & $cmd,10)
      Exit
EndIf

 

Пример 1.

Сформируем приказ на создание, скажем, таблицы заявок. В новой строке командной таблицы создаем приказ: 

;~ Создаем таблицу заявок
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Orders") ; Таблица заявок

Создастся таблица с информацией о заявках. Имя этой таблицы будет указано в той же строке, что и приказ в колонке Result:

 

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

Содержимое таблицы изменяется синхронно с обновлением в терминале информации о заявках: новые заявки дописываются, измененные меняют свои поля.

 

Пример 2.

Аналогично заказывается создание таблицы сделок, стоп-ордеров и прочих. 

;~ Создаем таблицу сделок
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Trades")                ; Таблица сделок

 

Пример 3.

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

;~ Таблица текущих параметров - параметр last для LKOH
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH last")
;~ Таблица текущих параметров - параметр bid для RIM4
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters SPBFUT RIM4 bid")

 

 

Пример 4.

Получение истории инструмента. Выведем в таблицу историю инструмента Лукойл на минутном графике:

 

$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES QJSIM LKOH 60")

 

 

Пример 5.

Кроме открытия таблиц, можно выполнить функцию (да и просто любой текст) на lua

 

$line = $line+1
$amisharp.SetCell($cmd,0,$line,"ASK")
$amisharp.SetCell($cmd,1,$line,"getClassesList()")

Получим результат, который вернет функций getClassesList(). Можно попросить исполнить не только одну функцию, а вообще произвольный код и получить результат исполнения. С некоторой осторожностью можно даже запустить другой скрипт lua. Дразнюсь

 

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

 

 


Что в сухом остатке?

  1. Не требуется городить никаких DDE серверов в тексте внешних программ
  2. Нет больше проблем с настройкой руками требуемых таблиц терминала
  3. Нет проблем с включением/отключением DDE экспорта
  4. Не нужно обращать внимание на наличие и доступность требуемых данных - скрипт закажет все сам
  5. Никогда не отключается экспорт
  6. Параллельно запущенные роботы могут использовать одни и те же таблицы
  7. Нет никаких сложностей с экспортом данных из нескольких терминалов одновременно
  8. Никаких задержек, неотличимое от нуля потребление ресурсов процессора
  9. Все возможности AmiSharp (выставление заявок в терминал Quik и проч.) остаются доступными для любого подключенного к нему робота.

 

Текст тестового примера на языке AutoIt:

 

#NoTrayIcon
#pragma compile(LegalCopyright, Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра.)
#pragma compile(CompanyName, www.bot4sale.ru)
#pragma compile(ProductName, LuaSharp Test)
#pragma compile(FileVersion, 2.0)
;~ Создаём объект AmiSharp
$amisharp = ObjCreate("Amisharp.Mutant")
;~ $amisharp.Tracelog("e:\a.log") 
;~ имя таблицы приказов. В нее посылаем запросы для LuaSharp
;~ Строка. Состоит из двух частей: пути к терминалу quik и фиксированной строки "LuaSharp Command Table"
$cmd = "C:\Program Files\QUIK-Junior:LuaSharp Command Table"
;~ $cmd = "E:\QUIK:LuaSharp Command Table" 
;~ Проверим, запущен ли LuaSharp
If $amisharp.IsTableExists($cmd) == "0" Then
MsgBox(16,"Test LuaSharp","Не обнаружена командная таблица " & $cmd,10)
Exit
EndIf 
;~ Формирование приказов
;~ Каждый новый приказ - в новой строке
$line = $amisharp.GetHeight($cmd) 
;~ Узнаём версию Luasharp
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Version") ; Версия LuaSharp
;~ Создаем таблицу заявок
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Orders") ; таблица заявок
;~ После выполнения команды в той же строке в колонке Result появится имя созданной таблицы
;~ Создаем таблицу сделок
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Trades") ; Таблица сделок 
;~ Таблица стоп-заявок
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Stop_Orders") ; Стоп-заявки 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create futures_client_holding") ; Позиции по фьючерсам 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create futures_client_limits") ; Лимиты по фьючерсам 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create depo_limits") 
;~ Повторяем команду - что будет?
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create depo_limits") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create account_balance") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create account_position") 
;~ Таблица текущих параметров - параметр last для LKOH
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH last") ; Параметр 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH time") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH short_name") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH min_price_step") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH lot_size") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters QJSIM LKOH scale") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create Parameters SPBFUT SiU5 pricemin")
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TTP SPBFUT RIU5 bid") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TTP SPBFUT RIU5 biddepth") 
;~ Повторение параметра
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TTP QJSIM GAZP biddepth") 
;~ Несуществующий параметр
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TTP QJSIM GAZP xxxx") 
;~ Несуществующий параметр
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TTP SPBFUT XYZ4 offer")
;~ Статус соединения с брокером
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create CONNECT") 
;~ Список фирм
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create FIRMS") 
;~ Торговые счета
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TRADE_ACCOUNTS") 
;~ Коды клиентов
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create CLIENT_CODES") 
;~ Классы
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create CLASSES") 
;~ Стакан
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES_LEVEL_II QJSIM LKOH") 
;~ Еще раз вызовем стакан для того же инструмента
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES_LEVEL_II QJSIM LKOH")
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES_LEVEL_II QJSIM GAZP") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES_LEVEL_II SPBFUT SVU5") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES_LEVEL_II SPBFUT RIU5") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"ASK getClassesList()") 
;~ Котировки лукойла на 1 мин таймфрейме. Укажите правильно код класса и инструмент
; Таймфрейм можно задать или его длительностью в секундах (60 - это таймфрейм 1 минута) или
; идентификатором.
;~ INTERVAL_M1
;~ INTERVAL_M2
;~ INTERVAL_M3
;~ INTERVAL_M4
;~ INTERVAL_M5
;~ INTERVAL_M6
;~ INTERVAL_M10
;~ INTERVAL_M15
;~ INTERVAL_M20
;~ INTERVAL_M30
;~ INTERVAL_H1
;~ INTERVAL_H2
;~ INTERVAL_H4
;~ INTERVAL_D1
;~ INTERVAL_W1 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES QJSIM LKOH 60") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES QJSIM LKOH INTERVAL_M5") 
; На тиковом графике RI может быть очень много свечей. Поэтому:
; Получить Out of memory на ликвидном инструменте типа RI - почти с гарантией
; Будьте терпеливы, пока терминал подкачивает тиковую историю
; Для экономии оперативной памяти на тиковой истории выводится только одно поле Close. Поля Open,Low,High не выводятся: они совпадают с Close
; Время сделки выводится с точностью до миллисекунд. 
;~ $line = $line+1
;~ $amisharp.SetCell($cmd,0,$line,"Create QUOTES SPBFUT EuU5 INTERVAL_TICK") 
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create QUOTES QJSIM LKOH 900") 
;~ Создадим таблицу ответов торговой системы на транзакции, посланные через LuaSharp
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"Create TRANSACTIONS") 
;~ Пошлем транзакцию
$line = $line+1
$amisharp.SetCell($cmd,0,$line,"SENDTRANSACTION ACTION=NEW_ORDER;TRANS_ID=1234567890;PRICE=2500;QUANTITY=1;ACCOUNT=NL0011100043;CLIENT_CODE=qtest078;CLASSCODE=QJSIM;SECCODE=LKOH;OPERATION=B;TYPE=L") 
;~ Теперь можно читать содержимое любой таблицы обычным способом (функциями Амишарпа GetCell или GetCellName)

 

 После выполнения этой программы командная таблица будет выглядеть так:

 

В колонке RESULT для каждой команды указан результат ее исполнения. Для команд открытия таблиц оказывается ее имя. При ошибке выдаётся диагностика. Вот этот список:

 

 Вид сформированных таблиц:

 

 Ну и возможность выводить данные в амишарп из разных терминалов одновременно:

 Обсуждение на форуме.

  Скачать скрипт (потребуется пароль)


Настроение от Альбиони...

Комментарии   

# swerg 03.04.2014 21:17
Монстр!
Разрешите пожать вашу руку
Ответить | Ответить с цитатой | Цитировать
# admin 03.04.2014 21:26
Кто же мешает? Жмите! )))
Ответить | Ответить с цитатой | Цитировать
# Stanislav 14.04.2014 16:46
Сколько стоит?
Ответить | Ответить с цитатой | Цитировать
# Archie 13.07.2014 11:09
А можно получить пароль к архиву?
Ответить | Ответить с цитатой | Цитировать
# admin 13.07.2014 12:36
Вот здесь написано как получить амишарп. Luasharp тоже можно добавить в комплект, вопрос лишь в литраже :lol:

www.bot4sale.ru/.../51-nuzhen-amisharp.html
Ответить | Ответить с цитатой | Цитировать
# ВячеславS 11.03.2015 11:43
Ну а все-таки насчет литража нельзя ли по-конкретнее по мейлу, имея ввиду и луа- и ами - шарпы?
Ответить | Ответить с цитатой | Цитировать
# admin 11.03.2015 22:39
Вячеслав. К сожалению, мне нечего добавить. Ценников нет и не будет. Все определяется вашим пониманием справедливости.
Ответить | Ответить с цитатой | Цитировать
# Mazai 15.03.2015 18:18
не совсем понятно как связанны qlua и dde сервер :sad:
Ответить | Ответить с цитатой | Цитировать
# admin 15.03.2015 23:44
Добрый день. Они не связаны никак.

луашарп и был написан с целью замены протокола дде на механизм ком-сервера. Кроме значительно более высокой надежности (никогда не отключается и т.п.) последнего также появилась возможность заказывать данные динамически в процессе работы - не нужно настраивать экспортируемые таблицы. Ну и масштабируемост ь - несколько разнородных внешних программ могут безопасно работать параллельно ничего не зная друг о друге.
Ответить | Ответить с цитатой | Цитировать
# Mazai 16.03.2015 13:22
и вам добрый .

но у вас по схеме QUIK ->LuaSharp ->AmiSharp -> робот (насколько я понял AmiSharp фактически и есть dde сервер запакованный в dll).
Ответить | Ответить с цитатой | Цитировать
# admin 16.03.2015 13:48
В этой схеме dde возможности амишарпа не используются. Поставкой данных в амишарп вместо dde протокола занимается скрипт lua (luasharp.lua)

Используется только программный интерфейс амишарпа
Ответить | Ответить с цитатой | Цитировать
# Mazai 16.03.2015 19:43
Поставкой данных в амишарп вместо dde протокола занимается скрипт lua (luasharp.lua) -- как?
Ответить | Ответить с цитатой | Цитировать
# admin 16.03.2015 20:34
Неясен вопрос. Вас интересует принцип работы скрипта luasharp с точки зрения программиста?

Извольте. Скрипт ведет реестр подписок, заказанных ему внешним агентом, садится на штатные прерывания терминала по требуемым событиям и по приходу событий обновляет все соответствующие таблицы ком-сервера посредством встроенного в амишарп программного интерфейса.
Ответить | Ответить с цитатой | Цитировать
# Mazai 11.04.2015 17:59
Цитирую admin:
Неясен вопрос. Вас интересует принцип работы скрипта luasharp с точки зрения программиста?


нет просто не думал что LUA может работать с COM.
Ответить | Ответить с цитатой | Цитировать
# AlexLan 28.05.2015 22:22
Михаил, Спасибо Вам за проделанную работу. :-)
за программы LuaSharp :-) и AmiSharp за наглядные примеры и документацию - как это использовать.
Переделал привод на LuaSharp стало работать надежней.
Только не получилось достать из ТТП значение "status"
Если не трудно приведите пример как это можно сделать.
С уважением, Александр
Ответить | Ответить с цитатой | Цитировать
# admin 28.05.2015 22:36
Цитирую AlexLan:
не получилось достать из ТТП значение "status"


Александр, вы можете получить луашарпом все данные, которые транслируются в терминал брокером.

Некоторые поля, которые вы видите в таблице текущих параметров, являются не транслируемыми, а вычисляются уже самим терминалом.

Такие данные получить нельзя и их надо точно так же вычислять.

Статус - одно их таких значений.

По вычисляемому значению в терминале невозможно построить график - так можно узнать тип параметра.
Ответить | Ответить с цитатой | Цитировать
# AlexLan 28.05.2015 22:44
Понятно. Спасибо.
Хотел ввести дополнительный контроль, производится торговля по бумаге или нет.
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий


Защитный код
Обновить