from serenity_sdk.api.core import SerenityApi
from serenity_sdk.client.raw import CallType, SerenityClient
from serenity_sdk.types.common import Portfolio
from serenity_sdk.types.valuation import ValuationResult
from serenity_types.portfolio.core import NetDeltaPortfolioPositions
from serenity_types.pricing.core import PricingContext
[docs]
class ValuationApi(SerenityApi):
"""
The valuation API group covers basic tools for NAV and other portfolio valuation calcs.
"""
def __init__(self, client: SerenityClient):
"""
:param client: the raw client to delegate to when making API calls
"""
super().__init__(client, 'valuation')
[docs]
def compute_portfolio_value(self, ctx: PricingContext, portfolio: Portfolio) -> ValuationResult:
"""
Computes portfolio NAV and other high-level valuation details at both the portfolio level
and position-by-position.
:param ctx: the pricing parameters to use, e.g. which base currency and the as-of date for prices
:param portfolio: the portfolio to value
:return: a parsed :class:`ValuationResult` containing all portfolio & position values
"""
request = {
'portfolio': {'assetPositions': portfolio.to_asset_positions()},
'pricing_context': {
**self._create_std_params(ctx.as_of_date),
'portfolio': {'assetPositions': portfolio.to_asset_positions()},
'markTime': ctx.mark_time.value if ctx.mark_time else None,
'baseCurrencyId': str(ctx.base_currency_id),
'cashTreatment': ctx.cash_treatment.value if ctx.cash_treatment else None
}
}
raw_json = self._call_api('/portfolio/compute', {}, request, CallType.POST)
return ValuationResult._parse(raw_json)
[docs]
def compute_portfolio_net_delta_value(
self, ctx: PricingContext, portfolio: Portfolio) -> NetDeltaPortfolioPositions:
"""
Given a pricing context (mark time, date, base currency) convert the
net delta equivalent of the given portfolio.
:param ctx: the pricing parameters to use, e.g. which base currency and the as-of date for prices
:param portfolio: the portfolio to value
:return: a parsed :class:`NetDeltaPortfolioPositions` the converted net delta of the asset positions
"""
request = {
'portfolio': portfolio.to_asset_positions(),
'pricing_context': {
**self._create_std_params(ctx.as_of_time),
'markTime': ctx.mark_time.value if ctx.mark_time else None,
'baseCurrencyId': str(ctx.base_currency_id),
'cashTreatment': ctx.cash_treatment.value if ctx.cash_treatment else None
}
}
raw_json = self._call_api('/portfolio/net_delta', {}, request, CallType.POST)
return NetDeltaPortfolioPositions(**raw_json['result'])