python - range() 用于计算带间隔的余额
问题描述
我的输出如下:
ISIN DatesforAccrual Days Accrual@Coupon Balance AccrualYield
0 Test1 October 22nd, 2019 0 0.00 4,875,358.20 nan
1 Test1 February 8th, 2020 106 83,638.42 4,819,281.81 27,562.03
2 Test1 August 8th, 2020 180 142,027.50 4,723,519.41 46,265.11
3 Test1 February 8th, 2021 180 142,027.50 4,626,837.70 45,345.79
4 Test1 June 19th, 2021 131 103,364.46 4,555,799.41 32,326.17
5 Test2 July 31st, 2020 0 0.00 4,555,799.41 0.00
6 Test2 September 21st, 2020 51 12,661.46 4,555,529.73 12,391.77
7 Test2 March 21st, 2021 180 44,687.50 4,554,575.32 43,733.09
8 Test2 June 19th, 2021 88 21,847.22 4,554,104.23 21,376.14
9 Test3 January 1st, 2021 0 0.00 4,554,104.23 0.00
10 Test3 April 3rd, 2021 92 8,025.98 4,568,423.73 22,345.47
11 Test3 June 19th, 2021 76 6,630.16 4,580,310.92 18,517.34
代码如下
import QuantLib as ql
import pandas as pd
import numpy as np
import datetime
data = pd.read_excel (r'C:\Users\Avishen\Desktop\Python\BONDDATA.xlsx')
data['issuedate'] = data['issuedate'].dt.strftime('%d-%m-%Y')
data['maturitydate'] = data['maturitydate'].dt.strftime('%d-%m-%Y')
t_list = []
t1_list = []
t2_list = []
t3_list = []
t4_list = []
for _, row in data.iterrows():
today = ql.Date.todaysDate()
issueDate = ql.Date(row['issuedate'], '%d-%m-%Y')
maturityDate = ql.Date(row['maturitydate'], '%d-%m-%Y')
tenor = ql.Period(ql.Semiannual)
day_count = ql.Thirty360
coupon=(row['coupon'])
Tradeyield = (row['Tradeyield'])
Bond_Price = (row['Bond_Price'])
face_value=100
Nominal_Amount=(row['Nominal_Amount'])
calendar = ql.UnitedStates()
businessConvention = ql.Unadjusted
dateGeneration = ql.DateGeneration.Backward
monthEnd = False
schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, ql.Unadjusted,ql.Unadjusted, dateGeneration, monthEnd)
DatesinCoupon = list(schedule)
Balance = 100
DatesinCouponfiltered = list(filter(lambda score: score <today, DatesinCoupon))
DatesforAccrual = DatesinCouponfiltered + [today]
NoofDaysinAccrual=[0]+[int(ql.Thirty360().yearFraction(start, end)*360) for start, end in zip(DatesforAccrual[:-1], DatesforAccrual[1:])]
Calculate Accrued interest in each coupon period
if day_count == ql.Thirty360:
DC = (360)
elif day_count == ql.Thirty365:
DC = (365)
else:
DC = (366)
AccruedCoupon = [(i * (coupon))/(DC) *face_value *Nominal_Amount/100 for i in NoofDaysinAccrual]
t_list.append(row['ISIN'])
t1_list.append(DatesforAccrual)
t2_list.append(NoofDaysinAccrual)
t3_list.append(AccruedCoupon)
t4_list.append(Nominal_Amount*Bond_Price/100)
new_df = pd.DataFrame({'ISIN':t_list, 'DatesforAccrual':t1_list,'Days':t2_list,'Accrual@Coupon':t3_list})
s = new_df.apply(pd.Series.explode).reset_index(drop=True)
s.loc[s.drop_duplicates('ISIN').index, "Balance"] = (t4_list)
for i in range(1, len(s),1):
s.loc[i, 'AccrualYield'] = s.loc[i-1,'Balance']*s.loc[i,'Days']* Tradeyield / DC
s.loc[i , 'Balance'] = s.loc[i-1,'Balance']-s.loc[i,'Accrual@Coupon']+ s.loc[i,'AccrualYield']
excel中的值如下
ISIN issuedate maturitydate coupon Tradeyield Bond_Price MarketPrice Nominal_Amount
Test1 22-Oct-19 08-Aug-23 6.53% 2.37% 112.0772 110.787 4,350,000
Test2 31-Jul-20 21-Mar-25 3.25% 3.30% 111.235 109.253 2,750,000
Test3 01-Jan-21 03-Apr-24 2.51% 1.92% 109.4521 113.4561 1,251,235
我希望天平在第 4 行停止计算,并在第 6 行重新开始,然后在第 8 行再次停止并在第 10 行重新开始,然后在第 11 行停止。这将根据ISIN
df 中的再次继续。我怎样才能做到这一点?
扩展输出:
ISIN DatesforAccrual Days Accrual@Coupon AccrualYield Balance
0 Test1 October 22nd, 2019 0 0 4,875,358.20
1 Test1 February 8th, 2020 106 83,638.42 34,021.87 4,825,741.65
2 Test1 August 8th, 2020 180 142,027.50 57,185.04 4,740,899.19
3 Test1 February 8th, 2021 180 142,027.50 56,179.66 4,655,051.35
4 Test1 June 19th, 2021 131 103,364.46 40,145.94 4,591,832.83
5 Test2 July 31st, 2020 0 0 3,058,962.50
6 Test2 September 21st, 2020 51 12,661.46 14,300.65 3,060,601.69
7 Test2 March 21st, 2021 180 44,687.50 50,499.93 3,066,414.12
8 Test2 June 19th, 2021 88 21,847.22 24,735.74 3,069,302.64
9 Test3 January 1st, 2021 0 0 1,369,502.98
10 Test3 April 3rd, 2021 92 8,025.98 11,549.48 1,373,026.48
11 Test3 June 19th, 2021 76 6,630.16 9,565.42 1,375,961.74
解决方案
s.groupby('ISIN')
然后的想法是将其链接到.agg()
,.apply()
等等。
此外,要遍历数据帧的行,您通常不需要编写 for 循环并使用s.loc[i, colname]
. 使用.apply()
或.sum()
或其他操作。当您需要访问前一行(在该 ISIN 组中)时,请使用.shift(-1)
就像是:
s['AccrualYield'] = s.['Balance'].shift(-1) * s['NoofDaysinAccrual'] * Tradeyield / DC
如果您可以发布可重现的数据片段,那么我将尝试显示完整的表达式s['Balance']
推荐阅读
- amazon-web-services - 卓:我的账户会收到意外费用吗?
- java - 为什么导入字体会破坏代码的其他部分?
- html - 如何使 Navbar 和 Carousel 始终全屏结合
- javascript - IPFS 返回文件地址
- yii2 - 无法打开文件以读取 [filename.pdf] yii2 swiftmailer
- javascript - 如何在 FlatList 中的项目之间切换?
- django - 有没有办法通过 Django 模板在 if 条件中使用模型字段?
- python - 如何更快地裁剪出高振幅的音频部分
- c# - Add-Type 不支持字典初始化语法?
- java - 重构 if else 分支的最佳方法是什么