示例#1
0
def _dates_gen_structure(bond):
    """
    Generate date structures. Function can be used for all coupon bearing
    products with bullet principal repayment

            Parameters:
                bonds: a dictionary with the following keys - value_date,
                business_day, issue_date, value_date, maturity,
                frequency, day_count, date_generation.

            Returns:
                a dictionary or an array of dictionaries with the following
                keys - "start_date" and "end_date"
    """
    bus_day = None
    if bond['business_day'] == 'NULL':
        bus_day = 'No Adjustment'
    else:
        bus_day = bond['business_day']

    start_date = bond.get('issue_date')
    if start_date is not None:
        start_date = dt64(start_date, 'D')
    value_date = bond.get('value_date')

    if value_date is not None:
        value_date = dt64(value_date, 'D')
    if start_date is not None and value_date is not None:
        use_date = start_date
    elif start_date is not None:
        use_date = start_date
    elif value_date is not None:
        use_date = value_date
    else:
        raise Exception('Both value_date and issue_date do not have any value')
    # dates is a deque
    dates = gen_dates(use_date,
                      bond['maturity'],
                      issueDate=start_date,
                      frequency=fre[bond['frequency']],
                      business_day=bus_day,
                      method=bond['date_generation'])

    start_dates = deque(dates)
    end_dates = deque(dates)
    start_dates.pop()
    end_dates.popleft()
    noofcpns = len(start_dates)
    structures = deque()
    for no in range(noofcpns):
        structure = {"start_date": start_dates[no], "end_date": end_dates[no]}
        structures.append(structure)

    newstructure = list(
        map(lambda sdate, edate: {
            "start_date": sdate,
            "end_date": edate
        }, start_dates, end_dates))

    return newstructure
示例#2
0
def discount_factor_from_ytm_using_structures(value_date, date_structure,
                                              day_count, frequency,
                                              business_day, ytm):

    df = 1
    maturity = date_structure[-1]["end_date"]

    data = [{
        "start_date": x["start_date"],
        "end_date": x["end_date"]
    } for x in date_structure if value_date < dt64(x["end_date"])]

    for datum in data:
        if dt64(datum["start_date"]) >= value_date:
            datum["dcf"] = day_cf(day_count,
                                  datum["start_date"],
                                  datum["end_date"],
                                  bondmat_date=maturity,
                                  next_coupon_date=datum["end_date"],
                                  business_day=business_day,
                                  Frequency=12 / frequencies[frequency])
            datum["time"] = day_cf("Actual/365",
                                   value_date,
                                   datum["end_date"],
                                   bondmat_date=maturity,
                                   next_coupon_date=datum["end_date"],
                                   business_day=business_day,
                                   Frequency=12 / frequencies[frequency])

        elif datum["start_date"] < value_date:
            datum["dcf"] = day_cf(day_count,
                                  value_date,
                                  datum["end_date"],
                                  bondmat_date=maturity,
                                  next_coupon_date=datum["end_date"],
                                  business_day=business_day,
                                  Frequency=12 / frequencies[frequency])
            datum["time"] = day_cf("Actual/365",
                                   value_date,
                                   datum["end_date"],
                                   bondmat_date=maturity,
                                   next_coupon_date=datum["end_date"],
                                   business_day=business_day,
                                   Frequency=12 / frequencies[frequency])

        datum["period_df"] = 1 / (1 + ytm * datum["dcf"] / 100)
        df = datum["df"] = df * datum["period_df"]

    disfac = list(
        map(lambda datum: {
            "times": datum["time"],
            "df": datum["df"]
        }, data))
    disfac.insert(0, {"times": 0, "df": 1})
    return disfac
示例#3
0
def calc_df_from_shortrate(startdate,
                           enddate,
                           rate,
                           day_count,
                           rate_basis="Money Market"):
    sdate = dt64(startdate, "D")
    edate = dt64(enddate, "D")
    dcf = day_cf(day_count, sdate, edate, next_coupon_date=edate)
    if rate_basis == "Discount Rate":
        return _dr2df(rate, dcf)
    else:
        return _mmr2df(rate, dcf)
    return None
示例#4
0
def movedatebymonth(your_date,
                    no_of_month=1,
                    business_day='No Adjustment',
                    holidays=[]):

    bdc = np.busdaycalendar(weekmask='1111100', holidays=holidays)
    start_m = dt64(your_date, 'M')
    day = dt64(your_date, 'D') - dt64(start_m, 'D')
    end_m = start_m + no_of_month
    next_m = end_m + 1
    days_in_end_m = dt64(next_m, 'D') - dt64(end_m, 'D')

    if days_in_end_m > day:
        enddate = dt64(end_m, 'D') + day
    else:
        enddate = dt64(end_m, 'D') + days_in_end_m - 1

    if business_day == 'No Adjustment' or business_day is None:
        return enddate

    elif business_day == 'Following':
        return np.busday_offset(enddate, 0, roll='forward', busdaycal=bdc)

    elif business_day == 'Preceeding':
        return np.busday_offset(enddate, 0, roll='backward', busdaycal=bdc)

    elif business_day == 'Modified Following':
        new_date = np.busday_offset(enddate, 0, roll='forward', busdaycal=bdc)
        if dt64(new_date, 'M') > end_m:
            return np.busday_offset(enddate, 0, roll='backward', busdaycal=bdc)
        else:
            return new_date
示例#5
0
def flat_curve(start_date,
               end_date,
               rate,
               rate_basis="Money Market",
               day_count="Actual/365",
               bus_day="No Adjustment",
               tenors=None,
               return_type="time"):
    if tenors is None:
        mytenors = [x for x in std_tenors if x != "12M"]
    else:
        mytenors = list(tenors)
    sdate = dt64(start_date, "D")
    edate = dt64(end_date, "D")
    time = day_cf("Actual/365", sdate, edate)
    dcf = day_cf(day_count, sdate, edate)
    if rate_basis == "Money Market":
        df = _mmr2df(float(rate), float(dcf))
    elif rate_basis == "Discount Rate":
        df = _dr2df(float(rate), float(dcf))
    else:
        return None

    time = day_cf("Actual/365", sdate, edate)
    crate = -math.log(df) / time
    dates = [ttm(sdate, tenor, day_count, bus_day) for tenor in mytenors]

    times = [{
        "times": float(day_cf("Actual/365", sdate, date))
    } for date in dates]
    timelen = len(times)
    ret_array = []
    if return_type == "time":
        dfs = [{"df": math.exp(-crate * time["times"])} for time in times]
        for i in range(timelen):
            time = times[i]
            df = dfs[i]
            time.update(df)
            ret_array.append(time)

    elif return_type == "days":
        days = [{"days": (date - sdate).astype("float")} for date in dates]
        dfs = [{"df": math.exp(-crate * time["times"])} for time in times]
        for i in range(timelen):
            day = days[i]
            df = dfs[i]
            day.update(df)
            ret_array.append(day)
    return ret_array
示例#6
0
def _dcf_a365_4ayear(start, end, business_day=None, Frequency=1):

    year1 = np.datetime64(start, 'Y')
    year2 = np.datetime64(dt64(end), 'Y')
    if year2 == year1:
        daysinayear = daysintheyear(start)
        days = np.int64(dt64(end) - start)
        return days/daysinayear
    else:
        daysinayear1 = daysintheyear(start)
        end1 = np.datetime64(year1 + 1, 'D')
        days1 = np.int64(end1 - start)

        daysinayear2 = daysintheyear(end)
        start2 = np.datetime64(year2, 'D')
        days2 = np.int64(dt64(end) - start2)
        return days1/daysinayear1 + days2/daysinayear2
示例#7
0
 def current_date(self, current_date):
     if current_date is not None:
         try:
             self.__current_date = dt64(current_date)
         except:
             raise ValueError('current date is not a date')
     else:
         self.__current_date = current_date
示例#8
0
 def value_date(self, value_date):
     if value_date is not None:
         try:
             self.__value_date = dt64(value_date, "D")
         except:
             raise ValueError('value_date is not a date')
     else:
         self.__value_date = value_date
示例#9
0
 def start_date(self, start_date):
     if start_date is not None:
         try:
             self.__start_date = dt64(start_date)
         except:
             raise ValueError('start_date is not a date')
     else:
         self.__start_date = start_date
示例#10
0
def calc_shortrate_from_df(startdate,
                           enddate,
                           df,
                           day_count,
                           rate_basis="Money Market"):
    sdate = dt64(startdate, "D")
    edate = dt64(enddate, "D")
    dcf = day_cf(day_count,
                 sdate,
                 edate,
                 bondmat_date=edate,
                 next_coupon_date=edate)
    if rate_basis == "Discount Rate":
        return _df2dr(df, dcf)
    else:
        return _df2mmr(float(df), float(dcf))
    return None
示例#11
0
def adjustdates(months, dates, business_day, holidays=[]):

    bdc = np.busdaycalendar(weekmask='1111100', holidays=holidays)
    datalen = len(dates)
    newdates = []

    for i in range(datalen):
        month = months[i]
        dmonth = dt64(dates[i], 'M')
        if dmonth == month:
            if business_day == 'Following':
                dates[i] = np.busday_offset(dates[i],
                                            0,
                                            roll='forward',
                                            busdaycal=bdc)

            elif business_day == 'Preceeding':
                dates[i] = np.busday_offset(dates[i],
                                            0,
                                            roll='backward',
                                            busdaycal=bdc)

            elif business_day == 'Modified Following':
                new_date = np.busday_offset(dates[i],
                                            0,
                                            roll='forward',
                                            busdaycal=bdc)
                if dt64(new_date, 'M') > month:
                    dates[i] = np.busday_offset(dates[i],
                                                0,
                                                roll='backward',
                                                busdaycal=bdc)
        elif dmonth > month:
            #print(month,dmonth)
            nextmonth = month + td64(1, 'M')
            nextmonthdate = dt64(nextmonth, 'D')
            days = _datediff(dt64(month, 'D'), nextmonthdate)
            dates[i] = dt64(month, 'D') + days - 1
            if business_day == 'Following':
                dates[i] = np.busday_offset(dates[i],
                                            0,
                                            roll='forward',
                                            busdaycal=bdc)

            elif business_day == 'Preceeding':
                dates[i] = np.busday_offset(dates[i],
                                            0,
                                            roll='backward',
                                            busdaycal=bdc)

            elif business_day == 'Modified Following':
                new_date = np.busday_offset(dates[i],
                                            0,
                                            roll='forward',
                                            busdaycal=bdc)
                if dt64(new_date, 'M') > month:
                    dates[i] = np.busday_offset(dates[i],
                                                0,
                                                roll='backward',
                                                busdaycal=bdc)
示例#12
0
def cut_log_spectra(fileinpaths, times, fileoutpaths_list, **kwargs):
    for i, fileinpath in enumerate(fileinpaths):
        fileoutpaths = fileoutpaths_list[i]
        tdmsfile = TF(fileinpath)
        for j, t in enumerate(times):
            fileoutpath = fileoutpaths[j]

            direc = os.path.split(fileoutpath)[0]
            if not os.path.exists(direc):
                os.makedirs(direc)

            root_object = RootObject(properties={})

            try:
                with TdmsWriter(fileoutpath, mode='w') as tdms_writer:
                    timedata = [
                        dt64(y)
                        for y in tdmsfile.channel_data('Global', 'Time')
                    ]
                    idx1, idx2 = _get_indextime(timedata, t[0], t[1])
                    if idx1 == idx2:
                        pass
                    else:
                        for group in tdmsfile.groups():
                            group_object = GroupObject(group, properties={})
                            if group == "Global":
                                for channel in tdmsfile.group_channels(group):
                                    if channel.channel == 'Wavelength':
                                        channel_object = ChannelObject(
                                            channel.group, channel.channel,
                                            channel.data)
                                    else:
                                        channel_object = ChannelObject(
                                            channel.group, channel.channel,
                                            channel.data[idx1:idx2])
                                    tdms_writer.write_segment([
                                        root_object, group_object,
                                        channel_object
                                    ])
                            else:
                                for channel_object in tdmsfile.group_channels(
                                        group)[idx1:idx2]:
                                    tdms_writer.write_segment([
                                        root_object, group_object,
                                        channel_object
                                    ])

            except ValueError as error:
                print(error)
                print('removing the file at: \n', fileoutpath)
                os.remove(fileoutpath)
示例#13
0
def _dcf_a365(prev_date, current_date, business_day=None, Frequency=1):
    year1 = np.datetime64(prev_date, 'Y')
    year2 = np.datetime64(current_date, 'Y')
    years = np.int64(year2 - year1)

    if years == 0:
        return _dcf_a365_4ayear(prev_date,
                                current_date,
                                business_day=business_day,
                                Frequency=Frequency)
    else:
        start_m = np.datetime64(prev_date, 'M')
        start_day = np.int64(
            np.datetime64(prev_date, 'D') - np.datetime64(start_m, 'D'))

        years_enddate_m = np.datetime64(prev_date, 'M') + years * 12
        years_enddate = np.datetime64(years_enddate_m, 'D') + start_day

        extra_days = np.int64(dt64(current_date) - years_enddate)

        if years == 1:
            if extra_days == 0:
                return years
            elif extra_days < 0:
                return _dcf_a365_4ayear(prev_date,
                                        current_date,
                                        business_day=business_day,
                                        Frequency=Frequency)
            else:
                yearfrac = _dcf_a365_4ayear(years_enddate,
                                            current_date,
                                            business_day=business_day,
                                            Frequency=Frequency)
                return years + yearfrac
        else:
            if extra_days == 0:
                return years
            else:
                yearfrac = _dcf_a365_4ayear(years_enddate,
                                            current_date,
                                            business_day=business_day,
                                            Frequency=Frequency)
                return years + yearfrac
示例#14
0
def fixbond_value(value_date,
                  structures,
                  yld,
                  day_count,
                  frequency,
                  business_day="No Adjustment"):
    const = 0.01
    try:
        ytm = float(yld)
        ytm1 = ytm + const
        ytm2 = ytm1 + const
    except Exception:
        return None
    newstructures = [dict(x) for x in structures]
    maturity = newstructures[-1]["end_date"]

    # Curves to be used in calculation of duration, convexity and pvbp01
    df_curve = ytm_df_struct(value_date, newstructures, day_count, frequency,
                             business_day, ytm)
    x_axis = [x["times"] for x in df_curve]
    y_axis = [x["df"] for x in df_curve]
    ifunc = interpolation(x_axis, y_axis, float(1 / 366), is_function=True)

    df_curve1 = ytm_df_struct(value_date, newstructures, day_count, frequency,
                              business_day, ytm1)
    x_axis1 = [x["times"] for x in df_curve1]
    y_axis1 = [x["df"] for x in df_curve1]
    ifunc1 = interpolation(x_axis1, y_axis1, float(1 / 366), is_function=True)

    df_curve2 = ytm_df_struct(value_date, newstructures, day_count, frequency,
                              business_day, ytm2)
    x_axis2 = [x["times"] for x in df_curve2]
    y_axis2 = [x["df"] for x in df_curve2]
    ifunc2 = interpolation(x_axis2, y_axis2, float(1 / 366), is_function=True)

    # covert data into list
    dates = [{
        "start_date": x["start_date"],
        "end_date": x["end_date"]
    } for x in structures if value_date < dt64(x["end_date"])]
    cfs = np.asarray([
        x["cash_flow"] for x in structures if value_date < dt64(x["end_date"])
    ])

    times = np.asarray(
        [day_cf("Actual/365", value_date, x["end_date"]) for x in dates])
    # interpolating discount factors
    dfs = [ifunc(x) for x in times]
    # calculating the present values
    pvs = cfs * dfs
    weighted_pvs = pvs * times
    value = np.sum(pvs)
    weighted_value = np.sum(weighted_pvs)

    # interpolating 2nd discount factors
    dfs1 = [ifunc1(x) for x in times]
    # calculating the 2nd present values
    pvs1 = cfs * dfs1
    value1 = np.sum(pvs1)

    # interpolating 3rd discount factors
    dfs2 = [ifunc2(x) for x in times]
    # calculating the 3rd present values
    pvs2 = cfs * dfs2
    value2 = np.sum(pvs2)

    mac_dur = weighted_value / value
    compound = 12 / frequencies[frequency]
    mod_dur = mac_dur / pow((1 + ytm / (compound * 100)), compound)
    pvbp01 = value1 - value

    # 1st derivative at ytm using forward differential
    der0 = (value1 - value) / (ytm1 - ytm)
    # 1st derivative at ytm1 using forward differential
    der1 = (value2 - value1) / (ytm2 - ytm1)
    # 2nd derivative at ytm using forward differential
    conv = (der1 - der0) / (ytm2 - ytm1)

    return {
        "macaulay_duration": mac_dur,
        "modified_duration": mod_dur,
        "pvbp01": pvbp01,
        "convexity": conv,
        "value": value
    }
示例#15
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov  4 07:32:58 2020

@author: RMS671214
"""
from faspy.interestrate import discount_curve as dcurve
from numpy import datetime64 as dt64
import time

vdate = dt64("2020-10-30", "D")
start0 = time.perf_counter()
# %%
# Historical Discount Factors
rates = []
rate = {
    "value_date": "2020-10-30",
    "st_busday": "Modified Following",
    "st_ratebasis": "Simple",
    "st_daycount": "Actual/365",
    "lt_busday": "No Adjustment",
    "lt_frequency": "Semi-Annual",
    "lt_daycount": "Actual/Actual",
    "rates": {
        'O/N': 2.30,
        '1W': 2.35,
        '1M': 2.45,
        '3M': 2.55,
        '6M': 2.65,
        '1Y': 2.70,
示例#16
0
文件: buckets.py 项目: romsey67/faspy
def bucketing(data, buckets, value_date, dfcurve=None):
    """
    Generate bonds coupon structures.

            Parameters:
                data: a list containing dictionary with the following keys -
                "id", "date" and "amount"
                buckets: a list containg dictionaries with the following keys -
                "name", "from" and "to". The value for each key is number of days


            Returns:
                a dictionary with the following keys - date, dcf, time,
                days, df, rate
    """
    vdate = dt64(value_date, "D")
    mydata = list(data)
    calc_data = [{
        "days": _datediff(vdate, dt64(x["date"], "D")).astype("int"),
        "tenor": day_cf("Actual/365", vdate, dt64(x["date"], "D"))
    } for x in mydata]
    if dfcurve is not None:
        df_xaxis = [x["times"] for x in dfcurve]
        df_yaxis = [x["df"] for x in dfcurve]
        i_func = interpolation(df_xaxis, df_yaxis, 1, is_function=True)
        df_array = [{"df": float(i_func(x["tenor"]))} for x in calc_data]

    dtlen = len(mydata)
    newdata = []
    for i in range(dtlen):
        old = dict(mydata[i])
        new = dict(calc_data[i])
        old.update(new)

        if dfcurve is not None:
            df_dic = df_array[i]
            old.update(df_dic)
            old["pv"] = old["df"] * old["amount"]
        newdata.append(old)

    mdur = [{
        "mod_duration": _mod_duration(float(x["tenor"]), float(x["df"]))
    } for x in newdata]
    bucket = [{"bucket": assign_bucket(x["tenor"], buckets)} for x in newdata]

    for i in range(dtlen):
        old = newdata[i]
        new = mdur[i]
        buc = bucket[i]
        old.update(new)
        old.update(buc)

    sortedbucket = sorted(buckets, key=sorter)
    buclen = len(sortedbucket)
    bucket_list = {}
    # return sortedbucket
    for i in range(buclen):
        bucket_list[sortedbucket[i]["name"]] = 0

    for datum in newdata:
        bucket_list[datum["bucket"]] += datum["pv"]

    return (newdata, bucket_list)
示例#17
0
def _calc_shorttenor(tenors, rates, setting, holidays=[]):

    v_date = dt64(setting['cdate'])
    tenors1 = tenors[3:]
    tenors2 = tenors[:3]
    tomdate, spotdate, spotnext = _calc_ondate(v_date, holidays=holidays)
    dates = {'current': v_date, 'Tom': tomdate, 'Spot': spotdate}
    data_len = len(tenors)
    data = []
    rates1 = rates[3:]
    rates2 = rates[:3]

    ratebasis = 0
    if setting['rate_basis'] == 'Discount Rate':
        ratebasis = 1

    data_len = len(tenors2)
    for i in range(data_len):
        datum = {}
        datum['tenor'] = tenors2[i]
        datum['rate'] = rates2[i]
        if datum['tenor'] == 'O/N':
            datum['start'] = v_date
            datum['maturity'] = tomdate
        elif datum['tenor'] == 'T/N':
            datum['start'] = tomdate
            datum['maturity'] = spotdate
        elif datum['tenor'] == 'S/N':
            datum['start'] = spotdate
            datum['maturity'] = spotnext

        datum['stime'] = float(day_cf('Actual/365', v_date, datum['start']))
        datum['dcf'] = float(
            day_cf(setting['day_count'], datum['start'], datum['maturity']))
        if datum['rate'] is not None:
            datum['df'] = _strate_to_df(datum['rate'], datum['dcf'], ratebasis)
        else:
            datum['df'] = None
        datum['time'] = day_cf('Actual/365', v_date, datum['maturity'])
        data.append(datum)

    maturities = _calc_maturities(setting['start_basis'], setting['day_count'],
                                  setting['bus_day'], dates, tenors1)
    start_date = None
    if setting['start_basis'] == 'Same Day':
        start_date = v_date
    elif setting['start_basis'] == 'Tom':
        start_date = tomdate
    elif setting['start_basis'] == 'Spot':
        start_date = spotdate

    stime = day_cf('Actual/365', v_date, start_date)
    data_len = len(tenors1)
    for i in range(data_len):
        datum = {}
        datum['tenor'] = tenors1[i]
        datum['rate'] = rates1[i]
        datum['maturity'] = maturities[i]
        datum['start'] = start_date
        datum['stime'] = stime
        datum['dcf'] = float(
            day_cf(setting['day_count'], datum['start'], datum['maturity']))
        if datum['rate'] is not None:
            datum['df'] = _strate_to_df(datum['rate'], datum['dcf'], ratebasis)
        else:
            datum['df'] = None
        datum['time'] = float(
            day_cf('Actual/365', datum['start'], datum['maturity']))
        data.append(datum)

    # Calculate df to current date
    data_len = len(data)
    if setting['start_basis'] == 'Same Day':
        for i in range(data_len):
            datum = data[i]
            if datum['tenor'] == 'O/N':
                if datum.get('df') is not None:
                    datum['df_tocdate'] = datum['df']
                else:
                    datum['df_tocdate'] = None
            elif datum['tenor'] == 'T/N' and datum.get('df') is not None:
                on = dict(data[i - 1])
                if on.get('df') is not None:
                    datum['df_tocdate'] = on['df'] * datum['df']
                else:
                    on['rate'] = datum['rate']
                    on['df'] = 1 / (1 + on['rate'] * 0.01 * on['dcf'])
                    datum['df_tocdate'] = on['df'] * datum['df']

            elif datum['tenor'] == 'S/N' and datum.get('df') is not None:
                tn = dict(data[i - 1])
                if tn.get('df_tocdate') is not None:
                    datum['df_tocdate'] = tn['df_tocdate'] * datum['df']
                else:
                    on = dict(data[i - 2])
                    on['rate'] = datum['rate']
                    on['df'] = 1 / (1 + on['rate'] * 0.01 * on['dcf'])
                    on['df_tocdate'] = on['df']
                    tn['rate'] = datum['rate']
                    tn['df'] = 1 / (1 + tn['rate'] * 0.01 * tn['dcf'])
                    tn['df_tocdate'] = on['df'] * tn['df']
                    datum['df_tocdate'] = tn['df'] * datum['df']
            else:
                datum['df_tocdate'] = datum['df']

    elif setting['start_basis'] == 'Spot':
        _adjustdf_fromspot(data)

    elif setting['start_basis'] == 'Tom':
        df_totom = None
        ondf = None
        ontime = None

        for i in range(0, 1, 1):
            datum = data[i]

            if datum['tenor'] == 'O/N':
                ondf = datum['df']
                ontime = datum['time']
                if ondf is not None:
                    datum['df_tocdate'] = ondf

        tomtime = ontime
        if ondf is None:
            df_totom = ondf
            # get discount factor to interpolate
            x_axis = [0]
            y_axis = [1]
            for n in range(1, data_len, 1):
                datum1 = data[n]
                if datum1['df'] is not None:
                    x_axis.append(datum1['time'])
                    y_axis.append(datum1['df'])

            if ondf is None:
                x_value = tomtime
                df_totom = interpolation(x_axis, y_axis, x_value)

        for i in range(1, data_len, 1):
            datum = data[i]
            if datum['df'] is not None:
                datum['df_tocdate'] = datum['df'] * df_totom

    return data
示例#18
0
def day_count_factor(convention,
                     prev_date,
                     current_date,
                     bondmat_date=None,
                     next_coupon_date=None,
                     business_day=None,
                     Frequency=1):

    if convention in _a365:
        return _dcf_a365(prev_date, current_date)

    elif convention in _a360:
        return _dcf_a360(prev_date, current_date)

    elif convention in _a365f:

        return _dcf_a365f(dt64(prev_date, 'D'), dt64(current_date, 'D'))

    elif convention in _a364:
        return _dcf_a364(prev_date, current_date)

    elif convention in _a365l:
        return _dcf_a365l(prev_date, current_date, Frequency=Frequency)

    elif (convention in _a30_360 or convention in _o30_360bb
          or convention in _o30_360us or convention in _a30e_360
          or convention in _a30e_360i):
        year1 = np.datetime64(prev_date, 'Y')
        month1 = np.datetime64(prev_date, 'M')
        d1 = np.int32(prev_date - np.datetime64(month1)) + 1
        m1 = np.int32(month1 - np.datetime64(year1, 'M')) + 1
        y1 = np.int64(year1)

        year2 = np.datetime64(current_date, 'Y')
        month2 = np.datetime64(current_date, 'M')
        d2 = np.int32(current_date - np.datetime64(month2)) + 1
        m2 = np.int32(month2 - np.datetime64(year2, 'M')) + 1
        y2 = np.int64(year2)

        if convention in _o30_360bb:
            d1 = min(d1, 30)
            if d1 >= 30:
                d2 = min(d2, 30)
            return _dcf_360(d1, m1, y1, d2, m2, y2)

        elif convention in _o30_360us:
            str_date1 = str(prev_date)
            str_date2 = str(current_date)
            arr_date1 = str_date1.split('-')
            arr_date2 = str_date2.split('-')

            date1m = np.datetime64(prev_date, 'M')
            days = np.int32(prev_date - np.datetime64(date1m, 'D'))
            addmonth = date1m + 1
            nextmonth = np.datetime64(addmonth, 'D') + days
            daysinamonth1 = np.int32(nextmonth - prev_date)

            date2m = np.datetime64(current_date, 'M')
            days2 = np.int32(current_date - np.datetime64(date2m, 'D'))
            addmonth2 = date2m + 1
            nextmonth2 = np.datetime64(addmonth2, 'D') + days2
            daysinamonth2 = np.int32(nextmonth2 - current_date)

            if (np.int32(arr_date1[1]) == 2 and np.int32(arr_date2[1]) == 2
                    and days == daysinamonth1 and days2 == daysinamonth2
                    and business_day == 'EOM'):
                d2 = 30
            if (np.int32(arr_date1[1]) == 2 and days == daysinamonth1
                    and business_day == 'End of Month'):
                d1 = 30
            if d2 == 31 and d1 >= 30:
                d2 = 30
            if d1 == 31:
                d1 = 30

            return _dcf_360(d1, m1, y1, d2, m2, y2)

        elif convention in _a30e_360:
            if d1 == 31:
                d1 = 30
            if d2 == 31:
                d2 = 30
            value = _dcf_360(d1, m1, y1, d2, m2, y2)
            return value

        elif convention in _a30e_360i:
            daysinamonth = daysinthemonth(prev_date)
            monthend = np.datetime64(month1, 'D') + daysinamonth - 1
            if monthend == prev_date:
                d1 = 30

            daysinamonth2 = daysinthemonth(current_date)
            monthend2 = np.datetime64(month2, 'D') + daysinamonth2 - 1
            if bondmat_date != monthend2 and m2 != 2:
                d2 = 30

            return _dcf_360(d1, m1, y1, d2, m2, y2)

    elif convention in _A_A_icma:
        if next_coupon_date is None:
            return None
        else:
            accrued_days = _datediff(prev_date, current_date).astype('int')
            coupon_days = _datediff(prev_date, next_coupon_date).astype('int')
            dcf = accrued_days / (Frequency * coupon_days)

            return dcf

    elif convention in _A_A_isda:
        return _dcf_a365(prev_date,
                         current_date,
                         business_day=business_day,
                         Frequency=Frequency)

    elif convention in _A_A_afb:
        return "In development"
示例#19
0
def construct_frn(bond, holidays=[]):
    bdc = np.busdaycalendar(weekmask='1111100', holidays=holidays)

    bus_day = None
    if bond['business_day'] == 'NULL':
        bus_day = 'No Adjustment'
    else:
        bus_day = bond['business_day']

    if bond['day_count'] == 'NULL':
        day_count = 'Actual/365'
    else:
        day_count = bond['day_count']

    start_date = bond.get('issue_date')
    if start_date is not None:
        start_date = dt64(start_date, 'D')
    value_date = bond.get('value_date')

    if value_date is not None:
        value_date = dt64(value_date, 'D')

    if start_date is not None and value_date is not None:
        use_date = start_date
    elif start_date is not None:
        use_date = start_date
    elif value_date is not None:
        use_date = value_date
    else:
        raise Exception('Both value_date and issue_date do not have any value')

    dates = gen_dates(use_date,
                      bond['maturity'],
                      issueDate=start_date,
                      frequency=fre[bond['frequency']],
                      business_day=bus_day,
                      method=bond['date_generation'])

    #print(dates)
    # *********************************************************************************
    #
    #               CALCULATING THE DATA FOR FULL STRUCTURES
    #
    # *********************************************************************************
    fs = list(dates)

    flen = len(fs)
    for i in range(flen):
        row = fs[i]
        row['cf'] = 0
        row['time'] = day_cf('Actual/365',
                             use_date,
                             row['date'],
                             bondmat_date=fs[-1]['date'],
                             next_coupon_date=row['date'])
        if i == 0:
            row['dcf'] = 0
            row['y_dcf'] = 0
            row['margin'] = 0
            row['fv'] = 0
            row['fv_flow'] = 0
            row['fixing_date'] = None

        else:
            row['dcf'] = day_cf(day_count,
                                fs[i - 1]['date'],
                                row['date'],
                                bondmat_date=fs[-1]['date'],
                                next_coupon_date=row['date'],
                                Frequency=12 / fre[bond['frequency']])
            row['y_dcf'] = row['dcf']
            row['margin'] = bond['margin']
            row['fv'] = bond['face_value']
            row['fv_flow'] = 0
            if i == flen - 1:
                row['fv_flow'] = bond['face_value']
            row['fixing_date'] = bus_off(fs[i - 1]['date'],
                                         -start_basis[bond['fixing_basis']],
                                         roll='backward',
                                         busdaycal=bdc)

    bond['full_structures'] = fs

    # *********************************************************************************
    #
    #               CALCULATING THE DATA FOR ACTIVE STRUCTURES
    #
    # *********************************************************************************
    if value_date is None:
        bond['active_structures'] = {}

    elif value_date is not None and start_date is None:
        bond['active_structures'] = bond['full_structures']

    elif value_date < start_date:
        bond['active_structures'] = bond['full_structures']

    else:
        # print(value_date,start_date)
        booldate = list(map(lambda x: x['date'] > value_date, fs))
        index = booldate.index(True)  # exclude paid coupon period/start_date
        acs = list(fs[index - 1:])
        acs[0]['y_dcf'] = 0
        acs[1]['y_dcf'] = day_cf(day_count,
                                 bond['value_date'],
                                 acs[1]['date'],
                                 bondmat_date=acs[-1]['date'],
                                 next_coupon_date=acs[1]['date'],
                                 Frequency=12 / fre[bond['frequency']])
        alen = len(acs)
        for i in range(alen):
            acs[i]['time'] = day_cf('Actual/365',
                                    bond['value_date'],
                                    acs[i]['date'],
                                    bondmat_date=acs[-1]['date'],
                                    next_coupon_date=acs[i]['date'])

        bond['active_structures'] = acs

    return bond
示例#20
0
def fixbond_price(value_date, bond, yld):

    try:
        val_date = dt64(value_date)

    except Exception:
        raise Exception('Value date is not a date')

    try:
        acs = bond['active_structures']
    except Exception:
        raise Exception('full_structures does not have the required key(s)')

    try:
        freq = bond['frequency']
    except Exception:
        raise Exception('Error getting frequency of the floating leg')

    if bond['value_date'] is None:
        raise Exception('Value date for the bond is not set')

    bond['last_coupon_date'] = acs[0]['date']
    bond['accrued_interest'] = 0
    next_cpn = acs[1]
    # Calculation for fixed coupon
    if bond['value_date'] >= acs[0]['date']:
        coupon = bond.get('coupon')
        if coupon is not None:
            #print(next_cpn)
            next_cpn['coupon'] = coupon
            next_cpn['cf'] = coupon * next_cpn['dcf'] * next_cpn['fv'] * 0.01
            y_dcf = day_cf(bond['day_count'],
                           val_date,
                           next_cpn['date'],
                           bondmat_date=acs[-1]['date'],
                           next_coupon_date=next_cpn['date'],
                           Frequency=12 / fre[bond['frequency']])
            next_cpn['y_dcf'] = y_dcf
            df = 1 / (1 + yld * y_dcf * 0.01)
            next_cpn['pv'] = (next_cpn['cf'] + next_cpn['fv_flow']) * df
            next_cpn['df'] = df
            next_cpn['p_df'] = df

            # Calculation for PVBP01
            df01 = 1 / (1 + (yld + 0.01) * y_dcf * 0.01)
            next_cpn['pv01'] = (next_cpn['cf'] + next_cpn['fv_flow']) * df01
            next_cpn['df01'] = df01
            next_cpn['p_df01'] = df01
            #print(next_cpn)
        accrued_dcf = day_cf(bond['day_count'],
                             bond['last_coupon_date'],
                             bond['value_date'],
                             bondmat_date=acs[-1]['date'],
                             next_coupon_date=next_cpn['date'],
                             Frequency=12 / fre[bond['frequency']])
        # print(bond.get('current_coupon'), next_cpn)
        bond['accrued'] = accrued_dcf
        bond['accrued_interest'] = (accrued_dcf * next_cpn['coupon'] * 0.01 *
                                    next_cpn['fv'])

        lacs = len(acs)
        for i in range(2, lacs, 1):
            acs_sgl = acs[i]
            lastrow = acs[i - 1]
            acs_sgl['y_dcf'] = acs_sgl['cpn_dcf']
            acs_sgl['p_df'] = 1 / (1 + yld * acs_sgl['y_dcf'] * 0.01)
            acs_sgl['p_df01'] = 1 / (1 +
                                     (yld + 0.01) * acs_sgl['y_dcf'] * 0.01)
            acs_sgl['df'] = acs_sgl['p_df'] * lastrow['df']
            acs_sgl['df01'] = acs_sgl['p_df01'] * lastrow['df01']
            acs_sgl['pv'] = ((acs_sgl['cf'] + acs_sgl['fv_flow']) *
                             acs_sgl['df'])
            acs_sgl['pv01'] = ((acs_sgl['cf'] + acs_sgl['fv_flow']) *
                               acs_sgl['df01'])

        sum_pv = 0
        sum_pv01 = 0
        for i in range(1, lacs, 1):
            sgl_acs = acs[i]
            sum_pv += sgl_acs['pv']
            sum_pv01 += sgl_acs['pv01']
        bond['pvbp01'] = sum_pv01 - sum_pv
        bond['proceed'] = sum_pv
        bond['price per 100'] = ((bond['proceed'] - bond['accrued_interest']) /
                                 bond['face_value'] * 100)

        macD = 0
        for i in range(1, lacs, 1):
            acs_sgl = acs[i]
            macD = (macD + acs_sgl['time'] *
                    (acs_sgl['cf'] + acs_sgl['fv_flow']) * acs_sgl['df'])

        macD = macD / bond['proceed']
        bond['modified duration'] = -macD / (1 + (yld * 0.01) /
                                             (12 / fre[freq]))
        bond['macaulay duration'] = macD
        #print('acs===>', acs)
        derivatives = bond_risk(acs, yld)
        bond['duration'] = derivatives['duration']
        bond['convexity'] = derivatives['convexity']
        bond['active_structures'] = acs
    else:
        # *******************************************************************
        # else clause process the bond as a forward issuance bond
        # disfac (discount factor) has to be provided to properly price the
        # bond) yld is taken to be the fwd yield of the bond
        # ********************************************************************
        raise Exception('Forward bond issuance is yet to be done')
示例#21
0
def frn_price(bond, disc_curve):

    try:
        val_date = dt64(bond.get('value_date'))

    except Exception:
        raise Exception('Value date is not a date')

    try:
        acs = bond['active_structures']

    except Exception:
        raise Exception('full_structures does not have the required key(s)')

    bond['last_coupon_date'] = acs[0]['date']
    bond['accrued_interest'] = 0
    next_cpn = acs[1]
    interp = disc_curve.interpolate(1, is_function=True)
    # Calculation for fixed coupon
    if bond['value_date'] >= acs[0]['date']:
        coupon = next_cpn['coupon']
        if coupon is not None:
            gen_time = next_cpn['time']
            next_cpn['cf'] = coupon * next_cpn['dcf'] * next_cpn['fv'] * 0.01
            dcf = next_cpn['dcf']
            df = interp(gen_time)
            next_cpn['ref_rate'] = (1 / df - 1) / (dcf * 0.01)
            next_cpn['ref_with_spread'] = (next_cpn['ref_rate'] +
                                           bond['spread'])
            df = 1 / (1 + next_cpn['ref_with_spread'] * dcf * 0.01)
            next_cpn['pv'] = (next_cpn['cf'] + next_cpn['fv_flow']) * df
            next_cpn['df'] = df
            # Calculation for PVBP01
            next_cpn['coupon01'] = coupon
            next_cpn['cf01'] = next_cpn['cf']
            df = interp(gen_time)
            next_cpn['ref_rate01'] = (1 / df - 1) / (dcf * 0.01) + 0.01
            next_cpn['ref01_with_spread'] = (next_cpn['ref_rate01'] +
                                             bond['spread'])
            #print(next_cpn['ref_rate01'], bond['spread'])
            df01 = 1 / (1 + next_cpn['ref01_with_spread'] * dcf * 0.01)
            next_cpn['pv01'] = (next_cpn['cf01'] + next_cpn['fv_flow']) * df01
            next_cpn['df01'] = df01

    accrued_dcf = day_cf(bond['day_count'],
                         bond['last_coupon_date'],
                         bond['value_date'],
                         bondmat_date=acs[-1]['date'],
                         next_coupon_date=next_cpn['date'],
                         Frequency=12 / fre[bond['frequency']])
    #print(bond.get('current_coupon'), next_cpn)
    bond['accrued'] = accrued_dcf
    bond['accrued_interest'] = (accrued_dcf * next_cpn['coupon'] * 0.01 *
                                next_cpn['fv'])

    lacs = len(acs)
    # Calculation for unfixed coupon
    for i in range(2, lacs, 1):
        prev_acs = acs[i - 1]
        sgl_acs = acs[i]
        #sgl_acs['fixed'] = False
        time0 = prev_acs['time']
        time1 = sgl_acs['time']
        df0 = disc_curve.interpolate(time0)
        df1 = disc_curve.interpolate(time1)
        dcf = sgl_acs['dcf']
        fwd_df = df1 / df0
        sgl_acs['ref_rate'] = (1 / fwd_df - 1) / (dcf * 0.01)
        sgl_acs['coupon'] = (sgl_acs['ref_rate'] + sgl_acs['margin'])
        sgl_acs['cf'] = sgl_acs['coupon'] * dcf * 0.01 * sgl_acs['fv']
        sgl_acs['ref_with_spread'] = (sgl_acs['ref_rate'] + bond['spread'])
        sgl_acs['fwd_df'] = 1 / (1 + sgl_acs['ref_with_spread'] * dcf * 0.01)
        sgl_acs['df'] = sgl_acs['fwd_df'] * prev_acs['df']
        sgl_acs['pv'] = (sgl_acs['cf'] + sgl_acs['fv_flow']) * sgl_acs['df']
        # Calculation for PVBP01
        sgl_acs['ref_rate01'] = (1 / fwd_df - 1) / (dcf * 0.01) + 0.01
        sgl_acs['coupon01'] = (sgl_acs['ref_rate01'] + sgl_acs['margin'])
        sgl_acs['cf01'] = sgl_acs['coupon01'] * dcf * 0.01 * sgl_acs['fv']
        sgl_acs['ref01_with_spread'] = (sgl_acs['ref_rate01'] + bond['spread'])
        sgl_acs['fwd_df01'] = 1 / (1 +
                                   sgl_acs['ref01_with_spread'] * dcf * 0.01)
        sgl_acs['df01'] = sgl_acs['fwd_df01'] * prev_acs['df01']
        sgl_acs['pv01'] = ((sgl_acs['cf01'] + sgl_acs['fv_flow']) *
                           sgl_acs['df01'])

    sum_pv = 0
    sum_pv01 = 0
    for i in range(1, lacs, 1):
        sgl_acs = acs[i]
        sum_pv += sgl_acs['pv']
        sum_pv01 += sgl_acs['pv01']
    bond['pvbp01'] = sum_pv01 - sum_pv
    bond['proceed'] = sum_pv
    bond['price per 100'] = ((bond['proceed'] - bond['accrued_interest']) /
                             bond['face_value'] * 100)
示例#22
0
@author: RMS671214
"""
import time
from numpy import datetime64 as dt64
from nbutils.curvebootstrapping import df_st

