У меня есть некоторые данные обмена из Bitmex, которые я получаю через API и WebSocket и сохраняю в базе данных SQL. Я создал таблицу под названием Свечи. Я создал столбцы из XML для того, что мне нужно. Bitmex может предоставлять только данные свечей за 1 мин, 5 мин, 1 час и 1 день.
Мне нужно как можно быстрее свернуть эти данные в разные временные рамки для моих разных торговых алгоритмов.
Сначала я начал писать функцию свертывания свечей в своей IDE, но как Вы можете представить себе количество данных, это будет длиться вечно, поскольку исходные данные относятся к 2015 году. Самая быстрая обработка, которую я мог бы выполнить, - 10 новых свечей в секунду.
Затем я немного прочитал и здесь, в StackOverFlow, рекомендуется создать хранимую процедуру в базе данных MS SQL. Я должен быть администратором, мои SQL знания по сравнению с большинством здесь очень ограничены, поэтому я выложил все это здесь для некоторого совета.
5 минут в качестве источника, имеет 484949 записей для свертывания. 1 час в качестве источника, имеет 40327 записей для свертывания.
Снимок экрана журнала, иллюстрирующий время, необходимое для свертывания каждого требуемого периода времени
Для свертывания требуется около 57 минут данные от 5 минут свечи в 15 минут. Требуется около 47 минут, чтобы свернуть данные из 5 минут свечей в 30 минут. Требуется около 7 минут, чтобы свернуть данные из 1-часовых свечей в 2-часовой. Требуется приблизительно 4 минуты, чтобы свернуть данные от 1-часовых свечей в 4-часовой. Требуется приблизительно 3 минуты, чтобы свернуть данные от 1-часовых свечей до 6-часового. Требуется около 2 минут, чтобы свернуть данные из 1-часовых свечей в 12-часовой.
Создайте свечу и хранимую процедуру ниже:
USE CryptoSwingTradeZ
create table Candles (
rID BIGINT PRIMARY KEY IDENTITY,
exchange varchar(50),
symbol varchar(20),
interval varchar(20),
timestampHuman_utc varchar(50),
timestamp_utc Decimal(30,0),
price_open Decimal(30,8),
price_close Decimal(30,8),
price_high Decimal(30,8),
price_low Decimal(30,8),
volume Decimal(30,8)
);
CREATE INDEX idx_interval ON Candles (interval);
CREATE INDEX idx_timestampHuman_utc ON Candles (timestampHuman_utc);
CREATE INDEX idx_timestamp_utc ON Candles (timestamp_utc);
CREATE INDEX idx_interval_timestamp_utc ON Candles (interval,timestamp_utc);
CREATE INDEX idx_exchange_interval_timestamp_utc ON Candles (exchange,interval,timestamp_utc);
GO
ALTER PROCEDURE dbo.spRollUpData
@desired_interval nvarchar(5),
@delete_source bit
AS
--DROP
--CREATE
--ALTER
DECLARE @exchange nvarchar(30) = 'BITMEX';
DECLARE @symbol nvarchar(10) = 'XBTUSD';
DECLARE @source_interval nvarchar(5);
DECLARE @interval_n int = 0;
DECLARE @interval_off_set int = 0;
DECLARE @timestamp_utc_source_start int;
DECLARE @timestamp_utc_source_end int;
DECLARE @timestamp_utc_range_start int;
DECLARE @timestamp_utc_range_end int;
DECLARE @Bitmex_utc_start int;
IF @delete_source = 1
DELETE FROM Candles WHERE interval = @desired_interval; --Use this if you want rebuild from scratch.
IF @desired_interval = '15m'
BEGIN
SET @Bitmex_utc_start = 1443184500;
SET @source_interval = '5m'
SET @interval_n = 10;
SET @interval_off_set = @interval_n;
END;
ELSE IF @desired_interval = '30m'
BEGIN
SET @Bitmex_utc_start = 1443184500;
SET @source_interval = '5m'
SET @interval_n = 20;
SET @interval_off_set = @interval_n;
END;
ELSE IF @desired_interval = '2h'
BEGIN
SET @Bitmex_utc_start = 1443189600;
SET @source_interval = '1h'
SET @interval_n = 2;
SET @interval_off_set = 60*(@interval_n);
END;
ELSE IF @desired_interval = '4h'
BEGIN
SET @Bitmex_utc_start = 1443193200;
SET @source_interval = '1h'
SET @interval_n = 4;
SET @interval_off_set = 60*(@interval_n);
END;
ELSE IF @desired_interval = '6h'
BEGIN
SET @Bitmex_utc_start = 1443186000;
SET @source_interval = '1h'
SET @interval_n = 6;
SET @interval_off_set = 60*(@interval_n);
END;
ELSE IF @desired_interval = '12h'
BEGIN
SET @Bitmex_utc_start = 1443186000;
SET @source_interval = '1h'
SET @interval_n = 12;
SET @interval_off_set = 60*(@interval_n);
END;
ELSE
BEGIN
PRINT 'spRollUpData - Not coded yet for ' + @desired_interval;
RETURN --exit immediately
END;
--Get the min and max of the timestamp_utc from the source interval
SELECT @timestamp_utc_source_start = ISNULL(min(timestamp_utc),0),
@timestamp_utc_source_end = ISNULL(MAX(timestamp_utc),0)
FROM Candles
WHERE interval = @source_interval;
--Get the max timestamp_utc from the desired interval
SELECT @timestamp_utc_range_start = ISNULL(MAX(timestamp_utc),0)
FROM Candles
WHERE interval = @desired_interval;
--This is to check that the source data to roll up from is available
if @timestamp_utc_source_start = 0
BEGIN
PRINT 'spRollUpData - Cannot role up data without SOURCE DATA!'
RETURN
END;
--Range start should be the desired last entry if it exists else use @Bitmex_utc_start above
if @timestamp_utc_range_start = 0
SET @timestamp_utc_range_start = @Bitmex_utc_start;
WHILE @timestamp_utc_range_start <= @timestamp_utc_source_end
BEGIN
INSERT INTO Candles
SELECT @exchange exchange,
@symbol symbol,
@desired_interval interval,
CandleOpenData.timestampHuman_utc timestampHuman_utc,
CandleOpenData.timestamp_utc timestamp_utc,
CandleOpenData.price_open price_open,
CandleCloseData.price_close price_close,
CandleSum.price_high price_high,
CandleSum.price_low price_low,
CandleSum.volume volume
FROM
(SELECT timestampHuman_utc,timestamp_utc,price_open
FROM Candles
WHERE exchange = @exchange
and interval = @source_interval
and timestamp_utc = @timestamp_utc_range_start ) CandleOpenData,
(SELECT
price_close
FROM Candles
WHERE exchange = @exchange
and interval = @source_interval
and timestamp_utc = @timestamp_utc_range_start + (60*@interval_off_set) ) CandleCloseData
,
(SELECT
max(price_high) price_high,
min(price_low) price_low,
sum(volume) volume
FROM Candles
WHERE exchange = @exchange
and interval = @source_interval
and timestamp_utc >= @timestamp_utc_range_start
and timestamp_utc <= @timestamp_utc_range_start + (60*@interval_off_set) ) CandleSum
WHERE NOT EXISTS (
SELECT timestamp_utc
FROM Candles
WHERE exchange = 'Bitmex'
and symbol = @symbol
and interval = @desired_interval
and timestamp_utc = @timestamp_utc_range_start
and CandleOpenData.timestamp_utc = timestamp_utc
);
SET @timestamp_utc_range_start = @timestamp_utc_range_start + (60*@interval_off_set);
END
GO
Таким образом, хранимая процедура будет использовать время запуска источника Я обеспечу это и закончу, когда все петли будут сделаны. Постепенно я получаю данные, необходимые для создания свечных данных, а затем вставляю.
Пример снимка экрана
На снимке экрана в качестве примера при запуске это через хранимую процедуру, это создаст 6 х 15 м свечи. Если запрос SELECT вернет менее 3 свечей за последний l oop, он проигнорирует его, поскольку он все еще не завершен.
Как я могу свернуть данные быстрее? :)