Алгоритмически обнаруживать скачки во временном ряду - PullRequest
3 голосов
/ 07 мая 2019

У меня есть около 50 наборов данных, которые включают все сделки в течение 30 дней для 10 пар на 5 биржах.Все пары относятся к одному и тому же классу активов, что означает, что они сильно коррелированы и ожидают, что будут иметь одинаковые свойства, но в разных масштабах.Примером этих данных будет

set.seed(1)

n <- 1000
dates <- seq(as.POSIXct("2019-08-05 00:00:00", tz="UTC"), as.POSIXct("2019-08-05 23:59:00", tz="UTC"), by="1 min")
x <- data.frame("t" = sort(sample(dates, 1000)),"p" = cumsum(sample(c(-1, 1), n, TRUE)))

Plot example

Грубо говоря, мне нужно определить соответствующие локальные минимумы и максимумы, которые происходят ежедневно.Желтые отметки - мои достопримечательности.В отличие от этого примера, обычно есть только одна такая точка в день, и я рассматриваю каждый день отдельно.Тем не менее, трудно отфильтровать шум из моих реальных достопримечательностей.

Моя настоящая цель - найти точную точку, в которой пара начала совершать прыжок, и точную точку, в которой произошел прыжок.кончено.Это должно быть как можно более точным, так как я хочу наблюдать, какой актив перемещался первым, а какой актив следовал в какой-то момент времени (как сказано, они сильно коррелированы).Между двумя экстремальными значениями я хочу минимизировать расстояние и максимизировать относительное / абсолютное изменение, так как мои достопримечательности обычно близки друг к другу, и их разница довольно велика.

Я уже смотрел на другие вопросы, такие как Поиск локальных максимумов и минимумов и Алгоритм определения местоположения локальных максимумов , а также этот алгоритм, имеющий ту же цель.Тем не менее, мой набор данных очень шумно.Я уже сократил набор данных до 5-минутных интервалов, однако это привело к отсутствию соответствующих точек в функциях для определения локальных минимумов и максимумов.Следовательно, это было не очень хорошее решение, учитывая мою цель.

Как мне достичь своей цели с помощью довольно точного алгоритма?Просматривать все временные ряды вручную невозможно, так как для этого потребуется вручную оценивать временные ряды 50 * 30, что отнимает слишком много времени.Я действительно озадачен и пытаюсь найти подходящее решение на неделю.

Если потребуется больше фрагментов кода, я рад поделиться, однако они не дали мне значимых результатов, что было бы противк идее предоставления минимального рабочего примера, поэтому я решил пока их оставить.

РЕДАКТИРОВАТЬ: Во-первых, я обновил график и добавил временные метки в набор данных, чтобы дать вамидея (фактическое разрешение).В идеале алгоритм должен обнаруживать оба перехода слева.Внутренние две точки, потому что они ближе друг к другу и прыгают без перехвата, а внешние точки, потому что они более экстремальны в ценностях.Фактически, это может быть ответом на вопрос, разрешено ли алгоритму заглядывать в будущее.Да, если есть еще один локальный экстремум в диапазоне, скажем, 30 наблюдений (или 30 минут), тогда игнорируйте промежуточные локальные экстремумы.По моим данным, скачки были от 2% до ~ 15%, так что скачок должен составлять не менее 2%, чтобы его учитывать.И только если порог в 15 (это может быть адаптировано) последовательных шагов в одном и том же направлении до / после достижения пиков и впадин.

Очень наивный подход состоял в том, чтобы поместить данные вокруг глобального минимума и максимумадня.В большинстве случаев это обесценивало данные и работало как индикатор.Однако это не является надежным, когда глобальные экстремумы не находятся в диапазоне скачка.

Надеюсь, это проясняет, почему это не статистический вопрос (есть некоторые тесты, чтобы определить, произошел ли скачок, ноне для времени прибытия прыжка afaik).


В случае, если кому-то нужен реальный пример: this является соответствующим графиком, this является необработанными даннымисоответствующий период и это является сокращенным набором данных.


1 Ответ

1 голос
/ 09 мая 2019

Возможно, в качестве отправной точки, посмотрите на функцию streaks в пакете PMwR (который я поддерживаю). Полоса определяется как движение определенного размера, который не прерывается противодействием того же размера. функция работает с возвратами, а не с различиями, поэтому добавлю 100 к вашим данным.

Например:

set.seed(1)
n <- 1000
x <- 100 + cumsum(sample(c(-1, 1), n, TRUE))

plot(x, type = "l")
s <- streaks(x, 0.12, -0.12)
abline(v = s[, 1])
abline(v = s[, 2])

Вертикальные линии показывают начало и конец полос.

Streaks

Возможно, вы сможете отфильтровать идентифицированные полосы по требуемым критериям, таким как длина. Или же вы можете поиграть с разными порогами для до и ходы вниз (хотя это не очень рекомендуется в текущей реализации, но, возможно, результаты достаточно хороши). Например, полосы вверх могут выглядеть следующим образом. Зеленая вертикаль показывает начало полосы; красная линия показывает его конец.

plot(x, type = "l")
s <- streaks(x, up = 0.12, down = -0.05)
s <- s[!is.na(s$state) & s$state == "up", ]
abline(v = s[, 1], col = "green")
abline(v = s[, 2], col = "red")

Up streaks

...