Esempio n. 1
0
 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 __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()
Esempio n. 3
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
 def __init__(self, memory, file_system, clock):
     self.file_system = file_system(Disc())
     self.memory_admin = MemoryAdmin(AsignacionContinua(memory))
     self.pid = 0
     self.scheduler = Scheduler()
     self.cpu = Cpu(self)
     self.pcb_table = PCBTable()
     self.clock = clock
Esempio n. 5
0
 def test_calculate_times(self):
     input_data = SchedulerApp.process_input(
         'ConferencetrackmanagementPythonGA/tests/test_input.txt')
     my_scheduler = Scheduler()
     self.assertEquals(my_scheduler.calculate_times(input_data),
                       [('talk2 60min', 60), ('talk3 45min', 45),
                        ('talk5 30min', 30), ('talk1 25min', 25),
                        ('talk4 lightning', 5)])
Esempio n. 6
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
 def __init__(self):
     self.OIS = []
     self.filename = WORKING_DIR + '/CorpData.dat'
     self.corporates = []
     self.ratings = ['AAA', 'AA', 'A', 'BBB', 'BB', 'B', 'CCC']
     self.corpSpreads = {}
     self.corporates = pd.DataFrame()
     self.tenors = []
     self.unPickleMe(file=self.filename)
     self.myScheduler=Scheduler()
Esempio n. 8
0
 def __init__(self):
     self.OIS = []
     self.filename = WORKING_DIR + '/CorpData.dat'
     self.corporates = []
     self.ratings = ['AAA', 'AA', 'A', 'BBB', 'BB', 'B', 'CCC']
     self.corpSpreads = {}
     self.corporates = pd.DataFrame()
     self.tenors = []
     self.unPickleMe(file=self.filename)
     self.myScheduler = Scheduler(start=trim_start,
                                  end=trim_end,
                                  freq=freq,
                                  reference=referenceDate)
 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 __init__(self, memory, file_system, clock):
     self.file_system = file_system(Disc())
     self.memory_admin = MemoryAdmin(AsignacionContinua(memory))
     self.pid = 0
     self.scheduler = Scheduler()
     self.cpu = Cpu(self)
     self.pcb_table = PCBTable()
     self.clock = clock
 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 = []
Esempio n. 12
0
 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 __init__(self):
     self.OIS = []
     self.filename = WORKING_DIR + '/CorpData.dat'
     self.corporates = []
     self.ratings = {
         'AAA': "BAMLC0A1CAAA",
         'AA': "BAMLC0A2CAA",
         'A': "BAMLC0A3CA",
         'BBB': "BAMLC0A4CBBB",
         'BB': "BAMLH0A1HYBB",
         'B': "BAMLH0A2HYB",
         'CCC': "BAMLH0A3HYC"
     }
     self.corpSpreads = {}
     self.corporates = pd.DataFrame()
     self.Qcorporates = pd.DataFrame()  # survival function for corporates
     self.tenors = []
     self.unPickleMe(file=self.filename)
     self.myScheduler = Scheduler()
     self.myVasicek = MC_Vasicek_Sim()
     self.R = 0.4
Esempio n. 14
0
    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
