From e5f30402091e8d3d3d713af3074c6fc6bd52a431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=A7=D0=B5=D1=87=D0=B5?= =?UTF-8?q?=D1=82?= Date: Fri, 12 Mar 2021 22:30:20 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B5=20=D0=B2=D1=81=D0=B5=D0=B3=D0=B4?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20=D1=81=D0=B2=D0=B5?= =?UTF-8?q?=D1=87=D0=BA=D0=B8=20=D0=B2=20=D1=84=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20data=5Fsource=5Fcallback=20=D0=BC=D0=BE=D0=BD?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D0=BD=D0=BD=D0=BE=20=D0=B2=D0=BE=D0=B7=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QUIK/lua/qsfunctions.lua | 26 +++++++++---------- README.md | 56 +--------------------------------------- 2 files changed, 14 insertions(+), 68 deletions(-) diff --git a/QUIK/lua/qsfunctions.lua b/QUIK/lua/qsfunctions.lua index 9d3faf8..9ff621d 100644 --- a/QUIK/lua/qsfunctions.lua +++ b/QUIK/lua/qsfunctions.lua @@ -781,18 +781,18 @@ function qsfunctions.get_candles(msg) end --- Возвращаем все свечи по заданному инструменту и интервалу ---- (ichechet) Если исторические данные по тикеру не приходят, то QUIK блокируется. Чтобы это не происходило, вводим таймаут +-- (ichechet) Если исторические данные по тикеру не приходят, то QUIK блокируется. Чтобы это не происходило, вводим таймаут function qsfunctions.get_candles_from_data_source(msg) local ds, is_error = create_data_source(msg) if not is_error then - --- Источник данных изначально приходит пустым. Нужно подождать пока он заполнится данными. Бесконечно ждать тоже нельзя. Вводим таймаут - local s = 0 --- Будем ждать 5 секунд, прежде чем вернем таймаут - repeat --- Ждем - sleep(100) --- 100 миллисекунд - s = s + 100 --- Запоминаем кол-во прошедших миллисекунд - until (ds:Size() > 0 or s > 5000) --- До тех пор, пока не придут данные или пока не наступит таймаут + -- Источник данных изначально приходит пустым. Нужно подождать пока он заполнится данными. Бесконечно ждать тоже нельзя. Вводим таймаут + local s = 0 -- Будем ждать 5 секунд, прежде чем вернем таймаут + repeat -- Ждем + sleep(100) -- 100 миллисекунд + s = s + 100 -- Запоминаем кол-во прошедших миллисекунд + until (ds:Size() > 0 or s > 5000) -- До тех пор, пока не придут данные или пока не наступит таймаут - local count = tonumber(split(msg.data, "|")[4]) --- возвращаем последние count свечей. Если равен 0, то возвращаем все доступные свечи. + local count = tonumber(split(msg.data, "|")[4]) -- возвращаем последние count свечей. Если равен 0, то возвращаем все доступные свечи. local class, sec, interval = get_candles_param(msg) local candles = {} local start_i = count == 0 and 1 or math.max(1, ds:Size() - count + 1) @@ -839,7 +839,6 @@ end --- Словарь открытых подписок (datasources) на свечи data_sources = {} last_indexes = {} - --- Подписаться на получения свечей по заданному инструмент и интервалу function qsfunctions.subscribe_to_candles(msg) local ds, is_error = create_data_source(msg) @@ -856,12 +855,13 @@ function qsfunctions.subscribe_to_candles(msg) return msg end +--- (ichechet) Функция обработки новой свечки function data_source_callback(index, class, sec, interval) local key = get_key(class, sec, interval) - if index ~= last_indexes[key] then - last_indexes[key] = index - - local candle = fetch_candle(data_sources[key], index - 1) + if index ~= last_indexes[key] then -- Номер свечки изменился. Не всегда номер свечки монотонно возрастает https://forum.quik.ru/forum10/topic2530/ + log(index, 0) + local candle = fetch_candle(data_sources[key], last_indexes[key]) -- Получаем только что сформированную прошлую свечку + last_indexes[key] = index -- Запоминаем новый номер свечки candle.sec = sec candle.class = class candle.interval = interval diff --git a/README.md b/README.md index 09b2edb..d017767 100644 --- a/README.md +++ b/README.md @@ -4,67 +4,13 @@ ### Для чего нужна С помощью этой библиотеки можно создавать автоматические торговые системы любой сложности на Python для Quik. Также библиотека может быть использована для написания дополнений на Python к системам Технического Анализа. Например, для тестирования и автоматической торговли в [BackTrader](https://www.backtrader.com/). -### Установка коннектора. Метод 1. Из этого репозитория +### Установка коннектора 1. Скопируйте папку **QUIK\lua** в папку установки Quik. В ней находятся скрипты LUA. 2. Скопируйте папку **QUIK\socket** в папку установки Quik. 3. Запустите Quik. Из меню **Сервисы** выберите **Lua скрипты**. Нажмите кнопку **Добавить**. Выберете скрипт **QuikSharp.lua** Нажмите кнопку **OK**. Выделите скрипт из списка. Нажмите кнопку **Запустить**. Скрипт должен запуститься без ошибок, в окне сообщений Quik выдать **QUIK# is waiting for client connection...** -### Установка коннектора. Метод 2. Из оригинального [репозитория QuikSharp](https://github.com/finsight/QUIKSharp/tree/master/src/QuikSharp/lua) -1. В файле **config.json** замените строки "responseHostname": "127.0.0.1" на "responseHostname": "*" Иначе удаленный компьютер с Quik не будет отвечать на запросы. -2. В файле **qsfunctions.lua** замените функцию **qsfunctions.getFuturesHolding(msg)** на: - - --- (ichechet) Через getFuturesHolding позиции не приходили. Пришлось сделать обработку таблицы futures_client_holding - function qsfunctions.getFuturesHolding(msg) - if msg.data ~= "" then - local spl = split(msg.data, "|") - local firmId, accId, secCode, posType = spl[1], spl[2], spl[3], spl[4] - end - - local fchs = {} - for i = 0, getNumberOf("futures_client_holding") - 1 do - local fch = getItem("futures_client_holding", i) - if msg.data == "" or (fch.firmid == firmId and fch.trdaccid == accId and fch.sec_code == secCode and fch.type == posType*1) then - table.insert(fchs, fch) - end - end - msg.data = fchs - return msg - end - Иначе, фьючерсные позиции приходить не будут. -3. В файле **qsfunctions.lua** дополните функцию **qsfunctions.get_candles_from_data_source(msg)** - - --- Возвращаем все свечи по заданному инструменту и интервалу - --- (ichechet) Если исторические данные по тикеру не приходят, то QUIK блокируется. Чтобы это не происходило, вводим таймаут - function qsfunctions.get_candles_from_data_source(msg) - local ds, is_error = create_data_source(msg) - if not is_error then - --- Источник данных изначально приходит пустым. Нужно подождать пока он заполнится данными. Бесконечно ждать тоже нельзя. Вводим таймаут - local s = 0 --- Будем ждать 5 секунд, прежде чем вернем таймаут - repeat --- Ждем - sleep(100) --- 100 миллисекунд - s = s + 100 --- Запоминаем кол-во прошедших миллисекунд - until (ds:Size() > 0 or s > 5000) --- До тех пор, пока не придут данные или пока не наступит таймаут - - local count = tonumber(split(msg.data, "|")[4]) --- возвращаем последние count свечей. Если равен 0, то возвращаем все доступные свечи. - local class, sec, interval = get_candles_param(msg) - local candles = {} - local start_i = count == 0 and 1 or math.max(1, ds:Size() - count + 1) - for i = start_i, ds:Size() do - local candle = fetch_candle(ds, i) - candle.sec = sec - candle.class = class - candle.interval = interval - table.insert(candles, candle) - end - ds:Close() - msg.data = candles - end - return msg - end - Иначе, если исторические данные по тикеру Quik не возвращает, то он блокируется, дальнейшая работа невозможна. - ### Начало работы В папке Examples находится хорошо документированный код примеров. С них лучше начать разбираться с библиотекой.