Пример #1
0
    def __init__(self, start, underlyings):

        myScheduler = Scheduler()
        myDelays = []
        freqs = ['3M', '6M', '1Y', '3Y']
        for i in range(0, len(freqs)):
            myDelays.append(myScheduler.extractDelay(freqs[i]))
        AAA = {}
        for i in range(0, len(freqs)):
            vas = MC_Vasicek_Sim(x=AAAx[freqs[i]],
                                 datelist=[start, myDelays[i] + start],
                                 t_step=1 / 365.,
                                 simNumber=500)
            AAA[freqs[i]] = vas.getLibor()[0].loc[myDelays[i] + start]

        BBB = {
            '3M':
            MC_Vasicek_Sim(x=BBBx[freqs[0]],
                           datelist=[start, myDelays[0] + start],
                           t_step=1 / 365.,
                           simNumber=500).getLibor()[0].loc[myDelays[0] +
                                                            start]
        }
        self.probs = {'AAA': AAA, 'BBB': BBB}
        self.underlyings = underlyings
Пример #2
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 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]
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
Пример #5
0
#SDE parameter
t_step = 1.0/365
r0 = 0.08
sigmaR = 0.09
sigmaRef = 0.03
muR = 0.05
alphaR=3.0
simNumber=1000
muHazardRate = 0.005
k = 0.1
recovery = 0.4

#Bond parameters
coupon = 0.08

#Monte Carlo trajectories creation
t1 = datetime.datetime.now()
myVasicek = MC_Vasicek_Sim(datelist, r0,sigmaR, sigmaRef, muR, muHazardRate,alphaR, k, simNumber,t_step)
longLibor = myVasicek.getLibor()
libor = myVasicek.getSmallLibor()
longsurvival = myVasicek.getSurvival()
survival = myVasicek.getSmallSurvival()
#myVasicek.saveMeExcel()

#Bond Pricing
myBond = bond(libor,coupon,datelist,survival, recovery)
myCDS = CDS(libor, datelist, survival, recovery)
print('Risky Bond Price = ', str(1000*myBond.pv().sum()))
print('Riskless Bond Price = ', str(1000*myBond.riskless().sum() ))
print ('5 years Par Spread for each quarter= ', str(myCDS.parSpread()))
print ('5 years Mark to Market Value for each quarter = ', myCDS.MTM())
Пример #6
0
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,
                endDate=trim_end,
                referenceDate=referenceDate,
                effectiveDate=effDay,
                rating="AAA",
                freq=freq,
                notional=1000,
                xR=xR)
