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 __init__(self, risk_model_id: str, factor_name: str): risk_model = FactorRiskModel(risk_model_id) factor_data = risk_model.get_factor_data(format=ReturnFormat.JSON) name_matches = [factor for factor in factor_data if factor['name'] == factor_name] if not name_matches: raise MqValueError(f'Factor with name {factor_name} does not in exist in risk model {risk_model_id}') factor = name_matches.pop() self.__risk_model_id: str = risk_model_id self.__id = factor['identifier'] self.__name: str = factor['name'] self.__type: str = factor['type'] self.__category: str = factor.get('factorCategory')
def _get_factor_data(report_id: str, factor_name: str, query_type: QueryType) -> pd.Series: # Check params report = FactorRiskReport.get(report_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"]' ) model = FactorRiskModel.get(report.get_risk_model_id()) factor = model.get_factor(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_results(factors=[factor_name], start_date=DataContext.current.start_date, end_date=DataContext.current.end_date, return_format=ReturnFormat.JSON) factor_exposures = [{ 'date': d['date'], col_name: d[data_type] } for d in factor_data if d.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_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 """ model = FactorRiskModel.get(risk_model_id) factor_1 = model.get_factor(factor_name_1) factor_2 = model.get_factor(factor_name_2) covariance_curve = factor_1.covariance(factor_2, DataContext.current.start_date, DataContext.current.end_date, ReturnFormat.JSON) return __format_plot_measure_results(covariance_curve, QueryType.COVARIANCE)
def get(cls, risk_model_id: str, factor_name: str): risk_model = FactorRiskModel.get(risk_model_id) factor_data = risk_model.get_factor_data(format=ReturnFormat.JSON) name_matches = [factor for factor in factor_data if factor['name'] == factor_name] if not name_matches: raise MqValueError(f'Factor with name {factor_name} does not in exist in risk model {risk_model_id}') factor = name_matches.pop() return Factor(risk_model_id, factor['identifier'], factor['name'], factor['type'], factor.get('factorCategory'))
def test_create_risk_model(mocker): mock_risk_model(mocker) risk_model_id = 'model_id' mocker.patch.object(GsSession.current, '_post', return_value=mock_risk_model_obj) new_model = FactorRiskModel(risk_model_id, 'Fake Risk Model', 'Country', 'Long', 'gsid', 'GS', 0.1, entitlements={}, description='Test') new_model.upload() assert new_model.id == mock_risk_model_obj.id assert new_model.name == mock_risk_model_obj.name assert new_model.description == mock_risk_model_obj.description assert new_model.term == mock_risk_model_obj.term assert new_model.coverage == mock_risk_model_obj.coverage assert new_model.universe_identifier == mock_risk_model_obj.universe_identifier
def mock_risk_model(): replace = Replacer() # mock getting risk model entity() mock = replace('gs_quant.api.gs.risk_models.GsRiskModelApi.get_risk_model', Mock()) mock.return_value = mock_risk_model_obj actual = Factor_Risk_Model.get(model_id='model_id') replace.restore() return actual
def get_report_factor_risk_models(self) -> Tuple[FactorRiskModel, ...]: all_reports = self.get_reports() risk_model_ids = [] for report in all_reports: if report.parameters.risk_model is not None and report.parameters.risk_model not in risk_model_ids: risk_model_ids.append(report.parameters.risk_model) if not len(risk_model_ids): raise ValueError('No factor risk models available for ' + self.id) risk_models = FactorRiskModel.get_many(risk_model_ids) return risk_models
def test_create_risk_model(mocker): mock_risk_model(mocker) risk_model_id = 'model_id' mocker.patch.object(GsSession.current, '_post', return_value=mock_risk_model_obj) new_model = FactorRiskModel(risk_model_id, 'Fake Risk Model', RiskModelCoverage.Country, RiskModelTerm.Long, RiskModelUniverseIdentifier.gsid, 'GS', 0.1, entitlements={}, description='Test', expected_update_time=dt.datetime.strptime('00:00:00', '%H:%M:%S').time()) new_model.save() assert new_model.id == mock_risk_model_obj.id assert new_model.name == mock_risk_model_obj.name assert new_model.description == mock_risk_model_obj.description assert new_model.term == mock_risk_model_obj.term assert new_model.coverage == mock_risk_model_obj.coverage assert new_model.universe_identifier == mock_risk_model_obj.universe_identifier assert new_model.expected_update_time == dt.datetime.strptime( mock_risk_model_obj.expected_update_time, '%H:%M:%S').time()
def mock_risk_model(): risk_model = RiskModel(coverage=CoverageType.Country, id_='model_id', name='Fake Risk Model', term=Term.Long, universe_identifier=UniverseIdentifier.gsid, vendor='GS', version=1.0) replace = Replacer() # mock getting risk model entity() mock = replace('gs_quant.api.gs.risk_models.GsRiskModelApi.get_risk_model', Mock()) mock.return_value = risk_model actual = Factor_Risk_Model.get(model_id='model_id') replace.restore() return actual
def test_create_risk_model(mocker): mock_risk_model(mocker) risk_model_id = 'model_id' mocker.patch.object(GsSession.current, '_get', return_value=mock_risk_model_obj) new_model = FactorRiskModel.create( coverage=CoverageType.Country, id_=risk_model_id, name='Fake Risk Model', term=Term.Long, universe_identifier=UniverseIdentifier.gsid, vendor='GS', version=1.0) assert new_model.id == risk_model_id
def mock_risk_model(mocker): from gs_quant.session import OAuth2Session OAuth2Session.init = mock.MagicMock(return_value=None) GsSession.use(Environment.QA, 'client_id', 'secret') mocker.patch.object( GsSession.__class__, 'default_value', return_value=GsSession.get( Environment.QA, 'client_id', 'secret')) mocker.patch.object(GsSession.current, '_post', return_value=mock_risk_model_obj) mocker.patch.object(GsSession.current, '_get', return_value=mock_risk_model_obj) mocker.patch.object(GsSession.current, '_put', return_value=mock_risk_model_obj) return FactorRiskModel.get('model_id')
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 """ model = FactorRiskModel.get(risk_model_id) factor = model.get_factor(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 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 """ model = FactorRiskModel.get(risk_model_id) factor = model.get_factor(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)