Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion internal/quik/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ type DataSourceRequest struct {
Interval int `json:"interval"`
}

// SubscribeOrderBookRequest — данные для работы с DataSource.
type SubscribeOrderBookRequest struct {
ClassCode string `json:"class_code"`
SecCode string `json:"sec_code"`
}

// CreateDataSourceRequest — данные для создания DataSource.
type CreateDataSourceRequest struct {
DataSourceRequest
Class string `json:"class_code"`
ClassCode string `json:"class_code"`
}

// GetPortfolioRequest — данные для создания DataSource.
Expand Down
26 changes: 26 additions & 0 deletions internal/quik/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,32 @@ func (q *QuikClient) CloseDataSource(data DataSourceRequest, ctx context.Context
return nil
}

func (q *QuikClient) SubscribeOrderBook(data SubscribeOrderBookRequest, ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

request := getRequest()
defer putRequest(request)

request.Cmd = "subscribeOrderBook"
request.Data = data

q.logger.Debug("subscribe OrderBook request", zap.String("classCode", data.ClassCode), zap.String("ticker", data.SecCode))

response, err := q.client.sendRequest(ctx, request)
if err != nil {
return errors.Wrap(err, "failed to subscribe OrderBook")
}

if !response.Success {
return fmt.Errorf("failed to subscribe OrderBook with message: %s", response.Message)
}

q.logger.Debug("subscribe to OrderBook", zap.Bool("success", response.Success))

return nil
}

// GetCandles возвращает свечи из источника данных.
func (q *QuikClient) GetCandles(data GetCandlesRequest, ctx context.Context) ([]Candle, error) {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
Expand Down
55 changes: 54 additions & 1 deletion quik/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ local response_server
local response_client
local is_connected = false
local is_subscribed = false
local INTERVAL_TICKS = 1

-- Хранилище DataSource
local data_sources = {}
Expand Down Expand Up @@ -379,7 +380,17 @@ function OnTransReply(trans_reply)
end

function OnQuote(class_code, sec_code)
send_event("OnQuote", { class_code = class_code, sec_code = sec_code })
local msg = {}
local status, ql2 = pcall(getQuoteLevel2, class_code, sec_code)
if status then
msg.data = ql2
msg.data.class_code = class_code
msg.data.sec_code = sec_code

send_event("OnQuote", msg)
else
log("Ошибка при получении стакана для " .. sec_code, 3)
end
end

function OnConnected()
Expand Down Expand Up @@ -447,6 +458,46 @@ function OnInit(script_path)
log("QUIK# is initialized from "..script_path, 0)
end

-- Функция для подписки на обновления стакана котировок
function subscribe_to_order_book(class_code, sec_code)
local key = sec_code .. "|ORDERBOOK"
if data_sources[key] then
log("Подписка на стакан для " .. sec_code .. " уже существует.", 2)
return
end

-- Создаем DataSource для стакана котировок
local ds, err = create_data_source(class_code, sec_code, INTERVAL_TICKS)
if not ds then
log("Ошибка при создании DataSource для стакана " .. sec_code .. ": " .. err, 3)
return
end

-- Сохраняем DataSource в таблицу
data_sources[key] = ds

-- Callback-функция для обработки обновлений стакана
function OnData(ds)
local msg = {}
local status, ql2 = pcall(getQuoteLevel2, class_code, sec_code)
if status then
msg.data = ql2
msg.data.class_code = class_code
msg.data.sec_code = sec_code

-- Отправляем данные клиенту
send_event("OrderBookUpdate", msg)
else
log("Ошибка при получении стакана для " .. sec_code, 3)
end
end

-- Подписываемся на обновления
ds:SetUpdateCallback(OnData)

log("Подписка на стакан для " .. sec_code .. " успешно создана.", 1)
end

-- Функция отправки событий
function send_event(event_name, event_data)
if not event_client then
Expand All @@ -473,6 +524,8 @@ function process_request(request)
return handle_create_data_source(request.data)
elseif request.cmd == "closeDataSource" then
return handle_close_data_source(request.data)
elseif request.cmd == "subscribeOrderBook" then
return subscribe_to_order_book(request.data.class_code, request.data.sec_code)
elseif request.cmd == "getСandles" then
return handle_get_candles(request.data)
elseif request.cmd == "getTradeAccounts" then
Expand Down