# Backtester-RB30
## Description
Backtester-RB30 is a framework for stock market analysis.
## Installation
> pip install backtesterrb30
## Quick start
### Basic example
Basic strategy example making random trades.
> poetry install
> poetry run basic_example
### Advanced example
More advanced example with debug mode enabled, live debug code reloads and more data sources with not equal intervals.
> sudo python3 examples/live_reloading_example/live_reloading_strategy.py
Root privilages are required.
### Issues:
If matplotlib plots doesn't works in virtual environment try:
>sudo apt-get install python3-tk
# Strategy implementation
## Define input data
List of instruments provided every step of your strategy.
Avaliable data sources:
- [ binance ] avaliable instruments in "historical_data_feeds/data_sources/binance/binance_instruments.txt"
- [ dukascopy ] avaliable instruments in https://github.com/Leo4815162342/dukascopy-node
- [ coingecko ] avaliable instruments in https://www.coingecko.com/
- [ exante ] avaliable instruments in https://drive.google.com/drive/folders/1qJAGedEWhGehG2Hh48ITgE7LjGWwyzOw?usp=sharing
- [ tradingview ] avaliable instruments in https://www.tradingview.com/
Dictionary must fit to bt.DataSchema interface
~~~
import backtesterrb30 as bt
from datetime import datetime
class Data:
data={
'log_scale_valuation_chart': True,
'data':[
{
'symbol': 'bitcoin',
'historical_data_source': bt.HISTORICAL_SOURCES.coingecko,
'backtest_date_start': datetime(2019,5,1),
'backtest_date_stop': datetime(2022,8,1),
'interval': bt.HISTORICAL_SOURCES.coingecko.INTERVALS.day4,
},
{
'symbol': 'ethereum',
'historical_data_source': bt.HISTORICAL_SOURCES.coingecko,
'backtest_date_start': datetime(2019,5,1),
'backtest_date_stop': datetime(2022,8,1),
'interval': bt.HISTORICAL_SOURCES.coingecko.INTERVALS.day4,
}
]
}
~~~
## Define Engine class
Engine class "on_feed()" function is being called every interval of your strategy. attribute "data" provided to "on_feed()" is an array with timestamp and symbols values. In this example data will look like:
~~~
data = [[timestamps array with 100 elements],
[bitcoin prices array with 100 elements],
[ethereum prices array with 100 elements]]
~~~
Number of elements in arrays (buffer length) are being defined by set_buffer_length() method.
You can use "_trigger_event()" function to send any message to executor module.
More about avaliable methods:
https://pazernykormoran.github.io/Backtester-RB30/backtesterrb30.python_engine.html
Below example sending messages with random values:
~~~
import backtesterrb30 as bt
from random import randint
class Engine(bt.Engine):
def __init__(self, *args):
super().__init__(*args)
self.counter = 0
self.set_buffer_length(100)
#override
async def on_feed(self, data: list):
if self.counter % 5 == 0:
quant = randint(-2,2)
if quant != 0:
message = {
'value': quant
}
await self.trigger_event(message)
self.counter += 1
~~~
## Define Executor class
Executor class manages transactions and current money level. You can use "trade()" function here. Method "on_event" is being triggered by Engine class. Making trade, you have to provide instrument on which to do trade. One of instruments defined in Data class.
More about avaliable methods:
https://pazernykormoran.github.io/Backtester-RB30/backtesterrb30.python_executor.html
~~~
import backtesterrb30 as bt
from random import randint
class TradeExecutor(bt.Executor):
def __init__(self, *args):
super().__init__(*args)
#override
async def on_event(self, message):
await self.trade(message['value'], \
self.get_data_schema().data[randint(0,1)])
~~~
## Strategy run
~~~
strategy = bt.Strategy(Model, TradeExecutor, Data)
strategy.run()
~~~
By default strategy is being run in backtest mode.
Full code example is in folder "examples/basic_example/basic_example.py"
# Data Sources
Some data sources requires providing authentication keys which you have to find on your own. For this puropuse you have to provide ".env" file in the folder which from you are running your strategy. Example:
~~~
KEY="value"
KEY2="value2"
KEY3="value3"
~~~
## Descriptions:
1. Coingecko
Coingecko is working without any keys.
2. Dukascopy
For dukascopy no keys are required. But for this data source working, you have to have node and npm with npx installed.
~~~
https://nodejs.org/en/download/package-manager
~~~
3. Binance
~~~
binance_api_secret="value"
binance_api_key="value"
~~~
4. Exante
In exante you have to privide keys for basic auth. Now working only with live accounts.
~~~
exante_app_id='value'
exante_access_key = 'value'
~~~
5. Tradingview
In tradingview you have to provide login and password to tradingview account.
~~~
trading_view_user='value'
trading_view_password='value'
~~~
# Debug mode
## Usage of debug mode
Debug mode is only avaliable with root privilages because of keyboard package usage. To run your strategy with allowed debugging , provide debug parameter to Strategy class constructor.
~~~
import backtesterrb30 as bt
strategy = bt.Strategy(Engine, TradeExecutor, Data, debug=True)
strategy.run()
~~~
Framework gives you access to debug mode that allows you printing summary charts and descriptions every step of your debug. To enable using debug mode while implementing your strategy follow below steps:
- Use "debug_breakpoint()" method somewhere in your "on_feed" method. This works as breakpoint while debugging.
- Press "ctrl+d" in any moment during backtest loop. This will cause entering debug mode and stopping the code in the nearest moment when your code occurs "debug_breakpoint" function.
- Press "ctrl+n" for next. You should see summary and charts printed for current moment of backtest.
- Press "ctrl+q" for quit debug mode.
## Live code reloads in debug mode
Debug mode enables user to develop his strategies live with backtest running in debud mode. Thats only possible importable modules to bo live reloaded. To achive this use "add_reloading_module(path_to_module)" in the init function in your Engine class. As an argument to the function pass the path to the module you are goint to be reloaded after every step of your debug. Path to the module is absoule path but you can use your "self.config.strategy_path + relative path".
# Data source implementation
TODO.
Raw data
{
"_id": null,
"home_page": "https://github.com/threeal/python-starter",
"name": "backtesterrb30",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "backtesting, market, finance, trading",
"author": "pazerny kormoran",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/7f/1b/bac63975fa0710a68ff990971c49d39b311451d5d9319cf2b2eba9b5e11c/backtesterrb30-0.1.17.tar.gz",
"platform": null,
"description": "# Backtester-RB30\n\n## Description\n\nBacktester-RB30 is a framework for stock market analysis.\n\n## Installation\n\n> pip install backtesterrb30\n\n## Quick start\n\n### Basic example\nBasic strategy example making random trades.\n> poetry install\n\n> poetry run basic_example\n\n### Advanced example\nMore advanced example with debug mode enabled, live debug code reloads and more data sources with not equal intervals. \n> sudo python3 examples/live_reloading_example/live_reloading_strategy.py\nRoot privilages are required.\n\n### Issues:\nIf matplotlib plots doesn't works in virtual environment try:\n>sudo apt-get install python3-tk\n\n\n# Strategy implementation\n\n## Define input data\nList of instruments provided every step of your strategy.\nAvaliable data sources: \n- [ binance ] avaliable instruments in \"historical_data_feeds/data_sources/binance/binance_instruments.txt\"\n- [ dukascopy ] avaliable instruments in https://github.com/Leo4815162342/dukascopy-node\n- [ coingecko ] avaliable instruments in https://www.coingecko.com/\n- [ exante ] avaliable instruments in https://drive.google.com/drive/folders/1qJAGedEWhGehG2Hh48ITgE7LjGWwyzOw?usp=sharing\n- [ tradingview ] avaliable instruments in https://www.tradingview.com/\n\nDictionary must fit to bt.DataSchema interface\n~~~\nimport backtesterrb30 as bt\nfrom datetime import datetime\n\nclass Data:\n data={\n 'log_scale_valuation_chart': True,\n 'data':[\n {\n 'symbol': 'bitcoin',\n 'historical_data_source': bt.HISTORICAL_SOURCES.coingecko,\n 'backtest_date_start': datetime(2019,5,1),\n 'backtest_date_stop': datetime(2022,8,1),\n 'interval': bt.HISTORICAL_SOURCES.coingecko.INTERVALS.day4,\n },\n {\n 'symbol': 'ethereum',\n 'historical_data_source': bt.HISTORICAL_SOURCES.coingecko,\n 'backtest_date_start': datetime(2019,5,1),\n 'backtest_date_stop': datetime(2022,8,1),\n 'interval': bt.HISTORICAL_SOURCES.coingecko.INTERVALS.day4,\n }\n ]\n }\n~~~\n\n## Define Engine class\nEngine class \"on_feed()\" function is being called every interval of your strategy. attribute \"data\" provided to \"on_feed()\" is an array with timestamp and symbols values. In this example data will look like:\n\n~~~\ndata = [[timestamps array with 100 elements],\n [bitcoin prices array with 100 elements],\n [ethereum prices array with 100 elements]]\n~~~\nNumber of elements in arrays (buffer length) are being defined by set_buffer_length() method.\nYou can use \"_trigger_event()\" function to send any message to executor module.\nMore about avaliable methods: \n\nhttps://pazernykormoran.github.io/Backtester-RB30/backtesterrb30.python_engine.html\n\nBelow example sending messages with random values:\n\n~~~\nimport backtesterrb30 as bt\nfrom random import randint\n\nclass Engine(bt.Engine):\n \n def __init__(self, *args):\n super().__init__(*args)\n self.counter = 0\n self.set_buffer_length(100)\n\n #override\n async def on_feed(self, data: list):\n if self.counter % 5 == 0:\n quant = randint(-2,2)\n if quant != 0:\n message = {\n 'value': quant\n }\n await self.trigger_event(message)\n self.counter += 1\n~~~\n\n## Define Executor class\nExecutor class manages transactions and current money level. You can use \"trade()\" function here. Method \"on_event\" is being triggered by Engine class. Making trade, you have to provide instrument on which to do trade. One of instruments defined in Data class.\n\nMore about avaliable methods:\n\nhttps://pazernykormoran.github.io/Backtester-RB30/backtesterrb30.python_executor.html\n~~~\nimport backtesterrb30 as bt\nfrom random import randint\n\nclass TradeExecutor(bt.Executor):\n\n def __init__(self, *args):\n super().__init__(*args)\n\n #override\n async def on_event(self, message):\n await self.trade(message['value'], \\\n self.get_data_schema().data[randint(0,1)])\n~~~\n\n## Strategy run\n~~~\nstrategy = bt.Strategy(Model, TradeExecutor, Data)\nstrategy.run()\n~~~\n\nBy default strategy is being run in backtest mode.\nFull code example is in folder \"examples/basic_example/basic_example.py\"\n\n\n# Data Sources\n\nSome data sources requires providing authentication keys which you have to find on your own. For this puropuse you have to provide \".env\" file in the folder which from you are running your strategy. Example:\n~~~\nKEY=\"value\"\nKEY2=\"value2\"\nKEY3=\"value3\"\n~~~\n\n## Descriptions:\n\n1. Coingecko\n\nCoingecko is working without any keys.\n\n2. Dukascopy\n\nFor dukascopy no keys are required. But for this data source working, you have to have node and npm with npx installed.\n~~~\nhttps://nodejs.org/en/download/package-manager\n~~~\n\n3. Binance\n\n~~~\nbinance_api_secret=\"value\"\nbinance_api_key=\"value\"\n~~~\n\n4. Exante\n\nIn exante you have to privide keys for basic auth. Now working only with live accounts.\n~~~\nexante_app_id='value'\nexante_access_key = 'value'\n~~~\n\n5. Tradingview\n\nIn tradingview you have to provide login and password to tradingview account.\n~~~\ntrading_view_user='value'\ntrading_view_password='value'\n~~~\n\n# Debug mode\n\n## Usage of debug mode\nDebug mode is only avaliable with root privilages because of keyboard package usage. To run your strategy with allowed debugging , provide debug parameter to Strategy class constructor.\n~~~\nimport backtesterrb30 as bt\nstrategy = bt.Strategy(Engine, TradeExecutor, Data, debug=True)\nstrategy.run()\n~~~\n\nFramework gives you access to debug mode that allows you printing summary charts and descriptions every step of your debug. To enable using debug mode while implementing your strategy follow below steps:\n- Use \"debug_breakpoint()\" method somewhere in your \"on_feed\" method. This works as breakpoint while debugging.\n- Press \"ctrl+d\" in any moment during backtest loop. This will cause entering debug mode and stopping the code in the nearest moment when your code occurs \"debug_breakpoint\" function.\n- Press \"ctrl+n\" for next. You should see summary and charts printed for current moment of backtest.\n- Press \"ctrl+q\" for quit debug mode.\n\n\n## Live code reloads in debug mode\nDebug mode enables user to develop his strategies live with backtest running in debud mode. Thats only possible importable modules to bo live reloaded. To achive this use \"add_reloading_module(path_to_module)\" in the init function in your Engine class. As an argument to the function pass the path to the module you are goint to be reloaded after every step of your debug. Path to the module is absoule path but you can use your \"self.config.strategy_path + relative path\".\n\n\n# Data source implementation\n\nTODO. \n\n",
"bugtrack_url": null,
"license": "Unlicense",
"summary": "Backtesting and data loading engine",
"version": "0.1.17",
"project_urls": {
"Homepage": "https://github.com/threeal/python-starter",
"Repository": "https://github.com/threeal/python-starter"
},
"split_keywords": [
"backtesting",
" market",
" finance",
" trading"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "98987936ca32cc00f65c5f9c1137c0eb599a4f7ea68f40f0bbb393cc36ab01f0",
"md5": "f37be3647ea059e89776b85e227573ca",
"sha256": "0a96355cb6e6e5416b0b583bc77d68efd09f4cea96bc9cbaa6281578efe9ba0a"
},
"downloads": -1,
"filename": "backtesterrb30-0.1.17-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f37be3647ea059e89776b85e227573ca",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 171359,
"upload_time": "2025-01-11T12:06:25",
"upload_time_iso_8601": "2025-01-11T12:06:25.707569Z",
"url": "https://files.pythonhosted.org/packages/98/98/7936ca32cc00f65c5f9c1137c0eb599a4f7ea68f40f0bbb393cc36ab01f0/backtesterrb30-0.1.17-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7f1bbac63975fa0710a68ff990971c49d39b311451d5d9319cf2b2eba9b5e11c",
"md5": "7649c84f4391e3816de71458aeab8062",
"sha256": "027ce1b1b68dfbc4c2deae1ae31c2b5fc1f36199da1179d21039891d19a7142e"
},
"downloads": -1,
"filename": "backtesterrb30-0.1.17.tar.gz",
"has_sig": false,
"md5_digest": "7649c84f4391e3816de71458aeab8062",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 136614,
"upload_time": "2025-01-11T12:06:27",
"upload_time_iso_8601": "2025-01-11T12:06:27.049651Z",
"url": "https://files.pythonhosted.org/packages/7f/1b/bac63975fa0710a68ff990971c49d39b311451d5d9319cf2b2eba9b5e11c/backtesterrb30-0.1.17.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-11 12:06:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "threeal",
"github_project": "python-starter",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "backtesterrb30"
}