# %%
rate_basis = "Simple"
day_count = "Actual/365"
bus_day = "No Adjustment"

rate = {
    'O/N': 2.30,
    '1W': 2.35,
    '1M': 2.45,
    '3M': 2.55,
    '6M': 2.65,
    '12M': 2.75
}
date = dt64('2021-01-01', 'D')
x = 1000
rates = [rate for i in range(x)]
dates = [date for i in range(x)]

print(f"rates size is {len(rates)}")
start0 = time.perf_counter()
dfs = df_st(dates, rates, day_count, bus_day)
end0 = time.perf_counter()

print(f"Time taken is {end0-start0} seconds. Size is {len(dfs)}")
示例#23
0
def construct_fixbond(bond):
    bus_day = None
    if bond['business_day'] == 'NULL':
        bus_day = 'No Adjustment'
    else:
        bus_day = bond['business_day']

    if bond['day_count'] == 'NULL':
        day_count = 'Actual/Actual ICMA'
    else:
        day_count = bond['day_count']

    start_date = bond.get('issue_date')
    if start_date is not None:
        start_date = dt64(start_date, 'D')
    value_date = bond.get('value_date')

    if value_date is not None:
        value_date = dt64(value_date, 'D')

    if start_date is not None and value_date is not None:
        use_date = start_date
    elif start_date is not None:
        use_date = start_date
    elif value_date is not None:
        use_date = value_date
    else:
        raise Exception('Both value_date and issue_date do not have any value')

    dates = gen_dates(use_date,
                      bond['maturity'],
                      issueDate=start_date,
                      frequency=fre[bond['frequency']],
                      business_day=bus_day,
                      method=bond['date_generation'])

    #print(dates)
    # *********************************************************************************
    #
    #               CALCULATING THE DATA FOR FULL STRUCTURES
    #
    # *********************************************************************************
    fs = list(dates)
    flen = len(fs)
    for i in range(flen):
        fs_sgl = fs[i]
        fs_sgl['fv_flow'] = 0.00
        fs_sgl['fv'] = bond['face_value']
        if i > 0:
            fs_prev = fs[i - 1]
            fs_sgl['cpn_dcf'] = day_cf(day_count,
                                       fs_prev['date'],
                                       fs_sgl['date'],
                                       bondmat_date=fs[-1]['date'],
                                       next_coupon_date=fs_sgl['date'],
                                       Frequency=12 / fre[bond['frequency']])
            fs_sgl['coupon'] = bond['coupon']
            fs_sgl['time'] = day_cf('Actual/365',
                                    use_date,
                                    fs_sgl['date'],
                                    bondmat_date=fs[-1]['date'],
                                    next_coupon_date=fs_sgl['date'],
                                    Frequency=12 / fre[bond['frequency']])
            fs_sgl['cf'] = (fs_sgl['coupon'] * fs_sgl['cpn_dcf'] * 0.01 *
                            fs_sgl['fv'])
        else:
            fs_sgl['cpn_dcf'] = 0.00
            fs_sgl['coupon'] = 0.00
            fs_sgl['fv'] = 0.00
            fs_sgl['cf'] = 0.00

    fs[-1]['fv_flow'] = bond['face_value']
    bond['full_structures'] = fs

    # *********************************************************************************
    #
    #               CALCULATING THE DATA FOR ACTIVE STRUCTURES
    #
    # *********************************************************************************
    if value_date is None:
        bond['active_structures'] = {}

    elif value_date is not None and start_date is None:
        bond['active_structures'] = bond['full_structures']

    elif value_date < start_date:
        bond['active_structures'] = bond['full_structures']

    else:
        booldate = list(map(lambda x: x['date'] > value_date, fs))
        index = booldate.index(True)  # exclude paid coupon period/start_date
        acs = list(fs[index - 1:])
        acs[0]['dcf'] = 0
        acs[1]['dcf'] = day_cf(day_count,
                               bond['value_date'],
                               acs[1]['date'],
                               bondmat_date=acs[-1]['date'],
                               next_coupon_date=acs[1]['date'],
                               Frequency=12 / fre[bond['frequency']])
        alen = len(acs)
        for i in range(alen):
            acs[i]['time'] = day_cf('Actual/365',
                                    bond['value_date'],
                                    acs[i]['date'],
                                    bondmat_date=acs[-1]['date'],
                                    next_coupon_date=acs[i]['date'])

        bond['active_structures'] = acs
