Не всегда номер свечки в функции data_source_callback монотонно возрастает
This commit is contained in:
@@ -781,18 +781,18 @@ function qsfunctions.get_candles(msg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Возвращаем все свечи по заданному инструменту и интервалу
|
--- Возвращаем все свечи по заданному инструменту и интервалу
|
||||||
--- (ichechet) Если исторические данные по тикеру не приходят, то QUIK блокируется. Чтобы это не происходило, вводим таймаут
|
-- (ichechet) Если исторические данные по тикеру не приходят, то QUIK блокируется. Чтобы это не происходило, вводим таймаут
|
||||||
function qsfunctions.get_candles_from_data_source(msg)
|
function qsfunctions.get_candles_from_data_source(msg)
|
||||||
local ds, is_error = create_data_source(msg)
|
local ds, is_error = create_data_source(msg)
|
||||||
if not is_error then
|
if not is_error then
|
||||||
--- Источник данных изначально приходит пустым. Нужно подождать пока он заполнится данными. Бесконечно ждать тоже нельзя. Вводим таймаут
|
-- Источник данных изначально приходит пустым. Нужно подождать пока он заполнится данными. Бесконечно ждать тоже нельзя. Вводим таймаут
|
||||||
local s = 0 --- Будем ждать 5 секунд, прежде чем вернем таймаут
|
local s = 0 -- Будем ждать 5 секунд, прежде чем вернем таймаут
|
||||||
repeat --- Ждем
|
repeat -- Ждем
|
||||||
sleep(100) --- 100 миллисекунд
|
sleep(100) -- 100 миллисекунд
|
||||||
s = s + 100 --- Запоминаем кол-во прошедших миллисекунд
|
s = s + 100 -- Запоминаем кол-во прошедших миллисекунд
|
||||||
until (ds:Size() > 0 or s > 5000) --- До тех пор, пока не придут данные или пока не наступит таймаут
|
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 class, sec, interval = get_candles_param(msg)
|
||||||
local candles = {}
|
local candles = {}
|
||||||
local start_i = count == 0 and 1 or math.max(1, ds:Size() - count + 1)
|
local start_i = count == 0 and 1 or math.max(1, ds:Size() - count + 1)
|
||||||
@@ -839,7 +839,6 @@ end
|
|||||||
--- Словарь открытых подписок (datasources) на свечи
|
--- Словарь открытых подписок (datasources) на свечи
|
||||||
data_sources = {}
|
data_sources = {}
|
||||||
last_indexes = {}
|
last_indexes = {}
|
||||||
|
|
||||||
--- Подписаться на получения свечей по заданному инструмент и интервалу
|
--- Подписаться на получения свечей по заданному инструмент и интервалу
|
||||||
function qsfunctions.subscribe_to_candles(msg)
|
function qsfunctions.subscribe_to_candles(msg)
|
||||||
local ds, is_error = create_data_source(msg)
|
local ds, is_error = create_data_source(msg)
|
||||||
@@ -856,12 +855,13 @@ function qsfunctions.subscribe_to_candles(msg)
|
|||||||
return msg
|
return msg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (ichechet) Функция обработки новой свечки
|
||||||
function data_source_callback(index, class, sec, interval)
|
function data_source_callback(index, class, sec, interval)
|
||||||
local key = get_key(class, sec, interval)
|
local key = get_key(class, sec, interval)
|
||||||
if index ~= last_indexes[key] then
|
if index ~= last_indexes[key] then -- Номер свечки изменился. Не всегда номер свечки монотонно возрастает https://forum.quik.ru/forum10/topic2530/
|
||||||
last_indexes[key] = index
|
log(index, 0)
|
||||||
|
local candle = fetch_candle(data_sources[key], last_indexes[key]) -- Получаем только что сформированную прошлую свечку
|
||||||
local candle = fetch_candle(data_sources[key], index - 1)
|
last_indexes[key] = index -- Запоминаем новый номер свечки
|
||||||
candle.sec = sec
|
candle.sec = sec
|
||||||
candle.class = class
|
candle.class = class
|
||||||
candle.interval = interval
|
candle.interval = interval
|
||||||
|
|||||||
56
README.md
56
README.md
@@ -4,67 +4,13 @@
|
|||||||
### Для чего нужна
|
### Для чего нужна
|
||||||
С помощью этой библиотеки можно создавать автоматические торговые системы любой сложности на Python для Quik. Также библиотека может быть использована для написания дополнений на Python к системам Технического Анализа. Например, для тестирования и автоматической торговли в [BackTrader](https://www.backtrader.com/).
|
С помощью этой библиотеки можно создавать автоматические торговые системы любой сложности на Python для Quik. Также библиотека может быть использована для написания дополнений на Python к системам Технического Анализа. Например, для тестирования и автоматической торговли в [BackTrader](https://www.backtrader.com/).
|
||||||
|
|
||||||
### Установка коннектора. Метод 1. Из этого репозитория
|
### Установка коннектора
|
||||||
1. Скопируйте папку **QUIK\lua** в папку установки Quik. В ней находятся скрипты LUA.
|
1. Скопируйте папку **QUIK\lua** в папку установки Quik. В ней находятся скрипты LUA.
|
||||||
2. Скопируйте папку **QUIK\socket** в папку установки Quik.
|
2. Скопируйте папку **QUIK\socket** в папку установки Quik.
|
||||||
3. Запустите Quik. Из меню **Сервисы** выберите **Lua скрипты**. Нажмите кнопку **Добавить**. Выберете скрипт **QuikSharp.lua** Нажмите кнопку **OK**. Выделите скрипт из списка. Нажмите кнопку **Запустить**.
|
3. Запустите Quik. Из меню **Сервисы** выберите **Lua скрипты**. Нажмите кнопку **Добавить**. Выберете скрипт **QuikSharp.lua** Нажмите кнопку **OK**. Выделите скрипт из списка. Нажмите кнопку **Запустить**.
|
||||||
|
|
||||||
Скрипт должен запуститься без ошибок, в окне сообщений Quik выдать **QUIK# is waiting for client connection...**
|
Скрипт должен запуститься без ошибок, в окне сообщений 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 находится хорошо документированный код примеров. С них лучше начать разбираться с библиотекой.
|
В папке Examples находится хорошо документированный код примеров. С них лучше начать разбираться с библиотекой.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user