Open:Risk API

  • SECTIONS
  • Overview
  • API Definition
  • SDK Libraries
  • Notebooks
  • Code Snippet
  • Changelog
Overview

Gain comprehensive access to a factor-based linear risk analytics engine. This API offers flexible and powerful risk analyses with full capability ranging from requesting risk calculation, full-blown what-if risk analysis directly editing model inputs, coverage check, etc. Compatible risk models are not only the models stored in FactSet including vendor-models and custom risk models, but you can also supply your proprietary custom risk models for ad-hoc risk research purpose.

API Definition
SDK Libraries
Notebooks
Delta Risk Analysis: Systematic Analysis on Risk Change from Day t-1 to Day t
Manager Rebalancing using Trade Simulation
Code Snippet
Snapshot Risk Analysis
from fds.sdk.utils.authentication import ConfidentialClient
import fds.sdk.OpenRisk
from fds.sdk.OpenRisk.api import operations_api
from fds.sdk.OpenRisk.models import *
from dateutil.parser import parse as dateutil_parser
from pprint import pprint

# (Preferred) OAuth 2.0: FactSetOAuth2
# See https://github.com/FactSet/enterprise-sdk#oauth-20
# for information on how to create the app-config.json file
# See https://github.com/FactSet/enterprise-sdk-utils-python#authentication
# for more information on using the ConfidentialClient class
# configuration = fds.sdk.OpenRisk.Configuration(
#    fds_oauth_client=ConfidentialClient('/path/to/app-config.json')
# )

# Basic authentication: FactSetApiKey
# See https://github.com/FactSet/enterprise-sdk#api-key
# for information how to create an API key
configuration = fds.sdk.OpenRisk.Configuration(
    username='USERNAME-SERIAL',
    password='API-KEY'
)

