示例#1
0
 def getScheduleComplete(self):
     myscheduler = Scheduler()
     self.datelist = myscheduler.getSchedule(self.start, self.maturity,
                                             self.freq, self.start)
     self.ntimes = len(self.datelist)
     fullset = sorted(
         set(self.datelist).union([self.start]).union([self.maturity]))
     return fullset, self.datelist
class CDSSwaption(object):

    def __init__(self, option_start, cds_start,cds_end,strike,cds_freq,cds_flavor,cds_recovery,Q):
        self.option_start = option_start
        self.strike = strike
        self.cds_start = cds_start
        self.cds_end = cds_end
        self.cds_freq = cds_freq
        # payer to pay strike K, spread - k; receiver to receive strike K, k - spread
        self.cds_flavor = cds_flavor
        self.cds_recovery = cds_recovery
        self.myScheduler = Scheduler()
        self.cds_datelist = self.myScheduler.getSchedule(self.cds_start,self.cds_end,self.cds_freq,self.cds_start)
        self.OIS = OIS(option_start,cds_end)
        self.Q = Q
        self.ntimes = np.shape(self.Q)[0]
        self.ntrajectories = np.shape(self.Q)[1]

    def getCDSSwaption(self,premium_rate):
        Q_truncation = self.Q[self.cds_start:]
        Q_truncation = Q_truncation.divide(Q_truncation.ix[0])
        OIS_DCF_List = []
        for cds_date in self.cds_datelist: OIS_DCF_List.append(self.OIS.getDF_trimstartDate(cds_date))
        OIS_truncation = pd.Series(OIS_DCF_List,index=self.cds_datelist)
        OIS_truncation = OIS_truncation.divide(OIS_truncation.ix[0])
        # add one day since this is header not index
        OIS_truncation = OIS_truncation[self.cds_start+datetime.timedelta(days=1):]
        self.CDS = CDS(OIS_truncation, Q_truncation, self.cds_start, self.cds_end, self.cds_freq, self.cds_flavor, self.cds_recovery)

        total_instance = 0
        for i in range(self.ntrajectories):
            cur_default = self.Q.loc[self.cds_start][i]
            cur_discount = self.OIS.getDF_trimstartDate(self.cds_start)
            cur_spread, cur_ra = self.CDS.getSingleSpread(self.CDS.Q[i])
            if self.cds_flavor: total_instance += cur_discount * cur_default * max(cur_spread-premium_rate,0) * cur_ra
            else: total_instance += cur_discount * cur_default * max(-cur_spread + premium_rate,0) * cur_ra

        return total_instance / self.ntrajectories
from unittest import TestCase

from parameters import xR, simNumber, t_step, trim_start, trim_end, freq, periods, referenceDate, start, inArrears, WORKING_DIR
from MonteCarloSimulators.Vasicek.vasicekMCSim import MC_Vasicek_Sim
from Scheduler.Scheduler import Scheduler

mySchedule = Scheduler()

# Global Variables
mySchedule = mySchedule.getSchedule(start=trim_start, end=trim_end, freq="M")
mySimulator = MC_Vasicek_Sim(datelist=mySchedule,
                             x=xR,
                             simNumber=simNumber,
                             t_step=t_step)
mySimulator.getLibor()
mySimulator.getSmallLibor()
a = 1


class TestMC_Vasicek_Sim(TestCase):
    def test_getLibor(self):
        mySimulator.getLibor()

    def test_getSmallLibor(self):
        # Monte Carlo trajectories creation - R
        Libor = mySimulator.getSmallLibor(mySchedule)
        return Libor
示例#4
0
myScheduler = Scheduler()
periods = '1Y'
freq = '1M'
t_step = 1.0 / 365.0
simNumber = 10
trim_start = date(2000, 1, 1)
trim_end = date(2000, 12, 31)
trim_endMC = date(2001, 12, 31)
effDay = date(2000, 4, 1)
referenceDate = date(2000, 1, 1)
testSched = pd.date_range(trim_start, trim_start)
scheduleComplete = pd.date_range(start=trim_start, end=trim_end)
xR = [3.0, 0.05, 0.04, 0.03]
datelist = myScheduler.getSchedule(start=trim_start,
                                   end=trim_end,
                                   freq=freq,
                                   referencedate=referenceDate)
myMC = MC_Vasicek_Sim()
myMC.setVasicek(x=xR,
                minDay=trim_start,
                maxDay=trim_endMC,
                simNumber=simNumber,
                t_step=t_step)
myMC.getLibor()
myCorp = CorporateRates()
myCorp.getCorporatesFred(trim_start, trim_end)
testRatings = myCorp.getCorporateData("AAA", testSched)
testSurvival = myCorp.getCorporateQData("AAA", scheduleComplete, 0.4)

mySwap = IRSwap(zCurve=myMC.getLibor(),
                startDate=trim_start,
class MC_CIR_Sim(object):
    def __init__(self):
        pass

    def setCIR(self, minDay, maxDay, x, simNumber, t_step):
        # dλ(t) = k(θ − λ(t))dt + σ*sqrt(λ(t))*dW(t)
        self.kappa = x[0]
        self.theta = x[1]
        self.sigma = x[2]
        self.r0 = x[3]
        self.simNumber = simNumber
        self.t_step = t_step
        # creation of a fine grid for Monte Carlo integration
        # Create fine date grid for SDE integration
        self.Schedule = Scheduler()
        self.datelistlong = self.Schedule.getSchedule(start=minDay,end=maxDay,freq="1M",referencedate=minDay)
        self.datelistlong_daily = pd.date_range(minDay, maxDay).tolist()
        self.datelistlong_daily = [x.date() for x in self.datelistlong_daily]
        self.ntimes = len(self.datelistlong)
        self.ntimes_daily = len(self.datelistlong_daily)
        self.survival = []
        self.smallSurvival = []

    def getSurvival(self):
        rd = np.random.standard_normal((self.ntimes, self.simNumber))  # array of numbers for the number of samples
        r = np.zeros(np.shape(rd))
        nrows = np.shape(rd)[0]
        sigmaDT = self.sigma * np.sqrt(self.t_step)
        #calculate λ(t)
        r[1,:] = self.r0 + r[1,:]
        for i in np.arange(2, nrows):
            r[i,:] = r[i-1,:] + self.kappa * (self.theta - r[i-1,:]) * self.t_step + sigmaDT * rd[i,:]*np.sqrt(r[i-1,:])
        # calculate integral(λ(s)ds)
        integralR = r.cumsum(axis=0) * self.t_step
        # calculate Survival Prob
        self.survival = np.exp(-integralR)
        self.survival = pd.DataFrame(data=self.survival, index=self.datelistlong)
        return self.survival

    def getSurvival_daily(self):
        t_step = 1.0/365
        rd = np.random.standard_normal((self.ntimes_daily, self.simNumber))  # array of numbers for the number of samples
        r = np.zeros(np.shape(rd))
        nrows = np.shape(rd)[0]
        sigmaDT = self.sigma * np.sqrt(t_step)
        #calculate λ(t)
        r[1,:] = self.r0 + r[1,:]
        for i in np.arange(2, nrows):
            r[i,:] = r[i-1,:] + self.kappa * (self.theta - r[i-1,:]) * t_step + sigmaDT * rd[i,:]*np.sqrt(r[i-1,:])
        # calculate integral(λ(s)ds)
        integralR = r.cumsum(axis=0) * t_step
        # calculate Survival Prob
        self.survival = np.exp(-integralR)
        self.survival = pd.DataFrame(data=self.survival, index=self.datelistlong_daily)
        # r = pd.DataFrame(data=r, index=self.datelistlong_daily)
        return self.survival

    def getHazard_daily(self):
        t_step = 1.0/365
        rd = np.random.standard_normal((self.ntimes_daily, self.simNumber))  # array of numbers for the number of samples
        r = np.zeros(np.shape(rd))
        nrows = np.shape(rd)[0]
        sigmaDT = self.sigma * np.sqrt(t_step)
        #calculate λ(t)
        r[1,:] = self.r0 + r[1,:]
        for i in np.arange(2, nrows):
            r[i,:] = r[i-1,:] + self.kappa * (self.theta - r[i-1,:]) * t_step + sigmaDT * rd[i,:]*np.sqrt(r[i-1,:])
        r = pd.DataFrame(data=r, index=self.datelistlong_daily)
        return r

    def getSmallSurvival(self,datelist = None):
        # calculate indexes
        if (datelist is None):
            datelist = self.datelist
        ind = self.return_indices1_of_a(self.datelistlong, datelist)
        self.smallSruvival = self.survival.iloc[ind, :]
        return self.smallSurvival

    def saveMeExcel(self):
        df = DataFrame(self.libor)
        df.to_excel(os.path.join(WORKING_DIR,'MC_CIR_Sim.xlsx'), sheet_name='survival', index=False)

    def return_indices1_of_a(self, a, b):
        b_set = set(b)
        ind = [i for i, v in enumerate(a) if v in b_set]
        return ind

    def return_indices2_of_a(self, a, b):
        index = []
        for item in a:
            index.append(np.bisect.bisect(b,item))
        return np.unique(index).tolist()
示例#6
0
class CouponBond(object):
    def __init__(self,
                 fee,
                 coupon,
                 start,
                 maturity,
                 freq,
                 referencedate,
                 observationdate,
                 rating,
                 notional=1,
                 recovery=0.4):
        self.numSim = 10
        self.t_step = 1.0 / 365
        self.fee = fee
        self.coupon = coupon
        self.start = start
        self.maturity = maturity
        self.freq = freq
        self.recovery = recovery
        self.rating = rating
        self.referencedate = referencedate
        self.observationdate = observationdate
        self.myScheduler = Scheduler()
        self.delay = self.myScheduler.extractDelay(freq=freq)
        self.referencedate = referencedate
        self.getScheduleComplete()
        self.fullDateList = self.datelist
        self.ntimes = len(self.datelist)
        self.pvAvg = 0.0
        self.cashFlows = DataFrame()
        self.cashFlowsAvg = []
        self.yieldIn = 0.0
        self.notional = notional
        self.errorCurve = []
        self.mcSim = MC_Vasicek_Sim()

    def getScheduleComplete(self):
        self.datelist = self.myScheduler.getSchedule(
            start=self.start,
            end=self.maturity,
            freq=self.freq,
            referencedate=self.referencedate)
        self.ntimes = len(self.datelist)
        fullset = sorted(
            set(self.datelist).union([self.referencedate]).union([
                self.start
            ]).union([self.maturity]).union([self.observationdate]))
        a = 1
        return fullset, self.datelist

    def setLibor(self, libor):
        self.libor = libor / libor.loc[self.referencedate]
        #self.ntimes = np.shape(self.datelist)[0]
        self.ntrajectories = np.shape(self.libor)[1]
        self.ones = np.ones(shape=[self.ntrajectories])

    def getExposure(self, referencedate):
        if self.referencedate != referencedate:
            self.referencedate = referencedate
            self.getScheduleComplete()
        deltaT = np.zeros(self.ntrajectories)
        if self.ntimes == 0:
            pdzeros = pd.DataFrame(data=np.zeros([1, self.ntrajectories]),
                                   index=[referencedate])
            self.pv = pdzeros
            self.pvAvg = 0.0
            self.cashFlows = pdzeros
            self.cashFlowsAvg = 0.0
            return self.pv
        for i in range(1, self.ntimes):
            deltaTrow = ((self.datelist[i] - self.datelist[i - 1]).days /
                         365) * self.ones
            deltaT = np.vstack((deltaT, deltaTrow))
        self.cashFlows = self.coupon * deltaT
        principal = self.ones
        if self.ntimes > 1:
            self.cashFlows[-1:] += principal
        else:
            self.cashFlows = self.cashFlows + principal
        if (self.datelist[0] <= self.start):
            self.cashFlows[0] = -self.fee * self.ones

        if self.ntimes > 1:
            self.cashFlowsAvg = self.cashFlows.mean(axis=1) * self.notional
        else:
            self.cashFlowsAvg = self.cashFlows.mean() * self.notional
        pv = self.cashFlows * self.libor.loc[self.datelist]
        self.pv = pv.sum(axis=0) * self.notional
        self.pvAvg = np.average(self.pv) * self.notional
        return self.pv

    def getPV(self, referencedate):
        self.getExposure(referencedate=referencedate)
        return self.pv / self.libor.loc[self.referencedate]

    def getFullExposure(self):
        fullExposure = pd.DataFrame(data=np.zeros(len(self.fullDateList)),
                                    index=self.fullDateList)
        for days in self.fullDateList:
            fullExposure.loc[days] = self.getExposure(days)
        self.fullExposure = fullExposure

    def setCorpData(self, corpData):
        self.corpData = corpData.loc[self.rating, :, "1 MO"]

    def setxQ(self, xQ):
        res = optimize.fmin(func=self.mcSim.errorFunction,
                            x0=np.array([xQ[0], xQ[1]]),
                            args=(self.corpData.values[:-1],
                                  self.corpData.values[1:], self.t_step))
        xQSigma = np.std(self.corpData.values[:-1] - self.corpData.values[1:])
        self.xQ = np.append(res, np.array([xQSigma, xQ[3]]))
        self.mcSim.setVasicek(minDay=self.start,
                              maxDay=self.maturity,
                              x=self.xQ,
                              simNumber=self.numSim,
                              t_step=self.t_step)

    def setQCurve(self):
        self.qCurve = self.mcSim.getLibor().loc[:, 0]
        return

    def getCVA(self):
        self.CVA = (1 - self.recovery) * self.fullExposure.loc[
            self.fullDateList, 0].values * self.qCurve.loc[
                self.fullDateList] * self.libor.loc[self.fullDateList, 0]

    def getLiborAvg(self, yieldIn, datelist):
        self.yieldIn = yieldIn
        time0 = datelist[0]
        # this function is used to calculate exponential single parameter (r or lambda) Survival or Libor Functions
        Z = np.exp(-self.yieldIn *
                   pd.DataFrame(np.tile([(x - time0).days / 365.0
                                         for x in self.datelist],
                                        reps=[self.ntrajectories, 1]).T,
                                index=self.datelist))
        return Z

    def getYield(self, price):
        # Fit model to curve data
        yield0 = 0.05 * self.ones
        self.price = price
        self.yieldIn = self.fitModel2Curve(x=yield0)
        return self.yieldIn

    def fitModel2Curve(self, x):
        # Minimization procedure to fit curve to model
        results = optimize.minimize(fun=self.fCurve, x0=x)
        a = 1
        return results.x

    def fCurve(self, x):
        # raw data error function
        calcCurve = self.getLiborAvg(x, self.datelist)
        thisPV = np.multiply(self.cashFlows,
                             calcCurve).mean(axis=1).sum(axis=0)
        error = 1e4 * (self.price - thisPV)**2
        self.errorCurve = error
        return error
示例#7
0
class CouponBond(object):
    def __init__(self, fee, start,coupon,  maturity, freq, referencedate, observationdate,notional):
        self.fee = fee
        self.coupon=coupon
        self.start = start
        self.maturity = maturity
        self.freq= freq
        self.referencedate = referencedate
        self.observationdate = observationdate
        self.myScheduler = Scheduler()
        self.delay = self.myScheduler.extractDelay(freq=freq)
        self.getScheduleComplete()
        self.ntimes=len(self.datelist)
        self.referencedate = referencedate
        self.pvAvg=0.0
        self.cashFlows = DataFrame()
        self.cashFlowsAvg = []
        self.yieldIn = 0.0
        self.notional=notional

    def getScheduleComplete(self):
        self.datelist = self.myScheduler.getSchedule(start=self.start,end=self.maturity,freq=self.freq,referencedate=self.referencedate)
        fullset = list(sorted(list(set(self.datelist)
                                   .union([self.referencedate])
                                   .union([self.start])
                                   .union([self.maturity])
                                   .union([self.observationdate])
                                   )))
        return fullset,self.datelist

    def setLibor(self,libor):
        self.libor = libor/libor.loc[self.referencedate]
        self.ntimes = np.shape(self.datelist)[0]
        self.ntrajectories = np.shape(self.libor)[1]
        self.ones = np.ones(shape=[self.ntrajectories])

    def getExposure(self, referencedate):
        if self.referencedate!=referencedate:
            self.referencedate=referencedate
            self.getScheduleComplete()
        deltaT= np.zeros(self.ntrajectories)
        if self.ntimes==0:
            pdzeros= pd.DataFrame(data=np.zeros([1,self.ntrajectories]), index=[referencedate])
            self.pv=pdzeros
            self.pvAvg=0.0
            self.cashFlows=pdzeros
            self.cashFlowsAvg=0.0
            return self.pv
        for i in range(1,self.ntimes):
            deltaTrow = ((self.datelist[i]-self.datelist[i-1]).days/365)*self.ones
            deltaT = np.vstack ((deltaT,deltaTrow) )
        self.cashFlows= self.coupon*deltaT
        principal = self.ones
        if self.ntimes>1:
            self.cashFlows[-1:]+= principal
        else:
            self.cashFlows = self.cashFlows + principal
        if(self.datelist[0]<= self.start):
            self.cashFlows[0]=-self.fee*self.ones
    
        if self.ntimes>1:
            self.cashFlowsAvg = self.cashFlows.mean(axis=1)*self.notional
        else:
            self.cashFlowsAvg = self.cashFlows.mean() * self.notional
        pv = self.cashFlows*self.libor.loc[self.datelist]
        self.pv = pv.sum(axis=0)*self.notional
        self.pvAvg = np.average(self.pv)*self.notional
        return self.pv

    def getPV(self,referencedate):
        self.getExposure(referencedate=referencedate)
        return self.pv/self.libor.loc[self.observationdate]

    def getLiborAvg(self, yieldIn, datelist):
        self.yieldIn = yieldIn
        time0 = datelist[0]
        # this function is used to calculate exponential single parameter (r or lambda) Survival or Libor Functions
        Z = np.exp(-self.yieldIn * pd.DataFrame(np.tile([(x - time0).days / 365.0 for x in self.datelist], reps=[self.ntrajectories,1]).T,index=self.datelist))
        return Z

    def getYield(self,price):
        # Fit model to curve data
        yield0 = 0.05 * self.ones
        self.price = price
        self.yieldIn = self.fitModel2Curve(x=yield0)
        return self.yieldIn


    def fitModel2Curve(self, x ):
        # Minimization procedure to fit curve to model
        results = minimize(fun=self.fCurve, x0=x)
        return results.x

    def fCurve(self, x):
        # raw data error function
        calcCurve = self.getLiborAvg(x, self.datelist)
        thisPV = np.multiply(self.cashFlows,calcCurve).mean(axis=1).sum(axis=0)
        error = 1e4 * (self.price - thisPV) ** 2
        return error
class PortfolioLossCalculation(object):
    def __init__(self, K1, K2, Fs, Rs, betas, start_dates, end_dates, freqs,
                 coupons, referenceDates, ratings, bootstrap):
        self.bootstrap = bootstrap
        self.K1 = K1
        self.K2 = K2
        self.Fs = Fs
        self.Rs = Rs
        self.betas = betas
        self.referenceDates = referenceDates
        self.freqs = freqs
        self.coupons = coupons
        self.start_dates = start_dates
        self.end_dates = end_dates
        self.ratings = ratings

        self.R = Rs[0]
        self.beta = betas[0]
        self.referenceDate = referenceDates[0]
        self.freq = freqs[0]
        self.coupon = coupons[0]
        self.start_date = start_dates[0]
        self.end_date = end_dates[0]
        self.rating = ratings[0]
        self.maturity = end_dates[0]

        self.myScheduler = Scheduler()

    def setParameters(self, R, rating, coupon, beta, start_date, referenceDate,
                      end_date, freq):
        self.R = R
        self.beta = beta
        self.referenceDate = referenceDate
        self.freq = freq
        self.coupon = coupon
        self.start_date = start_date
        self.end_date = end_date
        self.rating = rating
        self.maturity = end_date

    def getQ(self, start_date, referenceDate, end_date, freq, coupon, rating,
             R):
        ## Use CorporateDaily to get Q for referencedates ##
        # print("GET Q")
        # print(self.portfolioScheduleOfCF)

        if self.bootstrap:
            print("Q bootstrap")
            CDSClass = CDS(start_date=start_date,
                           end_date=end_date,
                           freq=freq,
                           coupon=coupon,
                           referenceDate=referenceDate,
                           rating=rating,
                           R=R)
            myLad = BootstrapperCDSLadder(start=self.start_date,
                                          freq=[freq],
                                          CDSList=[CDSClass],
                                          R=CDSClass.R).getXList(x0Vas)[freq]
            self.Q1M = MC_Vasicek_Sim(
                x=myLad,
                t_step=1 / 365,
                datelist=[CDSClass.referenceDate, CDSClass.end_date],
                simNumber=simNumber).getLibor()[0]
            print(self.Q1M)
        else:
            myQ = CorporateRates()
            myQ.getCorporatesFred(trim_start=referenceDate, trim_end=end_date)
            ## Return the calculated Q(t,t_i) for bonds ranging over maturities for a given rating
            daterange = pd.date_range(start=referenceDate, end=end_date).date
            myQ = myQ.getCorporateQData(rating=rating, datelist=daterange, R=R)
            Q1M = myQ[freq]
            print(Q1M)

        return (Q1M)

    def Q_lhp(self, t, K1, K2, R, beta, Q):
        """Calculates the Tranche survival curve for the LHP model.

        Args:
            T (datetime.date): Should be given in "days" (no hours, minutes, etc.)
            K1 (float): The starting value of the tranche. Its value should be
                between 0 & 1.
            K2 (float): The final value of the tranche.
            beta (float): Correlation perameter. Its value should be between 0 and 1.
            R (float): Recovery rate. Usually between 0 and 1.
            Q (callable function): A function Q that takes in a dateime.date and
                outputs a float from 0 to 1. It is assumed that Q(0) = 1 and Q is
                decreasing. Represents survival curve of each credit.
        """
        if Q(t) == 1:
            return 1  # prevents infinity

        def emin(K):
            # Calculates E[min(L(T), K)] in LHP model
            C = norm.ppf(1 - Q(t))
            A = (1 / beta) * (C - sqrt(1 - beta * beta) * norm.ppf(K /
                                                                   (1 - R)))
            return (1 - R) * mvn.mvndst(
                upper=[C, -1 * A],
                lower=[0, 0],
                infin=[0, 0],  # set lower bounds = -infty
                correl=-1 * beta)[1] + K * norm.cdf(A)

        return 1 - (emin(K2) - emin(K1)) / (K2 - K1)

    def Q_gauss(self, t, K1, K2, Fs, Rs, betas, Qs):
        """ Calculate the tranche survival probability in the Gaussian heterogenous model.

        Arguments:
            t (float): Time. Positive.
            K1 (float): Starting tranche value. Between 0 and 1.
            K2 (float): Ending tranche value. Between 0 and 1.
            Fs (list): List of fractional face values for each credit. Each entry must be
                between 0 and 1.
            Rs (list): List of recovery rates for each credit. Each entry must be between
                0 and 1.
            betas (list): Correlation perameters for each credit. Each entry must be between
                0 and 1.
            Qs (list): Survival curves for each credit. Each entry must be a callable function
                that takes in a datetime.date argument and returns a number from 0 to 1.
        """
        Cs = [norm.ppf(1 - q(t)) for q in Qs]
        N = len(Fs)

        def f(K, z):
            ps = [
                norm.cdf((C - beta * z) / sqrt(1 - beta**2))
                for C, beta in zip(Cs, betas)
            ]
            mu = 1 / N * sum([p * F * (1 - R) for p, F, R in zip(ps, Fs, Rs)])
            sigma_squared = 1 / N / N * sum([
                p * (1 - p) * F**2 * (1 - R)**2 for p, F, R in zip(ps, Fs, Rs)
            ])
            sigma = sqrt(sigma_squared)
            return -1 * sigma * norm.pdf(
                (mu - K) / sigma) - (mu - K) * norm.cdf((mu - K) / sigma)

        emin = lambda K: quad(lambda z: norm.pdf(z) * f(K, z), -10, 10)[0]
        return 1 - (emin(K2) - emin(K1)) / (K2 - K1)

    def Q_adjbinom(self, t, K1, K2, Fs, Rs, betas, Qs):
        """ Calculates the tranche survival probability under the adjusted
            binomial model.

            Arguments:
                t (datetime.date): Time.
                K1 (float): Starting tranche value (0 to 1).
                K2 (float): Final tranche value (0 to 1).
                Fs (list): List of fractional face values (floats) for each credit.
                Rs (list): List of recovery rates (floats) for each credit.
                betas (list): List of correlation perameters
                Qs (list): List of survival probabilities. These are callable functions that
                    takes in a single datetime.date argument and returns a float.
            Returns:
                float: The value of the tranche survival curve.
        """
        if Qs[0](t) == 1:
            return 1.0  # initial value -- avoids weird nan return
        N = len(Fs)
        Cs = [norm.ppf(1 - Q(t)) for Q in Qs]
        L = sum([(1 - R) * F for R, F in zip(Rs, Fs)]) / N

        def choose(n, k):  # Calculates binomial coeffecient: n choose k.
            if k == 0 or k == n:
                return 1
            return choose(n - 1, k - 1) + choose(n - 1, k)

        def g(k, z):
            ps = [
                norm.cdf((C - beta * z) / sqrt(1 - beta * beta))
                for C, beta in zip(Cs, betas)
            ]
            p_avg = sum([(1 - R) * F / L * p
                         for R, F, p in zip(Rs, Fs, ps)]) / N
            f = lambda k: choose(N, k) * p_avg**k * (1 - p_avg)**(N - k)
            vA = p_avg * (1 - p_avg) / N
            vE = 1 / N / N * sum([((1 - R) * F / L)**2 * p * (1 - p)
                                  for R, F, p in zip(Rs, Fs, ps)])
            m = p_avg * N
            l = int(m)
            u = l + 1
            o = (u - m)**2 + ((l - m)**2 - (u - m)**2) * (u - m)
            alpha = (vE * N + o) / (vA * N + o)
            if k == l:
                return f(l) + (1 - alpha) * (u - m)
            if k == u:
                return f(u) - (1 - alpha) * (l - m)
            return alpha * f(k)

        I = lambda k: quad(lambda z: norm.pdf(z) * g(k, z), -10, 10)[0]
        emin = lambda K: sum([I(k) * min(L * k, K) for k in range(0, N + 1)])
        return 1 - (emin(K2) - emin(K1)) / (K2 - K1)

    def gcd(self, a, b):
        if a * b == 0:
            return max(a, b)
        if a < b:
            return self.gcd(a, b % a)
        return self.gcd(a % b, b)

    def Q_exact(self, t, K1, K2, Fs, Rs, betas, Qs):
        Cs = [norm.ppf(1 - Q(t)) for Q in Qs]
        N = len(Fs)
        g = round(3600 * Fs[0] * (1 - Rs[0]))
        for j in range(1, N):
            g = self.gcd(g, round(3600 * Fs[j] * (1 - Rs[j])))
        g = g / 3600
        ns = [round(F * (1 - R) / g) for F, R in zip(Fs, Rs)]

        def f(j, k, z):
            if (j, k) == (0, 0):
                return 1.0
            if j == 0:
                return 0.0
            ps = [
                norm.cdf((C - beta * z) / sqrt(1 - beta**2))
                for C, beta in zip(Cs, betas)
            ]
            if k < ns[j - 1]:
                return f(j - 1, k, z) * (1 - ps[j - 1])
            return f(j - 1, k, z) * (1 - ps[j - 1]) + f(
                j - 1, k - ns[j - 1], z) * ps[j - 1]

        I = [
            quad(lambda z: norm.pdf(z) * f(N, k, z), -12, 12)[0]
            for k in range(sum(ns))
        ]
        emin = lambda K: sum([I[k] * min(k * g, K) for k in range(sum(ns))])
        return 1 - (emin(K2) - emin(K1)) / (K2 - K1)

    def getZ_Vasicek(self):
        ### Get Z(t,t_i) for t_i in datelist #####

        ## Simulate Vasicek model with paramters given in workspace.parameters
        # xR = [5.0, 0.05, 0.01, 0.05]
        # kappa = x[0]
        # theta = x[1]
        # sigma = x[2]
        # r0 = x[3]
        vasicekMC = MC_Vasicek_Sim(
            datelist=[self.referenceDate, self.end_date],
            x=xR,
            simNumber=10,
            t_step=t_step)
        self.myZ = vasicekMC.getLibor()
        self.myZ = self.myZ.loc[:, 0]

    def getScheduleComplete(self):
        datelist = self.myScheduler.getSchedule(
            start=self.start_date,
            end=self.maturity,
            freq=self.freq,
            referencedate=self.referenceDate)
        ntimes = len(datelist)
        fullset = list(
            sorted(
                list(
                    set(datelist).union([self.referenceDate]).union([
                        self.start_date
                    ]).union([self.maturity]).union([self.referenceDate]))))
        return fullset, datelist

    def getPremiumLegZ(self, myQ):
        Q1M = myQ
        # Q1M = self.myQ["QTranche"]
        fulllist, datelist = self.getScheduleComplete()
        portfolioScheduleOfCF = fulllist
        timed = portfolioScheduleOfCF[portfolioScheduleOfCF.
                                      index(self.referenceDate):]

        Q1M = Q1M.loc[timed]

        zbarPremLeg = self.myZ / self.myZ.loc[self.referenceDate]
        zbarPremLeg = zbarPremLeg.loc[timed]
        ## Calculate Q(t_i) + Q(t_(i-1))
        Qplus = []
        out = 0
        for i in range(1, len(Q1M)):
            out = out + (Q1M[(i - 1)] + Q1M[i]) * float(
                (timed[i] - timed[i - 1]).days / 365) * zbarPremLeg[i]

        zbarPremLeg = pd.DataFrame(zbarPremLeg, index=timed)
        # print("Premium LEg")
        PVpremiumLeg = out * (1 / 2)
        # print(PVpremiumLeg)
        ## Get coupon bond ###
        print(PVpremiumLeg)
        return PVpremiumLeg

        # //////////////// Get Protection leg Z(t_i)( Q(t_(i-1)) - Q(t_i) )

    def getProtectionLeg(self, myQ):
        print("Protection Leg ")
        Q1M = myQ
        #Qminus = np.gradient(Q1M)
        zbarProtectionLeg = self.myZ

        out = 0
        for i in range(1, zbarProtectionLeg.shape[0]):
            #out = -Qminus[i] * zbarProtectionLeg.iloc[i]*float(1/365)
            out = out - (Q1M.iloc[i] -
                         Q1M.iloc[i - 1]) * zbarProtectionLeg.iloc[i]

        ## Calculate the PV of the premium leg using the bond class
        print(out)
        return out

    def CDOPortfolio(self):
        self.setParameters(R=self.Rs[0],
                           rating=self.ratings[0],
                           coupon=self.coupons[0],
                           beta=self.betas[0],
                           start_date=start_dates[0],
                           referenceDate=referenceDates[0],
                           end_date=end_dates[0],
                           freq=self.freqs[0])
        ## price CDOs using LHP
        Q_now1 = self.getQ(start_date=self.start_dates[0],
                           referenceDate=self.referenceDates[0],
                           end_date=self.end_dates[0],
                           freq=self.freqs[0],
                           coupon=self.coupons[0],
                           rating=self.ratings[0],
                           R=self.Rs[0])

        ## Estimate default probabilites from Qtranche list ###
        ## Assume that lambda is constant over a small period of time
        def getApproxDefaultProbs(Qvals, freq, tvalues):
            t_start = tvalues[0]
            delay = self.myScheduler.extractDelay(freq)
            delay_days = ((t_start + delay) - t_start).days
            ## Estimate constant lambda
            lam = -(1 / delay_days) * np.log(Qvals[t_start])
            Qvals = [
                ((Qvals[t_start] * exp(-lam * (t - t_start).days)) / Qvals[t])
                for t in tvalues
            ]
            return (Qvals)

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

        print(Q_now1)
        ### Create Q dataframe
        tvalues = Q_now1.index.tolist()
        Cs = pd.Series(Q_now1, index=tvalues)
        for cds_num in range(1, len(Fs)):
            Q_add = self.getQ(start_date=self.start_dates[cds_num],
                              referenceDate=self.referenceDates[cds_num],
                              end_date=self.end_dates[cds_num],
                              freq=self.freqs[cds_num],
                              coupon=self.coupons[cds_num],
                              rating=self.ratings[cds_num],
                              R=self.Rs[cds_num])
            Q_add = pd.Series(Q_add, index=tvalues)
            Cs = pd.concat([Cs, Q_add], axis=1)

        def expdecay(n):
            return lambda t: Cs.ix[t, n]

        ##
        #Qs = [expdecay(0),expdecay(1)]
        Qs = [expdecay(n) for n in range(0, Cs.shape[1])]

        self.getZ_Vasicek()

        ###### LHP Method #####################################################################
        Rs_mean = np.mean(self.Rs)
        betas_mean = np.mean(betas)

        lhpcurve = [
            self.Q_lhp(t, self.K1, self.K2, R=Rs[0], beta=betas[0], Q=Qs[0])
            for t in tvalues
        ]

        lhpcurve = pd.Series(lhpcurve, index=tvalues)
        lhpcurve = getApproxDefaultProbs(lhpcurve,
                                         freq=self.freq,
                                         tvalues=tvalues)
        lhpcurve = pd.Series(lhpcurve, index=tvalues)

        ProtectionLeg = self.getProtectionLeg(myQ=lhpcurve)
        PremiumLeg = self.getPremiumLegZ(myQ=lhpcurve)
        spreads = ProtectionLeg / PremiumLeg
        print("The spread for LHP is: ", 10000 * spreads, ".")
        ########################################################################################

        ###### Gaussian Method #####################################################################
        print('Gaussian progression: ', end="")
        gaussiancurve = [
            self.Q_gauss(t,
                         self.K1,
                         self.K2,
                         Fs=self.Fs,
                         Rs=self.Rs,
                         betas=self.betas,
                         Qs=Qs) for t in tvalues
        ]
        gaussiancurve = pd.Series(gaussiancurve, index=tvalues)
        gaussiancurve = getApproxDefaultProbs(gaussiancurve,
                                              freq=self.freq,
                                              tvalues=tvalues)
        gaussiancurve = pd.Series(gaussiancurve, index=tvalues)

        ProtectionLeg = self.getProtectionLeg(myQ=gaussiancurve)
        PremiumLeg = self.getPremiumLegZ(myQ=gaussiancurve)
        spreads = ProtectionLeg / PremiumLeg
        print("The spread for Gaussian is: ", 10000 * spreads, ".")
        ########################################################################################

        ###### Adjusted Binomial Method #####################################################################
        adjustedbinomialcurve = [
            self.Q_adjbinom(t,
                            self.K1,
                            self.K2,
                            Fs=self.Fs,
                            Rs=self.Rs,
                            betas=self.betas,
                            Qs=Qs) for t in tvalues
        ]
        adjustedbinomialcurve = pd.Series(adjustedbinomialcurve, index=tvalues)
        adjustedbinomialcurve = getApproxDefaultProbs(adjustedbinomialcurve,
                                                      freq=self.freq,
                                                      tvalues=tvalues)
        adjustedbinomialcurve = pd.Series(adjustedbinomialcurve, index=tvalues)
        #adjustedbinomialcurve = adjustedbinomialcurve.to_frame(self.freqs[0])

        ProtectionLeg = self.getProtectionLeg(myQ=adjustedbinomialcurve)
        PremiumLeg = self.getPremiumLegZ(myQ=adjustedbinomialcurve)
        spreads = ProtectionLeg / PremiumLeg
        print("The spread for Ajusted Binomial is: ", 10000 * spreads, ".")
        ########################################################################################

        ###### Exact Method #####################################################################
        exactcurve = [
            self.Q_exact(t,
                         self.K1,
                         self.K2,
                         Fs=self.Fs,
                         Rs=self.Rs,
                         betas=self.betas,
                         Qs=Qs) for t in tvalues
        ]
        exactcurve = pd.Series(exactcurve, index=tvalues)
        exactcurve = getApproxDefaultProbs(exactcurve,
                                           freq=self.freq,
                                           tvalues=tvalues)
        exactcurve = pd.Series(exactcurve, index=tvalues)
        #exactcurve = exactcurve.to_frame(self.freqs[0])

        ProtectionLeg = self.getProtectionLeg(myQ=exactcurve)
        PremiumLeg = self.getPremiumLegZ(myQ=exactcurve)
        spreads = ProtectionLeg / PremiumLeg
        print("The spread for Exact is: ", 10000 * spreads, ".")
示例#9
0
class IRSwap(object):
    def __init__(self,
                 startDate,
                 endDate,
                 referenceDate,
                 effectiveDate,
                 freq,
                 notional,
                 recovery=0.4):
        """
            effective date is the start of the payments, startDate is when the contract is entered, endDate is maturity
            referenceDate is the date when the PV is taken
            We are paying a fixed rate to receive a floating rate
        """
        self.recovery = recovery
        self.simNum = 10
        self.xR = []
        self.xQ = []
        # use MC to generate scenarios for exposure
        self.mcSim = MC_Vasicek_Sim()
        #self.mcSim.setVasicek(minDay=startDate,maxDay=endDate,x=xR,t_step=1.0/365, simNumber=self.simNum)
        # z is discount curve
        self.zCurve = []
        self.swapRate = []
        self.freq = freq
        self.notional = notional
        self.fixedLeg = []
        self.floatingLeg = []
        self.startDate = startDate
        self.endDate = endDate
        self.referenceDate = referenceDate
        self.effctiveDate = effectiveDate
        self.initialSpread = []
        self.myScheduler = Scheduler()
        self.datelist = pd.date_range(start=effectiveDate,
                                      end=endDate,
                                      freq=freq)

    def getScheduleComplete(self):
        self.datelist = self.myScheduler.getSchedule(
            start=self.startDate,
            end=self.endDate,
            freq=self.freq,
            referencedate=self.referenceDate)
        self.ntimes = len(self.datelist)
        fullset = sorted(
            set(self.datelist).union([self.referenceDate]).union([
                self.startDate
            ]).union([self.endDate]).union([self.referenceDate]))
        return fullset, self.datelist

    def setLibor(self, libor):
        self.zCurve = libor / libor.loc[self.referenceDate]

    def setxR(self, xR):
        self.xR = xR
        self.mcSim.setVasicek(minDay=self.startDate,
                              maxDay=self.endDate,
                              x=xR,
                              t_step=1.0 / 365,
                              simNumber=self.simNum)

    def setSwapRate(self):
        # getting initial spread at time zero
        floatLegPV = (self.zCurve.loc[self.effctiveDate,
                                      0]) - (self.zCurve.loc[self.endDate, 0])
        fixedLegPV = 0
        delta = (self.datelist[1] - self.datelist[0]).days / 365
        for payDate in self.datelist:
            fixedLegPV += delta * self.zCurve.loc[payDate.date(), 0]
        swapRate = floatLegPV / fixedLegPV
        self.swapRate = swapRate
        return

    def setCashFlows(self):
        fixedLegCF = np.ones(len(self.datelist)) * self.swapRate
        floatLegCF = []
        delta = (self.datelist[1] - self.datelist[0]).days / 365
        for payDate in self.datelist:
            if payDate.date() == self.endDate:
                floatLegCF.append(
                    ((self.zCurve.loc[payDate.date(), 0] / self.zCurve.loc[
                        payDate.date() + timedelta(delta * 365), 0]) - 1) /
                    delta)
            else:
                floatLegCF.append(
                    (self.zCurve.loc[payDate.date(), 0] / self.zCurve.loc[
                        (payDate + 1).date(), 0] - 1) / delta)
        fixedLegCF = pd.DataFrame(data=fixedLegCF, index=self.datelist)
        floatLegCF = pd.DataFrame(data=floatLegCF, index=self.datelist)
        self.fixedLeg = fixedLegCF
        self.floatingLeg = floatLegCF
        return

    def getExposure(self):
        fullDate = pd.date_range(start=self.startDate,
                                 end=self.endDate,
                                 freq=self.freq)
        EE = np.zeros((len(fullDate), self.simNum))
        for i in range(0, self.simNum):
            zCurveNew = self.mcSim.getLibor()
            row = 0
            for day in fullDate:
                if day < self.datelist[0]:
                    npv = (np.sum(
                        (self.floatingLeg - self.fixedLeg).values.ravel() *
                        zCurveNew.loc[self.datelist, 0].values))
                elif day >= self.datelist[0] and day < self.datelist[-1]:
                    fixedPartial = self.fixedLeg.loc[day.date():]
                    floatPartial = self.floatingLeg.loc[day.date():]
                    npv = (np.sum(
                        (floatPartial - fixedPartial).values.ravel() *
                        zCurveNew.loc[fixedPartial.index, 0].values))
                else:
                    npv = 0
                #if npv < 0:
                #    npv = 0
                EE[row, i] = npv
                row += 1
        EE = pd.DataFrame(data=EE, index=fullDate)
        self.fullDate = fullDate
        self.fullExposure = EE
        self.avgExposure = EE.mean(axis=1)
        return

    def getCVA(self, survCurve):
        # CVA = LGD * EE * PD * Discount, LGD =1-R
        CVA = self.notional * (
            1 - self.recovery) * self.avgExposure.values * survCurve.loc[
                self.fullDate].values * self.zCurve.loc[self.fullDate,
                                                        0].values
        CVA = pd.DataFrame(data=CVA, index=self.fullDate)
        self.CVA = CVA
        return
示例#10
0
from IPython.core.pylabtools import figsize
figsize(15, 4)
from pandas import ExcelWriter
import numpy.random as nprnd
from pprint import pprint

t_step = 1.0 / 365.0
simNumber = 10
trim_start = date(2005, 3, 10)
trim_end = date(2010, 12, 31)  # Last Date of the Portfolio
start = date(2005, 3, 10)
referenceDate = date(2005, 3, 10)

myScheduler = Scheduler()
ReferenceDateList = myScheduler.getSchedule(start=referenceDate,
                                            end=trim_end,
                                            freq="1M",
                                            referencedate=referenceDate)
# Create Simulator
xOIS = [3.0, 0.07536509, -0.208477, 0.07536509]
myVasicek = MC_Vasicek_Sim(datelist=[trim_start, trim_end],
                           x=xOIS,
                           simNumber=simNumber,
                           t_step=1 / 365.0)
#myVasicek.setVasicek(x=xOIS,minDay=trim_start,maxDay=trim_end,simNumber=simNumber,t_step=1/365.0)
myVasicek.getLibor()

# Create Coupon Bond with several startDates.
SixMonthDelay = myScheduler.extractDelay("6M")
TwoYearsDelay = myScheduler.extractDelay("2Y")
startDates = [
    referenceDate + nprnd.randint(0, 3) * SixMonthDelay for r in range(10)
示例#11
0
class CDS(object):
    def __init__(self,
                 start_date,
                 end_date,
                 freq,
                 coupon,
                 referenceDate,
                 rating,
                 R=.4):
        ### Parameters passed to external functions
        self.start_date = start_date
        self.end_date = end_date
        self.freq = freq
        self.R = R
        self.notional = 1
        self.fee = fee
        self.rating = rating
        self.coupon = coupon
        self.referenceDate = referenceDate
        self.observationDate = referenceDate

        ## Get datelist ##
        self.myScheduler = Scheduler()
        # ReferenceDateList = self.myScheduler.getSchedule(start=referenceDate,end=end_date,freq=freq, referencedate=referenceDate)

        ## Delay start and maturity
        delay = self.myScheduler.extractDelay(self.freq)
        cashFlowDays = self.myScheduler.extractDelay("3M")
        ## Delay maturity and start date
        # self.start_date = self.start_date +SixMonthDelay
        # self.maturity =self.start_date + delay
        self.maturity = self.start_date + delay

        fulllist, datelist = self.getScheduleComplete()
        self.datelist = datelist
        self.portfolioScheduleOfCF = fulllist

        self.myZ = None
        self.myQ = None

    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////// SET FUNCTIONS ///////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#

    def setZ(self, Zin):
        ## Zin needs to be a pandas dataframe
        self.myZ = Zin

    def setQ(self, Qin):
        self.myQ = Qin

    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////// GET FUNCTIONS ///////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#
    # ////////////////////////////////////////////////////////////////////////////////////////////#

    # //////////////// Get Vasicek simulated Z(t,t_j)
    def getZ_Vasicek(self):
        ### Get Z(t,t_i) for t_i in datelist #####

        ## Simulate Vasicek model with paramters given in workspace.parameters
        # xR = [5.0, 0.05, 0.01, 0.05]
        # kappa = x[0]
        # theta = x[1]
        # sigma = x[2]
        # r0 = x[3]
        vasicekMC = MC_Vasicek_Sim(
            datelist=[self.referenceDate, self.maturity],
            x=xR,
            simNumber=100,
            t_step=t_step)
        self.myZ = vasicekMC.getLibor()

        self.myLibor = self.myZ
        self.myZ = self.myZ.loc[:, 0]

        ## get Libor Z for reference dates ##
        # self.myZ = vasicekMC.getSmallLibor(datelist= self.portfolioScheduleOfCF).loc[:,0]

    # //////////////// Get Corporates simulated Q(t,t_j)
    def getQ_Corporate(self):
        ## Use CorporateDaily to get Q for referencedates ##
        # print("GET Q")
        # print(self.portfolioScheduleOfCF)
        myQ = CorporateRates()
        myQ.getCorporatesFred(trim_start=self.referenceDate,
                              trim_end=self.end_date)
        ## Return the calculated Q(t,t_i) for bonds ranging over maturities for a given rating
        daterange = pd.date_range(start=self.referenceDate,
                                  end=self.maturity).date
        self.myQ = myQ.getCorporateQData(rating=self.rating,
                                         datelist=daterange,
                                         R=self.R)

        return (self.myQ)

    # //////////////// Get Premium leg Z(t_i)( Q(t_(i-1)) + Q(t_i) )
    def getPremiumLegZ(self):
        ## Check if Z and Q exists
        if self.myZ is None:
            self.getZ_Vasicek()

        if self.myQ is None:
            self.getQ_Corporate()

        ## Choose 1month Q
        '''
        Q1M = self.myQ[self.freq]
        # Q1M = self.myQ["QTranche"]
        timed = self.portfolioScheduleOfCF[self.portfolioScheduleOfCF.index(self.referenceDate):]
        Q1M = Q1M.loc[timed]
        Q1M = Q1M.cumprod(axis=0)
        zbarPremLeg = self.myZ / self.myZ.loc[self.referenceDate]
        zbarPremLeg = zbarPremLeg.loc[timed]
        ## Calculate Q(t_i) + Q(t_(i-1))
        out = 0
        for i in range(1, len(Q1M)):
            out = out + (Q1M[(i - 1)] + Q1M[i]) * float((timed[i] - timed[i - 1]).days / 365) * zbarPremLeg[i]

        ## Calculate the PV of the premium leg using the bond class

        # zbarPremLeg = zbarPremLeg.cumsum(axis=0)
        zbarPremLeg = pd.DataFrame(zbarPremLeg, index=timed)
        # print("Premium LEg")
        PVpremiumLeg = out * (1 / 2)
        # print(PVpremiumLeg)
        ## Get coupon bond ###
        return PVpremiumLeg
        '''
        Q1M = self.myQ[self.freq]
        # Q1M = self.myQ["QTranche"]
        timed = self.portfolioScheduleOfCF[self.portfolioScheduleOfCF.
                                           index(self.referenceDate):]
        Q1M = Q1M.loc[timed]
        Q1M = Q1M.cumprod()
        zbarPremLeg = self.myZ / self.myZ.loc[self.referenceDate]
        zbarPremLeg = zbarPremLeg.loc[timed]
        ## Calculate Q(t_i) + Q(t_(i-1))
        Qplus = []
        out = 0
        for i in range(1, len(Q1M)):
            out = out + (Q1M[(i - 1)] + Q1M[i]) * float(
                (timed[i] - timed[i - 1]).days / 365) * zbarPremLeg[i]
        ## Calculate the PV of the premium leg using the bond class
        # zbarPremLeg = zbarPremLeg.cumsum(axis=0)
        zbarPremLeg = pd.DataFrame(zbarPremLeg, index=timed)
        # print("Premium LEg")
        PVpremiumLeg = out * (1 / 2)
        # print(PVpremiumLeg)
        ## Get coupon bond ###
        return PVpremiumLeg

    # //////////////// Get Protection leg Z(t_i)( Q(t_(i-1)) - Q(t_i) )
    def getProtectionLeg(self):
        if self.myZ is None:
            self.getZ_Vasicek()

        if self.myQ is None:
            self.getQ_Corporate()

        # Q1M = self.myQ["QTranche"]

        ## Calculate Q(t_i) + Q(t_(i-1))
        # Qminus = np.gradient(np.array(Q1M))
        # print(Qminus)
        # QArray = np.array(Q1M)
        # QArray = np.insert(QArray, obj = 0, values = 1)
        # print(QArray)

        # Q1M = self.myQ["QTranche"]
        '''
        Q1M = self.myQ[self.freq]
        Q1M = Q1M.cumprod()
        timed = Q1M.index.tolist()
        timed = self.portfolioScheduleOfCF[self.portfolioScheduleOfCF.index(self.referenceDate):]
        Q1M = Q1M.loc[timed]
        zbarPremLeg = self.myZ / self.myZ.loc[self.referenceDate]
        zbarPremLeg = zbarPremLeg.loc[timed]

        ## Calculate Q(t_i) + Q(t_(i-1))
        Qplus = []
        out = 0
        for i in range(1, len(Q1M)):
            out = out + (Q1M[(i-1)] - Q1M[(i)]) * float((timed[i] - timed[i - 1]).days / 365) * zbarPremLeg[i]

        return(out)
        ## Calculate Z Bar ##
        
        Qminus = np.gradient(Q1M)

        zbarProtectionLeg = self.myZ / self.myZ.loc[self.referenceDate]
        for i in range(1,zbarProtectionLeg.shape[0]):
            zbarProtectionLeg.iloc[i] = -Qminus[i] * zbarProtectionLeg.iloc[i] * (1/365)

        ## Calculate the PV of the premium leg using the bond class

        zbarProtectionLeg = zbarProtectionLeg.cumsum(axis=0)
        zbarProtectionLeg = pd.DataFrame(zbarProtectionLeg, index=Q1M.index)
        PVprotectionLeg = (1 - self.R) * zbarProtectionLeg
        ## Get coupon bond ###
        return PVprotectionLeg.loc[self.maturity]
        '''
        Q1M = self.myQ[self.freq]
        Q1M = Q1M.cumprod()
        Qminus = np.gradient(Q1M)
        zbarProtectionLeg = self.myZ / self.myZ.loc[self.referenceDate]
        for i in range(zbarProtectionLeg.shape[0]):
            zbarProtectionLeg.iloc[
                i] = -Qminus[i] * zbarProtectionLeg.iloc[i] * (1 / 365)
        ## Calculate the PV of the premium leg using the bond class
        zbarProtectionLeg = zbarProtectionLeg.cumsum(axis=0)
        zbarProtectionLeg = pd.DataFrame(zbarProtectionLeg, index=Q1M.index)
        PVprotectionLeg = (1 - self.R) * zbarProtectionLeg
        ## Get coupon bond ###
        return PVprotectionLeg.loc[self.maturity]

    # /////////////////////// Functions to get the exposure sum [delta Z(t,t_j)( Q(t,t_(j-1)) +/- Q(t,t_j) )
    # ////// These are copied from Coupon bond
    def getScheduleComplete(self):
        self.datelist = self.myScheduler.getSchedule(
            start=self.start_date,
            end=self.maturity,
            freq='3M',
            referencedate=self.referenceDate)
        self.ntimes = len(self.datelist)
        fullset = list(
            sorted(
                list(
                    set(self.datelist).union([self.referenceDate]).union([
                        self.start_date
                    ]).union([self.maturity]).union([self.observationDate]))))
        return fullset, self.datelist

    # /////// Get exposure
    def getExposure(self, referencedate, libor):
        self.ntrajectories = np.shape(libor)[1]
        self.ones = np.ones(shape=[self.ntrajectories])
        deltaT = np.zeros(self.ntrajectories)
        if self.ntimes == 0:
            pdzeros = pd.DataFrame(data=np.zeros([1, self.ntrajectories]),
                                   index=[referencedate])
            self.pv = pdzeros
            self.pvAvg = 0.0
            self.cashFlows = pdzeros
            self.cashFlowsAvg = 0.0
            return self.pv
        for i in range(1, self.ntimes):
            deltaTrow = ((self.datelist[i] - self.datelist[i - 1]).days /
                         365) * self.ones
            deltaT = np.vstack((deltaT, deltaTrow))
        self.cashFlows = self.coupon * deltaT
        principal = self.ones
        if self.ntimes > 1:
            self.cashFlows[-1:] += principal
        else:
            self.cashFlows = self.cashFlows + principal
        if (self.datelist[0] <= self.start_date):
            self.cashFlows[0] = -self.fee * self.ones

        if self.ntimes > 1:
            self.cashFlowsAvg = self.cashFlows.mean(axis=1) * self.notional
        else:
            self.cashFlowsAvg = self.cashFlows.mean() * self.notional
        pv = self.cashFlows * libor.loc[self.datelist]
        self.pv = pv.sum(axis=0) * self.notional
        self.pvAvg = np.average(self.pv) * self.notional
        return self.pv

    # ///// Get the calculated Market to Market based on spread
    def getValue(self, spread=1, R=0, buyer=True):
        ## Assume V(t) = S/2 sum Z(t_i) (Q(t_i) + Q(t_{i-1})) - (1-R)sum Z(t_i) (Q(t_{i-1}) - Q(t_{i}))
        ## Premium leg = S/2 sum Z(t_i) (Q(t_i) + Q(t_{i-1}))
        ## Protection leg =sum Z(t_i) (Q(t_i) + Q(t_{i-1}))
        premiumLeg = self.getPremiumLegZ()
        protectionLeg = self.getProtectionLeg()

        mtm = (spread / 2) * premiumLeg - (1 - R) * protectionLeg
        if buyer is True:
            return mtm
        else:
            return -mtm

    def getSpread(self):

        out = self.getProtectionLeg() / self.getPremiumLegZ()

        return out.values[0]

    def changeGuessForSpread(self, x):
        '''
        inputs a x list of guesses for the Vasicek simulator than changes the myQ
        '''
        vasicekMC = MC_Vasicek_Sim(
            datelist=[self.referenceDate, self.maturity],
            x=x,
            simNumber=20,
            t_step=t_step)
        self.myQ = vasicekMC.getLibor()[0]
        self.myQ = pd.DataFrame(self.myQ, index=self.myQ.index)
        self.myQ.columns = [self.freq]
        spread = self.bootProtec() / self.bootPrem()
        return spread.values[0]

    def bootProtec(self):
        Q1M = self.myQ[self.freq]
        Q1M = Q1M.cumprod()
        Qminus = np.gradient(Q1M)
        zbarProtectionLeg = self.myZ / self.myZ.loc[self.referenceDate]
        for i in range(zbarProtectionLeg.shape[0]):
            zbarProtectionLeg.iloc[
                i] = -Qminus[i] * zbarProtectionLeg.iloc[i] * (1 / 365)
        ## Calculate the PV of the premium leg using the bond class
        zbarProtectionLeg = zbarProtectionLeg.cumsum(axis=0)
        zbarProtectionLeg = pd.DataFrame(zbarProtectionLeg, index=Q1M.index)
        PVprotectionLeg = (1 - self.R) * zbarProtectionLeg
        ## Get coupon bond ###
        return PVprotectionLeg.loc[self.maturity]

    def bootPrem(self):
        Q1M = self.myQ[self.freq]
        # Q1M = self.myQ["QTranche"]
        timed = self.portfolioScheduleOfCF[self.portfolioScheduleOfCF.
                                           index(self.referenceDate):]
        Q1M = Q1M.loc[timed]
        Q1M = Q1M.cumprod()
        zbarPremLeg = self.myZ / self.myZ.loc[self.referenceDate]
        zbarPremLeg = zbarPremLeg.loc[timed]
        ## Calculate Q(t_i) + Q(t_(i-1))
        Qplus = []
        out = 0
        for i in range(1, len(Q1M)):
            out = out + (Q1M[(i - 1)] + Q1M[i]) * float(
                (timed[i] - timed[i - 1]).days / 365) * zbarPremLeg[i]
        ## Calculate the PV of the premium leg using the bond class
        # zbarPremLeg = zbarPremLeg.cumsum(axis=0)
        zbarPremLeg = pd.DataFrame(zbarPremLeg, index=timed)
        # print("Premium LEg")
        PVpremiumLeg = out * (1 / 2)
        # print(PVpremiumLeg)
        ## Get coupon bond ###
        return PVpremiumLeg
示例#12
0
observationdate = minDay = date(2005,1,10) # Observation Date
maxDay = date(2010,1,10)  # Last Date of the Portfolio
start = date(2005, 3, 30)
maturity = start+ myScheduler.extractDelay("1Y")
referenceDate = date(2005, 5, 3)  # 6 months after trim_start
simNumber = 5
R = 0.4
inArrears = True
freq = '3M'
t_step = 1.0/365

simNumber=5
coupon = 0.08
fee= 1.0
xR = [3.0, 0.05, 0.04, 0.03]
datelist = myScheduler.getSchedule(start=start, end=maxDay, freq=freq, referencedate=referenceDate)

myBond = CouponBond(fee=fee, start=start, maturity=maturity, coupon=coupon, freq="3M", referencedate=referenceDate, observationdate = observationdate)
fulllist, datelist = myBond.getScheduleComplete()
myMC = MC_Vasicek_Sim()
myMC.setVasicek(x=xR, minDay=minDay, maxDay=maxDay, simNumber=simNumber, t_step=t_step)
myMC.getLibor()
libor = myMC.getSmallLibor(datelist=fulllist)
myBond.setLibor(libor=libor)
myBond.getExposure(referenceDate)
myBond.getYield(price=1)
print(myBond.getLiborAvg())
a=1


class TestBond(TestCase):