Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import numpy as np 

2 

3from statsmodels.tools.validation import array_like, PandasWrapper 

4 

5 

6# the data is sampled quarterly, so cut-off frequency of 18 

7 

8# Wn is normalized cut-off freq 

9#Cutoff frequency is that frequency where the magnitude response of the filter 

10# is sqrt(1/2.). For butter, the normalized cutoff frequency Wn must be a 

11# number between 0 and 1, where 1 corresponds to the Nyquist frequency, p 

12# radians per sample. 

13 

14 

15# NOTE: uses a loop, could probably be sped-up for very large datasets 

16def cffilter(x, low=6, high=32, drift=True): 

17 """ 

18 Christiano Fitzgerald asymmetric, random walk filter. 

19 

20 Parameters 

21 ---------- 

22 x : array_like 

23 The 1 or 2d array to filter. If 2d, variables are assumed to be in 

24 columns. 

25 low : float 

26 Minimum period of oscillations. Features below low periodicity are 

27 filtered out. Default is 6 for quarterly data, giving a 1.5 year 

28 periodicity. 

29 high : float 

30 Maximum period of oscillations. Features above high periodicity are 

31 filtered out. Default is 32 for quarterly data, giving an 8 year 

32 periodicity. 

33 drift : bool 

34 Whether or not to remove a trend from the data. The trend is estimated 

35 as np.arange(nobs)*(x[-1] - x[0])/(len(x)-1). 

36 

37 Returns 

38 ------- 

39 cycle : array_like 

40 The features of x between the periodicities low and high. 

41 trend : array_like 

42 The trend in the data with the cycles removed. 

43 

44 See Also 

45 -------- 

46 statsmodels.tsa.filters.bk_filter.bkfilter 

47 Baxter-King filter. 

48 statsmodels.tsa.filters.bk_filter.hpfilter 

49 Hodrick-Prescott filter. 

50 statsmodels.tsa.seasonal.seasonal_decompose 

51 Decompose a time series using moving averages. 

52 statsmodels.tsa.seasonal.STL 

53 Season-Trend decomposition using LOESS. 

54 

55 Examples 

56 -------- 

57 >>> dta = sm.datasets.macrodata.load_pandas().data 

58 >>> index = pd.DatetimeIndex(start='1959Q1', end='2009Q4', freq='Q') 

59 >>> dta.set_index(index, inplace=True) 

60 

61 >>> cf_cycles, cf_trend = sm.tsa.filters.cffilter(dta[["infl", "unemp"]]) 

62 

63 >>> import matplotlib.pyplot as plt 

64 >>> fig, ax = plt.subplots() 

65 >>> cf_cycles.plot(ax=ax, style=['r--', 'b-']) 

66 >>> plt.show() 

67 

68 .. plot:: plots/cff_plot.py 

69 """ 

70 #TODO: cythonize/vectorize loop?, add ability for symmetric filter, 

71 # and estimates of theta other than random walk. 

72 if low < 2: 

73 raise ValueError("low must be >= 2") 

74 pw = PandasWrapper(x) 

75 x = array_like(x, 'x', ndim=2) 

76 nobs, nseries = x.shape 

77 a = 2*np.pi/high 

78 b = 2*np.pi/low 

79 

80 if drift: # get drift adjusted series 

81 x = x - np.arange(nobs)[:, None] * (x[-1] - x[0]) / (nobs - 1) 

82 

83 J = np.arange(1, nobs + 1) 

84 Bj = (np.sin(b * J) - np.sin(a * J)) / (np.pi * J) 

85 B0 = (b - a) / np.pi 

86 Bj = np.r_[B0, Bj][:, None] 

87 y = np.zeros((nobs, nseries)) 

88 

89 for i in range(nobs): 

90 B = -.5 * Bj[0] - np.sum(Bj[1:-i - 2]) 

91 A = -Bj[0] - np.sum(Bj[1:-i - 2]) - np.sum(Bj[1:i]) - B 

92 y[i] = (Bj[0] * x[i] + np.dot(Bj[1:-i - 2].T, x[i + 1:-1]) + 

93 B * x[-1] + np.dot(Bj[1:i].T, x[1:i][::-1]) + A * x[0]) 

94 y = y.squeeze() 

95 

96 cycle, trend = y.squeeze(), x.squeeze() - y 

97 

98 return pw.wrap(cycle, append='cycle'), pw.wrap(trend, append='trend') 

99 

100 

101if __name__ == "__main__": 

102 import statsmodels as sm 

103 dta = sm.datasets.macrodata.load(as_pandas=False).data[['infl','tbilrate']].view((float,2))[1:] 

104 cycle, trend = cffilter(dta, 6, 32, drift=True) 

105 dta = sm.datasets.macrodata.load(as_pandas=False).data['tbilrate'][1:] 

106 cycle2, trend2 = cffilter(dta, 6, 32, drift=True)