Source code for serenity_types.risk.scenarios

from datetime import date, datetime
from enum import Enum
from typing import List, Optional, Union
from uuid import UUID

from serenity_types.portfolio.core import SimplePortfolio
from serenity_types.pricing.core import PricingContext
from serenity_types.utils.serialization import CamelModel


[docs] class ShockPnL(CamelModel): """ Value object with information about a particular dimension's P&L impact from a single shock. """ shock_id: UUID """ Unique ID for the shock from the original ShockDefinition. """ shock_pnl: float """ The PnL, in base currency, from the shock, e.g. the portfolio would have lost an additional $2K if this shock had been applied. """
[docs] class PnL(CamelModel): """ Value object with information about a particular dimension's P&L impact from all shocks. """ base_pnl: float """ The PnL, in base currency, over the period (default 1 day) absent all the shocks, e.g. portfolio lost $12K in the last 24 hours. """ total_shock_pnl: float """ The PnL, in base currency, from all shocks combined, e.g. the portfolio would have lost an additional $50K if all shocks had been applied. """ pnl_by_shock: List[ShockPnL] """ The PnL, in base currency, from applying each shock individually, e.g. the portfolio would have lost $4K from shocking ETH down 10% and $35K from shocking BTC down 10%. """
[docs] class AssetPnL(CamelModel): """ A single entry representing an asset-level impact of this scenario's shocks. It supports both by-asset and by-sector views in Serenity UX. """ asset_id: UUID """ Unique asset identifier from the Asset Master. """ sector_levels: List[str] """ A list of sector level names that identifies a “path” to a particular level in the sector taxonomy, as defined above; note we only have the leaf level here; we don't need to show PnL at each level in the sector hierarchy above the assets, UX can do the aggregation since $ values are additive here. """ asset_pnl: PnL """ P&L impact in total and by shock for this asset. """
[docs] class FactorPnL(CamelModel): """ A single entry representing a factor-level impact of this scenario's shocks. """ factor: str """ Factor name, e.g. MOMENTUM. """ factor_exposure_base_ccy: float """ Total factor exposure in the portfolio, in base currency. """ factor_pnl: PnL """ P&L impact in total and by shock for this factor. """
[docs] class ScenarioSource(Enum): """ Enum classifying scenarios by whether they are user- or system-defined. """ CUSTOM = 'CUSTOM' """ A user-defined scenario. """ PREDEFINED = 'PREDEFINED' """ A canned scenario provided by the platform; typically these represent fitted historical events like the 2020 COVID Crash. """ CUSTOM_GENERATED = 'CUSTOM_GENERATED' """ Custom date range-based scenario using Serenity's model for shock generation. """
[docs] class ShockTo(Enum): """ Enum classifying what is being shocked, e.g. asset returns or factor returns. """ ASSET = "ASSET" """ Shock applied additively to the asset's returns at the close, per MarkTime. """ FACTOR = "FACTOR" """ Shock applied additively to the factor's returns at the close, per MarkTime. """
[docs] class Shock(CamelModel): """ A discrete market shock that is being simulated in a scenario. """ shock_id: Optional[UUID] """ Unique ID for the shock; this can be generated and stored with the ShockDefinition (and thus unchanging) or if the scenario is run on-the-fly, the UUID should be generate at request time so there is a clear linkage between Shock and ShockPnL. """ target_type: ShockTo """ What to shock: asset returns or factor returns? """ shock_target: Union[UUID, str] """ UUID for asset ID, or name of the factor to shock. """ magnitude: float """ Magnitude of the shock, + / - for up or down shock actions; note this is expressed as a fraction, not a percentage. """
[docs] class ScenarioDefinition(CamelModel): """ A complete definition of a stress test to perform for scenario analysis. """ scenario_id: Optional[UUID] """ Unique ID for this scenario, optional when creating or if we are dealing with a transient scenario to run. """ scenario_version: Optional[int] """ Monotonically increasing version number, optional when creating or if we are dealing with a transient scenario to run. """ source: ScenarioSource """ Whether this shock is user- or system-defined. """ name: str """ A descriptive name for this scenario. """ shocks: List[Shock] """ The discrete shocks to apply as part of this scenario. """ deleted: Optional[bool] = False """ If set, this definition was logically deleted in the database and is not current. """ last_updated: Optional[datetime] """ Last update timestamp, in UTC. """ last_updated_by: str """ Last update user. """ owner: Optional[str] """ Owner of the Scenario. """ model_config_id: Optional[UUID] """ The model config to use with the Scenario """ start_date_display: Optional[date] """ The start date of the Scenario """ end_date_display: Optional[date] """ The end date of the Scenario """ description: Optional[str] """ Description for the Scenario """
[docs] class ScenarioCloneRequest(CamelModel): """ A request to clone an existing scenario; typically used to allow the client to customize a canned scenario. """ scenario_id: UUID """ Unique ID of the custom or predefined scenario to clone. """ scenario_name: str """ Name to use post-cloning to avoid ambiguity. """
[docs] class ScenarioRequest(CamelModel): """ A request to run a scenario against a portfolio. This scenario may be stored or transient. """ scenario_id: Optional[UUID] """ Unique ID of the scenario to run; if not provided, user must provide a transient scenario instead. """ scenario: Optional[ScenarioDefinition] """ Transient scenario to run; if not provided, user must provide a scenario ID instead. """ portfolio: SimplePortfolio """ Portfolio to run the scenario on. """ pricing_context: Optional[PricingContext] """ Common model inputs, e.g. mark time. """ sector_taxonomy_id: Optional[UUID] """ References a taxonomy UUID from the Refdata API, specifically the getSectorTaxonomies call. """ model_config_id: UUID """ Factor model configuration ID to use for risk purposes. """ start_date: Optional[date] """ Start of the shock period; in the instantaneous case, same as end_date. """ end_date: Optional[date] """ End of the shock period; in the instantaneous case, same as start_date. """ schema_version: Optional[int] """ Version number for the scenario schema. """
[docs] class ScenarioResult(CamelModel): """ ScenarioResult provides the portfolio base & shock P&L and the breakdowns by asset, sector and by factor. """ portfolio_pnl: PnL """ The impact to the portfolio broken out by shocks. """ asset_pnl: List[AssetPnL] """ Report on P&L impact by asset & sector. """ factor_pnl: Optional[List[FactorPnL]] """ Report on P&L impact by risk factor in the provided factor risk model. """ start_date: date """ Start of the shock period; in the instantaneous case, same as end_date. """ end_date: date """ End of the shock period; in the instantaneous case, same as start_date. """ scenario_run_id: UUID """ The run that this result is associated with. """ warnings: Optional[List[str]] """ Any warnings generated at the time of the run. """ schema_version: Optional[int] """ Version number for the scenario schema. """
[docs] class RunStatus(Enum): """ Results of the scenario run at a high level. """ RUNNING = 'RUNNING' """ Job sent to the scenario engine and running, may be async / long-running. """ COMPLETED = 'COMPLETED' """ Job completed with no errors. """ FAILED = 'FAILED' """ Job failed with an error. """
[docs] class ScenarioRun(CamelModel): """ A summary of the run. Note that to get the detail you need to call getScenarioRun with the runId; this just gives you the status, the base PnL absent all the shocks and the total shock PnL. """ run_id: UUID """ Unique ID of this run. """ scenario_request: ScenarioRequest """ The request that was run previously. """ status: RunStatus """ Current state of the run. """ base_pnl: Optional[float] """ The PnL, in base currency, over the period (default 1 day) absent all the shocks, e.g. portfolio lost $12K in the last 24 hours. """ total_shock_pnl: Optional[float] """ the PnL, in base currency, from all shocks combined, e.g. the portfolio would have lost an additional $50K if all shocks had been applied. """ start_datetime: datetime """ UTC datetime of the run start. """ end_datetime: Optional[datetime] """ UTC datetime of the run completion, if COMPLETED. """
[docs] class CustomScenarioGeneratorRequest(CamelModel): name: str """ A descriptive name for this scenario. """ start_date: date """ Start of the shock period. """ end_date: date """ End of the shock period. """ model_config_id: UUID """ The model config to use with the Scenario """