Дмитрий К
Дмитрий К личный блог
24 февраля 2020, 14:49

Как экспортировать данные из квика через сокеты - ответ и тут же вопрос

Последние несколько месяцев время от времени начинал времени ломать голову над одной задачкой.
Суть в следующем.
Я сделал скрипт на питоне, на основе торговых данных пишет заявки в tri файл квиковский.
Чтоб заявку создать нужно принять решение на основе каких то данных из таблиц квика (например исполнилась какая то ранняя заявка, или банально цена дошла до нужного уровня, и т.п.)
Данные из таблиц квика, как известно, встроенными методами можно экспортировать через ДДЕ сервер, или в базы данных через ODBC.
То есть — для этого не надо обладать знаниями по программированию, это простые, очевидные способы, доступные всем, у кого установлен квик.
Я выбрал способ по ODBC, и пользуюсь им.
Связка работает стабильно, ничего не рушится, правда пару раз за несколько месяцев зависал сам квик из за того, что кончалась оперативная память (сервер слабенький у меня).

Но у такой связки есть слабое место, приходится в питоне запускать таймер, по кjторому питон опрашивает базу данных.
Это не логично, робот должен совершать какие то действия в ответ на событие, а не просто молотить запросы в БД.

В итоге, путем гугления выяснилось что существуют в  теории еще два пособа экспорта данных из квика.
Первый способ — это экспорт в библиотеку dll trans2quik — библиотека позволяет  как импортировать заявки в квик, так и экспортировать заявки и сделки из квика.
С импортом заявок я разобрался (кому интересно, по простому могу объяснить), а вот по поводу экспорта так и не понял, суть в том, что сделки  приходят в бибдиотеку dll а оттуда уже в скрипт питона. Подписаться на отправку удается, а вот как получать сами сделки в переменные, я так и не понял.

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

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

Как это все я запустил?
Из библиотеки с архивом сокета кинул все файлы в корневой каталог квика, не заменял только основной файл lua5.1.exe (оставил родной)
туда же положил и файл со скриптом клиента, перед тем как запускать клиент, само собой надо запустить сервер на питоне, 
и после этого все сразу заработало на 32 разрядной версии квика.

Кому надо, могу прислать  ту библиотеку сокет, которая у меня заработала, а также примеры скриптов сервера и клиента

проблема в том, что на 64 разрядной версии не запускается, пишет ошибку

error loading module 'socket.core' from file 'C:\QUIK_VTB24\socket\core.dll':
%1 не является приложением Win32.

пока времени нет нагуглить решение, может кто знает как наладить?

Update:
библиотеку 64 нашел, все заработало с сокетами


64 Комментария
  • Karim
    24 февраля 2020, 15:02
    По всей видимости у вас старая библиотека Сокет для луа 32 разрядная, нужно либо найти вариант 64 разрядной, либо исходники и потом их собрать для 64 разряда.
  • Свой Мужик
    24 февраля 2020, 15:04
    Читал мануил и единственное, что там написано про 64 версию — ищите dll под неё :(
  • luks sluk
    24 февраля 2020, 15:13
    RPC-сервис для вызова API Lua-библиотеки торгового терминала QUIK
    https://github.com/Enfernuz/quik-lua-rpc

    Пример клиента на python для quik-lua-rpc 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":"SiH0", "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']
    
  • luks sluk
    24 февраля 2020, 15:42

    иллюстрация, куда можно это дальше применить

    quotes = {}
    quotes['open']=numpy.asarray([item['open'] for item in data])
    quotes['close']=numpy.asarray([item['close'] for item in data])
    quotes['high']=numpy.asarray([item['high'] for item in data])
    quotes['low']=numpy.asarray([item['low'] for item in data])
    quotes['datetime']=numpy.asarray([item['datetime'] for item in data])
    fig, ax = plt.subplots(3, sharex=True)
    candlestick2_ohlc(ax[0],quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6)
    ax[0].xaxis.set_major_locator(ticker.MaxNLocator(6))
    def chart_date(x,pos):
        try:
            return quotes['datetime'][int(x)]
        except IndexError:
            return ''
    ax[0].xaxis.set_major_formatter(ticker.FuncFormatter(chart_date))
    fig.autofmt_xdate()
    fig.tight_layout()
    quotes['close'] = numpy.array([float(x) for x in quotes['close']])
    sma = talib.SMA(quotes['close'], timeperiod=50)
    ax[0].plot(sma)
    ema = talib.EMA(quotes['close'], timeperiod=20)
    ax[0].plot(ema)
    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9)
    ax[1].plot(macd, color="y")
    ax[1].plot(macdsignal)
    hist_data = []
    for elem in macdhist:
        if not numpy.isnan(elem):
            v = 0 if numpy.isnan(elem) else elem
            hist_data.append(v*100)
    ax[2].fill_between([x for x in range(len(macdhist))], 0,macdhist)
    plt.show()
    

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн