def float_leg(df, payer_receiver, notional, spread, dsc_curve, fwd_curve, cal, day_count_basis, dirty_flag=True, roll_conv='modifiedfollowing'): # Dirty valuation, include interest accrued before valuation date if dirty_flag: d1 = pd.DatetimeIndex(df['Start Date']) d2 = pd.DatetimeIndex(df['End Date']) df['Days'] = sch.day_count(d1, d2, day_count_basis) df['Year Fraction'] = sch.year_fraction(d1, d2, day_count_basis) # Clean valuation, exclude interest accrued before valuation date else: tmp = df['Start Date'].copy() tmp[tmp<dsc_curve.curve_date] = dsc_curve.curve_date d1 = pd.DatetimeIndex(tmp) d2 = pd.DatetimeIndex(df['End Date']) df['Days'] = sch.day_count(d1, d2, day_count_basis) df['Year Fraction'] = sch.year_fraction(d1, d2, day_count_basis) df['Notional'] = notional fixing_dates, fixings = get_fwd_rates(DatetimeIndex(df['Start Date']),DatetimeIndex(df['End Date']),fwd_curve,cal,roll_conv) df['Fixing Date'] = fixing_dates df['Index Rate'] = fixings df['Spread'] = spread / 10000.0 df['Floating Rate'] = df['Index Rate'] + df.Spread df['Cash Flow'] = notional * df['Floating Rate'] * df['Year Fraction'] * payer_receiver df['Discount Factor'] = dsc_curve.get_dcf(DatetimeIndex(df['Payment Date'])) df.loc[df['Payment Date'] == dsc_curve.curve_date,'Discount Factor'] = 0.0 df['Cash Flow PV'] = df['Cash Flow'] * df['Discount Factor'] return df
def get_fwd_rates(d1, d2, fwd_curve, cal, roll_conv): # Get historical fixings historical_dates = d1[d1 <= fwd_curve.curve_date] historical_fixings = [] historical_fixing_dates = [] for i,d in enumerate(historical_dates): if d in fwd_curve.historical_fixings.keys(): historical_fixings.append(fwd_curve.historical_fixings[d]/100.0) historical_fixing_dates.append(d) else: j = 1 while j < 10: d = DatetimeIndex([d]) d = pd.Timestamp(np.busday_offset(dates=d.astype(str), offsets=j, roll=roll_conv, busdaycal=cal)[0]) if d in fwd_curve.historical_fixings.keys(): historical_fixings.append(fwd_curve.historical_fixings[d]/100.0) historical_fixing_dates.append(d) break j += 1 # Calculate future fixings d2 = d2[d1 > fwd_curve.curve_date] d1 = d1[d1 > fwd_curve.curve_date] t = pd.Series(sch.year_fraction(d1,d2,fwd_curve.day_count_basis)) future_fixings = list((1 / t) * (fwd_curve.get_dcf(d1) / fwd_curve.get_dcf(d2) - 1)) return pd.Series(historical_fixing_dates + d1.to_list()), pd.Series(historical_fixings + future_fixings)
def fixed_leg(df, payer_receiver, notional, fixed_rate, dsc_curve, day_count_basis, dirty_flag=True): # Dirty valuation, include interest accrued before valuation date if dirty_flag: d1 = pd.DatetimeIndex(df['Start Date']) d2 = pd.DatetimeIndex(df['End Date']) df['Days'] = sch.day_count(d1, d2, day_count_basis) df['Year Fraction'] = sch.year_fraction(d1, d2, day_count_basis) # Clean valuation, exclude interest accrued before valuation date else: tmp = df['Start Date'].copy() tmp[tmp<dsc_curve.curve_date] = dsc_curve.curve_date d1 = pd.DatetimeIndex(tmp) d2 = pd.DatetimeIndex(df['End Date']) df['Days'] = sch.day_count(d1, d2, day_count_basis) df['Year Fraction'] = sch.year_fraction(d1, d2, day_count_basis) df['Fixed Rate'] = fixed_rate / 100.0 df['Notional'] = notional df['Cash Flow'] = df['Notional'] * df['Fixed Rate'] * df['Year Fraction'] * payer_receiver df['Discount Factor'] = dsc_curve.get_dcf(DatetimeIndex(df['Payment Date'])) df.loc[df['Payment Date'] == dsc_curve.curve_date,'Discount Factor'] = 0.0 df['Cash Flow PV'] = df['Cash Flow'] * df['Discount Factor'] return df
def __init__(self, name, curve_date, discount_data, day_count_basis, historical_fixings=None): def calc_discount_factors(self,t,discount_factors,date_range, bps_shift): # Construct the log-discount curve using cubic spline interpolation log_discount = CubicSpline(t,-np.log(list(discount_factors)) + bps_shift*t) # basis point shift to the zero curve return np.exp(-log_discount(pd.Series(sch.year_fraction(self.curve_date,date_range,self.day_count_basis)))) # Store the defining terms of the curve self.name = name self.curve_date = curve_date self.discount_data = discount_data self.day_count_basis = day_count_basis # Calculate the time in years from the curve_date to the relevant dates of discount factors d = DatetimeIndex(discount_data.keys()) t = np.array(sch.year_fraction(DatetimeIndex([curve_date for _ in range(len(d))]),d,day_count_basis)) # Dates to precalc discount factors for date_range = pd.date_range(self.curve_date,pd.Timestamp('2059-12-31'),freq='d') discount_factors = calc_discount_factors(self, t=t, discount_factors=discount_data.values(), date_range=date_range, bps_shift=0) self.discount_factors_base = pd.DataFrame({'Dates': date_range, 'DiscountFactors': discount_factors}) discount_factors = calc_discount_factors(self, t=t, discount_factors=discount_data.values(), date_range=date_range, bps_shift=1/100/100) self.discount_factors_upshift = pd.DataFrame({'Dates': date_range, 'DiscountFactors': discount_factors}) discount_factors = calc_discount_factors(self, t=t, discount_factors=discount_data.values(), date_range=date_range, bps_shift=-1/100/100) self.discount_factors_downshift = pd.DataFrame({'Dates': date_range, 'DiscountFactors': discount_factors}) self.discount_factors = self.discount_factors_base if historical_fixings is not None: self.historical_fixings = historical_fixings
def calc_discount_factors(self,t,discount_factors,date_range, bps_shift): # Construct the log-discount curve using cubic spline interpolation log_discount = CubicSpline(t,-np.log(list(discount_factors)) + bps_shift*t) # basis point shift to the zero curve return np.exp(-log_discount(pd.Series(sch.year_fraction(self.curve_date,date_range,self.day_count_basis))))