{"id":21554810,"url":"https://github.com/genedan/tmval","last_synced_at":"2025-04-10T09:27:34.587Z","repository":{"id":57476019,"uuid":"282549293","full_name":"genedan/TmVal","owner":"genedan","description":"Time Value of Money - a Python package for mathematical interest theory, annuity, and bond calculations.","archived":false,"fork":false,"pushed_at":"2021-06-08T01:54:55.000Z","size":441,"stargazers_count":32,"open_issues_count":37,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T08:21:16.738Z","etag":null,"topics":["actuarial","annuity","bonds","finance","financial-mathematics","insurance","interest-theory"],"latest_commit_sha":null,"homepage":"https://genedan.com/tmval/docs","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/genedan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-26T00:43:00.000Z","updated_at":"2025-03-14T02:02:18.000Z","dependencies_parsed_at":"2022-09-07T17:13:04.174Z","dependency_job_id":null,"html_url":"https://github.com/genedan/TmVal","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/genedan%2FTmVal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/genedan%2FTmVal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/genedan%2FTmVal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/genedan%2FTmVal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/genedan","download_url":"https://codeload.github.com/genedan/TmVal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248191024,"owners_count":21062406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actuarial","annuity","bonds","finance","financial-mathematics","insurance","interest-theory"],"created_at":"2024-11-24T07:16:12.608Z","updated_at":"2025-04-10T09:27:34.555Z","avatar_url":"https://github.com/genedan.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TmVal\n[![PyPI version](https://badge.fury.io/py/tmval.svg)](https://badge.fury.io/py/tmval)\n\nTime Value of Money\n\n## Introduction\n[Documentation](https://genedan.com/tmval/docs) | [Development Blog](https://genedan.com) | [PyPI](https://pypi.org/project/tmval/)\n\nTmVal is a package that provides tools for the valuation of various financial instruments (annuities, bonds).\n\nIt can be used to study for Actuarial Exam FM, and (hopefully) used on the job for projects where time value of money is relevant.\n\n## Installation\n\n```\npip install tmval\n```\n\nor\n\n```\ngit clone https://github.com/genedan/TmVal\ncd TmVal\npython3 -m setup sdist bdist_wheel\ncd dist\nsudo pip3 install tmval*\n```\n\n## Feature Highlights\n\n-   TmVal supports growth patterns that are more complex than compound\n    interest. In addition to supporting simple, compound, and nominal\n    interest, TmVal handles growth patterns that may be of theoretical\n    interest to actuaries, such as continuously compounded rates (Force\n    of Interest), polynomial growth, and arbitrary amount and\n    accumulation functions.\n    \n-   TmVal provides equations of value computations for core financial\ninstruments in actuarial science, such as annuities, loans, and\narbitrary cash flow streams. As development is still in the alpha\nstage, the types of investments TmVal supports is rapidly expanding.\nI expect the package to soon offer classes for bonds, stocks, and\noptions.\n    \n-   TmVal's classes are intended to correspond closely to symbols used\nin actuarial notation. Well-known symbols encountered by actuaries are supported. Refer to the\n[Notation Guide](https://genedan.com/tmval/docs/notation.html) in this documentation\nto see the available symbols.\n\n### Amount and Accumulation Functions\n\nTmVal supports the core growth functions of mathematical interest\ntheory, the [amount](https://genedan.com/tmval/docs/usage/growth/amount.html) and [accumulation](https://genedan.com/tmval/docs/usage/growth/ccumulation.html) functions, implemented via the\n[Amount](https://genedan.com/tmval/docs/api_ref/amount/index.html) and\n[Accumulation](https://genedan.com/tmval/docs/api_ref/amount/index.html) classes. These classes support all sorts of growth patterns, from simple and compound interest to more complex cases such as tiered investment accounts and polynomial growth.\n\nFor instance, suppose we have the tiered investment account with\nannually compounded interest rates:\n\nRequired Minimum Balance | Interest Rate \n-------------------------|----------------\n0|1%\n10,000|2%\n20,000| 3%\n\nIf we invest 18,000 today, to what value does it grow after 10 years?\n\n```python\nfrom tmval import Accumulation\n\ndef f(t):\n    return .05 * (t **2) + .05 * t + 1\n\n\nmy_acc = Accumulation(gr=f)\n\nprint(my_acc.val(5))\n2.5\n```\n\nIf we were to invest 5000 today, how long would it take to reach 2% and\n3% interest, assuming no future contributions?\n\n```python\nprint(tb.get_jump_times(k=5000))\n[69.66071689357483, 104.66350567472134]\n```\nIt will take almost 70 years to reach 2%, and about 105 years to reach\n3%. That\\'s a long time!\n\n### Interest Rate Conversions\n\nInterest rates are represented by a core data type in TmVal, the\n[Rate](file:///home/ubuntu/TmVal/docs/_build/html/api_ref/rate/index.html) class. This custom data type offers a convenient way to perform computations with a variety of interest rate patterns as well as conversions between them. The main patterns supported by the [Rate](file:///home/ubuntu/TmVal/docs/_build/html/api_ref/rate/index.html) class\nare:\n\n1.  Effective Interest\n2.  Effective Discount\n3.  Nominal Interest\n4.  Nominal Discount\n5.  Force of Interest\n6.  Simple Interest\n7.  Simple Discount\n\nThe relationships between compound interest rates can be represented\nwith the following expression:\n\n![interest conversion](https://raw.githubusercontent.com/genedan/TmVal/master/docs/readme_gh/interest_conversion.svg)\n\nSince there are so many varieties of rates, as well as relationships\nbetween them, an actuary would have to write over twenty conversion\nfunctions to handle the full spectrum of interest rates if they weren't\nusing a package like TmVal. The good news is that TmVal handles all\nthese conversions with a single method,\n[Rate.convert_rate](https://genedan.com/tmval/docs/api_ref/rate/convert_rate.html).\n\nFor example, if we needed to convert 5% rate compounded annually to a\nnominal discount rate convertible monthly, we could do the following:\n\n```python\nfrom tmval import Rate\n\ni = Rate(.05)\n\nnom_d = i.convert_rate(\n    pattern=\"Nominal Discount\",\n    freq=12\n)\n\nprint(nom_d)\nPattern: Nominal Discount\nRate: 0.048691111787194874\nCompounding Frequency: 12 times per year\n```\n\nFurthermore, we can demonstrate a conversion to nominal interest\ncompounded quarterly, and then to δ, the force of interest, and\nthen back to compound annual effective interest:\n\n```python\nnom_i = nom_d.convert_rate(\n    pattern=\"Nominal Interest\",\n    freq=4\n)\n\nprint(nom_i)\nPattern: Nominal Interest\nRate: 0.04908893771615652\nCompounding Frequency: 4 times per year\n\ndelta = nom_i.convert_rate(\n    pattern=\"Force of Interest\"\n)\n\nprint(delta)\nPattern: Force of Interest\nRate: 0.04879016416943141\n\ni2 = delta.convert_rate(\n    pattern=\"Effective Interest\",\n    interval=1\n)\n\nprint(i2)\nPattern: Effective Interest\nRate: 0.04999999999999938\nUnit of time: 1 year\n```\n\nFor more details, see [The Rate Class, Revisited](https://genedan.com/tmval/docs/usage/growth/rate_revisit.html) of the [Usage Tutorial](https://genedan.com/tmval/docs/usage/index.html).\n\n### Equations of Value\n\nTmVal can solve for the time τ equation of value for common\nfinancial instruments such as annuities and loans, as well as for\narbitrary cash flows. This is done via the [Payments](https://genedan.com/tmval/docs/api_ref/payments/index.html) class:\n\n![equation of value](https://raw.githubusercontent.com/genedan/TmVal/master/docs/readme_gh/eq_val.svg)\n\nFor example, we can solve for the internal rate of return of an\ninvestment of 10,000 at time 0 which returns 5,000 at time 1 and 6,000\nat time 2:\n\n```python\nfrom tmval import Payments\n\npmts = Payments(\n    amounts=[-10000, 5000, 6000],\n    times=[0, 1, 2]\n)\n\n# internal rate of return\nprint(pmts.irr())\n[0.0639410298049854, -1.5639410298049854]\n```\n\nWe can also use the [Payments](https://genedan.com/tmval/docs/api_ref/payments/index.html) class to\nfind the time-weighted yield:\n\n![time weighted yield](https://raw.githubusercontent.com/genedan/TmVal/master/docs/readme_gh/tw_yield.svg)\n\nwhere\n\n![time weighted factor](https://raw.githubusercontent.com/genedan/TmVal/master/docs/readme_gh/tw_factor.svg)\n\nSuppose we deposit 100,000 in a bank account at time 0. It grows to\n105,000 at time 1, and we immediately deposit an additional 5,000. It\nthen grows to 115,000 at time 2. The time-weighted yield is:\n\n```python\npmts = Payments(\n   amounts=[100000, 5000],\n   times=[0, 1]\n)\n\ni = pmts.time_weighted_yield(\n   balance_times=[0, 1, 2],\n   balance_amounts=[100000, 105000, 115000],\n   annual=True\n)\n\n# time-weighted yield\nprint(i)\nPattern: Effective Interest\nRate: 0.0477248077273309\nUnit of time: 1 year\n```\n\n### Annuities\n\nAnnuities are one of the core financial instruments underlying life\ninsurance products. TmVal provides support for many kinds of annuities\nvia its [Annuity](https://genedan.com/tmval/docs/api_ref/annuity/index.html#tmval.annuity.Annuity) class, such as:\n\n1.  Annuity-immediate\n2.  Annuity-due\n3.  Perpetuity-immediate\n4.  Perpetuity-due\n5.  Arithmetically increasing annuity-immediate\n6.  Arithmetically increasing annuity-due\n7.  Arithmetically increasing perpetuity-immediate\n8.  Arithmetically increasing perpetuity-due\n9.  Geometrically increasing annuity-immediate\n10. Geometrically increasing annuity-due\n11. Geometrically increasing perpetuity-immediate\n12. Geometrically increasing perpetuity-due\n13. Level annuity-immediate with payments more frequent than each\n    interest period\n14. Continuously-paying annuity\n\n... and many more. To see what other symbols are supported, consult the\n[Notation Guide](https://genedan.com/tmval/docs/notation.html).\n\nUnlike other packages, which tend to use functions to represent the\ndifferent types of annuities, TmVal represents annuities as a class,\nwhich gives it access to several methods that can be performed on the\nannuity, such as equations of value. So rather than simply returning a\nfloat value via a function, TmVal expands the manipulations that can be\ndone with an annuity. My aim is to allow the\n[Annuity](https://genedan.com/tmval/docs/api_ref/annuity/index.html#tmval.annuity.Annuity) class to serve as a base\nclass for or be embedded in more complex insurance products.\n\nWe can perform simple calculations, such as finding the present value of\na basic annuity-immediate with a five year term and a compound interest rate of 5%:\n\n```python\nfrom tmval import Annuity\n\nprint(Annuity(gr=.05, n=5).pv())\n4.329476670630819\n```\n\nTo more complex ones, such as the accumulated value of an arithmetically\nincreasing annuity-due with a starting payment of 5,000, and subsequent payments of 100 over a 5-year term, at 5% compound interest:\n```python\nann = Annuity(\n    amount=5000,\n    gr=.05,\n    n=5,\n    aprog=100,\n    imd='due'\n)\n\nprint(ann.sv())\n30113.389687500014\n```\n\n### Amortization\n\n\nTmVal's Loan class has methods for\nobtaining information that we might want about loans, such as\namortization schedules and outstanding loan balances.\n\nThe output for several TmVal\\'s classes are intended to be compatible\nwith [Pandas](https://pandas.pydata.org), a popular data analysis\nlibrary. The output for the Loan class's\namortization method is one such\nexample.\n\nFor example, suppose we were to obtain a 2-year loan of 50,000, to be\npaid back with monthly payments made at the end of each month. If the\ninterest rate were 4% convertible quarterly, what is the amortization\nschedule?\n\n```python\nimport pandas as pd\n\nfrom tmval import Loan, Rate\n\ngr = Rate(\n    rate=.04,\n    pattern=\"Nominal Interest\",\n    freq=4\n)\n\nmy_loan = Loan(\n    amt=50000,\n    period=1/12,\n    term=2,\n    gr=gr,\n    cents=True\n)\n\namort = pd.DataFrame(my_loan.amortization())\n\nprint(amort)\n    time  payment_amt  interest_paid  principal_paid  remaining_balance\n0   0.00          NaN            NaN             NaN           50000.00\n1   0.08      2170.96         166.11         2004.85           47995.15\n2   0.17      2170.96         159.45         2011.51           45983.65\n3   0.25      2170.96         152.77         2018.19           43965.46\n4   0.33      2170.96         146.07         2024.89           41940.56\n5   0.42      2170.96         139.34         2031.62           39908.94\n6   0.50      2170.96         132.59         2038.37           37870.57\n7   0.58      2170.96         125.82         2045.14           35825.43\n8   0.67      2170.96         119.02         2051.94           33773.49\n9   0.75      2170.96         112.21         2058.75           31714.74\n10  0.83      2170.96         105.37         2065.59           29649.14\n11  0.92      2170.96          98.50         2072.46           27576.68\n12  1.00      2170.96          91.62         2079.34           25497.34\n13  1.08      2170.96          84.71         2086.25           23411.09\n14  1.17      2170.96          77.78         2093.18           21317.91\n15  1.25      2170.96          70.82         2100.14           19217.77\n16  1.33      2170.96          63.85         2107.11           17110.66\n17  1.42      2170.96          56.85         2114.11           14996.55\n18  1.50      2170.96          49.82         2121.14           12875.41\n19  1.58      2170.96          42.78         2128.18           10747.22\n20  1.67      2170.96          35.71         2135.25            8611.97\n21  1.75      2170.96          28.61         2142.35            6469.62\n22  1.83      2170.96          21.49         2149.47            4320.16\n23  1.92      2170.96          14.35         2156.61            2163.55\n24  2.00      2170.74           7.19         2163.55              -0.00\n\n```\n\nUsing the Loan class's\nolb_r method, we can calculate the\noutstanding loan balance at any time, such as after 1 year, using the\n[retrospective method](https://genedan.com/tmval/docs/usage/loan/retrospective.html#outstanding-loan-balance-retrospective-method):\n\n![olb retrospective](https://raw.githubusercontent.com/genedan/TmVal/master/docs/readme_gh/olb_r.svg)\n\n```python\nprint(my_loan.olb_r(t=1))\n25497.34126843426\n```\n\nNow, what if we choose to overpay during the first two months, with\npayments of 3,000 each, and then returning to normal payments? What is\nthe outstanding loan balance after 1 year?\n\n```python\npmts = Payments(\n    amounts=[3000] * 2 + [2170.06] * 10,\n    times=[(x + 1) / 12 for x in range(12)]\n)\n\nprint(my_loan.olb_r(t=1, payments=pmts))\n23789.6328174795\n```\n\n## Development Status\n\nTmVal is currently in the alpha stage of development. In the coming\nweeks, I expect to add many more features, such as:\n\n1.  Bonds\n2.  Stocks\n3.  Options\n4.  Immunization\n\nI anticipate declaring the project to be in beta stage once I\\'ve\nincorporated all of the main concepts on the syllabus of the SOA\\'s\nfinancial mathematics exam. The beta stage of the project will involve\nthe construction of a testing suite to insure the accuracy of the\ncomputations in preparation for commercial use.\n\n## Further Reading\n\n\nGo ahead and give TmVal a try! The next section is the\n[Installation and Quickstart](https://genedan.com/tmval/docs/quickstart.html#installation-and-quickstart) followed by\nthe [Usage Tutorial](https://genedan.com/tmval/docs/usage/index.html#usage-tutorial). For technical\ndocumentation, consult the [API Reference](https://genedan.com/tmval/docs/api_ref/index.html#api-reference), which links to the source code of the project.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgenedan%2Ftmval","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgenedan%2Ftmval","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgenedan%2Ftmval/lists"}