quik-lua-rpc icon indicating copy to clipboard operation
quik-lua-rpc copied to clipboard

Пример клиента на python для quik-lua-rpc v2.0-alpha.0 JSON?

Open euvgub opened this issue 6 years ago • 17 comments

Пример клиента на python?

euvgub avatar Jan 19 '19 15:01 euvgub

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

Enfernuz avatar Jan 19 '19 17:01 Enfernuz

Механизм аутентификации ZeroMQ:"NULL" (нет аутентификации)

-- coding: utf-8 --

import zmq context = zmq.Context() print("Connecting to test server") socket = context.socket(zmq.REQ) socket.connect("tcp://localhost:5560") print("Sending request") socket.send_string('GET_SCRIPT_PATH') message = socket.recv() print("Received reply [ %s ]" % (message))

Connecting to test server Sending request Received reply [ b"\x10\x01\x1a\xe6\x01\xd0\xa0\xd1\x9b\xd0\xa1\xe2\x82\xac\xd0\xa0\xd1\x91\xd0\xa0\xc2\xb1\xd0\xa0\xd1\x94\xd0\xa0\xc2\xb0 \xd0\xa0\xd1\x97\xd0\xa1\xd0\x82\xd0\xa0\xd1\x91 \xd0\xa0\xd1\x95\xd0\xa0\xc2\xb1\xd0\xa1\xd0\x82\xd0\xa0\xc2\xb0\xd0\xa0\xc2\xb1\xd0\xa0\xd1\x95\xd0\xa1\xe2\x80\x9a\xd0\xa0\xd1\x94\xd0\xa0\xc2\xb5 \xd0\xa0\xd0\x86\xd0\xa1\xe2\x80\xa6\xd0\xa0\xd1\x95\xd0\xa0\xd2\x91\xd0\xa1\xd0\x8f\xd0\xa1\xe2\x80\xb0\xd0\xa0\xc2\xb5\xd0\xa0\xd1\x96\xd0\xa0\xd1\x95 \xd0\xa0\xc2\xb7\xd0\xa0\xc2\xb0\xd0\xa0\xd1\x97\xd0\xa1\xd0\x82\xd0\xa0\xd1\x95\xd0\xa1\xd0\x83\xd0\xa0\xc2\xb0: 'C:\Test_QUIK\lua\protobuf\decoder.lua:311: Tag had invalid wire type.'." ]

euvgub avatar Jan 19 '19 22:01 euvgub

Эмм, нет, это не так работает. В той версии, что лежит сейчас в ветке master, сообщения от/к серверу сериализуются/десериализуются с помощью Protobuf (гайд для Python). Сами схемы сообщений (файлы .proto) можно найти в директории qlua/rpc RPC-сервиса. То есть, фактически, сервис с Вами общается посредством бинарных сообщений, которые закодированы Protobuf'ом.

Есть наработки для общения посредством JSON, но там ещё не доделано. Думаю, в течение следующей недели дозалью коммиты к альфа-версии.

Если нужна помощью по Protobuf -- пишите.

Enfernuz avatar Jan 20 '19 01:01 Enfernuz

В ветке master теперь лежит альфа-версия с поддержкой JSON.

Почему альфа?

  • нет покрытия авто-тестами
  • вручную тоже не всё тестировал
  • не обновлял структуры данных коллбэков (OnFirm и прочие) в соответствии с последним руководством к терминалу (у меня структуры от руководства ~июля 2018) -- каких-то полей, добавленных позднее, может не хватать
  • нет документации
import zmq
context = zmq.Context()
print("Connecting to test server")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5560")

print("\nSending request")
socket.send_string("{\"method\":\"message\", \"args\":{\"message\":\"Hello!\",\"icon_type\":\"WARNING\"}}")
message = socket.recv()
print("Received reply [ %s ]\n" % (message))

print("Sending request")
socket.send_string("{\"method\":\"getScriptPath\"}")
message = socket.recv()
print("Received reply [ %s ]\n" % (message))

print("Sending request")
socket.send_string("{\"method\":\"getClassesList\"}")
message = socket.recv()
print("Received reply [ %s ]" % (message))

Connecting to test server

Sending request Received reply [ b'{"result":{"result":1}}' ]

Sending request Received reply [ b'{"result":{"script_path":"D:\\programs\\Quik_KF\\lua\\quik-lua-rpc"}}' ]

Sending request Received reply [ b'{"result":{"classes_list":"CROSSRATE,PSAU,AUCT,INDX,TQTC,EQOB,EQEO,EQDB,EQRP_INFO,TQBR,TQDE,TQOB,EQTC,TQIF,TQTF,SPEQ,TQTD,TQOD,EQTD,CETS,INDXC,CETS_MTL,REPORT,REPORTFORTS,SPBXM,RTSIDX,SPBFUT,SPBOPT,USDRUB,OPTW,"}}' ]

Документацию по API пока не написал, но вскоре займусь ей. В общих чертах, формат сообщений такой:

Запрос:

{
  "method":"НАЗВАНИЕ_QLUA-ФУНКЦИИ",
  "args": {
    // АРГУМЕНТЫ QLUA-ФУНКЦИИ
  }
}

Ответ:

{
  "method": "НАЗВАНИЕ_QLUA-ФУНКЦИИ",
  "result": // РЕЗУЛЬТАТ QLUA-ФУНКЦИИ (число, объект, строка -- в зависимости от вызываемой функции)
}

Ответ в случае ошибки сервиса:

