from abc import ABC, abstractmethod
from tensorflow import GradientTape
from ..instruments.product import Product
from ..markethandles.marketenvironment import MarketEnvironment
[docs]
class Pricer(ABC):
"""Abstract base class for pricing financial products.
This abstract class defines the interface for pricing financial products. Concrete implementations
must provide a method for calculating the price of a product based on the trade date and market curves.
Methods:
calculate_price: Abstract method to be implemented by subclasses to calculate the price of a product.
price: Calculates the price of a product and optionally returns the gradient if autodiff is enabled.
"""
def __init__(self) -> None:
self._tape = None
@property
def tape(self):
if self._tape is None:
raise ValueError("autodiff must be enabled")
return self._tape
[docs]
@abstractmethod
def calculate_price(self, product, market_env: MarketEnvironment):
"""Abstract method to calculate the price of a financial product.
Args:
product (Product): The financial product to be priced.
market_env (MarketEnvironment): The market environment providing
access to market data (curves, spots, volatilities).
Returns:
float: The calculated price of the product.
Notes:
This method must be implemented by any subclass of Pricer.
"""
return
[docs]
def price(self, product: Product, market_env: MarketEnvironment, autodiff: bool = False):
"""Calculates the price of a financial product, with optional automatic differentiation.
Args:
product (Product): The financial product to be priced.
market_env (MarketEnvironment): The market environment providing
access to market data (curves, spots, volatilities).
autodiff (bool, optional): Whether to compute gradients using TensorFlow's autodiff. Defaults to False.
"""
if autodiff:
with GradientTape() as tape:
npv = self.calculate_price(product, market_env)
product.price = npv
self._tape = tape
else:
product.price = self.calculate_price(product, market_env)