Esempio n. 15
0
 def test_calculate_tracks(self):
     input_data = SchedulerApp.process_input(
         'ConferencetrackmanagementPythonGA/tests/test_input2.txt')
     my_scheduler = Scheduler()
     times = my_scheduler.calculate_times(input_data)
     self.assertEquals(my_scheduler.calculate_tracks(times), ({
         0: ('talk12 60min', 60),
         120: ('talk14 60min', 60),
         60: ('talk13 60min', 60)
     }, {
         0: ('talk8 60min', 60),
         120: ('talk10 60min', 60),
         180: ('talk11 60min', 60),
         60: ('talk9 60min', 60)
     }, {
         0: ('talk5 60min', 60),
         120: ('talk7 60min', 60),
         60: ('talk6 60min', 60)
     }, {
         0: ('talk1 60min', 60),
         120: ('talk3 60min', 60),
         180: ('talk4 60min', 60),
         60: ('talk2 60min', 60)
     }, 0))
     input_data = SchedulerApp.process_input(
         'ConferencetrackmanagementPythonGA/tests/test_input3.txt')
     my_scheduler = Scheduler()
     times = my_scheduler.calculate_times(input_data)
     self.assertEquals(my_scheduler.calculate_tracks(times), ({
         0: ('talk12 60min', 60),
         120: ('talk14 60min', 60),
         60: ('talk13 60min', 60)
     }, {
         0: ('talk8 60min', 60),
         120: ('talk10 60min', 60),
         180: ('talk11 60min', 60),
         60: ('talk9 60min', 60)
     }, {
         0: ('talk5 60min', 60),
         120: ('talk7 60min', 60),
         60: ('talk6 60min', 60)
     }, {
         0: ('talk1 60min', 60),
         120: ('talk3 60min', 60),
         180: ('talk4 60min', 60),
         60: ('talk2 60min', 60)
     }, 1))
class Kernel:

    def __init__(self, memory, file_system, clock):
        self.file_system = file_system(Disc())
        self.memory_admin = MemoryAdmin(AsignacionContinua(memory))
        self.pid = 0
        self.scheduler = Scheduler()
        self.cpu = Cpu(self)
        self.pcb_table = PCBTable()
        self.clock = clock

    def memory_admin(self):
        return self.memory_admin

    def scheduler(self):
        return self.scheduler

    def get_pid(self):
        return self.pid

    def set_scheduler_policy(self):
        self.scheduler.set_as_fifo()

    def create_pcb(self, program, priority):
        if self.memory_admin.has_room_for(program.size()):
            initial_pos = self.memory_admin.next_post_free()
            final_pos = (initial_pos+program.size())
            pcb = PCB(initial_pos, final_pos, 0, self.get_pid(), priority)
            self.pid += 1
            self.pcb_table.add(pcb)
            self.scheduler.add_pcb(pcb)
            self.memory_admin.save(pcb, program)

        else:
            print("No hay lugar para esto")

    def get_program(self, program_name, path):
        return self.file_system.find(path, program_name)

    def get_ready_queue(self):
        return self.scheduler.ready_queue

    def handle_signal(self, signal, pcb):
        #La senial deberia hacer que la ejecucion de un proceso cambie
        try:
            signal.alert_cpu(pcb, self.cpu, self.pcb_table)
        except Exception as e:
            print("Handle unexpected signal! details: " + e.message)
            TimeoutAlert().alert_cpu(pcb, self.cpu, self.pcb_table)

    def timing(self):
        self.clock.tick()

    def execute(self, program_name, path, priority):
        program = self.get_program(program_name, path)
        self.create_pcb(program, priority)
        self.scheduler.get_pcb()
Esempio n. 17
0
 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)
