[paper_website]: https://www.newyorkfed.org/medialibrary/media/research/staff_reports/sr340.pdf
[inference_atribute]: https://github.com/gusamarante/pyacm/blob/ba641c14e450fc83d22db4ef5e60eadbd489b351/pyacm/acm.py#L203
# pyacm
Implementation of ["Pricing the Term Structure with Linear Regressions" from
Adrian, Crump and Moench (2013)][paper_website].
The `NominalACM` class prices the time series and cross-section of the term
structure of interest rates using a three-step linear regression approach.
Computations are fast, even with a large number of pricing factors. The object
carries all the relevant variables as atributes:
- The yield curve itself
- The excess returns from the synthetic zero coupon bonds
- The principal components of the curve used as princing factors
- Risk premium parameter estimates
- Yields fitted by the model
- Risk-neutral yields
- Term premium
- Historical in-sample expected returns
- Expected return loadings
- Hypothesis testing (Not sure if correct, more info observations below)
# Instalation
```bash
pip install pyacm
```
# Usage
```python
from pyacm import NominalACM
acm = NominalACM(
curve=yield_curve,
n_factors=5,
)
```
The tricky part of using this model is getting the correct data format. The
`yield_curve` dataframe in the expression above requires:
- Annualized log-yields for zero-coupon bonds
- Observations (index) must be in either monthly or daily frequency
- Maturities (columns) must be equally spaced in **monthly** frequency and start
at month 1. This means that you need to construct a bootstraped curve for every
date and interpolate it at fixed monthly maturities
- Whichever maturity you want to be the longest, your input data should have one
column more. For example, if you want term premium estimate up to the 10-year
yield (120 months), your input data should include maturities up to 121 months.
This is needed to properly compute the returns.
# Examples
The estimates for the US are available on the [NY FED website](https://www.newyorkfed.org/research/data_indicators/term-premia-tabs#/overview).
The jupyter notebook [`example_br`](https://github.com/gusamarante/pyacm/blob/main/example_br.ipynb)
contains an example application to the Brazilian DI futures curve that showcases all the available methods.
<p align="center">
<img src="https://raw.githubusercontent.com/gusamarante/pyacm/refs/heads/main/images/DI%20term%20premium.png" alt="DI Term Premium"/>
<img src="https://raw.githubusercontent.com/gusamarante/pyacm/refs/heads/main/images/DI%20observed%20vs%20risk%20neutral.png" alt="Observed VS Risk Neutral"/>
</p>
# Original Article
> Adrian, Tobias and Crump, Richard K. and Moench, Emanuel,
> Pricing the Term Structure with Linear Regressions (April 11, 2013).
> FRB of New York Staff Report No. 340,
> Available at SSRN: https://ssrn.com/abstract=1362586 or http://dx.doi.org/10.2139/ssrn.1362586
The version of the article that was published by the NY FED is not 100% explicit on how the data is being manipulated,
but I found an earlier version of the paper on SSRN where the authors go deeper into the details on how everything is being estimated:
- Data for zero yields uses monthly maturities starting from month 1
- All principal components and model parameters are estiamted with data resampled to a monthly frequency, averaging observations in each month
- To get daily / real-time estimates, the factor loadings estimated from the monthly frquency are used to transform the daily data
# Observations
I am not completely sure that computations in the [inferences attributes][inference_atribute]
are correct. If you find any mistakes, please open a pull request following the contributing
guidelines.
Raw data
{
"_id": null,
"home_page": null,
"name": "pyacm",
"maintainer": "Gustavo Amarante",
"docs_url": null,
"requires_python": null,
"maintainer_email": "developer@dsgepy.com",
"keywords": "asset pricing, yield curve, term premium",
"author": "Tobias Adrian, Richard K. Crump, Emanuel Moench",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/10/4c/9b7d30555b58407812622e836226c7f2eb375fb096fc6dc690d236dd2b23/pyacm-0.4.tar.gz",
"platform": null,
"description": "\n[paper_website]: https://www.newyorkfed.org/medialibrary/media/research/staff_reports/sr340.pdf\n[inference_atribute]: https://github.com/gusamarante/pyacm/blob/ba641c14e450fc83d22db4ef5e60eadbd489b351/pyacm/acm.py#L203\n\n# pyacm\nImplementation of [\"Pricing the Term Structure with Linear Regressions\" from \nAdrian, Crump and Moench (2013)][paper_website].\n\nThe `NominalACM` class prices the time series and cross-section of the term \nstructure of interest rates using a three-step linear regression approach.\nComputations are fast, even with a large number of pricing factors. The object \ncarries all the relevant variables as atributes:\n- The yield curve itself\n- The excess returns from the synthetic zero coupon bonds\n- The principal components of the curve used as princing factors\n- Risk premium parameter estimates\n- Yields fitted by the model\n- Risk-neutral yields\n- Term premium\n- Historical in-sample expected returns \n- Expected return loadings\n- Hypothesis testing (Not sure if correct, more info observations below)\n\n\n# Instalation\n```bash\npip install pyacm\n```\n\n# Usage\n```python\nfrom pyacm import NominalACM\n\nacm = NominalACM(\n curve=yield_curve,\n n_factors=5,\n)\n```\nThe tricky part of using this model is getting the correct data format. The \n`yield_curve` dataframe in the expression above requires:\n- Annualized log-yields for zero-coupon bonds\n- Observations (index) must be in either monthly or daily frequency\n- Maturities (columns) must be equally spaced in **monthly** frequency and start \nat month 1. This means that you need to construct a bootstraped curve for every \ndate and interpolate it at fixed monthly maturities\n- Whichever maturity you want to be the longest, your input data should have one\ncolumn more. For example, if you want term premium estimate up to the 10-year \nyield (120 months), your input data should include maturities up to 121 months. \nThis is needed to properly compute the returns.\n\n# Examples\n\nThe estimates for the US are available on the [NY FED website](https://www.newyorkfed.org/research/data_indicators/term-premia-tabs#/overview).\n\nThe jupyter notebook [`example_br`](https://github.com/gusamarante/pyacm/blob/main/example_br.ipynb) \ncontains an example application to the Brazilian DI futures curve that showcases all the available methods.\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/gusamarante/pyacm/refs/heads/main/images/DI%20term%20premium.png\" alt=\"DI Term Premium\"/>\n <img src=\"https://raw.githubusercontent.com/gusamarante/pyacm/refs/heads/main/images/DI%20observed%20vs%20risk%20neutral.png\" alt=\"Observed VS Risk Neutral\"/>\n</p>\n\n# Original Article\n> Adrian, Tobias and Crump, Richard K. and Moench, Emanuel, \n> Pricing the Term Structure with Linear Regressions (April 11, 2013). \n> FRB of New York Staff Report No. 340, \n> Available at SSRN: https://ssrn.com/abstract=1362586 or http://dx.doi.org/10.2139/ssrn.1362586\n\nThe version of the article that was published by the NY FED is not 100% explicit on how the data is being manipulated, \nbut I found an earlier version of the paper on SSRN where the authors go deeper into the details on how everything is being estimated:\n- Data for zero yields uses monthly maturities starting from month 1\n- All principal components and model parameters are estiamted with data resampled to a monthly frequency, averaging observations in each month\n- To get daily / real-time estimates, the factor loadings estimated from the monthly frquency are used to transform the daily data\n\n\n# Observations\nI am not completely sure that computations in the [inferences attributes][inference_atribute] \nare correct. If you find any mistakes, please open a pull request following the contributing \nguidelines.\n",
"bugtrack_url": null,
"license": null,
"summary": "ACM Term Premium",
"version": "0.4",
"project_urls": null,
"split_keywords": [
"asset pricing",
" yield curve",
" term premium"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f820f7834ffe5763229cfe1c289e512fc9b293e93e1067183b1033d2d9790212",
"md5": "53533440abc7a781cfe9e10d19a74092",
"sha256": "bcae171299f13cdc6a7e3a87b4362b6677833518365838c9828324f1d2c1ab1e"
},
"downloads": -1,
"filename": "pyacm-0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "53533440abc7a781cfe9e10d19a74092",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 8755,
"upload_time": "2024-12-08T12:06:39",
"upload_time_iso_8601": "2024-12-08T12:06:39.475348Z",
"url": "https://files.pythonhosted.org/packages/f8/20/f7834ffe5763229cfe1c289e512fc9b293e93e1067183b1033d2d9790212/pyacm-0.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "104c9b7d30555b58407812622e836226c7f2eb375fb096fc6dc690d236dd2b23",
"md5": "add96872f050936faaff9396c4ec4e7a",
"sha256": "569d4fffc599c8a1be4626cfaef02e593c769e3f3167ab327afe35c9de476f61"
},
"downloads": -1,
"filename": "pyacm-0.4.tar.gz",
"has_sig": false,
"md5_digest": "add96872f050936faaff9396c4ec4e7a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8184,
"upload_time": "2024-12-08T12:06:41",
"upload_time_iso_8601": "2024-12-08T12:06:41.361276Z",
"url": "https://files.pythonhosted.org/packages/10/4c/9b7d30555b58407812622e836226c7f2eb375fb096fc6dc690d236dd2b23/pyacm-0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-08 12:06:41",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "pyacm"
}