diff --git a/financepy/__init__.py b/financepy/__init__.py index 33c57b03..aecdb21a 100644 --- a/financepy/__init__.py +++ b/financepy/__init__.py @@ -1,7 +1,7 @@ cr = "\n" s = "####################################################################" + cr -s += "# FINANCEPY BETA Version " + str('0.350') + " - This build: 30 Apr 2024 at 22:35 #" + cr +s += "# FINANCEPY BETA Version " + str('0.350') + " - This build: 01 May 2024 at 11:41 #" + cr s += "# This software is distributed FREE AND WITHOUT ANY WARRANTY #" + cr s += "# Report bugs as issues at https://github.com/domokane/FinancePy #" + cr s += "####################################################################" diff --git a/financepy/market/volatility/equity_vol_surface.py b/financepy/market/volatility/equity_vol_surface.py index 4c092d8d..654d3062 100644 --- a/financepy/market/volatility/equity_vol_surface.py +++ b/financepy/market/volatility/equity_vol_surface.py @@ -453,7 +453,7 @@ def vol_from_strike_date(self, K, expiry_dt): ############################################################################### - def vol_from_delta_dt(self, call_delta, expiry_dt, delta_method=None): + def vol_from_delta_date(self, call_delta, expiry_dt, delta_method=None): """ Interpolates the Black-Scholes volatility from the volatility surface given a call option delta and expiry date. Linear interpolation is done in variance space. The smile strikes at bracketed dates are diff --git a/financepy/market/volatility/swaption_vol_surface.py b/financepy/market/volatility/swaption_vol_surface.py index 5d43be03..714a4856 100644 --- a/financepy/market/volatility/swaption_vol_surface.py +++ b/financepy/market/volatility/swaption_vol_surface.py @@ -604,7 +604,7 @@ def vol_from_strike_dt(self, K, expiry_dt): ############################################################################### - # def vol_from_delta_dt(self, call_delta, expiry_dt, + # def vol_from_delta_date(self, call_delta, expiry_dt, # delta_method = None): # """ Interpolates the Black-Scholes volatility from the volatility # surface given a call option delta and expiry date. Linear interpolation diff --git a/financepy/products/bonds/bond_annuity.py b/financepy/products/bonds/bond_annuity.py index e5522b4d..ba29bd78 100644 --- a/financepy/products/bonds/bond_annuity.py +++ b/financepy/products/bonds/bond_annuity.py @@ -49,7 +49,7 @@ def __init__(self, self.cpn_dts = [] self.settle_dt = Date(1, 1, 1900) - self.accrued_int= None + self.accrued_int = None self.accrued_days = 0.0 self.alpha = 0.0 @@ -154,9 +154,11 @@ def accrued_interest(self, self.alpha = 1.0 - acc_factor * self.freq - self.accrued_int= acc_factor * face * self.cpn + self.accrual_factor = acc_factor + self.accrued_int = acc_factor * face * self.cpn self.accrued_days = num - return self.accrued_interest + + return self.accrued_int ########################################################################### diff --git a/financepy/products/bonds/bond_frn.py b/financepy/products/bonds/bond_frn.py index c47ce9b8..1da432f6 100644 --- a/financepy/products/bonds/bond_frn.py +++ b/financepy/products/bonds/bond_frn.py @@ -71,6 +71,7 @@ def __init__(self, self.accrued = None self.accrued_days = 0.0 self.accrual_factor = 0.0 + self.accrued_int = 0.0 self.cpn_dts = [] self.flow_amounts = [] @@ -436,6 +437,9 @@ def accrued_interest(self, self.alpha = 1.0 - acc_factor * self.freq self.accrual_factor = acc_factor self.accrued_days = num + self.accrued_int = acc_factor * next_cpn * 1.0 + + return self.accrued_int ########################################################################### diff --git a/notebooks/finutils/FINSCHEDULE_ScheduleGenerationTestCases.ipynb b/notebooks/finutils/FINSCHEDULE_ScheduleGenerationTestCases.ipynb index c06aa475..6f4e1e30 100644 --- a/notebooks/finutils/FINSCHEDULE_ScheduleGenerationTestCases.ipynb +++ b/notebooks/finutils/FINSCHEDULE_ScheduleGenerationTestCases.ipynb @@ -112,7 +112,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -168,7 +168,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -260,7 +260,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -339,7 +339,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -408,7 +408,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -484,7 +484,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -526,7 +526,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -579,7 +579,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { @@ -625,7 +625,7 @@ "schedule = Schedule(effective_dt, termination_dt, freq_type, cal_type, \n", " bd_type, dg_type, adjust_termination_dt, end_of_month_flag)\n", "\n", - "schedule._adjusted_dts" + "schedule.adjusted_dts" ] }, { diff --git a/tests/test_FinBondAnnuity.py b/tests/test_FinBondAnnuity.py index ba1b493c..4c0eb538 100644 --- a/tests/test_FinBondAnnuity.py +++ b/tests/test_FinBondAnnuity.py @@ -2,6 +2,9 @@ # Copyright (C) 2018, 2019, 2020 Dominic O'Kane ############################################################################### +import sys +sys.path.append("..") + from financepy.utils.calendar import DateGenRuleTypes from financepy.utils.calendar import BusDayAdjustTypes from financepy.utils.day_count import DayCountTypes @@ -188,3 +191,5 @@ def test_ForwardGenWithLongEndStub_BondAnnuity(): assert round(annuity.flow_amounts[-1]) == 25417.0 assert annuity.accrued_interest(settle_dt, face) == 0.0 + +test_SemiAnnual_BondAnnuity() diff --git a/tests/test_FinBondFRN.py b/tests/test_FinBondFRN.py index eff5b072..ec500cf4 100644 --- a/tests/test_FinBondFRN.py +++ b/tests/test_FinBondFRN.py @@ -219,3 +219,5 @@ def test_bond_frn_2(): dm) assert round(modified_duration, 4) == 6.0480 + +test_bond_frn_1() diff --git a/tests/test_FinBondYieldCurve.py b/tests/test_FinBondYieldCurve.py index 1e4d1e00..a7bf7964 100644 --- a/tests/test_FinBondYieldCurve.py +++ b/tests/test_FinBondYieldCurve.py @@ -44,7 +44,7 @@ def test_poly(): curveFitMethod = CurveFitPolynomial(5) fitted_curve = BondYieldCurve(settlement, bonds, ylds, curveFitMethod) - coeffs = fitted_curve._curve_fit._coeffs + coeffs = fitted_curve.curve_fit.coeffs assert round(coeffs[0] * 1e9, 4) == -1.4477 assert round(coeffs[1] * 1e7, 4) == 1.7840 assert round(coeffs[2] * 1e6, 4) == -7.4147 @@ -57,22 +57,22 @@ def test_nelson_siegel(): curveFitMethod = CurveFitNelsonSiegel() fitted_curve = BondYieldCurve(settlement, bonds, ylds, curveFitMethod) - assert round(fitted_curve._curve_fit._beta_1, 3) == -0.094 - assert round(fitted_curve._curve_fit._beta_2, 3) == 0.092 - assert round(fitted_curve._curve_fit._beta_3, 3) == 0.259 - assert round(fitted_curve._curve_fit._tau, 1) == 35.8 + assert round(fitted_curve.curve_fit.beta_1, 3) == -0.094 + assert round(fitted_curve.curve_fit.beta_2, 3) == 0.092 + assert round(fitted_curve.curve_fit.beta_3, 3) == 0.259 + assert round(fitted_curve.curve_fit.tau, 1) == 35.8 def test_nelson_siegel_svensson(): curveFitMethod = CurveFitNelsonSiegelSvensson() fitted_curve = BondYieldCurve(settlement, bonds, ylds, curveFitMethod) - assert round(fitted_curve._curve_fit._beta_1, 4) == 0.0460 - assert round(fitted_curve._curve_fit._beta_2, 4) == -0.0433 - assert round(fitted_curve._curve_fit._beta_3, 4) == -0.0523 - assert round(fitted_curve._curve_fit._beta_4, 4) == -0.0376 - assert round(fitted_curve._curve_fit._tau_1, 3) == 3.177 - assert round(fitted_curve._curve_fit._tau_2, 4) == 100.0000 + assert round(fitted_curve.curve_fit.beta_1, 4) == 0.0460 + assert round(fitted_curve.curve_fit.beta_2, 4) == -0.0433 + assert round(fitted_curve.curve_fit.beta_3, 4) == -0.0523 + assert round(fitted_curve.curve_fit.beta_4, 4) == -0.0376 + assert round(fitted_curve.curve_fit.tau_1, 3) == 3.177 + assert round(fitted_curve.curve_fit.tau_2, 4) == 100.0000 def test_interp_yield(): diff --git a/tests/test_FinCDSCurve.py b/tests/test_FinCDSCurve.py index 218755ac..0ab54204 100644 --- a/tests/test_FinCDSCurve.py +++ b/tests/test_FinCDSCurve.py @@ -52,12 +52,12 @@ def test_FinCDSCurve(): recovery_rate, use_cache=False) - assert round(issuer_curve.times[0], 4) == 0.0 - assert round(issuer_curve.times[5], 4) == 5.0027 - assert round(issuer_curve.times[9], 4) == 9.0055 - assert round(issuer_curve.values[0], 4) == 1.0 - assert round(issuer_curve.values[5], 4) == 0.9249 - assert round(issuer_curve.values[9], 4) == 0.8071 + assert round(issuer_curve._times[0], 4) == 0.0 + assert round(issuer_curve._times[5], 4) == 5.0027 + assert round(issuer_curve._times[9], 4) == 9.0055 + assert round(issuer_curve._values[0], 4) == 1.0 + assert round(issuer_curve._values[5], 4) == 0.9249 + assert round(issuer_curve._values[9], 4) == 0.8071 i = 1 maturity_dt = curve_dt.add_months(12 * i) diff --git a/tests/test_FinModelRatesBK.py b/tests/test_FinModelRatesBK.py index af611d41..41e97481 100644 --- a/tests/test_FinModelRatesBK.py +++ b/tests/test_FinModelRatesBK.py @@ -29,19 +29,19 @@ def test_BKExampleOne(): model = BKTree(sigma, a, num_time_steps) model.build_tree(t_mat, times, dfs) - assert [round(x, 4) for x in model._Q[2]] == \ + assert [round(x, 4) for x in model.Q[2]] == \ [0.0190, 0.2126, 0.5009, 0.2112, 0.0187] - assert [round(x, 4) for x in model._rt[2]] == \ + assert [round(x, 4) for x in model.rt[2]] == \ [0.0259, 0.0351, 0.0477, 0.0648, 0.0881] - assert [round(x, 4) for x in model._pu] == \ + assert [round(x, 4) for x in model.pu] == \ [0.0808, 0.2278, 0.1667, 0.1177, 0.8606] - assert [round(x, 4) for x in model._pm] == \ + assert [round(x, 4) for x in model.pm] == \ [0.0586, 0.6545, 0.6667, 0.6545, 0.0586] - assert [round(x, 4) for x in model._pd] == \ + assert [round(x, 4) for x in model.pd] == \ [0.8606, 0.1177, 0.1667, 0.2278, 0.0808] @@ -119,3 +119,5 @@ def test_BKExampleTwo(): assert round(v['call'], 4) == 0.6998 assert round(v['put'], 4) == 7.9605 + +test_BKExampleOne() diff --git a/tests/test_FinSchedule.py b/tests/test_FinSchedule.py index cd87a156..608f484c 100644 --- a/tests/test_FinSchedule.py +++ b/tests/test_FinSchedule.py @@ -86,7 +86,7 @@ def test_forward_frequencies(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 3 check_frequency(schedule) @@ -97,7 +97,7 @@ def test_forward_frequencies(): cal_type, bd_type, dg_type) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 5 check_frequency(schedule) @@ -109,7 +109,7 @@ def test_forward_frequencies(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 25 check_frequency(schedule) @@ -131,7 +131,7 @@ def test_backward_front_stub(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 9 check_frequency(schedule, start=1) @@ -151,7 +151,7 @@ def test_backward_front_stub(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 9 check_frequency(schedule, start=1) @@ -174,7 +174,7 @@ def test_forward_end_stub(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 5 check_frequency(schedule) @@ -192,7 +192,7 @@ def test_forward_end_stub(): cal_type, bd_type, dg_type) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 9 check_frequency(schedule) @@ -212,6 +212,6 @@ def test_forward_end_stub(): bd_type, dg_type, termination_date_adjust) - adjusted_dts = schedule._adjusted_dts + adjusted_dts = schedule.adjusted_dts assert len(adjusted_dts) == 5 check_frequency(schedule) diff --git a/tests_golden/TestFinEquityVolSurface.py b/tests_golden/TestFinEquityVolSurface.py index 3f6d09a2..b2cc0a18 100644 --- a/tests_golden/TestFinEquityVolSurface.py +++ b/tests_golden/TestFinEquityVolSurface.py @@ -95,7 +95,7 @@ def test_equity_vol_surface(verboseCalibration): test_cases.header("EXPIRY", "DELTA", "VOL", "STRIKE") for expiry_dt in expiry_dts: for delta in deltas: - vol = equitySurface.vol_from_delta_dt(delta, expiry_dt) + vol = equitySurface.vol_from_delta_date(delta, expiry_dt) test_cases.print(expiry_dt, delta, vol[0], vol[1]) ############################################################################### diff --git a/tests_golden/TestFinFXVolSurfacePlus.py b/tests_golden/TestFinFXVolSurfacePlus.py index 07c5fe10..30575120 100644 --- a/tests_golden/TestFinFXVolSurfacePlus.py +++ b/tests_golden/TestFinFXVolSurfacePlus.py @@ -280,7 +280,7 @@ def test_FinFXMktVolSurface3(verboseCalibration): for delta in deltas: volSmile = [] for dt in dates: - (vol, k) = fx_market_plus.vol_from_delta_dt(delta, dt) + (vol, k) = fx_market_plus.vol_from_delta_date(delta, dt) volSmile.append(vol*100.0) print(delta, k, dt, vol*100.0) @@ -375,7 +375,7 @@ def test_FinFXMktVolSurface4(verboseCalibration): for delta in deltas: volSmile = [] for dt in dates: - (vol, k) = fx_market_plus.vol_from_delta_dt(delta, dt) + (vol, k) = fx_market_plus.vol_from_delta_date(delta, dt) volSmile.append(vol*100.0) print(delta, k, dt, vol*100.0) diff --git a/tests_golden/TestFinSchedule.py b/tests_golden/TestFinSchedule.py index 8621f6ac..e311c68e 100644 --- a/tests_golden/TestFinSchedule.py +++ b/tests_golden/TestFinSchedule.py @@ -310,7 +310,7 @@ def test_FinSchedule(): DateGenRuleTypes.BACKWARD) # print(schedule) -# print(schedule._adjusted_dts) +# print(schedule.adjusted_dts) ############################################################################### @@ -407,8 +407,8 @@ def test_FinScheduleAlignmentLeapYearEOM(): adjust_termination_dt, eomFlag) -# print(sched1._adjusted_dts) -# print(sched2._adjusted_dts[:len(sched1._adjusted_dts)]) +# print(sched1.adjusted_dts) +# print(sched2.adjusted_dts[:len(sched1.adjusted_dts)]) compare = ( sched1.adjusted_dts[-1] == sched2.adjusted_dts[len(sched1.adjusted_dts)-1]) @@ -453,8 +453,8 @@ def test_FinScheduleAlignmentLeapYearNotEOM(): adjust_termination_dt, eomFlag) -# print(sched1._adjusted_dts) -# print(sched2._adjusted_dts[:len(sched1._adjusted_dts)]) +# print(sched1.adjusted_dts) +# print(sched2.adjusted_dts[:len(sched1.adjusted_dts)]) compare = ( sched1.adjusted_dts[-1] == sched2.adjusted_dts[len(sched1.adjusted_dts)-1])