Вычислить * прокат * максимальная просадка панд серии
Это'Довольно легко написать функцию, которая вычисляет максимальную просадку временного ряда. Нужно немного подумать, чтобы написать это вO(n)
время вместоO(n^2)
время. Но это'не так уж и плохо. Это будет работать:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def max_dd(ser):
max2here = pd.expanding_max(ser)
dd2here = ser - max2here
return dd2here.min()
Позволять's, чтобы поиграть в короткую серию:
np.random.seed(0)
n = 100
s = pd.Series(np.random.randn(n).cumsum())
s.plot()
plt.show()
Как и ожидалось,max_dd(s)
в итоге показывает что-то прямо около -17,6. Хорошо, отлично, грандиозно. Теперь скажи мнеЯ заинтересован в расчете скользящей просадки этой серии. То есть для каждого шага я хочу вычислить максимальную просадку из предыдущей подсерии заданной длины. Это легко сделать с помощьюpd.rolling_apply
, Это работает так:
rolling_dd = pd.rolling_apply(s, 10, max_dd, min_periods=0)
df = pd.concat([s, rolling_dd], axis=1)
df.columns = ['s', 'rol_dd_10']
df.plot()
Это работает отлично. Но это чувствуется очень медленно. Есть ли в пандах или другом инструментарии особенно удобный алгоритм, чтобы сделать это быстро? Я сделал попытку написать что-то сделанное на заказ: он отслеживает все виды промежуточных данных (местоположения наблюдаемых максимумов, местоположения ранее обнаруженных просадок), чтобы сократить множество избыточных вычислений. Это экономит некоторое время, но не очень много, и не так много, как должно быть возможно.
Я думаю это's из-за всех накладных расходов зацикливания в Python / Numpy / Pandas. Но я'В настоящее время я недостаточно владею Cython, чтобы действительно знать, как начать атаку с этой точки зрения. Я надеялся, что кто-то пробовал это раньше. Или, может быть, кто-то захочет посмотреть на меня?ручной работы" код и будьте готовы помочь мне преобразовать его в Cython.
Редактировать: Для тех, кто хочет просмотреть все функции, упомянутые здесь (и некоторые другие!), Посмотрите на записную книжку iPython по адресу:http://nbviewer.ipython.org/gist/8one6/8506455
Он показывает, как соотносятся некоторые подходы к этой проблеме, проверяет, дают ли они одинаковые результаты, и показывает время их выполнения на данных разных размеров.
Если кому-то интересно, тосделанный на заказ» Алгоритм, на который я ссылался в своем посте,rolling_dd_custom
, Я думаю, что это может быть очень быстрое решение, если оно реализовано на Cython.