def __QS_end__(self): self._Output["收益率"] = pd.DataFrame(self._Output["收益率"], index=self.QSEnv.FTM.DateSeries, columns=[args["测试因子"]]) self._Output["净值"] = (1 + self._Output["收益率"]).cumprod() self._Output["换手率"] = pd.DataFrame(self._Output["换手率"], index=self.QSEnv.FTM.DateSeries, columns=[args["测试因子"]]) self._Output["投资组合"] = pd.DataFrame(self._Output["投资组合"], index=self.QSEnv.FTM.DateSeries, columns=[args["测试因子"]]) nDate = self._Output["净值"].shape[0] nDays = (DateStr2Datetime(self.QSEnv.FTM.DateSeries[-1]) - DateStr2Datetime(self.QSEnv.FTM.DateSeries[0])).days nYear = nDays / 365 TotalReturn = self._Output["净值"].iloc[-1, :] - 1 self._Output["统计数据"] = pd.DataFrame(index=TotalReturn.index) self._Output["统计数据"]["总收益率"] = TotalReturn self._Output["统计数据"]["年化收益率"] = (1 + TotalReturn)**(1 / nYear) - 1 self._Output["统计数据"]["年化波动率"] = self._Output["收益率"].std() * np.sqrt( nDate / nYear) self._Output["统计数据"]["Sharpe比率"] = self._Output["统计数据"][ "年化收益率"] / self._Output["统计数据"]["年化波动率"] self._Output["统计数据"]["平均换手率"] = self._Output["换手率"].mean() self._Output["统计数据"]["最大回撤率"] = pd.Series(np.nan, self._Output["统计数据"].index) self._Output["统计数据"]["最大回撤开始时间"] = pd.Series( self._Output["统计数据"].index, dtype=np.dtype("O")) self._Output["统计数据"]["最大回撤结束时间"] = pd.Series( self._Output["统计数据"].index, dtype=np.dtype("O")) for iInd in self._Output["净值"].columns: iMaxDD, iStartPos, iEndPos = calcMaxDrawdownRate( self._Output["净值"].loc[:, iInd].values) self._Output["统计数据"]["最大回撤率"].loc[iInd] = abs(iMaxDD) self._Output["统计数据"]["最大回撤开始时间"].loc[iInd] = ( self._Output["净值"].index[iStartPos] if iStartPos is not None else None) self._Output["统计数据"]["最大回撤结束时间"].loc[iInd] = ( self._Output["净值"].index[iEndPos] if iEndPos is not None else None) if args["月度平均"]: self._Output["月度平均收益率"] = self.getMonthAvg(self._Output["收益率"]) self._Output["优化器"].endPC() self._Output.pop("优化器") return self._Output
def __QS_end__(self): if not self._isStarted: return 0 self._Output.pop("QP_P_CurPos") self._Output.pop("QP_P_MarketPos") for i in range(self.GroupNum): self._Output["净值"][i].pop(0) self._Output["净值"] = pd.DataFrame(np.array(self._Output["净值"]).T, index=self._Model.DateTimeSeries) self._Output["净值"]["市场"] = pd.Series(self._Output.pop("市场净值")[1:], index=self._Model.DateTimeSeries) self._Output["收益率"] = self._Output["净值"].iloc[ 1:, :].values / self._Output["净值"].iloc[:-1, :].values - 1 self._Output["收益率"] = pd.DataFrame( np.row_stack((np.zeros( (1, self.GroupNum + 1)), self._Output["收益率"])), index=self._Model.DateTimeSeries, columns=[i for i in range(self.GroupNum)] + ["市场"]) self._Output["收益率"]["L-S"] = self._Output[ "收益率"].iloc[:, 0] - self._Output["收益率"].iloc[:, -2] self._Output["净值"]["L-S"] = (1 + self._Output["收益率"]["L-S"]).cumprod() self._Output["换手率"] = pd.DataFrame(np.array(self._Output["换手率"]).T, index=self._Model.DateTimeSeries) self._Output["投资组合"] = { str(i): pd.DataFrame(self._Output["投资组合"][i], index=self._Output["调仓日"]) for i in range(self.GroupNum) } self._Output["超额收益率"] = self._Output["收益率"].copy() self._Output["超额净值"] = self._Output["超额收益率"].copy() for i in self._Output["超额收益率"]: self._Output["超额收益率"][ i] = self._Output["超额收益率"][i] - self._Output["收益率"]["市场"] self._Output["超额净值"][i] = (1 + self._Output["超额收益率"][i]).cumprod() nDate = self._Output["净值"].shape[0] nDays = (self._Model.DateTimeSeries[-1] - self._Model.DateTimeSeries[0]).days nYear = nDays / 365 TotalReturn = self._Output["净值"].iloc[-1, :] - 1 self._Output["统计数据"] = pd.DataFrame(index=TotalReturn.index) self._Output["统计数据"]["总收益率"] = TotalReturn self._Output["统计数据"]["年化收益率"] = (1 + TotalReturn)**(1 / nYear) - 1 self._Output["统计数据"]["波动率"] = self._Output["收益率"].std() * np.sqrt( nDate / nYear) self._Output["统计数据"]["Sharpe比率"] = self._Output["统计数据"][ "年化收益率"] / self._Output["统计数据"]["波动率"] self._Output["统计数据"]["t统计量(Sharpe比率)"] = ( self._Output["统计数据"]["Sharpe比率"] - self._Output["统计数据"]["Sharpe比率"]["市场"]) / np.sqrt(2 / nYear) self._Output["统计数据"]["平均换手率"] = self._Output["换手率"].mean() self._Output["统计数据"]["最大回撤率"] = pd.Series( np.nan, index=self._Output["统计数据"].index) self._Output["统计数据"]["最大回撤开始时间"] = pd.Series( index=self._Output["统计数据"].index, dtype="O") self._Output["统计数据"]["最大回撤结束时间"] = pd.Series( index=self._Output["统计数据"].index, dtype="O") for iCol in self._Output["净值"].columns: iMaxDD, iStartPos, iEndPos = calcMaxDrawdownRate( self._Output["净值"].loc[:, iCol].values) self._Output["统计数据"].loc[iCol, "最大回撤率"] = abs(iMaxDD) self._Output["统计数据"].loc[iCol, "最大回撤开始时间"] = ( self._Output["净值"].index[iStartPos] if iStartPos is not None else None) self._Output["统计数据"].loc[iCol, "最大回撤结束时间"] = ( self._Output["净值"].index[iEndPos] if iEndPos is not None else None) self._Output["统计数据"]["超额收益率"] = self._Output["超额净值"].iloc[-1, :] - 1 self._Output["统计数据"]["年化超额收益率"] = ( 1 + self._Output["统计数据"]["超额收益率"])**(1 / nYear) - 1 self._Output["统计数据"]["跟踪误差"] = self._Output["超额收益率"].std() * np.sqrt( nDate / nYear) self._Output["统计数据"]["信息比率"] = self._Output["统计数据"][ "年化超额收益率"] / self._Output["统计数据"]["跟踪误差"] self._Output["统计数据"][ "t统计量(信息比率)"] = self._Output["统计数据"]["信息比率"] * np.sqrt(nYear) self._Output["统计数据"]["胜率"] = (self._Output["超额收益率"] > 0).sum() / nDate self._Output["统计数据"]["超额最大回撤率"] = pd.Series( np.nan, index=self._Output["统计数据"].index) self._Output["统计数据"]["超额最大回撤开始时间"] = pd.Series( index=self._Output["统计数据"].index, dtype="O") self._Output["统计数据"]["超额最大回撤结束时间"] = pd.Series( index=self._Output["统计数据"].index, dtype="O") for iCol in self._Output["超额净值"].columns: iMaxDD, iStartPos, iEndPos = calcMaxDrawdownRate( self._Output["超额净值"].loc[:, iCol].values) self._Output["统计数据"].loc[iCol, "超额最大回撤率"] = abs(iMaxDD) self._Output["统计数据"].loc[iCol, "超额最大回撤开始时间"] = ( self._Output["超额净值"].index[iStartPos] if iStartPos is not None else None) self._Output["统计数据"].loc[iCol, "超额最大回撤结束时间"] = ( self._Output["超额净值"].index[iEndPos] if iEndPos is not None else None) self._Output["统计数据"]["CAPM Alpha"], self._Output["统计数据"][ "CAPM Beta"] = 0.0, 0.0 xData = sm.add_constant(self._Output["收益率"]["市场"].values, prepend=True) for iCol in self._Output["收益率"].columns: yData = self._Output["收益率"][iCol].values try: Result = sm.OLS(yData, xData, missing="drop").fit() self._Output["统计数据"].loc[iCol, "CAPM Beta"] = Result.params[1] self._Output["统计数据"].loc[iCol, "CAPM Alpha"] = Result.params[0] except: self._Output["统计数据"].loc[iCol, "CAPM Beta"] = np.nan self._Output["统计数据"].loc[iCol, "CAPM Alpha"] = np.nan self._Output.pop("调仓日") return 0
def __QS_end__(self): if not self._isStarted: return 0 super().__QS_end__() DTs = self._Model.DateTimeSeries self._Output["证券收益率"] = pd.DataFrame(self._Output["证券收益率"], index=DTs, columns=self._Output["证券ID"]) self._Output["证券净值"] = (self._Output["证券收益率"] + 1).cumprod() self._Output["因子值"] = pd.DataFrame(self._Output["因子值"], index=DTs, columns=self.FactorIDs) Groups = np.arange(1, self.GroupNum + 1).astype(str) Signal = self._Output["信号"] self._Output["信号"] = {} for i, iID in enumerate(self.FactorIDs): iSignal = pd.DataFrame(Signal[:, i, :], index=DTs, columns=Groups) iDTs = pd.notnull(iSignal).any(axis=1) iDTs = iDTs[iDTs].index if iDTs.shape[0] > 0: self._Output["信号"][iID] = iSignal.loc[iDTs[0]:] else: self._Output["信号"][iID] = pd.DataFrame(columns=Groups) SignalReturn = self._Output["信号收益率"] self._Output["信号收益率"] = {} self._Output["信号净值"] = {} self._Output["统计数据"] = {} nDate = len(DTs) nYear = (DTs[-1] - DTs[0]).days / 365 for j, jSecurityID in enumerate(self._Output["证券ID"]): self._Output["信号收益率"][jSecurityID] = {} self._Output["信号净值"][jSecurityID] = {} self._Output["统计数据"][jSecurityID] = {} for i, iID in enumerate(self.FactorIDs): ijSignalReturn = pd.DataFrame( SignalReturn[i, j, :, :], index=DTs, columns=Groups).loc[self._Output["信号"][iID].index] if ijSignalReturn.shape[0] == 0: self._Output["信号收益率"][jSecurityID][iID] = ijSignalReturn self._Output["信号净值"][jSecurityID][iID] = ijSignalReturn self._Output["统计数据"][jSecurityID][iID] = pd.DataFrame( index=ijSignalReturn.columns, columns=[ "总收益率", "年化收益率", "波动率", "Sharpe比率", "胜率", "最大回撤率", "最大回撤开始时间", "最大回撤结束时间" ]) else: ijNV = (1 + ijSignalReturn.fillna(0)).cumprod() self._Output["信号收益率"][jSecurityID][iID] = ijSignalReturn self._Output["信号净值"][jSecurityID][iID] = ijNV ijStat = pd.DataFrame(index=ijNV.columns) ijStat["总收益率"] = ijNV.iloc[-1, :] - 1 ijStat["年化收益率"] = ijNV.iloc[-1, :]**(1 / nYear) - 1 ijStat["波动率"] = ijSignalReturn.std() * np.sqrt( nDate / nYear) ijStat["Sharpe比率"] = ijStat["年化收益率"] / ijStat["波动率"] ijStat["胜率"] = (ijSignalReturn > 0 ).sum() / pd.notnull(ijSignalReturn).sum() ijStat["最大回撤率"] = pd.Series(np.nan, index=ijStat.index) ijStat["最大回撤开始时间"] = pd.Series(index=ijStat.index, dtype="O") ijStat["最大回撤结束时间"] = pd.Series(index=ijStat.index, dtype="O") for iCol in ijNV.columns: iMaxDD, iStartPos, iEndPos = calcMaxDrawdownRate( ijNV.loc[:, iCol].values) ijStat.loc[iCol, "最大回撤率"] = abs(iMaxDD) ijStat.loc[iCol, "最大回撤开始时间"] = (ijNV.index[iStartPos] if iStartPos is not None else None) ijStat.loc[iCol, "最大回撤结束时间"] = (ijNV.index[iEndPos] if iEndPos is not None else None) self._Output["统计数据"][jSecurityID][iID] = ijStat self._Output.pop("最新信号") self._Output.pop("因子符号") self._Output.pop("证券ID") return 0