示例#24
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 30 13:36:21 2020

@author: RMS671214
"""

from nbutils.nbcurves import generate_fulldf as gen_df
from numpy import datetime64 as dt64
import time

# %%
vdates = [dt64('2020-10-30')]
st_busday = 'Modified Following'
st_ratebasis = 'Simple'
st_daycount = 'Actual/365'
lt_busday = "No Adjustment"
lt_frequency =  "Semi-Annual"
lt_daycount = "Actual/Actual"

st_curves = [{'O/N': 2.30, '1W': 2.35, '1M': 2.45, '3M': 2.55,
                  '6M': 2.65}]
lt_curves = [{'1Y': 2.70, '2Y': 2.80, '3Y': 2.90,
                  '5Y': 3.00, '10Y': 3.10, '30Y': 3.25}]


start0 = time.perf_counter()
for i in range(100):
    dfs = gen_df(vdates, st_curves, st_daycount, st_busday,
                    st_ratebasis, lt_curves, lt_daycount,
示例#25
0
structures = list(fixbond_structures(mybond))
print("STRUCTURES")
print("===========")
print(structures)

try:
    import pandas as pd
    pd1 = pd.DataFrame(structures)
except:
    pass

# %%

testdata = {
    "value_date": dt64("2020-05-01"),
    "maturity": dt64("2025-10-01"),
    "day_count": "Actual/Actual",
    "frequency": "Semi-Annual",
    "business_day": "No Adjustment",
    "date_generation": "Backward from maturity date",
    "face_value": 10000000,
    "coupon": 2.00,
    "ytm": 2.00
}
val = fixbond(testdata)
print(val["risks"])

try:
    pd3 = pd.DataFrame(val["structure"])
示例#26
0
import numba
import time
from numpy import datetime64 as dt64, timedelta64 as td64
import numpy

sdate1 = '2021-01-01'
sdate2 = '2022-01-01'
date1 = dt64('2021-01-01')
date2 = dt64('2022-01-01')
nbdate1 = numba.types.NPDatetime('D')(date1)
nbdate2 = numba.types.NPDatetime('D')(date2)
print(type(nbdate2))
i = 1
t = 1


def differences(date1, date2):
    return (date2 - date1).astype('int') / 365


start0 = time.perf_counter()
for x in range(t):
    test1 = differences(date1, date2)
end0 = time.perf_counter()
print(f"Time taken is for test1 {end0-start0} seconds: result {test1}")


@numba.njit(numba.types.NPTimedelta('D')(numba.types.NPDatetime('D'),
                                         numba.types.NPDatetime('D')),
            cache=True)
def numba_differences2(date1, date2):