class Kernel:
    def __init__(self, memory, file_system, clock):
        self.file_system = file_system(Disc())
        self.memory_admin = MemoryAdmin(AsignacionContinua(memory))
        self.pid = 0
        self.scheduler = Scheduler()
        self.cpu = Cpu(self)
        self.pcb_table = PCBTable()
        self.clock = clock

    def memory_admin(self):
        return self.memory_admin

    def scheduler(self):
        return self.scheduler

    def get_pid(self):
        return self.pid

    def set_scheduler_policy(self):
        self.scheduler.set_as_fifo()

    def create_pcb(self, program, priority):
        if self.memory_admin.has_room_for(program.size()):
            initial_pos = self.memory_admin.next_post_free()
            final_pos = (initial_pos + program.size())
            pcb = PCB(initial_pos, final_pos, 0, self.get_pid(), priority)
            self.pid += 1
            self.pcb_table.add(pcb)
            self.scheduler.add_pcb(pcb)
            self.memory_admin.save(pcb, program)

        else:
            print("No hay lugar para esto")

    def get_program(self, program_name, path):
        return self.file_system.find(path, program_name)

    def get_ready_queue(self):
        return self.scheduler.ready_queue

    def handle_signal(self, signal, pcb):
        #La senial deberia hacer que la ejecucion de un proceso cambie
        try:
            signal.alert_cpu(pcb, self.cpu, self.pcb_table)
        except Exception as e:
            print("Handle unexpected signal! details: " + e.message)
            TimeoutAlert().alert_cpu(pcb, self.cpu, self.pcb_table)

    def timing(self):
        self.clock.tick()

    def execute(self, program_name, path, priority):
        program = self.get_program(program_name, path)
        self.create_pcb(program, priority)
        self.scheduler.get_pcb()
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
Esempio n. 20
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
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()
class CorporateRates(object):
    def __init__(self):
        self.OIS = []
        self.filename = WORKING_DIR + '/CorpData.dat'
        self.corporates = []
        self.ratings = {
            'AAA': "BAMLC0A1CAAA",
            'AA': "BAMLC0A2CAA",
            'A': "BAMLC0A3CA",
            'BBB': "BAMLC0A4CBBB",
            'BB': "BAMLH0A1HYBB",
            'B': "BAMLH0A2HYB",
            'CCC': "BAMLH0A3HYC"
        }
        self.corpSpreads = {}
        self.corporates = pd.DataFrame()
        self.Qcorporates = pd.DataFrame()  # survival function for corporates
        self.tenors = []
        self.unPickleMe(file=self.filename)
        self.myScheduler = Scheduler()
        #self.myVasicek = MC_Vasicek_Sim()
        self.R = 0.4

    def getCorporatesFred(self, trim_start, trim_end):
        self.corpSpreads = {}
        self.corpSpreads = {}

        fred = Fred(api_key=FRED_API_KEY)
        curr_trim_end = trim_start
        if (self.corporates.size != 0):
            self.trim_start = self.corporates['OIS'].index.min().date()
            curr_trim_end = self.corporates['OIS'].index.max().date()

        self.trim_start = trim_start
        self.trim_end = trim_end
        self.OIS = OIS(trim_start=trim_start, trim_end=trim_end)
        self.datesAll = self.OIS.datesAll
        #print(self.datesAll)
        self.datesAll.columns = [x.upper() for x in self.datesAll.columns]
        #print(self.datesAll)
        self.datesAll.index = self.datesAll.DATE
        self.OISData = self.OIS.getOIS()
        #print(self.OISData)
        for i in np.arange(len(self.OISData.columns)):
            freq = self.OISData.columns[i]
            self.tenors.append(self.myScheduler.extractDelay(freq=freq))
            #print(self.tenors)
        for rating in self.ratings.keys():
            index = self.ratings[rating]
            try:
                corpSpreads = 1e-2 * (fred.get_series(
                    index,
                    observation_start=trim_start,
                    observation_end=trim_end).to_frame())
                corpSpreads.index = [x.date() for x in corpSpreads.index[:]]
                corpSpreads = pd.merge(left=self.datesAll,
                                       right=corpSpreads,
                                       left_index=True,
                                       right_index=True,
                                       how="left")
                corpSpreads = corpSpreads.fillna(method='ffill').fillna(
                    method='bfill')
                corpSpreads = corpSpreads.drop("DATE", axis=1)
                self.corpSpreads[rating] = corpSpreads.T.fillna(
                    method='ffill').fillna(method='bfill').T
            except Exception as e:
                print(e)
                print(index, " not found")
        self.corpSpreads = pd.Panel.from_dict(self.corpSpreads)
        #print(self.corpSpreads)
        self.corporates = {}
        self.OISData.drop('DATE', axis=1, inplace=True)
        ntenors = np.shape(self.OISData)[1]
        for rating in self.ratings:
            try:
                tiledCorps = np.tile(self.corpSpreads[rating][0],
                                     ntenors).reshape(np.shape(self.OISData))
                self.corporates[rating] = pd.DataFrame(
                    data=(tiledCorps + self.OISData.values),
                    index=self.OISData.index,
                    columns=self.OISData.columns)
            except:
                print(rating)
                print("Error in addition of Corp Spreads")
        self.corporates['OIS'] = self.OISData
        self.corporates = pd.Panel(self.corporates)
        return self.corporates

    def convertCols(self, list):
        out = []
        for i in range(0, len(list)):
            out.append(list[i].split(' ', 1)[0] + list[i].split(' ', 1)[1][0])
        return out

    def getCorporateData(self, rating, datelist=None):
        # This method gets a curve for a given date or date list for a given rating (normally this will be just a date).
        # It returns a dict of curves read directly from the corporate rates created by getCorporatesFred.
        # Derive delays from self.corporates[rating].columns
        #print("GEt corporate data ")
        if datelist is None:
            return
        outCurve = {}
        datelist.sort()
        #need an iteratble object
        cols = self.convertCols(list(self.corporates[rating].columns))
        myDelays = []
        myDelays.append(relativedelta.relativedelta(days=0))
        #just putting an iterable object together
        for i in range(0, len(cols)):
            myDelays.append(self.myScheduler.extractDelay(freq=cols[i]))
        myCurve = self.corporates[rating]
        cols = ['0D'] + cols
        #print("My curve")
        #print(myCurve)
        #print(myDelays)
        #grabbing only the info with the rating I want and making a datelist to calulate time differences
        dates = []
        for day in range(0, len(datelist)):
            #print(day)
            dates.append([(myDelays[x] + datelist[day])
                          for x in range(0, len(myDelays))])
            #print(dates)
        #my array of interest rates
        r = np.zeros((len(datelist), len(dates[0])))
        #print(r)
        nrows = len(dates)
        #multiplying the rate by the delta t in days and saving it to a spot in the array
        for j in range(0, len(datelist)):
            #print(datelist[j])
            day_tenors = myCurve.loc[datelist[j]]
            for i in range(1, len(day_tenors) + 1):
                r[j, i] = r[j, i - 1] + day_tenors[i - 1] * (
                    (dates[j][i] - datelist[j]).days / 365)
        # Create curves
        # ..............
        # ..............
        # add curve to outcurve dict
        #integrating and taking e^-
        intR = r.cumsum(axis=1)
        outCurve = np.exp(-intR)
        out = pd.DataFrame(outCurve)
        out.columns = cols
        return out

    def getSpreads(self, rating, datelist=None):
        if datelist is None:
            return
        outCurve = {}
        #need an iteratble object
        #just putting an iterable object together
        myCurve = self.corpSpreads[rating]
        #grabbing only the info with the rating I want and making a datelist to calulate time differences
        #my array of interest rates
        r = np.zeros(len(datelist))
        #multiplying the rate by the delta t in days and saving it to a spot in the array
        for j in range(1, len(datelist)):
            r[j] = r[j - 1] + myCurve['VALUE'].loc[j - 1] * (
                datelist[j] - datelist[j - 1]).days / 365
        # Create curves
        # ..............
        # ..............
        # add curve to outcurve dict
        #integrating and taking e^-
        intR = r.cumsum(axis=0)
        outCurve = np.exp(-intR)
        out = pd.DataFrame(outCurve, index=datelist)
        return out

    def getCorporateQData(self, rating, datelist, R=0.4):
        #print("Get gorporate Q data")
        self.R = R
        if datelist is None:
            return

        trim_start = datelist[0]
        trim_end = datelist[-1]
        # Create Q curves using q-tilde equation

        outCurve = (
            (1 - (1 / (1 - R)) *
             (1 - (self.getCorporateData(rating=rating, datelist=datelist) /
                   self.getCorporateData(rating='OIS', datelist=datelist)))
             ).values).tolist()
        out = pd.DataFrame(outCurve, index=datelist)
        out[out < 0] = 0
        cols = self.convertCols(list(self.corporates[rating].columns))
        cols = ['0D'] + cols

        ## Get OIS ###
        #getOIS = OIS(trim_start = trim_start,trim_end=trim_end)
        #print(getOIS.getOIS(datelist = datelist))

        #outCurve = ((1 - (1 / (1 - R)) * (1 - (self.getCorporatesFred(trim_start) / self.getCorporateData(rating='OIS', datelist=datelist)))).values).tolist()

        out.columns = cols
        return out

    def pickleMe(self):
        data = [self.corporates, self.corpSpreads]
        with open(self.filename, "wb") as f:
            pickle.dump(len(data), f)
            for value in data:
                pickle.dump(value, f)

    def unPickleMe(self, file):
        data = []
        if (os.path.exists(file)):
            with open(file, "rb") as f:
                for _ in range(pickle.load(f)):
                    data.append(pickle.load(f))
            self.corporates = data[0]
            self.corpSpreads = data[1]

    def saveMeExcel(self, whichdata, fileName):
        try:
            df = pd.DataFrame(whichdata)
        except:
            df = whichdata
        df.to_excel(fileName)
