# portbt
**portbt** is a Python library designed to make backtesting a custom portfolio of assets easy and intuitive. With PortBT, you can test a range of rebalancing strategies and asset allocations using just a few lines of code.
## Features
- Simple and intuitive code
- Flexible rebalancing options
## Getting Started
To get started with PortBT, simply install the library using pip
```python
pip install portbt
```
Import it into your Python project. From there, you just have to create a *Portfolio* object with the asset prices to define your portfolio.
```python
import portbt as pbt
# sample from brazil, so decimal "," and sep ";"
prices = pd.read_csv('sample/prices.csv', sep=';', decimal=',')
prices.index = pd.to_datetime(prices.index) # index has to be datetime
prices[prices.columns] = prices[prices.columns].astype(float)
prices.name = 'prices'
prices.index.name = 'date'
print(prices)
```
Output
```
BBAS3 BOVA11 ITUB4 PETR4 SMAL11 VALE3
date
2008-11-28 5.848646 36.595901 6.496692 7.174176 23.760300 13.265061
2008-12-01 5.848646 34.744900 6.289404 6.580500 22.656500 12.286927
2008-12-02 5.828202 35.001598 6.447920 6.544737 22.606501 11.829182
2008-12-03 5.848646 35.293800 6.511325 6.905950 22.426001 11.983371
2008-12-04 5.971348 35.122101 6.567414 6.652028 22.636900 11.607532
... ... ... ... ... ... ...
2023-04-03 38.650002 98.300003 24.030001 24.490000 86.500000 80.309998
2023-04-04 39.290001 98.510002 24.510000 24.270000 87.000000 78.040001
2023-04-05 39.150002 97.629997 24.490000 24.350000 85.650002 76.889999
2023-04-06 39.020000 97.589996 24.410000 24.000000 85.879997 76.750000
2023-04-10 39.040001 98.660004 24.670000 24.510000 86.349998 78.230003
```
---
## Creating the portfolio and backtesting
```python
portfolio = pbt.Portfolio(prices)
backtest = portfolio.run_backtest(rebalance=False)
# backtest.prices -> prices for each asset, "raw data"
# backtest.values -> values for each asset (starting capital = 1)
# backtest.exposure -> exposure for each asset
# backtest.result -> backtest result, starting from 1
# backtest.all_dates -> all dates for the backtesting, if needed
# backtest.rebal_dates -> rebalace dates only
# example
print(backtest.exposure)
```
Output
```
BBAS3 BOVA11 ITUB4 PETR4 SMAL11 VALE3
date
2008-11-28 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667
2008-12-01 0.174991 0.166140 0.169408 0.160510 0.166862 0.162088
2008-12-02 0.174798 0.167769 0.174094 0.160021 0.166893 0.156424
2008-12-03 0.173115 0.166956 0.173505 0.166643 0.163393 0.156388
2008-12-04 0.177667 0.167009 0.175911 0.161351 0.165789 0.152272
... ... ... ... ... ... ...
2023-04-03 0.253178 0.102909 0.141708 0.130782 0.139475 0.231949
2023-04-04 0.257288 0.103096 0.144492 0.129566 0.140236 0.225321
2023-04-05 0.258185 0.102898 0.145396 0.130913 0.139037 0.223571
2023-04-06 0.258177 0.103195 0.145399 0.129457 0.139871 0.223901
2023-04-10 0.255589 0.103228 0.145400 0.130815 0.139155 0.225814
```
## Portfolio backtesting - main function
```
Portfolio.run_backtest() -> Backtest
Parameters:
- rebalance: bool (required)
If 'True', the backtest will rebalance itself.
- weights: str or dict, default 'ew'
If 'dict', than it is the weight for each asset (number between 0 and 1),
The sum can't be different than one.
Example:
asset_weights = {
'asset1': 0.3,
'asset2': 0.2,
'asset3': 0.5,
}
If str (has to be 'ew'), runs the backtest using equal weight for all
assets (1 / number of assets).
- rebal_freq: str, default '1M'
Rebalance frequency. Has the same valid inputs as pandas.DataFrame.resample()
function.
```
## TODO
- Performance metrics and visualizations
- Reports
- Yahoo Finance implementation
Raw data
{
"_id": null,
"home_page": "https://github.com/renanmoretto/portbt",
"name": "portbt",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.10,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "renanmoretto",
"author_email": "himynameisrenan@outlook.com",
"download_url": "https://files.pythonhosted.org/packages/f6/7b/d7f1aaa8335b081b69785234cd3dc0f693ba2074e34bdeabddf7d8b929a1/portbt-0.1.8.tar.gz",
"platform": null,
"description": "# portbt\n**portbt** is a Python library designed to make backtesting a custom portfolio of assets easy and intuitive. With PortBT, you can test a range of rebalancing strategies and asset allocations using just a few lines of code. \n\n## Features\n- Simple and intuitive code\n- Flexible rebalancing options\n\n## Getting Started\nTo get started with PortBT, simply install the library using pip\n```python\npip install portbt\n```\n Import it into your Python project. From there, you just have to create a *Portfolio* object with the asset prices to define your portfolio.\n ```python\nimport portbt as pbt\n\n# sample from brazil, so decimal \",\" and sep \";\"\nprices = pd.read_csv('sample/prices.csv', sep=';', decimal=',')\nprices.index = pd.to_datetime(prices.index) # index has to be datetime\nprices[prices.columns] = prices[prices.columns].astype(float)\nprices.name = 'prices'\nprices.index.name = 'date'\n\nprint(prices)\n```\nOutput\n```\n BBAS3 BOVA11 ITUB4 PETR4 SMAL11 VALE3\ndate \n2008-11-28 5.848646 36.595901 6.496692 7.174176 23.760300 13.265061\n2008-12-01 5.848646 34.744900 6.289404 6.580500 22.656500 12.286927\n2008-12-02 5.828202 35.001598 6.447920 6.544737 22.606501 11.829182\n2008-12-03 5.848646 35.293800 6.511325 6.905950 22.426001 11.983371\n2008-12-04 5.971348 35.122101 6.567414 6.652028 22.636900 11.607532\n... ... ... ... ... ... ...\n2023-04-03 38.650002 98.300003 24.030001 24.490000 86.500000 80.309998\n2023-04-04 39.290001 98.510002 24.510000 24.270000 87.000000 78.040001\n2023-04-05 39.150002 97.629997 24.490000 24.350000 85.650002 76.889999\n2023-04-06 39.020000 97.589996 24.410000 24.000000 85.879997 76.750000\n2023-04-10 39.040001 98.660004 24.670000 24.510000 86.349998 78.230003\n```\n---\n## Creating the portfolio and backtesting\n```python\nportfolio = pbt.Portfolio(prices)\n\nbacktest = portfolio.run_backtest(rebalance=False)\n\n# backtest.prices -> prices for each asset, \"raw data\"\n# backtest.values -> values for each asset (starting capital = 1)\n# backtest.exposure -> exposure for each asset\n# backtest.result -> backtest result, starting from 1\n# backtest.all_dates -> all dates for the backtesting, if needed\n# backtest.rebal_dates -> rebalace dates only\n\n# example\nprint(backtest.exposure)\n```\nOutput\n```\n BBAS3 BOVA11 ITUB4 PETR4 SMAL11 VALE3\ndate \n2008-11-28 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667\n2008-12-01 0.174991 0.166140 0.169408 0.160510 0.166862 0.162088\n2008-12-02 0.174798 0.167769 0.174094 0.160021 0.166893 0.156424\n2008-12-03 0.173115 0.166956 0.173505 0.166643 0.163393 0.156388\n2008-12-04 0.177667 0.167009 0.175911 0.161351 0.165789 0.152272\n... ... ... ... ... ... ...\n2023-04-03 0.253178 0.102909 0.141708 0.130782 0.139475 0.231949\n2023-04-04 0.257288 0.103096 0.144492 0.129566 0.140236 0.225321\n2023-04-05 0.258185 0.102898 0.145396 0.130913 0.139037 0.223571\n2023-04-06 0.258177 0.103195 0.145399 0.129457 0.139871 0.223901\n2023-04-10 0.255589 0.103228 0.145400 0.130815 0.139155 0.225814\n```\n\n## Portfolio backtesting - main function\n```\nPortfolio.run_backtest() -> Backtest\n\n Parameters:\n\n - rebalance: bool (required)\n If 'True', the backtest will rebalance itself.\n\n - weights: str or dict, default 'ew'\n If 'dict', than it is the weight for each asset (number between 0 and 1),\n The sum can't be different than one.\n Example:\n asset_weights = {\n 'asset1': 0.3,\n 'asset2': 0.2,\n 'asset3': 0.5,\n }\n If str (has to be 'ew'), runs the backtest using equal weight for all \n assets (1 / number of assets).\n\n - rebal_freq: str, default '1M'\n Rebalance frequency. Has the same valid inputs as pandas.DataFrame.resample() \n function.\n```\n\n## TODO\n- Performance metrics and visualizations\n- Reports\n- Yahoo Finance implementation",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python library designed to make portfolio backtesting easy and intuitive",
"version": "0.1.8",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e8c48fbf41538e39ff170c7e722cb81cf0006ce43df7921fb129457038233593",
"md5": "b8a61014ebf86e60be9f13493a7794c0",
"sha256": "80d6993fd0cbdbdb30aa7d359f47cdbde60874d9268fbfc89546045e448bec32"
},
"downloads": -1,
"filename": "portbt-0.1.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b8a61014ebf86e60be9f13493a7794c0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10,<4.0",
"size": 6368,
"upload_time": "2023-04-26T00:27:02",
"upload_time_iso_8601": "2023-04-26T00:27:02.438366Z",
"url": "https://files.pythonhosted.org/packages/e8/c4/8fbf41538e39ff170c7e722cb81cf0006ce43df7921fb129457038233593/portbt-0.1.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f67bd7f1aaa8335b081b69785234cd3dc0f693ba2074e34bdeabddf7d8b929a1",
"md5": "346cad0d5dbe24cfd11ca8d1e8e0ca39",
"sha256": "852fc775c16b400a41cb42b29946d1c2d4e343d0e29944e8cad12ea3a34f600d"
},
"downloads": -1,
"filename": "portbt-0.1.8.tar.gz",
"has_sig": false,
"md5_digest": "346cad0d5dbe24cfd11ca8d1e8e0ca39",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10,<4.0",
"size": 5398,
"upload_time": "2023-04-26T00:27:04",
"upload_time_iso_8601": "2023-04-26T00:27:04.729325Z",
"url": "https://files.pythonhosted.org/packages/f6/7b/d7f1aaa8335b081b69785234cd3dc0f693ba2074e34bdeabddf7d8b929a1/portbt-0.1.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-26 00:27:04",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "renanmoretto",
"github_project": "portbt",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "contourpy",
"specs": [
[
"==",
"1.0.7"
]
]
},
{
"name": "cycler",
"specs": [
[
"==",
"0.11.0"
]
]
},
{
"name": "datetime",
"specs": [
[
"==",
"5.1"
]
]
},
{
"name": "fonttools",
"specs": [
[
"==",
"4.39.3"
]
]
},
{
"name": "kiwisolver",
"specs": [
[
"==",
"1.4.4"
]
]
},
{
"name": "matplotlib",
"specs": [
[
"==",
"3.7.1"
]
]
},
{
"name": "numpy",
"specs": [
[
"==",
"1.24.2"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"23.0"
]
]
},
{
"name": "pandas",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "pillow",
"specs": [
[
"==",
"9.5.0"
]
]
},
{
"name": "pyparsing",
"specs": [
[
"==",
"3.0.9"
]
]
},
{
"name": "python-dateutil",
"specs": [
[
"==",
"2.8.2"
]
]
},
{
"name": "pytz",
"specs": [
[
"==",
"2023.3"
]
]
},
{
"name": "setuptools",
"specs": [
[
"==",
"67.6.1"
]
]
},
{
"name": "six",
"specs": [
[
"==",
"1.16.0"
]
]
},
{
"name": "tzdata",
"specs": [
[
"==",
"2023.3"
]
]
},
{
"name": "zope-interface",
"specs": [
[
"==",
"6.0"
]
]
}
],
"lcname": "portbt"
}