1

Suppose you have a dataframe with 1000 closing prices. You want to apply a risk calculation function (let's say VaR) named compute_var() on last 90 closing prices, on a rolling basis. How would you do it? I presume with apply():

def compute_var(df):
       return do_calculations_on(df[-90:])

def compute_rolling_var(self):
       self.var = self.closing.apply(compute_var)

Problem is that .apply only passes 1 day closing to compute_var, and not a dataframe. So it gives an error.

The only working solution I found is with iteration-style algo (.iterrow()): I pass the iteration index to compute_var and it crops the closing dataframe self.closing[:i] before performing calculation on the last 90 rows, then it populates the df.var dataframe via .loc(i) = computer_var_value.

I suspect there is a better way.

cs95
  • 379,657
  • 97
  • 704
  • 746
comte
  • 3,092
  • 5
  • 25
  • 41
  • 1
    I think you're looking for [`rolling_apply`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.rolling_apply.html#pandas.rolling_apply) it accepts a window param – EdChum Jun 12 '15 at 15:30
  • Seems that `rolling_apply` has been deprecated in favor of [`rolling.apply`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.core.window.Rolling.apply.html) – KT12 Mar 18 '19 at 18:50

1 Answers1

1

answer is apply_rolling as underlined by EdChum + min_periods adjustment

Problem came from a few NaN values in input data, and min_periods=None by default, which reacts as if no NaN value is allowed in your window (90 days here). Seems very counter-intuitive to me, but setting min_periods=1 resolved my issue.

cs95
  • 379,657
  • 97
  • 704
  • 746
comte
  • 3,092
  • 5
  • 25
  • 41
  • If you have solved your problem, please provide an answer and accept it, rather than editing the solution into the question. – euri10 Nov 30 '15 at 16:24