def VolatilityRegimeAdjustment(ret, forcast_volitility, half_life=90, forcast_num=21): BiasStats = pd.Series(np.nan, index=forcast_volitility.index) for i, iDate in enumerate(forcast_volitility.index): iInd = (ret.index <= iDate).sum() - 1 if forcast_num > 0: if ret.shape[0] >= iInd + forcast_num + 1: iRet = (1 + ret.iloc[iInd + 1:iInd + forcast_num + 1]).prod() - 1 else: continue else: if i == forcast_volitility.shape[0] - 1: continue else: iNextDate = forcast_volitility.index[i + 1] iNextInd = (ret.index <= iNextDate).sum() - 1 iRet = (1 + ret.iloc[iInd + 1:iNextInd + 1]).prod() - 1 iTemp = (iRet / forcast_volitility.loc[iDate])**2 BiasStats.loc[iDate] = iTemp.sum() / pd.notnull(iTemp).sum() BiasStats = BiasStats[pd.notnull(BiasStats)] Weight = getExpWeight(ret.shape[0], half_life=half_life, is_unitized=False) Weight.reverse() Weight = pd.Series(Weight, index=ret.index) Weight = Weight[BiasStats.index] / Weight[BiasStats.index].sum() return (Weight * BiasStats**2).sum()**0.5
def estimateSampleCovMatrix_EWMA(ret, forcast_num=1, half_life=np.inf): Weight = np.flipud(np.array(getExpWeight(ret.shape[0], half_life))) Weight = np.repeat(np.reshape(Weight, (ret.shape[0], 1)), ret.shape[1], axis=1) Mask = (~np.isnan(ret)) Weight = Weight * Mask WeightSqrt = Weight**0.5 ret = np.copy(ret) ret[~Mask] = 0.0 ret = ret * WeightSqrt TotalWeight = np.dot(WeightSqrt.T, WeightSqrt) TotalWeight[TotalWeight == 0] = np.nan BiasAdjust = (TotalWeight**2 - np.dot(Weight.T, Weight)) BiasAdjust[BiasAdjust == 0] = np.nan BiasAdjust = TotalWeight**2 / BiasAdjust AvgRet1 = np.dot(ret.T, WeightSqrt) / TotalWeight AvgRet2 = np.dot(WeightSqrt.T, ret) / TotalWeight CovMatrix = (np.dot(ret.T, ret) / TotalWeight - AvgRet1 * AvgRet2) * BiasAdjust Vol = np.diag(CovMatrix)**0.5 Temp = ( (np.dot((ret**2).T, Mask) / TotalWeight - AvgRet1**2) * (np.dot(Mask.T, ret**2) / TotalWeight - AvgRet2**2))**0.5 * BiasAdjust Temp[Temp == 0] = np.nan CovMatrix = (CovMatrix / Temp * Vol).T * Vol return (CovMatrix.T + CovMatrix) / 2 * forcast_num
def estimateCovMatrix(ret, forcast_num=21, auto_corr_num=10, half_life=480, calc_cov=True): if forcast_num > auto_corr_num + 1: N = auto_corr_num else: N = forcast_num - 1 Weight = np.flipud(np.array(getExpWeight(ret.shape[0], half_life))) if calc_cov: CovMatrix = pd.DataFrame(np.nan, index=ret.columns, columns=ret.columns) for j, jCol in enumerate(ret.columns): for kCol in ret.columns[j:]: jRet = ret[jCol].values kRet = ret[kCol].values Covs = np.zeros(N * 2 + 1) Coefs = np.zeros(N * 2 + 1) for Delta in range(-N, N + 1): Coefs[Delta + N] = N + 1 - np.abs(Delta) Covs[Delta + N] = calcCovariance(jRet, kRet, Weight, Delta) CovMatrix[jCol][kCol] = np.nansum(Coefs * Covs) CovMatrix[kCol][jCol] = CovMatrix[jCol][kCol] else: Columns = ret.columns CovMatrix = np.zeros(ret.shape[1]) + np.nan ret = ret.values for j in range(ret.shape[1]): jRet = ret[:, j] Covs = np.zeros(N * 2 + 1) Coefs = np.zeros(N * 2 + 1) for Delta in range(-N, N + 1): Coefs[Delta + N] = N + 1 - np.abs(Delta) Covs[Delta + N] = calcCovariance(jRet, jRet, Weight, Delta) CovMatrix[j] = np.nansum(Coefs * Covs) CovMatrix = pd.Series(CovMatrix, index=Columns) CovMatrix = CovMatrix * forcast_num / (N + 1) return CovMatrix