def genSignal(self, idt, trading_record): if self.RiskTable is not None: self.RiskTable.move(idt) IDs = self._PC.TargetIDs = self._FT.getID(idt=idt) if self.TargetIDs: self._PC.TargetIDs = self._FT.getFilteredID(idt=idt, ids=IDs, id_filter_str=self.TargetIDs) if self._Dependency.get("预期收益", False): self._PC.ExpectedReturn = self._FT.readData(factor_names=[self.ExpectedReturn], ids=IDs, dts=[idt]).iloc[0, 0, :] if self._Dependency.get("协方差矩阵", False): if isinstance(self.RiskTable, FactorRT): self._PC.FactorCov = self.RiskTable.readFactorCov(dts=[idt]).iloc[0] self._PC.RiskFactorData = self.RiskTable.readFactorData(dts=[idt], ids=IDs).iloc[:, 0] self._PC.SpecificRisk = self.RiskTable.readSpecificRisk(dts=[idt], ids=IDs).iloc[0] else: self._PC.CovMatrix = dropRiskMatrixNA(self.RiskTable.readCov(dts=[idt], ids=IDs)) if self._Dependency.get("成交金额", False): self._PC.AmountFactor = self._FT.readData(factor_names=[self.AmountFactor], ids=IDs, dts=[idt]).iloc[0, 0, :] if self._Dependency.get("因子", []): self._PC.FactorData = self._FT.readData(factor_names=self._Dependency["因子"], ids=IDs, dts=[idt]).iloc[:, 0, :] if self._Dependency.get("基准投资组合", False): self._PC.BenchmarkHolding = self._FT.readData(factor_names=[self.BenchmarkFactor], ids=IDs, dts=[idt]).iloc[0, 0, :] if self._Dependency.get("初始投资组合", False): AccountValue = self.TargetAccount.AccountValue if AccountValue!=0: self._PC.Holding = self.TargetAccount.PositionAmount / abs(AccountValue) else: self._PC.Holding = pd.Series(0.0, index=self.TargetAccount.PositionAmount.index) if self._Dependency.get("总财富", False): self._PC.Wealth = self.TargetAccount.AccountValue RawSignal, ResultInfo = self._PC.solve() if ResultInfo.get("Status", 1)!=1: self._Status.append((idt, ResultInfo)) if self.SignalAdjustment.Display: self._QS_Logger.error(idt.strftime("%Y-%m-%d %H:%M:%S.%f")+" : 错误代码-"+str(ResultInfo["ErrorCode"])+" "+ResultInfo["Msg"])# debug if ResultInfo["ReleasedConstraint"]: self._ReleasedConstraint.append((idt, ResultInfo["ReleasedConstraint"])) if self.SignalAdjustment.Display: self._QS_Logger.error(idt.strftime("%Y-%m-%d %H:%M:%S.%f")+" : 舍弃约束-"+str(ResultInfo["ReleasedConstraint"]))# debug return self._adjustSignal(RawSignal)
def __QS_move__(self, idt, **kwargs): if self._iDT == idt: return 0 self._iDT = idt if self.CalcDTs: if idt not in self.CalcDTs[self._CurCalcInd:]: return 0 self._CurCalcInd = self.CalcDTs[self._CurCalcInd:].index( idt) + self._CurCalcInd else: self._CurCalcInd = self._Model.DateTimeIndex IDs = self._FactorTable.getFilteredID(idt=idt, id_filter_str=self.IDFilter) FactorExpose = self._FactorTable.readData( dts=[idt], ids=IDs, factor_names=list(self.TestFactors)).iloc[:, 0, :].astype("float") if self._CorrMatrixNeeded and (self.RiskTable is not None): self.RiskTable.move(idt) CovMatrix = dropRiskMatrixNA( self.RiskTable.readCov(dts=[idt], ids=IDs).iloc[0]) FactorIDs = {} else: CovMatrix = None PairInd = 0 for i, iFactor in enumerate(self.TestFactors): iFactorExpose = FactorExpose[iFactor] if self._CorrMatrixNeeded: iIDs = FactorIDs.get(iFactor) if iIDs is None: if CovMatrix is not None: FactorIDs[iFactor] = list( set(CovMatrix.index).intersection( set(iFactorExpose[pd.notnull( iFactorExpose)].index))) else: FactorIDs[iFactor] = list( iFactorExpose[pd.notnull(iFactorExpose)].index) iIDs = FactorIDs[iFactor] for j, jFactor in enumerate(self.TestFactors): if j > i: jFactorExpose = FactorExpose[jFactor] if self._CorrMatrixNeeded: jIDs = FactorIDs.get(jFactor) if jIDs is None: if CovMatrix is not None: FactorIDs[jFactor] = list( set(CovMatrix.index).intersection( set(jFactorExpose[pd.notnull( jFactorExpose)].index))) else: FactorIDs[jFactor] = list(jFactorExpose[ pd.notnull(jFactorExpose)].index) jIDs = FactorIDs[jFactor] IDs = list(set(iIDs).intersection(set(jIDs))) iTempExpose = iFactorExpose.loc[IDs].values jTempExpose = jFactorExpose.loc[IDs].values if CovMatrix is not None: TempCovMatrix = CovMatrix.loc[IDs, IDs].values else: nID = len(IDs) TempCovMatrix = np.eye(nID, nID) for kMethod in self.CorrMethod: if kMethod == "factor-score correlation": ijCov = np.dot(iTempExpose.T, np.dot(TempCovMatrix, jTempExpose)) iStd = np.sqrt( np.dot(iTempExpose.T, np.dot(TempCovMatrix, iTempExpose))) jStd = np.sqrt( np.dot(jTempExpose.T, np.dot(TempCovMatrix, jTempExpose))) self._Output[kMethod][PairInd].append(ijCov / iStd / jStd) elif kMethod == "factor-portfolio correlation": TempCovMatrixInv = np.linalg.inv(TempCovMatrix) ijCov = np.dot( iTempExpose.T, np.dot(TempCovMatrixInv, jTempExpose)) iStd = np.sqrt( np.dot(iTempExpose.T, np.dot(TempCovMatrixInv, iTempExpose))) jStd = np.sqrt( np.dot(jTempExpose.T, np.dot(TempCovMatrixInv, jTempExpose))) self._Output[kMethod][PairInd].append(ijCov / iStd / jStd) else: self._Output[kMethod][PairInd].append( FactorExpose[iFactor].corr( FactorExpose[jFactor], method=kMethod)) PairInd += 1 self._Output["时点"].append(idt) return 0
def __QS_move__(self, idt, **kwargs): if self._iDT == idt: return 0 self._iDT = idt if self.CalcDTs: if idt not in self.CalcDTs[self._CurCalcInd:]: return 0 self._CurCalcInd = self.CalcDTs[self._CurCalcInd:].index( idt) + self._CurCalcInd LastInd = self._CurCalcInd - 1 LastDateTime = self.CalcDTs[LastInd] else: self._CurCalcInd = self._Model.DateTimeIndex LastInd = self._CurCalcInd - 1 LastDateTime = self._Model.DateTimeSeries[LastInd] if (LastInd < 0): return 0 IDs = self._FactorTable.getFilteredID(idt=idt, id_filter_str=self.IDFilter) LastCovMatrix, self._CovMatrix = self._CovMatrix, dropRiskMatrixNA( self.RiskTable.readCov(dts=[idt], ids=IDs).iloc[0]) IDs = self._CovMatrix.index.tolist() LastPortfolios, self._Portfolios = self._Portfolios, self._genPortfolio( idt, IDs) if not LastPortfolios: AllPortfolioNames = list(self._Portfolios) self._Output["Z-Score"] = pd.DataFrame(columns=AllPortfolioNames) self._Output["Robust Z-Score"] = pd.DataFrame( columns=AllPortfolioNames) self._Output["Bias 统计量"] = pd.DataFrame(columns=AllPortfolioNames) self._Output["Robust Bias 统计量"] = pd.DataFrame( columns=AllPortfolioNames) return 0 else: self._Output["Robust Bias 统计量"].loc[idt] = self._Output[ "Bias 统计量"].loc[idt] = self._Output["Robust Z-Score"].loc[ idt] = self._Output["Z-Score"].loc[idt] = np.nan Price = self._FactorTable.readData( dts=[LastDateTime, idt], ids=self._FactorTable.getID(ifactor_name=self.PriceFactor), factor_names=[self.PriceFactor]).iloc[0] Return = Price.iloc[1] / Price.iloc[0] - 1 for jPortfolioName, jPortfolio in LastPortfolios.items(): jCovMatrix = LastCovMatrix.loc[jPortfolio.index, jPortfolio.index] jStd = np.dot(np.dot(jPortfolio.values, jCovMatrix.values), jPortfolio.values)**0.5 jReturn = (Return[jPortfolio.index] * jPortfolio).sum() self._Output["Z-Score"].loc[idt, jPortfolioName] = jReturn / jStd self._Output["Robust Z-Score"].loc[idt, jPortfolioName] = max( (-3, min((3, jReturn / jStd)))) if self._Output["Z-Score"].shape[0] >= self.LookBack: self._Output["Bias 统计量"].loc[ idt, jPortfolioName] = self._Output["Z-Score"][ jPortfolioName].iloc[-self.LookBack:].std() self._Output["Robust Bias 统计量"].loc[ idt, jPortfolioName] = self._Output["Robust Z-Score"][ jPortfolioName].iloc[-self.LookBack:].std() AllPortfolioNames = list(LastPortfolios) self._Output["Z-Score"] = self._Output[ "Z-Score"].loc[:, AllPortfolioNames] self._Output["Robust Z-Score"] = self._Output[ "Robust Z-Score"].loc[:, AllPortfolioNames] self._Output["Bias 统计量"] = self._Output[ "Bias 统计量"].loc[:, AllPortfolioNames] self._Output["Robust Bias 统计量"] = self._Output[ "Robust Bias 统计量"].loc[:, AllPortfolioNames] return 0
def __QS_move__(self, idt, **kwargs): if self._iDT == idt: return 0 self._iDT = idt PreDT = None if self.CalcDTs: if idt not in self.CalcDTs[self._CurCalcInd:]: return 0 self._CurCalcInd = self.CalcDTs[self._CurCalcInd:].index( idt) + self._CurCalcInd if self._CurCalcInd > 0: PreDT = self.CalcDTs[self._CurCalcInd - 1] else: self._CurCalcInd = self._Model.DateTimeIndex if self._CurCalcInd > 0: PreDT = self._Model.DateTimeSeries[self._CurCalcInd - 1] if PreDT is None: return 0 Portfolio = self._FactorTable.readData(factor_names=[self.Portfolio], dts=[PreDT], ids=self._IDs).iloc[0, 0] Portfolio = self._normalizePortfolio(Portfolio[pd.notnull(Portfolio) & (Portfolio != 0)]) if self.BenchmarkPortfolio != "无": BenchmarkPortfolio = self._FactorTable.readData( factor_names=[self.BenchmarkPortfolio], dts=[PreDT], ids=self._IDs).iloc[0, 0] BenchmarkPortfolio = self._normalizePortfolio( BenchmarkPortfolio[pd.notnull(BenchmarkPortfolio) & (BenchmarkPortfolio != 0)]) IDs = Portfolio.index.union(BenchmarkPortfolio.index) if Portfolio.shape[0] > 0: Portfolio = Portfolio.loc[IDs] Portfolio.fillna(0.0, inplace=True) else: Portfolio = pd.Series(0.0, index=IDs) if BenchmarkPortfolio.shape[0] > 0: BenchmarkPortfolio = BenchmarkPortfolio.loc[IDs] BenchmarkPortfolio.fillna(0.0, inplace=True) else: BenchmarkPortfolio = pd.Series(0.0, index=IDs) Portfolio = Portfolio - BenchmarkPortfolio # 计算因子模拟组合 self.RiskTable.move(PreDT, **kwargs) CovMatrix = dropRiskMatrixNA( self.RiskTable.readCov(dts=[PreDT], ids=Portfolio.index.tolist()).iloc[0]) FactorExpose = self._FactorTable.readData( factor_names=list(self.AttributeFactors), ids=IDs, dts=[PreDT]).iloc[:, 0].dropna(axis=0) IDs = FactorExpose.index.intersection(CovMatrix.index).tolist() CovMatrix, FactorExpose = CovMatrix.loc[IDs, IDs], FactorExpose.loc[IDs, :] if self.IndustryFactor != "无": IndustryData = self._FactorTable.readData( factor_names=[self.IndustryFactor], ids=IDs, dts=[PreDT]).iloc[0, 0, :] DummyData = DummyVarTo01Var(IndustryData, ignore_nonstring=True) DummyData.columns.values[pd.isnull(DummyData.columns)] = "None" FactorExpose = pd.merge(FactorExpose, DummyData, left_index=True, right_index=True) CovMatrixInv = np.linalg.inv(CovMatrix.values) FMPHolding = np.dot( np.dot( np.linalg.inv( np.dot(np.dot(FactorExpose.values.T, CovMatrixInv), FactorExpose.values)), FactorExpose.values.T), CovMatrixInv) # 计算持仓对因子模拟组合的投资组合 Portfolio = self._normalizePortfolio(Portfolio.loc[IDs]) Beta = np.dot( np.dot( np.dot( np.linalg.inv( np.dot(np.dot(FMPHolding, CovMatrix.values), FMPHolding.T)), FMPHolding), CovMatrix.values), Portfolio.values) Price = self._FactorTable.readData(factor_names=[self.PriceFactor], dts=[PreDT, idt], ids=IDs).iloc[0] Return = Price.iloc[1] / Price.iloc[0] - 1 # 计算各统计指标 if FactorExpose.shape[1] > self._Output["因子暴露"].shape[1]: FactorNames = FactorExpose.columns.tolist() self._Output["因子暴露"] = self._Output["因子暴露"].loc[:, FactorNames] self._Output["风险调整的因子暴露"] = self._Output[ "风险调整的因子暴露"].loc[:, FactorNames] self._Output["风险贡献"] = self._Output["风险贡献"].loc[:, FactorNames + ["Alpha"]] self._Output["收益贡献"] = self._Output["收益贡献"].loc[:, FactorNames + ["Alpha"]] self._Output["因子收益"] = self._Output["因子收益"].loc[:, FactorNames] self._Output["因子暴露"].loc[PreDT, FactorExpose.columns] = Beta self._Output["风险调整的因子暴露"].loc[PreDT, FactorExpose.columns] = np.sqrt( np.diag(np.dot(np.dot(FMPHolding, CovMatrix.values), FMPHolding.T))) * Beta RiskContribution = np.dot(np.dot( FMPHolding, CovMatrix.values), Portfolio.values) / np.sqrt( np.dot(np.dot(Portfolio.values, CovMatrix.values), Portfolio.values)) * Beta self._Output["风险贡献"].loc[idt, FactorExpose.columns] = RiskContribution self._Output["风险贡献"].loc[idt, "Alpha"] = np.sqrt( np.dot(np.dot(Portfolio.values, CovMatrix), Portfolio.values)) - np.nansum(RiskContribution) self._Output["因子收益"].loc[idt, FactorExpose.columns] = np.nansum( Return.values * FMPHolding, axis=1) self._Output["收益贡献"].loc[idt, FactorExpose.columns] = self._Output[ "因子收益"].loc[idt, FactorExpose.columns] * self._Output["因子暴露"].loc[ PreDT, FactorExpose.columns] self._Output["收益贡献"].loc[idt, "Alpha"] = (Portfolio * Return).sum( ) - self._Output["收益贡献"].loc[idt, FactorExpose.columns].sum() return 0