Basic template for managing Backtrader backtests.
Backtrader Template creates new environments for onboarding clients at RunBacktest. The benefits of working with Backtrader Template are:
Follow these steps to install and run a basic backtest.
git clone https://github.com/neilsmurphy/backtrader_template. git
Then enter your user name and password.[email protected]:neilsmurphy/backtrader_template.git
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 setup.py
The key file for interfacing with Backtrader Template is the setup.py file. Here you will set your parameters for your backtests.
The first section of the backtest contains:
Input | Description |
---|---|
batchname | Name to identify multiple backtests together. (string) |
from_date | Date data starts loading from. Format "YYYY-MM-DD" (string) |
trade_start | Date trading starts from. Format "YYYY-MM-DD" (string) |
to_date | End date. Format "YYYY-MM-DD" (string) |
duration | Combined with start date. Used in multiple backtests. to_date must be off. (int) |
--------------------- | |
initinvestment | Amount of the initial investment. (float) |
instrument | Name of the security. (string) |
benchmark | Used in the tearsheet to compare against test results. (string) |
--------------------- | |
sma_fast | Simple moving average fast (int) |
sma_slow | Simple moving average slow (int) |
limit_price | Take profit (float) |
stop_price | Stop loss (float) |
--------------------- | |
print_dev | Developer terminal output. Can comment/uncomment lines in extension.strategy print_dev (True/False) |
print_orders_trades | Terminal output for orders. (True/False) |
print_ohlcv | Terminal output for ohlcv. (True/False) |
print_final_output | Terminal output for final trade list results. (True/False) |
printon | Terminal output for beginning/end details. (True/False) |
--------------------- | |
save_path | Name of the directory to save results to. (string) |
save_name | Name of the file/database to save results to. (string) |
save_result | Backtest results save to excel, tearsheet, or database. False is terminal only. (True/False) |
save_excel | Save detailed backtest results to a spreadsheet. (True/False) |
save_tearsheet | Save quanstats tearsheet to results . (True/False) |
save_db | Save backtest results to the database for use with analysis. (True/False) |
full_export | Full export exports all of the available date. (True/False) |
All stock data is downloaded using yahoo finance. Time frames are daily.
A simple indicator is used in this backtests. Of course this would be replaced with the users indicators.
When setting dates, the from_date
is when data is loaded, and trade_start
is
when trading starts. While Backtrader will automatically adjust lead times, this
gives more control of the actual trade start date.
print_dev
is used for custom logging. You can change this in extension/strategy.py
.
Multiple backtest can be run for optimization. All that is required is to use list where your parameters would be.
For example, run the following tests:
...
instrument= ["FB", "TSLA", "AAPL"],
benchmark="SPY",
sma_fast=range(15, 46, 15),
sma_slow=range(30, 61, 15),
limit_price=[0.04, 0.07, 0.09],
stop_price=[0.02, 0.05],
...
This will run the following tests.
There will be 108 backtests run.
batchname="Single Test",
batch_runtime="2021-06-20 06:52",
db_name=None,
test_number=0,
save_result=True,
save_tearsheet=True,
save_excel=True,
save_db=False,
full_export=True,
save_path="result",
save_name="my test name",
from_date="2016-01-01",
trade_start="2016-09-01",
to_date="2020-12-31",
duration=None,
instrument=['FB', 'TSLA', 'AAPL'],
benchmark="SPY",
initinvestment=100000,
commission=0.0,
margin=None,
mult=1,
print_dev=False,
print_orders_trades=True,
printon=True,
print_ohlcv=-1,
print_final_output=True,
ploton=False,
sma_fast=range(15, 46, 15),
sma_slow=range(30, 61, 15),
limit_price=[0.04, 0.07, 0.09],
stop_price=[0.02, 0.05],
trade_size=1.0,
The system will automatically calculate all of the possible combinations. The output
will tell you how many test will run. If you want to just check how many
test will run, set run_test_now = False
and run the backtests. It won't actually
run, just give you the parameters and number of test that will execute.
Criteria is set in the calculation of the backtest to ensure that the long sma is
higher than the short sma. This logic can be found in main/RunBacktest/scenario
at
line 457.
if scenario["sma_fast"] >= scenario["sma_slow"]:
continue
When running multiple backtest, make sure to use multi-pro = True
to turn on the
multi-processor. The multi-processor is set to use your number of cores - 2
.
To run multiple test at once over different dates, use the from_date
combined with
duration
. trade_start
and to_date
are ignored.
View your backtest results on the terminal, save to excel, database, or create a tearsheet.
There are several options for diplaying backtest results to the terminal.
To view all orders and trades, print_orders_trades
.
One can also select to view all of the ohlcv candles using print_ohlcv=0
. If there
are more than one data lines in the backtest, select increasing increments, eg:
print_ohlcv=1
to find the desired dataline. Use -1
for off.
Backtrader template offers a trade output list which can be accessed via
print_final_output=True
[Thanks to https://github.com/ab-trader]
There are some sundry printouts such as the final value, etc. printon=True
Also is available the ability to create a custom log to terminal using
'print_dev=False,' This can be modified in extensions/strategy.py
.
There are three options for saving to disk. To turn on/off saving in general, use
save_result=False
. To set the path for saving, save_path="result"
This will
save to the "result" directory. It is not necessary to create the directory, it will
be made if not already existing. A custom name can be added to the output file names.
save_name="my test name"
.
To save to excel, use save_excel=True
. The spreadsheet will have multple tabs with
the following information:
The above data can also be saved to database using save_db=True
This is necessary
for analysis. This default template uses SQLite3 for simplicity, but any database
could be used. I personally use postgres.
There is a very nice tearsheet provided by QuantStats. This can be accessed by using save_tearsheet=True
.
Here is a sample:
A discussion about memory. I try to separate analyzers into two categories. Those that essentially have one line output per test, and analyzers that have multiple lines per test. If I'm only executing a modest number of backtests, I will go ahead and use a 'full_export' to the database, meaning all analyzers. But saving OHLV data and other such large datasets is not conducive to large numbers of backtests. For large backtests I will set 'full_export=False' which is good for fast backtesting. You can control which analyzers are included in full or not full in the extension/analyzer module at the bottom.
There are two analysis notebooks.
To add a new parameter to the backtest, just add it into the RunBacktest class
self.params
dictionary found in main.py
. The default for the parameter is placed in the
first position of the list. This will then become available in the strat as a
parameter. For example, adding in rsi
as a true/false parameter:
rsi=[True, True],
This parameter is now availabe in your backtest in the strategy by using
self.p.rsi
The second parameter is boolean and is used to determine if this parameter is exported to the database after running the backtest for use in analysis.
Separate modules are stored in the extension directory and then import to main as needed. Modules that are stored here are:
Now encorporated is Dave Valance/Ed Bartosh ccxt stores into backtrader. You can now backtest cryptos on a wide variety of exchanges. Once backtested, you can sandbox test your algo, then go live.
The sample included is Binance. Set up your parameters as per the params-template.json
file.
WARNING Do not mix up your testnet and your live trading. Testnet is a fake sandbox account trading pretend money, actual trading is live with your money. |
---|
I have set up two apis, one for actual trading and one for the testnet sandbox.
"binance_actual": {
"apikey": "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"secret": "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"testorders": true
},
"binance_testnet": {
"apikey": "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"secret": "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"testorders": true
},
Create your configs for your store. For the testnet use:
config = {'urls': {'api': 'https://testnet.binance.vision/api'},
"apiKey": params["binance_testnet"]["apikey"],
"secret": params["binance_testnet"]["secret"],
"enableRateLimit": True,
}
For your actual store with live trading, use:
config = {
"apiKey": params["binance_actual"]["apikey"],
"secret": params["binance_actual"]["secret"],
"enableRateLimit": True,
}
When trading on the sandbox, set sandbox=True
when creating the store. And sandbox=False
when trading live.
store = CCXTStore(
exchange="binance", currency="USDT", config=config, retries=5, debug=False, sandbox=True
)
Packages required:
Black
Dash Bootstrap Components
Jupyter
Quandl
Pandas
Plot.ly
Plot.ly Dasy
tabulate
urllib3
XlsxWriter
Yfinance
If you wish to contact me, I can be reached:
Neil Murphy
[email protected]
RunBacktest