Esempio n. 23
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
Esempio n. 24
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
Esempio n. 25
0
# Method used to read the input_data
def process_input(input_path_var):
    with open(input_path_var, 'r') as f:
        read_data = f.read()
    return read_data.split(', ')


# Method called to do a 'clear', just for application visualization purposes
def clean_screen():
    print(chr(27) + "[2J")


if __name__ == '__main__':

    clean_screen()
    presentation()

    if len(sys.argv) == 1:
        input_path = 'ConferencetrackmanagementPythonGA/data/input.txt'
    else:
        input_path = sys.argv[1]

    input_data = process_input(input_path)
    my_scheduler = Scheduler()
    times = my_scheduler.calculate_times(input_data)
    track1morning, track1afternoon, track2morning, track2afternoon, left_sessions = Scheduler.calculate_tracks(
        times)
    Printer.show_tracks(track1morning, track1afternoon, track2morning,
                        track2afternoon)
Esempio n. 26
0
import itertools
marker = itertools.cycle((',', '+', '.', 'o', '*'))
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")
Esempio n. 27
0
__author__ = 'blee13'
from unittest import TestCase
from MonteCarloSimulators.Vasicek.vasicekMCSim import MC_Vasicek_Sim
from Products.Rates.CouponBond import CouponBond
from Curves.Corporates.CorporateDaily import CorporateRates
from Scheduler.Scheduler import Scheduler
import matplotlib.pyplot as plt
from Products.Credit.IRSwap import IRSwap
import pandas as pd
from datetime import date

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,
Esempio n. 28
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 CorporateRates(object):
    def __init__(self):
        self.OIS = []
        self.filename = WORKING_DIR + '/CorpData.dat'
        self.corporates = []
        self.ratings = {
            'AAA': "BAMLC0A1CAAA",
            'AA': "BAMLC0A2CAA",
            'A': "BAMLC0A3CA",
            'BBB': "BAMLC0A4CBBB",
            'BB': "BAMLH0A1HYBB",
            'B': "BAMLH0A2HYB",
            'CCC': "BAMLH0A3HYC"
        }
        self.corpSpreads = {}
        self.corporates = pd.DataFrame()
        self.Qcorporates = pd.DataFrame()  # survival function for corporates
        self.tenors = []
        self.unPickleMe(file=self.filename)
        self.myScheduler = Scheduler()
        self.myVasicek = MC_Vasicek_Sim()
        self.R = 0.4

    def getCorporatesFred(self, trim_start, trim_end):
        fred = Fred(api_key=FRED_API_KEY)
        curr_trim_end = trim_start
        if (self.corporates.size != 0):
            self.trim_start = self.corporates['OIS'].index.min().date()
            curr_trim_end = self.corporates['OIS'].index.max().date()
        if trim_end <= curr_trim_end:
            self.trim_end = curr_trim_end
            return self.corporates
        self.trim_start = trim_start
        self.trim_end = trim_end
        self.OIS = OIS(trim_start=trim_start, trim_end=trim_end)
        self.datesAll = self.OIS.datesAll
        self.datesAll.columns = [x.upper() for x in self.datesAll.columns]
        self.datesAll.index = self.datesAll.DATE
        self.OISData = self.OIS.getOIS()
        for i in np.arange(len(self.OISData.columns)):
            freq = self.OISData.columns[i]
            self.tenors.append(self.myScheduler.extractDelay(freq=freq))
        for rating in self.ratings.keys():
            index = self.ratings[rating]
            try:
                corpSpreads = 1e-2 * (fred.get_series(
                    index,
                    observation_start=trim_start,
                    observation_end=trim_end).to_frame())
                corpSpreads.index = [x.date() for x in corpSpreads.index[:]]
                corpSpreads = pd.merge(left=self.datesAll,
                                       right=corpSpreads,
                                       left_index=True,
                                       right_index=True,
                                       how="left")
                corpSpreads = corpSpreads.fillna(method='ffill').fillna(
                    method='bfill')
                corpSpreads = corpSpreads.drop("DATE", axis=1)
                self.corpSpreads[rating] = corpSpreads.T.fillna(
                    method='ffill').fillna(method='bfill').T
            except Exception as e:
                print(e)
                print(index, " not found")
        self.corpSpreads = pd.Panel.from_dict(self.corpSpreads)
        self.corporates = {}
        self.OISData.drop('DATE', axis=1, inplace=True)
        ntenors = np.shape(self.OISData)[1]
        for rating in self.ratings:
            try:
                tiledCorps = np.tile(self.corpSpreads[rating][0],
                                     ntenors).reshape(np.shape(self.OISData))
                self.corporates[rating] = pd.DataFrame(
                    data=(tiledCorps + self.OISData.values),
                    index=self.OISData.index,
                    columns=self.OISData.columns)
            except:
                print("Error in addition of Corp Spreads")
        self.corporates['OIS'] = self.OISData
        self.corporates = pd.Panel(self.corporates)
        return self.corporates

    def getCorporateData(self, rating, datelist=None):
        # This method gets a curve for a given date or date list for a given rating (normally this will be just a date).
        # It returns a dict of curves read directly from the corporate rates created by getCorporatesFred.
        # Derive delays from self.corporates[rating].columns
        myDelays = self.myScheduler.extractDelay(
            freq=list(self.corporates[rating].columns))
        if datelist is None:
            return
        outCurve = {}
        for day in datelist:
            # Create curves
            # ..............
            # ..............
            # add curve to outcurve dict
            outCurve[day] = myCurve
        return outCurve

    def getCorporateQData(self, rating, datelist=None, R=0.4):
        self.R = R
        if datelist is None:
            return
        outCurve = {}
        for day in datelist:
            # Create Q curves using q-tilde equation
            # ..............
            # ..............
            outCurve[day] = myCurve
        return outCurve

    def pickleMe(self):
        data = [self.corporates, self.corpSpreads]
        with open(self.filename, "wb") as f:
            pickle.dump(len(data), f)
            for value in data:
                pickle.dump(value, f)

    def unPickleMe(self, file):
        data = []
        if (os.path.exists(file)):
            with open(file, "rb") as f:
                for _ in range(pickle.load(f)):
                    data.append(pickle.load(f))
            self.corporates = data[0]
            self.corpSpreads = data[1]

    def saveMeExcel(self, whichdata, fileName):
        try:
            df = pd.DataFrame(whichdata)
        except:
            df = whichdata
        df.to_excel(fileName)
    def fitModel2Curve(self, x):
        results = minimize(fun=self.fCurve, x0=x)
        return results.x

    def fCurve(self, x):
        calCurve = self.getLiborAvg(x, self.datelist)
        thisPV = np.multiple(self.cashFlows,
                             calcCurve).mean(axis=1).sum(axis=0)
        error = 1e4 * (self.price - thisPV)**2
        return


if (__name__ == "__main__"):
    coupon = 0.03
    myscheduler = Scheduler()
    datelist = myscheduler(start=trim_start,
                           end=trim_end,
                           freq="3M",
                           referencedate=trim_start)
    myMC = MC_Vasicek_Sim(x=XR,
                          datelist=datelist,
                          simNumber=simnumber,
                          t_step=t_step)
    libor = myMC.getSmallLibor(datelist=datelist)
    myBond = Bond(libor=libor,
                  start=trim_start,
                  maturity=trim_end,
                  coupon=coupon,
                  freq="3M",
                  referencedate=trim_start)
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
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, ".")