{
  "method":"НАЗВАНИЕ_QLUA-ФУНКЦИИ",
  "error": {
    "code": // ЧИСЛОВОЙ КОД ОШИБКИ,
    "message": "ИНФОРМАЦИЯ ОБ ОШИБКЕ"
  }
}

!!! Все дробные числа передаются как строки (что в аргументах, что в ответе от сервиса).

Enfernuz avatar Feb 02 '19 11:02 Enfernuz

Чудесно! В отдельный бы репозиторий quik-lua-rpc-python-client - Пример Python-клиента к сервису 'quik-lua-rpc'.

euvgub avatar Feb 03 '19 20:02 euvgub

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

Enfernuz avatar Feb 04 '19 19:02 Enfernuz

Может кто в курсе. А нет просто нормального РФ брокера с апи? Чтобы не мучаться с этим адом квиком

sholoma avatar Feb 04 '19 19:02 sholoma

Какие-то брокеры предоставляют доступ на MOEX через MetaTrader. QUIK, имхо, -- он больше для профессиональных трейдеров в фирмах (в том числе брокерских), поэтому может показаться, что в нём много всякой "ненужной фигни".

Enfernuz avatar Feb 04 '19 19:02 Enfernuz

Квик для компа бесспорно норм. Но вот именно прямого апи у брокера жалко нету. Те недобиржи по крипте это все сделали давно...( Но они меня не интересуют.

sholoma avatar Feb 04 '19 19:02 sholoma

Ладно хоть Квик под wine пашет. Хоть что-то немного радует.)

sholoma avatar Feb 04 '19 19:02 sholoma

Вот уже есть пример Python-клиента к сервису quik-lua-rpc https://github.com/yofi2tofi/mmvddss

euvgub avatar Feb 04 '19 19:02 euvgub

sholoma, под прямым API Вы имеете в виду прямой доступ к бирже, минуя всякие терминалы? Если так, то такая штука давно существует и её предоставляют почти все брокеры.

Получение маркет-даты через следующие протоколы:

  • Plaza2 (самописный протокол от Московской Биржи);
  • FAST

Отправка транзакций:

  • Plaza2;
  • TWIME (самописный бинарный протокол от Московской Биржи)
  • FIX

Но, уверяю, работа с этими протоколами на порядок сложнее, чем с QUIK (особенно по части обработки транзакций -- говорю из собственного опыта), даже при использовании каких-то готовых библиотек. Проще всех из них, наверное, Plaza2. И по латенси не сказать что бы андердог.

Enfernuz avatar Feb 04 '19 19:02 Enfernuz

Вот уже есть пример Python-клиента к сервису quik-lua-rpc https://github.com/yofi2tofi/mmvddss

Да, в качестве клиента к первой версии, где только protobuf, очень даже сойдёт. Добавлю ссылку в доку. Да и для второй версии сгодится, если в нём перегенерировать .py-обвязки над .proto-файлами (я поменял везде название message Request на message Args -- так лучше вписывается в модель).

Enfernuz avatar Feb 04 '19 19:02 Enfernuz

Может кто в курсе. А нет просто нормального РФ брокера с апи? Чтобы не мучаться с этим адом квиком

Это прямо готовая идея подпольного стартапа moex data sharing по аналогии со спутниковым шарингом

euvgub avatar Feb 05 '19 14:02 euvgub

Актуальное руководство по Qlua QUIK Lua. Версия 7.24 от 21.01.2019 Интерпретатор языка Lua. Руководство пользователя. Версия 7.24 https://euvgub.github.io/

В ветке master теперь лежит альфа-версия с поддержкой JSON.

  • не обновлял структуры данных коллбэков (OnFirm и прочие) в соответствии с последним руководством к терминалу (у меня структуры от руководства ~июля 2018) -- каких-то полей, добавленных позднее, может не хватать

euvgub avatar Feb 06 '19 16:02 euvgub

Python клиент для второй версии quik-lua-rpc v2.0-alpha.0 JSON

import zmq

context = zmq.Context()
socket = self.context.socket(zmq.REQ)
socket.connect('tcp://127.0.0.1:5560')
socket.send_string('{"method":"datasource.CreateDataSource","args":{"class_code":"SPBFUT", "sec_code":"SiU9", "interval":"INTERVAL_M1", "param":""}}')
datasource_uuid = json.loads(socket.recv_string())['result']['datasource_uuid']
socket.send_string('{"method":"datasource.Size","args":{"datasource_uuid":"%s"}}' % (datasource_uuid))
num_candles = json.loads(socket.recv_string())['result']['value']
for i in range(0,num_candles):
    socket.send_string('{"method":"datasource.C","args":{"datasource_uuid":"%s","candle_index":%d}}' % (datasource_uuid, i))
    candle_close = json.loads(socket.recv_string())['result']['value']
    socket.send_string('{"method":"datasource.O","args":{"datasource_uuid":"%s","candle_index":%d}}' % (datasource_uuid, i))
    candle_open = json.loads(socket.recv_string())['result']['value']
    socket.send_string('{"method":"datasource.T","args":{"datasource_uuid":"%s","candle_index":%d}}' % (datasource_uuid, i))
    candle_time = json.loads(socket.recv_string())['result']['value']

euvgub avatar Aug 07 '19 11:08 euvgub

import zmq

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://127.0.0.1:5561")
socket.setsockopt(zmq.SUBSCRIBE, b"OnAllTrade")
while True:
    print(json.loads(socket.recv_unicode()))

euvgub avatar Aug 09 '19 20:08 euvgub