initSpread = mySwap.setSwapRate()
Пример #7
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
Пример #8
0
class CDS(object):
    def __init__(self,
                 start,
                 end,
                 reference,
                 recovery,
                 rating,
                 notional,
                 freq="1M"):
        self.numSim = 10
        self.t_step = 1.0 / 365
        #z curve is for discounting
        self.zCurve = []
        #q curve is for survival prob of the reference entity
        self.qCurve = []
        self.start = start
        self.end = end
        self.reference = reference
        self.freq = freq
        self.rating = rating
        self.notional = notional
        # mcSim used for simulating default prob, interest rate
        # xR should already be calibrated
        self.xR = []
        # xQ we need to calibrate inside CDS
        self.xQ = []
        self.mcSim = MC_Vasicek_Sim()
        self.mcSimSurvival = MC_Vasicek_Sim()

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

        self.dateList = pd.date_range(start=start, end=end, freq=freq)
        self.recovery = recovery

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

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

    def setxR(self, xR):
        self.xR = xR
        self.mcSim.setVasicek(minDay=self.start,
                              maxDay=self.end,
                              x=self.xR,
                              simNumber=self.numSim,
                              t_step=self.t_step)

    def setxQ(self, xQ):
        res = optimize.fmin(func=self.mcSimSurvival.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.mcSimSurvival.setVasicek(minDay=self.start,
                                      maxDay=self.end,
                                      x=self.xQ,
                                      simNumber=self.numSim,
                                      t_step=self.t_step)

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

    def getDefaultLegPV(self):
        interimSum = 0
        for payDates in self.dateList[1:]:
            interimSum += self.zCurve.loc[payDates.date(), 0] * (
                self.qCurve.loc[(payDates - 1).date()] -
                self.qCurve.loc[payDates.date()])
        defaultLeg = (1 - self.recovery) * interimSum
        return defaultLeg

    def getFeeLegPV(self):
        delta = (self.dateList[1] - self.dateList[0]).days / 365
        interimSum = 0
        for payDate in self.dateList[1:]:
            interimSum += self.zCurve.loc[payDate.date(), 0] * delta * (
                self.qCurve.loc[(payDate - 1).date()] +
                self.qCurve.loc[payDate.date()])
        feeLeg = 0.5 * interimSum
        return feeLeg

    def getSpread(self):
        spread = self.getDefaultLegPV() / self.getFeeLegPV()
        self.spread = spread
        return spread

    def setCF(self):
        feeLegCF = np.ones(len(self.dateList)) * self.spread
        defaultLegCF = np.ones(len(self.dateList)) * (
            1 - self.recovery) * self.qCurve.loc[self.dateList].values
        self.feeLeg = pd.DataFrame(data=feeLegCF, index=self.dateList)
        self.defaultLeg = pd.DataFrame(data=defaultLegCF, index=self.dateList)
        return

    def getExposure(self):
        #PV of protection leg - fee leg
        #use survivalCurve passed in as the survival prob of the reference entitity
        #simulate the default probability of the counterparty - newQcurve
        fullDate = pd.date_range(start=self.start,
                                 end=self.end,
                                 freq=self.freq)
        EE = np.zeros((len(self.dateList), self.numSim))
        for i in range(0, self.numSim):
            row = 0
            newZCurve = self.mcSim.getLibor()
            newQCurve = self.mcSimSurvival.getLibor()
            survivalCurve = self.qCurve
            for day in fullDate:
                if day == fullDate[0]:
                    #feePV - pay fee as long as counter and reference do not default
                    feePV = np.transpose(
                        self.feeLeg.values).ravel() * newZCurve.loc[
                            self.dateList, 0].values * survivalCurve.loc[
                                self.dateList].values * newQCurve.loc[
                                    self.dateList, 0].values
                    #defaultPV - recover a portion of the notional given the refernce defaults and the counterparty does NOT
                    defaultPV = (1 - self.recovery) * np.transpose(
                        self.defaultLeg.values).ravel() * self.zCurve.loc[
                            self.dateList, 0].values * (
                                np.ones(len(self.dateList)) -
                                survivalCurve.loc[self.dateList].values
                            ) * newQCurve.loc[self.dateList, 0].values

                elif day > fullDate[0] and day < fullDate[-1]:
                    partialFee = self.feeLeg.loc[day.date():]
                    partialDefault = self.defaultLeg.loc[day.date():]
                    feePV = np.transpose(
                        partialFee.values).ravel() * newZCurve.loc[
                            partialFee.index, 0].values * survivalCurve.loc[
                                partialFee.index].values * newQCurve.loc[
                                    partialFee.index, 0].values
                    defaultPV = (1 - self.recovery) * np.transpose(
                        partialDefault.values).ravel() * self.zCurve.loc[
                            partialFee.index, 0].values * (
                                np.ones(len(partialFee.index)) -
                                survivalCurve.loc[partialFee.index].values
                            ) * newQCurve.loc[partialFee.index, 0].values
                else:
                    feePV = 0
                    defaultPV = 0
                npv = np.sum(defaultPV - feePV)
                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)

    def getCVA(self):
        self.CVA = self.notional * (
            1 - self.recovery) * self.avgExposure.values * self.zCurve.loc[
                self.fullDate,
                0].values * self.qCurve.loc[self.fullDate].values
        return
Пример #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
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)
]

# For debugging uncomment this to choose a single date for the forward bond
# print(startDates)
startDates = [
    date(2005, 3, 10) + SixMonthDelay,
    date(2005, 3, 10) + TwoYearsDelay
]
maturities = [(x + TwoYearsDelay) for x in startDates]
Пример #11
0
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)


class TestBond(TestCase):
    def test01_PV(self):
        myPV = myBond.getPV(referencedate=referenceDate)
        print(myPV)
        print(myBond.pv)

    def test00_getLiborAvg(self):
        print(myBond.getLiborAvg(yieldIn=0.05, datelist=datelist))

    def test02_getYield(self):
        x = []