# -*- coding: utf-8 -*-

# -*- coding: utf-8 -*-
"""
Created on Fri Feb 12 16:51:05 2016

@author: <NAME>
"""

import numpy as np

from ...finutils.FinError import FinError
from ...finutils.FinMath import testMonotonicity
##########################################################################
# TODO: This is unfinished


class FinVolatilityCurve():
    ''' Class to manage a smile or skew in volatility at a single maturity 
    horizon. It fits the volatility using a polynomial. Includes analytics to 
    extract the implied pdf of the underyling at maturity. '''

    def __init__(self,
                 curveDate,
                 expiryDate,
                 strikes,
                 volatilities,
                 polynomial=3):

        if expiryDate <= curveDate:
            raise FinError("Expiry date before curve date.")

        if len(strikes) < 1:
            raise FinError("Volatility grid has zero length.")

        if testMonotonicity(strikes) is False:
            raise FinError("Strikes must be strictly monotonic.")

        numStrikes = len(strikes)
        numVols = len(volatilities)

        if numStrikes != numVols:
            raise FinError("Strike and volatility vectors not same length.")

        for i in range(1, numStrikes):
            if strikes[i] <= strikes[i - 1]:
                raise FinError("Grid Strikes are not in increasing order")

        self._curveDate = curveDate
        self._strikes = np.array(strikes)
        self._volatilities = np.array(volatilities)

        self._z = np.polyfit(self._strikes, self._volatilities, polynomial)
        self._f = np.poly1d(self._z)

###############################################################################

    def volatility(self, strike):
        ''' Return the volatility for a strike using a given polynomial 
        interpolation. '''

        vol = self._f(strike)

        if vol.any() < 0.0:
            raise ValueError("Negative volatility. Not permitted.")

        return vol

###############################################################################

    def calculatePDF():
        ''' calculate the probability density function of the underlying using 
        the volatility smile or skew curve following the approach set out in 
        Breedon and Litzenberger. '''
        pass

# -*- coding: utf-8 -*-

# -*- coding: utf-8 -*-
"""
Created on Fri Feb 12 16:51:05 2016

@author: <NAME>
"""

import numpy as np

from ...finutils.FinError import FinError
from ...finutils.FinMath import testMonotonicity
##########################################################################
# TODO: This is unfinished


class FinVolatilityCurve():
    ''' Class to manage a smile or skew in volatility at a single maturity 
    horizon. It fits the volatility using a polynomial. Includes analytics to 
    extract the implied pdf of the underyling at maturity. '''

    def __init__(self,
                 curveDate,
                 expiryDate,
                 strikes,
                 volatilities,
                 polynomial=3):

        if expiryDate <= curveDate:
            raise FinError("Expiry date before curve date.")

        if len(strikes) < 1:
            raise FinError("Volatility grid has zero length.")

        if testMonotonicity(strikes) is False:
            raise FinError("Strikes must be strictly monotonic.")

        numStrikes = len(strikes)
        numVols = len(volatilities)

        if numStrikes != numVols:
            raise FinError("Strike and volatility vectors not same length.")

        for i in range(1, numStrikes):
            if strikes[i] <= strikes[i - 1]:
                raise FinError("Grid Strikes are not in increasing order")

        self._curveDate = curveDate
        self._strikes = np.array(strikes)
        self._volatilities = np.array(volatilities)

        self._z = np.polyfit(self._strikes, self._volatilities, polynomial)
        self._f = np.poly1d(self._z)

###############################################################################

    def volatility(self, strike):
        ''' Return the volatility for a strike using a given polynomial 
        interpolation. '''

        vol = self._f(strike)

        if vol.any() < 0.0:
            raise ValueError("Negative volatility. Not permitted.")

        return vol

###############################################################################

    def calculatePDF():
        ''' calculate the probability density function of the underlying using 
        the volatility smile or skew curve following the approach set out in 
        Breedon and Litzenberger. '''
        pass

# -*- coding: utf-8 -*- # -*- coding: utf-8 -*- Created on Fri Feb 12 16:51:05 2016  @author: <NAME> ########################################################################## # TODO: This is unfinished Class to manage a smile or skew in volatility at a single maturity      horizon. It fits the volatility using a polynomial. Includes analytics to      extract the implied pdf of the underyling at maturity. ############################################################################### Return the volatility for a strike using a given polynomial          interpolation. ############################################################################### calculate the probability density function of the underlying using          the volatility smile or skew curve following the approach set out in          Breedon and Litzenberger.