The Pandas rolling_mean and rolling_std functions have been deprecated and replaced by a more general "rolling" framework. @elyase's example can be modified to:
import pandas as pd
import numpy as np
%matplotlib inline
# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()
#plot the time series
ts.plot(style='k--')
# calculate a 60 day rolling mean and plot
ts.rolling(window=60).mean().plot(style='k')
# add the 20 day rolling standard deviation:
ts.rolling(window=20).std().plot(style='b')
The rolling function supports a number of different window types, as documented here. A number of functions can be called on the rolling object, including var and other interesting statistics (skew, kurt, quantile, etc.). I've stuck with std since the plot is on the same graph as the mean, which makes more sense unit-wise.
The Pandas rolling_mean and rolling_std functions have been deprecated and replaced by a more general "rolling" framework. @elyase's example can be modified to:
import pandas as pd
import numpy as np
%matplotlib inline
# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()
#plot the time series
ts.plot(style='k--')
# calculate a 60 day rolling mean and plot
ts.rolling(window=60).mean().plot(style='k')
# add the 20 day rolling standard deviation:
ts.rolling(window=20).std().plot(style='b')
The rolling function supports a number of different window types, as documented here. A number of functions can be called on the rolling object, including var and other interesting statistics (skew, kurt, quantile, etc.). I've stuck with std since the plot is on the same graph as the mean, which makes more sense unit-wise.
You should take a look at pandas. For example:
import pandas as pd
import numpy as np
# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()
#plot the time series
ts.plot(style='k--')
# calculate a 60 day rolling mean and plot
pd.rolling_mean(ts, 60).plot(style='k')
# add the 20 day rolling variance:
pd.rolling_std(ts, 20).plot(style='b')

If you know, given a series, how to compute the semi std - then you use .rolling().apply() with that function.
Using the definition from https://www.investopedia.com/terms/s/semideviation.asp

We cannot use the built-in std because we need to use the whole group average, but only compute deviations based on those observations in the group that are below the average.
Looks like we'll need to define the semi-deviation as a function:
import numpy as np
def semi_std(ser):
average = np.nanmean(ser)
r_below = ser[ser < average]
return np.sqrt(1/len(r_below) * np.sum((average - r_below)**2))
x.rolling(window).apply(semi_std, raw=True)
# using raw=True speeds up the computation - this is applicable
# if the function works well with a numpy array instead of a Series
# also, if possible, investigate using numba.
I think for maximum robustness, probably add a condition that if len(r_below) == 0 then the result is 0 or NaN (it's a matter of definition - but 0 is probably the reasonable choice).
The solution is actually pretty simple if one knows how rolling windows work in Pandas. The trick here is to use the shift function on the dataframe first which shifts each row by one position so it becomes the last element of the previous row. Then we can do our rolling mean calculation without having any issues with type conversion etc.
import pandas as pd
from datetime import timedelta
df = pd.DataFrame(data=np.random.randn(5, 4), index=pd.date_range('1/1/2000', periods=5))
df.index = df.index + timedelta(days=10)
print(df)