У меня есть два набора данных с ценами валютных данных (максимум, минимум, открытие и закрытие) на двух разных таймфреймах (1 час и 5 минут).
У меня есть целевые цены для каждой строки данных 1-часового таймфрейма и целевое направление для сделки (либо 1, либо -1).
Для сделок с направлением «1» я пытаюсь найти первую точку на 5-минутном графике, где «минимум» <= целевого уровня. И наоборот, для сделок с направлением «-1» я хочу найти первую точку на 5-минутном графике, где «максимум» >= целевой уровень сделки.
Я разместил код ниже, чтобы продемонстрировать, что мне нужно.
Проблема, с которой я сталкиваюсь на практике, заключается в том, что я смотрю на периоды времени, охватывающие 10-20 лет, что делает соединения очень медленными. Я установил пример ниже с 2016 по 2022 год, чтобы он не был слишком медленным на моем компьютере, но если вы продлите его до более чем 10 лет, это действительно станет проблемой.
Это может быть то, с чем мне приходится жить, но я ищу руководство по двум вещам:
Заранее огромное спасибо, Фил
# Load required packages
library(data.table)
library(dplyr)
# Define timeframes for the data
Start <- as.POSIXct("2016-01-01 00:00:00")
End <- as.POSIXct("2022-01-01 23:55:00")
Hours <- floor(as.numeric(difftime(End,Start,units = "hours"))) + 1
Minutes <- floor(as.numeric(difftime(End,Start,units = "mins")) / 5) + 1
# Create the Hourly data
set.seed(123)
hourly_prices <- data.table(
datetime = seq(Start, End, by = "hour"),
open = rnorm(Hours, mean = 100, sd = 1),
high = rnorm(Hours, mean = 101, sd = 1),
low = rnorm(Hours, mean = 99, sd = 1),
close = rnorm(Hours, mean = 100, sd = 1),
Direction = sample(c(1,-1),Hours,replace = T)) %>%
.[,Target_price := ifelse(Direction == -1,rnorm(.N, mean = 104, sd = 1),rnorm(.N,mean = 97,sd = 1))]
# Create the 5-minute data
set.seed(456)
minute_prices <- data.table(
datetime = seq(Start, End, by = "5 min"),
open = rnorm(Minutes, mean = 100, sd = 1),
high = rnorm(Minutes, mean = 101, sd = 1),
low = rnorm(Minutes, mean = 99, sd = 1),
close = rnorm(Minutes, mean = 100, sd = 1),
Position = seq_len(Minutes))
# Join the two data.tables to find the first point at which price passes the target levels
hourly_prices[(Direction == 1),Location := minute_prices[.SD, on = .(datetime > datetime, low <= Target_price),mult = "first",x.Position]]
hourly_prices[(Direction == -1),Location := minute_prices[.SD, on = .(datetime > datetime, high >= Target_price),mult = "first",x.Position]]
Одно простое ускорение примерно в 3 раза состоит в том, чтобы подмножить minute_prices
data.table
, чтобы включить только те строки, которые являются кумулятивным минимумом/максимумом за текущий час (минус 1 секунда, так как соединение datetime > datetime
):
dtM <- copy(minute_prices)
dtH <- copy(hourly_prices)
system.time({
dtH[(Direction == 1),Location := dtM[dtM[, low == cummin(low), as.integer(datetime - 1)%/%3600L][[2]]][.SD, on = .(datetime > datetime, low <= Target_price),mult = "first",x.Position]]
dtH[(Direction == -1),Location := dtM[dtM[, high == cummax(high), as.integer(datetime - 1)%/%3600L][[2]]][.SD, on = .(datetime > datetime, high >= Target_price),mult = "first",x.Position]]
})
#> user system elapsed
#> 6.77 0.01 6.81
system.time({
hourly_prices[(Direction == 1),Location := minute_prices[.SD, on = .(datetime > datetime, low <= Target_price),mult = "first",x.Position]]
hourly_prices[(Direction == -1),Location := minute_prices[.SD, on = .(datetime > datetime, high >= Target_price),mult = "first",x.Position]]
})
#> user system elapsed
#> 22.97 0.00 23.04
identical(dtH, hourly_prices)
#> [1] TRUE
Вышеприведенный код выглядит нормально и сравнивает не менее 215 миллионов дат. Производительность уже неплохая.