Skip to main content

A Python library for generating discounted cashflows.

Project description

Python library dcf

Codeship Read the Docs GitHub GitHub release PyPI Version PyPI - Python Version PyPI Downloads

A Python library for generating discounted cashflows (dcf). Typical banking business methods are provided like interpolation, compounding, discounting and fx.

Example Usage

>>> from dcf import ZeroRateCurve
>>> ZeroRateCurve([0, 2], [.03, .05]).get_zero_rate(0, 1)
0.04
>>> ZeroRateCurve([0, 2], [.03, .05]).get_discount_factor(0, 1)
0.9607894391523232

Or use datetime

>>> from datetime import date
>>> start = date(2013,1,1)
>>> mid = date(2014,1,1)
>>> end = date(2015,1,1)
>>> ZeroRateCurve([start, end], [.03, .05]).get_zero_rate(start, mid)
0.04
>>> ZeroRateCurve([start, end], [.03, .05]).get_discount_factor(start, mid)
0.9608157444936446

The framework works fine with native datetime but we recommend businessdate package for more convenient functionality to roll out date schedules.

>>> from businessdate import BusinessDate, BusinessSchedule
>>> today = BusinessDate(20201031)
>>> schedule = BusinessSchedule(today, today + "8q", step="1q")
>>> schedule
[BusinessDate(20201031), BusinessDate(20210131), BusinessDate(20210430), BusinessDate(20210731), BusinessDate(20211031), BusinessDate(20220131), BusinessDate(20220430), BusinessDate(20220731), BusinessDate(20221031)]

To build payment plans for, e.g. annuity loans, pick a plan function and generate an redemption amount list for paying back the loan notional amount.

>>> from dcf import annuity, outstanding
>>> number_of_payments = 8
>>> interest_rate = 0.02
>>> notional = 1000.
>>> plan = annuity(number_of_payments, amount=notional, fixed_rate=interest_rate)
>>> plan
[116.50979913376267, 118.83999511643792, 121.21679501876667, 123.64113091914203, 126.11395353752485, 128.63623260827535, 131.20895726044085, 133.83313640564967]
>>> sum(plan)
1000.0
>>> out = outstanding(plan, amount=notional)
>>> out
[1000.0, 883.4902008662373, 764.6502057497994, 643.4334107310327, 519.7922798118907, 393.6783262743659, 265.0420936660905, 133.83313640564967]
>>> compound = [o * interest_rate + p for o, p in zip(out, plan)]
>>> compound
[136.50979913376267, 136.50979913376267, 136.50979913376267, 136.50979913376267, 136.50979913376267, 136.50979913376267, 136.50979913376267, 136.50979913376267]

Putting all together and feeding the plan into a FixedCashFlowList and the list of outstanding into a RateCashflowList gives the legs of a loan.

>>> from businessdate import BusinessDate, BusinessSchedule
>>> from dcf import amortize, outstanding
>>> from dcf import FixedCashFlowList, RateCashFlowList

Again, build a date schedule.

>>> today = BusinessDate(20201031)
>>> schedule = BusinessSchedule(today, today + "8q", step="1q")
>>> start_date, payment_dates = schedule[0], schedule[1:]

Fixing the properties of the product and rolling out the payment plan and list of notional outstanding.

>>> number_of_payments = 8
>>> interest_rate = 0.01
>>> notional = 1000.
>>> plan = amortize(number_of_payments, amount=notional)
>>> out = outstanding(plan, amount=notional)

Finally, create for each leg a CashFlowList.

>>> principal = FixedCashFlowList([start_date], [-notional], origin=start_date)
>>> print(principal)
FixedCashFlowList([BusinessDate(20201031) ... BusinessDate(20201031)], [-1000.0 ... -1000.0], origin=BusinessDate(20201031))
>>> redemption = FixedCashFlowList(payment_dates, plan, origin=start_date)
>>> print(redemption)
FixedCashFlowList([BusinessDate(20210131) ... BusinessDate(20221031)], [125.0 ... 125.0], origin=BusinessDate(20201031))
>>> interest = RateCashFlowList(payment_dates, out, origin=start_date, fixed_rate=interest_rate)
>>> print(interest)
RateCashFlowList([BusinessDate(20210131) ... BusinessDate(20221031)], [1000.0 ... 125.0], origin=BusinessDate(20201031), day_count=day_count)

Add those legs to CashFlowLegList provides a smart container for valuation (get_present_value()).

>>> from dcf import CashFlowLegList, ZeroRateCurve, get_present_value
>>> loan = CashFlowLegList([principal, redemption, interest])
>>> curve = ZeroRateCurve([today, today + '2y'], [-.005, .01])
>>> get_present_value(cashflow_list=loan, discount_curve=curve, valuation_date=today)
4.935421637918779

Moreover, variable interest derived from float rates as given by a forward rate curve, e.g. a CashRateCurve, are possible, too.

>>> from dcf import CashRateCurve, RateCashFlowList
>>> from tabulate import tabulate
>>> fwd = CashRateCurve([today, today + '2y'], [-.005, .007])
>>> spread = .001
>>> float_interest = RateCashFlowList(payment_dates, out, origin=start_date, fixed_rate=spread, forward_curve=fwd, pay_offset='2b', fixing_offset='2b')
>>> print(tabulate(float_interest.table, headers='firstrow'))
  cashflow  pay date      notional  start date    end date      year fraction    fixed rate    forward rate  fixing date    tenor
----------  ----------  ----------  ------------  ----------  ---------------  ------------  --------------  -------------  -------
 -0.974675  20210131          1000  20201031      20210128           0.243669         0.001    -0.005        20201029       3M
 -0.554077  20210430           875  20210128      20210428           0.246407         0.001    -0.00356986   20210126       3M
 -0.205991  20210731           750  20210428      20210729           0.251882         0.001    -0.00209041   20210426       3M
  0.065699  20211031           625  20210729      20211028           0.249144         0.001    -0.000578082  20210727       3M
  0.238906  20220131           500  20211028      20220127           0.249144         0.001     0.000917808  20211026       3M
  0.318939  20220430           375  20220127      20220428           0.249144         0.001     0.0024137    20220125       3M
  0.305799  20220731           250  20220428      20220728           0.249144         0.001     0.00390959   20220426       3M
  0.199486  20221031           125  20220728      20221027           0.249144         0.001     0.00540548   20220726       3M
>>> get_present_value(cashflow_list=float_interest, discount_curve=curve, valuation_date=today)
-0.61960891965599

Install

The latest stable version can always be installed or updated via pip:

$ pip install dcf

Development Version

The latest development version can be installed directly from GitHub:

$ pip install --upgrade git+https://github.com/sonntagsgesicht/dcf.git

Contributions

Issues and Pull Requests are always welcome.

License

Code and documentation are available according to the Apache Software License (see LICENSE).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dcf-0.6.zip (53.7 kB view details)

Uploaded Source

File details

Details for the file dcf-0.6.zip.

File metadata

  • Download URL: dcf-0.6.zip
  • Upload date:
  • Size: 53.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.6.0 importlib_metadata/4.8.2 pkginfo/1.8.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for dcf-0.6.zip
Algorithm Hash digest
SHA256 49036c9d22afd20dd61863f1fb7ac752cc7fb1e33276400c341e173989568180
MD5 de4925d74398b8cc11a3ff64cca27921
BLAKE2b-256 16176b5f3d7ca05e4a498b49e9bfba39f2d386e4a9050499f7cb3527307b6511

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page