# Enter a context with an instance of the API client
with fds.sdk.OpenRisk.ApiClient(configuration) as api_client:
    # Create an instance of the API class
    api_instance = operations_api.OperationsApi(api_client)

    # str | Semantic version number. See [this link here](https://regexr.com/47b7t) to test validate patterns.
    version = "v1"
    calculate_from_holdings_request_body = CalculateFromHoldingsRequestBody(
        data=CalculateFromHoldingsRequestData(
            holdings=Holdings(
                portfolio=Holding(ids=["IBM", "FDS", "FDX-US", "FDX-DE", "CA_ETF", "IDX_FUTURE", "CASH_USD_FUT"],
                                  market_values=[30.0, 30.0, 30.0, 30.0, 50.0, 50.0, -50.0],
                                  grouping=SecurityGroup(groups=[SecurityGroup(name="Group1", indices=[0, 1, 2, 3]),
                                                                 SecurityGroup(name="Group2", indices=[4, 5, 6])])),
                benchmark=Holding(ids=["MSFT", "AMZN"],
                                  market_values=[60.0, 60.0],
                                  grouping=SecurityGroup(groups=[SecurityGroup(name="Group1", indices=[0]),
                                                                 SecurityGroup(name="Group2", indices=[1])])
                                  ),
            ),
            composite_assets=CompositeAssetDefinitions(
                CA_ETF=IDsAndMarketValues(
                    ids=["AAPL", "SSNLF"], market_values=[100.0, 100.0],),
                IDX_FUTURE_UNDERLYING=IDsAndMarketValues(
                    ids=["00105510", "00130H10", "00206R10"], market_values=[25.0, 25.0, 50.0],)
            ),
            asset_types=AssetTypes(
                IDX_FUTURE="FUT_INDEX"
            ),
            underlying_ids=UnderlyingIDs(
                IDX_FUTURE="IDX_FUTURE_UNDERLYING",
            ),
            allow_forced_riskless_assets=True,
            calendar=CalendarCode("FIVEDAY"),
            currency=CurrencyISOCode("USD"),
            date=Date("2023-01-31"),
            factors_visible=FactorsVisible(
                list=["BETA", "SIZE"],
                type="Whitelist",
            ),
            remove_currency_risk=True,
            requires_factor_returns=RequiresFactorReturns("Daily"),
            risk_model=RiskModelCode("FDS:GLOBAL_EQUITY_D_V1"),
            factor_grouping=FactorGroup(
                nodes=[FactorGroupNodes(name="Market",
                                        nodes=[FactorGroupNodes(id="GLOBAL_MARKET")]),
                       FactorGroupNodes(name="Style",
                                        nodes=[FactorGroupNodes(name="Market Factors",
                                                                nodes=[FactorGroupNodes(id="BETA"),
                                                                       FactorGroupNodes(id="LIQUIDITY"),
                                                                       FactorGroupNodes(id="LONG_MOMENTUM"),
                                                                       FactorGroupNodes(id="SIZE"),
                                                                       FactorGroupNodes(id="VOLATILITY")]),
                                               FactorGroupNodes(name="Fundamental Factors",
                                                                nodes=[FactorGroupNodes(id="BOOK_TO_PRICE"),
                                                                       FactorGroupNodes(id="DIVIDEND_YIELD"),
                                                                       FactorGroupNodes(id="EARNINGS_YIELD"),
                                                                       FactorGroupNodes(id="GROWTH"),
                                                                       FactorGroupNodes(id="LEVERAGE")])]
                                        )
                       ],
                name="This factor grouping is incomplete; it omits factors for the sake of brevity and is not recommended for actual use"),
            stats=Stats([
                Stat(
                    name="ActiveVarianceToRisk",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True),
                ),
                Stat(
                    name="ActiveStockSpecificVariance",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="ActiveStockSpecificVariance",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=False)
                ),
                Stat(
                    name="ActiveVarianceToRisk",
                    level=StatCalculationLevel("SecurityGroup"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True),
                ),
                Stat(
                    name="ActiveFactorRisk",
                    level=StatCalculationLevel("Portfolio"),
                ),
                Stat(
                    name="PercentActiveFactorVarianceToVariance",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="ActiveStockSpecificVarianceToStockSpecificRisk",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PercentActiveFactorVarianceToVariance",
                    level=StatCalculationLevel("Security"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PercentActiveStockSpecificVarianceToVariance",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PercentActiveStockSpecificVarianceToVariance",
                    level=StatCalculationLevel("Security"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PercentActiveVariance",
                    level=StatCalculationLevel("Security"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PortfolioBetaToBenchmark",
                    level=StatCalculationLevel("Portfolio"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="PercentActiveFactorVarianceToVariance",
                    level=StatCalculationLevel("Factor"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="ActiveFactorVarianceToRisk",
                    level=StatCalculationLevel("FactorGroup"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="ActiveFactorEffect",
                    level=StatCalculationLevel("Portfolio"),
                ),
                Stat(
                    name="ActiveFactorEffect",
                    level=StatCalculationLevel("Factor"),
                ),
                Stat(
                    name="ActiveFactorEffect",
                    level=StatCalculationLevel("Security"),
                ),
                Stat(
                    name="ActiveFactorEffect",
                    level=StatCalculationLevel("FactorSecurity"),
                ),
                Stat(
                    name="ActiveExposure",
                    level=StatCalculationLevel("FactorGroup"),
                ),
                Stat(
                    name="RawFactorExposure",
                    level=StatCalculationLevel("FactorSecurity"),
                ),
                Stat(
                    name="RawFactorCovarianceMatrix",
                    level=StatCalculationLevel("FactorFactor"),
                ),
                Stat(
                    name="RawFactorCorrelationMatrix",
                    level=StatCalculationLevel("FactorFactor"),
                ),
                Stat(
                    name="RawAssetCovarianceMatrix",
                    level=StatCalculationLevel("SecuritySecurity"),
                    settings=StatCalculationSettings(
                        correlated_specific_risk=True)
                ),
                Stat(
                    name="RemoveCurrencyRiskFlag",
                    level=StatCalculationLevel("Security"),
                ),
                Stat(
                    name="ForcedRisklessFlag",
                    level=StatCalculationLevel("Security"),
                ),
            ]),
        ),
    )  # CalculateFromHoldingsRequestBody

    try:
        # Calculate risk statistics
        # Since Factor Grouping doesn't use all the factors of the risk model, it's expected to see a warning for missing factors
        # example passing only required values which don't have defaults set
        api_response = api_instance.calculate_from_holdings(version, calculate_from_holdings_request_body)
        pprint(api_response)

    except fds.sdk.OpenRisk.ApiException as e:
        print("Exception when calling OperationsApi->calculate_from_holdings: %s\n" % e)
Changelog

v1

Summary

  • Version 1.26.0 – Released on 08/08/2024
  • Version 1.25.0 – Released on 07/29/2024
  • Version 1.24.0 – Released on 04/13/2023
  • Version 1.23.0 – Released on 01/19/2023
  • Version 1.20.0 – Released on 04/07/2022
  • Version 1.19.0 – Released on 01/31/2022

Functionality Additions

  • Release the /generate/id-mapping/ route [v1.19.0]
  • Add 'supportedLevels' output field to responses of the /stats/ route [v1.25.0]

Changes

  • Add 'factorIdToIsoCurrency' output field to responses of the /riskmodels/{modelCode}/ route [v1.20.0]
  • Remove 'levels' output field from responses of the /stats/ route [v1.26.0]

Bug Fixes

  • Minor bug fixes [v1.24.0]
  • Factor grouping verification is performed using all factor IDs across time instead of on a specific date. This allows a single factor grouping with all factors to be used for every date for a risk model. Applies to the /calculate/from-holdings/ route. [v1.23.0]