def covariance(risk_model_id: str, factor_name_1: str, factor_name_2: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Covariance time-series between two factors in a risk model :param risk_model_id: risk model entity :param factor_name_1: first factor name :param factor_name_2: second factor name :param source: name of function caller :param real_time: whether to retrieve intraday data instead of EOD :param request_id: server request id :return: Time-series of covariances between the two factors across available risk model dates """ factor_1 = Factor(risk_model_id, factor_name_1) factor_2 = Factor(risk_model_id, factor_name_2) covariance_curve = factor_1.covariance(factor_2, DataContext.current.start_date, DataContext.current.end_date) return __format_plot_measure_results(covariance_curve, QueryType.COVARIANCE)
def _get_factor_data(report_id: str, factor_name: str, query_type: QueryType) -> pd.Series: # Check params report = RiskReport(report_id) if report.get_type() not in [ ReportType.Portfolio_Factor_Risk, ReportType.Asset_Factor_Risk ]: raise MqValueError('This report is not a factor risk report') risk_model_id = report.get_risk_model_id() factor = Factor(risk_model_id, factor_name) if factor.factor is None: raise MqValueError( 'Factor name requested is not available in the risk model associated with this report' ) # Extract relevant data for each date col_name = query_type.value.replace(' ', '') col_name = col_name[0].lower() + col_name[1:] data_type = QUERY_TO_FIELD_MAP[query_type] factor_data = report.get_factor_data(factor=factor.get_name()) factor_exposures = [{ 'date': data['date'], col_name: data[data_type] } for data in factor_data if data.get(data_type)] # Create and return timeseries df = pd.DataFrame(factor_exposures) df.set_index('date', inplace=True) df.index = pd.to_datetime(df.index) return _extract_series_from_df(df, query_type)
def get_factor(self, name: str) -> Factor: """ Get risk model factor from its name :param name: factor name associated with risk model :return: Factor object """ name_matches = [ f for f in self.get_factor_data(format=ReturnFormat.JSON) if f['name'] == name ] if not name_matches: raise MqValueError( f'Factor with name {name} does not in exist in risk model {self.id}' ) factor = name_matches.pop() return Factor(risk_model_id=self.id, id_=factor['identifier'], type_=factor['type'], name=factor.get('name'), category=factor.get('factorCategory'), tooltip=factor.get('tooltip'), description=factor.get('description'), glossary_description=factor.get('glossaryDescription'))
def factor_zscore(asset: Asset, risk_model_id: str, factor_name: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Asset factor exposure (in the form of z-scores) for a factor using specified risk model :param asset: asset object loaded from security master :param risk_model_id: requested risk model id :param factor_name: requested factor name :param source: name of function caller :param real_time: whether to retrieve intraday data instead of EOD :param request_id: service request id, if any :return: Time-series of asset factor exposure across available risk model dates """ risk_model = FactorRiskModel(risk_model_id) factor = Factor(risk_model_id, factor_name) gsid = asset.get_identifier('GSID') # Query risk model data query_results = risk_model.get_data( measures=[Measure.Factor_Name, Measure.Universe_Factor_Exposure, Measure.Asset_Universe], start_date=DataContext.current.start_time, end_date=DataContext.current.end_time, assets=DataAssetsRequest(identifier=UniverseIdentifier.gsid, universe=[gsid]) ).get('results', []) # Get the factor data from query results z_scores = {} for result in query_results: exposures = result.get('assetData', {}).get('factorExposure', []) if exposures: z_scores[result['date']] = exposures[0].get(factor.id) return __format_plot_measure_results(z_scores, QueryType.FACTOR_EXPOSURE)
def factor_exposure(asset: Asset, risk_model_id: str, factor_name: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Asset factor Exposure (in the form of z-scores) for a factor using specified risk model :param asset: asset object loaded from security master :param risk_model_id: requested risk model id :param factor_name: requested factor name :param source: name of function caller :param real_time: whether to retrieve intraday data instead of EOD :param request_id: service request id, if any :return: Timeseries of asset factor exposure across available risk model dates """ risk_model = RiskModel(risk_model_id) factor = Factor(risk_model_id, factor_name) if factor.factor is None or risk_model_id != factor.risk_model_id: raise MqValueError( 'Requested factor not available in requested risk model') asset_gsid = asset.get_identifiers().get('GSID') # Establish date interval for data query dates = risk_model.get_dates() start_date = dt.datetime.strptime(min(dates), "%Y-%m-%d").date() if dates else None end_date = dt.datetime.strptime(max(dates), "%Y-%m-%d").date() if dates else None # Query data and append pull requested factor exposure all_exposures = [] query_results = risk_model.get_data( measures=[ Measure.Factor_Name, Measure.Universe_Factor_Exposure, Measure.Asset_Universe ], start_date=start_date, end_date=end_date, assets=DataAssetsRequest(identifier=AssetUniverseIdentifier.gsid, universe=[asset_gsid])).get('results', []) for result in query_results: if result.get('date') in dates: exposures = result.get('assetData', {}).get('factorExposure', []) if exposures: all_exposures.append({ 'date': result['date'], 'factorExposure': exposures[0].get(factor.factor.identifier) }) # Create and return timeseries df = pd.DataFrame(all_exposures) df.set_index('date', inplace=True) df.index = pd.to_datetime(df.index) return _extract_series_from_df(df, QueryType.FACTOR_EXPOSURE)
def factor_volatility(risk_model_id: str, factor_name: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Volatility timeseries for a factor in a risk model :param risk_model_id: risk model entity :param factor_name: factor name :param source: name of function caller :param real_time: whether to retrieve intra-day data instead of EOD :param request_id: server request id :return: Time-series of a factor's volatility across available risk model dates """ factor = Factor(risk_model_id, factor_name) volatility = factor.volatility(DataContext.current.start_date, DataContext.current.end_date, ReturnFormat.JSON) return __format_plot_measure_results(volatility, QueryType.VOLATILITY, multiplier=100)
def get_many_factors(self): factors = self.get_factor_data(format=ReturnFormat.JSON) return [ Factor(risk_model_id=self.id, id_=f['identifier'], type_=f['type'], name=f.get('name'), category=f.get('factorCategory'), tooltip=f.get('tooltip'), description=f.get('description'), glossary_description=f.get('glossaryDescription')) for f in factors ]
def covariance(risk_model_id: str, factor_1: str, factor_2: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Covariance timeseries between two factors in a risk model :param risk_model_id: risk model entity :param factor_1: first factor name :param factor_2: second factor name :param source: name of function caller :param real_time: whether to retrieve intraday data instead of EOD :param request_id: server request id :return: Timeseries of covariances between the two factors across available risk model dates """ model = RiskModel(risk_model_id) factor_1 = Factor(risk_model_id, factor_1) factor_2 = Factor(risk_model_id, factor_2) if None in [factor_1.factor, factor_2.factor]: raise MqValueError( 'Factor names requested are not available for this risk model') # Find all covariances between two factors for date range dates = model.get_dates() start_date = dt.datetime.strptime(min(dates), '%Y-%m-%d') if dates else None end_date = dt.datetime.strptime(max(dates), '%Y-%m-%d') if dates else None covariances = factor_1.get_covariance(factor_2, start_date, end_date) # Create and return timeseries df = pd.DataFrame(covariances) df.set_index('date', inplace=True) df.index = pd.to_datetime(df.index) return _extract_series_from_df(df, QueryType.COVARIANCE)
def _get_factor_data(report_id: str, factor_name: str, query_type: QueryType) -> pd.Series: # Check params report = RiskReport(report_id) if report.get_type() not in [ ReportType.Portfolio_Factor_Risk, ReportType.Asset_Factor_Risk ]: raise MqValueError('This report is not a factor risk report') risk_model_id = report.get_risk_model_id() if factor_name not in ['Factor', 'Specific', 'Total']: if query_type in [QueryType.DAILY_RISK, QueryType.ANNUAL_RISK]: raise MqValueError( 'Please pick a factor name from the following: ["Total", "Factor", "Specific"]' ) factor = Factor(risk_model_id, factor_name) factor_name = factor.name # Extract relevant data for each date col_name = query_type.value.replace(' ', '') col_name = decapitalize(col_name) data_type = decapitalize( col_name[6:]) if col_name.startswith('factor') else col_name factor_data = report.get_factor_data( factor=factor_name, start_date=DataContext.current.start_time, end_date=DataContext.current.end_time) factor_exposures = [{ 'date': data['date'], col_name: data[data_type] } for data in factor_data if data.get(data_type)] # Create and return timeseries df = pd.DataFrame(factor_exposures) if not df.empty: df.set_index('date', inplace=True) df.index = pd.to_datetime(df.index) return _extract_series_from_df(df, query_type)
def factor_performance(risk_model_id: str, factor_name: str, *, source: str = None, real_time: bool = False, request_id: Optional[str] = None) -> pd.Series: """ Factor returns as a price time-series for a factor in a risk model :param risk_model_id: risk model entity :param factor_name: factor name :param source: name of function caller :param real_time: whether to retrieve intraday data instead of EOD :param request_id: server request id :return: Time-series of factor returns as a price series across available risk model dates """ factor = Factor.get(risk_model_id, factor_name) factor_returns = factor.returns(DataContext.current.start_date, DataContext.current.end_date, ReturnFormat.JSON) factor_return_timeseries = pd.Series(factor_returns) return prices(factor_return_timeseries, 100)