domokane / FinancePy

A Python Finance Library that focuses on the pricing and risk-management of Financial Derivatives, including fixed-income, equity, FX and credit derivatives.
GNU General Public License v3.0
2.16k stars 322 forks source link

Support for Zero-Coupon Bond #140

Closed DominicHong closed 2 years ago

DominicHong commented 2 years ago

I'd like to test a zero-coupon bond. I set the freq_type=FrequencyTypes.SIMPLE. It throwed an ZeroDivisionError:

        calendar = Calendar(self._calendar_type)
        frequency = annual_frequency(self._freq_type)
>     num_months = int(12 / frequency)
financepy\utils\schedule.py:135: ZeroDivisionError

How to create a zero-coupon bond?

domokane commented 2 years ago

Can you give me all of the code you used ?

DominicHong commented 2 years ago
class TestBond:
    @pytest.fixture(scope='class')
    def global_data(self):
        # A 3 months treasure with 0 coupon per year.
        bill = Bond(
            issue_date=Date(25, 7, 2022),
            maturity_date=Date(24, 10, 2022),
            coupon=0,
            freq_type=FrequencyTypes.SIMPLE,
            accrual_type=DayCountTypes.ACT_ACT_ICMA
        )

        settlement_date = Date(8, 8, 2022)
        return {
                'bill': bill,
                'date': settlement_date
        }

    def test_yield_to_maturity_no_coupon(self, global_data):
        bond = global_data['bill']
        assess_date = global_data['date']
        clean_price = 99.7056
        assert bond.yield_to_maturity(assess_date, clean_price, YTMCalcType.US_STREET) * 100 == \
               pytest.approx(1.3998)

If I change the freq_type=FrequencyTypes.MONTHLY, the code ran well. The resulted ytm was close but still not precise. If freq_type=FrequencyTypes.ANNUAL, the ytm was far away from the correct answer(1.3998)

domokane commented 2 years ago

Hi - this has been fixed. I added your test

https://github.com/domokane/FinancePy/blob/master/tests_golden/TestFinBondZeroCoupon.py

You will need to build it yourself or wait until the weekend and I will push a new version of financepy to PYPI.

DominicHong commented 2 years ago

Thank you for your quick fix. It seems to me that it would be better to use the ACT_ACT_ISDA convention for Zero Coupon Bond, in case that the period crosses a leap year and a non-leap-year. What's your opinion? Do you mind if I change the DayCountTypes.ZERO algorithm in year_frac() to ACT_ACT_ISDA ?