A Pythonic backtester for trading algorithms
Project description
Installation
Used packages and environment
- Main package: Zipline-reloaded 2.2.0
- Python 3.8
- Microsoft Windows OS or macOS
- Other Python dependency packages: Pandas, Numpy, Logbook, Exchange-calendars
How to install Zipline Reloaded modified by TEJ
-
We're going to illustrate under anaconda environment, so we suggest using Anaconda as development environment.
-
Download dependency packages.
-
Windows (zipline-tej.yml)
- Start an Anaconda (base) prompt, create an virtual environment and install the appropriate versions of packages: (We strongly recommand using virtual environment to keep every project independent.) (reason)
Windows Users
# change directionary to the folder exists zipline-tej.yml
$ cd <C:\Users\username\Downloads>
# create virtual env
$ conda env create -f zipline-tej.yml
# activate virtual env
$ conda activate zipline-tej
Mac Users
# change directionary to the folder exists zipline-tej_mac.yml
$ cd <C:\Users\username\Downloads>
# create virtual env
$ conda env create -f zipline-tej_mac.yml
# activate virtual env
$ conda activate zipline-tej
Also, if you are familiar with Python enough, you can create a virtual environment without zipline-tej.yml and here's the sample :
# create virtual env
$ conda create -n <env_name> python=3.8
# activate virtual env
$ conda activate <env_name>
# download dependency packages
$ conda install -c conda-forge -y ta-lib
$ conda install -y notebook=6.4.11
$ conda install -c conda-forge nb_conda_kernels
$ conda install -y xlrd=2.0.1
$ conda install -y openpyxl=3.0.9
$ pip install zipline-tej
- Notice that we need to download TA-lib at first, so that we can download zipline-tej successfully.
Quick start
CLI Interface
The following code implements a simple buy_and_hold trading algorithm.
from zipline.api import order, record, symbol
def initialize(context):
context.asset = symbol("2330")
def handle_data(context, data):
order(context.asset, 10)
record(TSMC=data.current(context.asset, "price"))
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(211)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel("Portfolio value (TWD)")
ax2 = plt.subplot(212, sharex=ax1)
results.TSMC.plot(ax=ax2)
ax2.set_ylabel("TSMC price (TWD)")
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
You can then run this algorithm using the Zipline CLI. But first, you need to download some market data with historical prices and trading volumes:
- Before ingesting data, you have to set some environment variables as follow:
# setting TEJAPI_KEY to get permissions loading data
$ set TEJAPI_KEY=<your_key>
$ set TEJAPI_BASE="https://api.tej.com.tw"
# setting download ticker
$ set ticker=2330 2317
# setting backtest period
$ set mdate=20200101 20220101
- Ingest and run backtesting algorithm
$ zipline ingest -b tquant
$ zipline run -f buy_and_hold.py --start 20200101 --end 20220101 -o bah.pickle --no-benchmark --trading-calendar TEJ_XTAI
Then, the resulting performance DataFrame is saved as bah.pickle, which you can load and analyze from Python.
More useful zipline commands
Before calling zipline in CLI, be sure that TEJAPI_KEY and TEJAPI_BASE were set. Use zipline --help to get more information.
New add tickers
$ zipline add -t "<ticker_wants_to_add>"
If tickers are more than 1 ticker, split them apart by " " or "," or ";".
For more detail use zipline add --help .
Display bundle-info
$ zipline bundle-info
To show what the tickers are there in newest bundle.
For more detail use zipline bundle-info --help .
Switch bundle
Before using switch, use zipline bundles to get the timestamp of each folder.
$ zipline switch -t "<The_timestamp_of_the_folder_want_to_use>"
Due to zipline only using the newest foler, switch can make previous folder become newest.
For more detail use zipline switch --help .
Update bundle
$ zipline update
To update the bundle information to newest date.
For more detail use zipline update --help .
Jupyter Notebook
Change Anaconda kernel
- Since we've downloaded package "nb_conda_kernels", we should be able to change kernel in jupyter notebook.
How to new a notebook using specific kernel
(1) Open anaconda prompt
(2) Enter the command as follow :
# First one can be ignore if already in environment of zipline-tej
$ conda activate zipline-tej
# start a jupyter notebook
$ jupyter notebook
(3) Start a notebook and select Python[conda env:zipline-tej]
(4)(Optional) If you have already written a notebook, you can open it and change kernel by clicking the "Kernel" in menu and "Change kernel" to select the specfic kernel.
Set environment variables TEJAPI_KEY, ticker and mdate
* ticker would be your target ticker symbol, and it should be a string. If there're more than one ticker needed, use " ", "," or ";" to split them apart.
* mdate refers the begin date and end date, use " ", "," or ";" to split them apart.
In[1]:
import os
os.environ['TEJAPI_KEY'] = <your_key>
os.environ['ticker'] ='2330 2317'
os.environ['mdate'] ='20200101 20220101'
Call ingest to download data to ~\.zipline
In[2]:
!zipline ingest -b tquant
[Out]:
Merging daily equity files:
[YYYY-MM-DD HH:mm:ss.ssssss] INFO: zipline.data.bundles.core: Ingesting tquant.
Design the backtesting strategy
In[3]:
from zipline.api import order, record, symbol
def initialize(context):
context.asset = symbol("2330")
def handle_data(context, data):
order(context.asset, 10)
record(TSMC=data.current(context.asset, "price"))
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(211)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel("Portfolio value (TWD)")
ax2 = plt.subplot(212, sharex=ax1)
results.TSMC.plot(ax=ax2)
ax2.set_ylabel("TSMC price (TWD)")
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
Run backtesting algorithm and plot
In[4]:
from zipline import run_algorithm
import pandas as pd
from zipline.utils.calendar_utils import get_calendar
trading_calendar = get_calendar('TEJ_XTAI')
start = pd.Timestamp('20200103', tz ='utc' )
end = pd.Timestamp('20211230', tz='utc')
result = run_algorithm(start=start,
end=end,
initialize=initialize,
capital_base=1000000,
handle_data=handle_data,
bundle='tquant',
trading_calendar=trading_calendar,
analyze=analyze,
data_frequency='daily'
)
[Out]:
Show trading process
In[5]:
result
[Out]:
period_open | period_close | starting_value | ending_value | starting_cash | ending_cash | portfolio_value | longs_count | shorts_count | long_value | ... | treasury_period_return | trading_days | period_label | algo_volatility | benchmark_period_return | benchmark_volatility | algorithm_period_return | alpha | beta | sharpe | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2020-01-03 05:30:00+00:00 | 2020-01-03 01:01:00+00:00 | 2020-01-03 05:30:00+00:00 | 0.0 | 0.0 | 1.000000e+06 | 1.000000e+06 | 1.000000e+06 | 0 | 0 | 0.0 | ... | 0.0 | 1 | 2020-01 | NaN | 0.0 | NaN | 0.000000 | None | None | NaN |
2020-01-06 05:30:00+00:00 | 2020-01-06 01:01:00+00:00 | 2020-01-06 05:30:00+00:00 | 0.0 | 3320.0 | 1.000000e+06 | 9.966783e+05 | 9.999983e+05 | 1 | 0 | 3320.0 | ... | 0.0 | 2 | 2020-01 | 0.000019 | 0.0 | 0.0 | -0.000002 | None | None | -11.224972 |
2020-01-07 05:30:00+00:00 | 2020-01-07 01:01:00+00:00 | 2020-01-07 05:30:00+00:00 | 3320.0 | 6590.0 | 9.966783e+05 | 9.933817e+05 | 9.999717e+05 | 1 | 0 | 6590.0 | ... | 0.0 | 3 | 2020-01 | 0.000237 | 0.0 | 0.0 | -0.000028 | None | None | -10.038514 |
2020-01-08 05:30:00+00:00 | 2020-01-08 01:01:00+00:00 | 2020-01-08 05:30:00+00:00 | 6590.0 | 9885.0 | 9.933817e+05 | 9.900850e+05 | 9.999700e+05 | 1 | 0 | 9885.0 | ... | 0.0 | 4 | 2020-01 | 0.000203 | 0.0 | 0.0 | -0.000030 | None | None | -9.298128 |
2020-01-09 05:30:00+00:00 | 2020-01-09 01:01:00+00:00 | 2020-01-09 05:30:00+00:00 | 9885.0 | 13500.0 | 9.900850e+05 | 9.867083e+05 | 1.000208e+06 | 1 | 0 | 13500.0 | ... | 0.0 | 5 | 2020-01 | 0.001754 | 0.0 | 0.0 | 0.000208 | None | None | 5.986418 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2021-12-24 05:30:00+00:00 | 2021-12-24 01:01:00+00:00 | 2021-12-24 05:30:00+00:00 | 2920920.0 | 2917320.0 | -1.308854e+06 | -1.314897e+06 | 1.602423e+06 | 1 | 0 | 2917320.0 | ... | 0.0 | 484 | 2021-12 | 0.232791 | 0.0 | 0.0 | 0.602423 | None | None | 1.170743 |
2021-12-27 05:30:00+00:00 | 2021-12-27 01:01:00+00:00 | 2021-12-27 05:30:00+00:00 | 2917320.0 | 2933040.0 | -1.314897e+06 | -1.320960e+06 | 1.612080e+06 | 1 | 0 | 2933040.0 | ... | 0.0 | 485 | 2021-12 | 0.232577 | 0.0 | 0.0 | 0.612080 | None | None | 1.182864 |
2021-12-28 05:30:00+00:00 | 2021-12-28 01:01:00+00:00 | 2021-12-28 05:30:00+00:00 | 2933040.0 | 2982750.0 | -1.320960e+06 | -1.327113e+06 | 1.655637e+06 | 1 | 0 | 2982750.0 | ... | 0.0 | 486 | 2021-12 | 0.233086 | 0.0 | 0.0 | 0.655637 | None | None | 1.237958 |
2021-12-29 05:30:00+00:00 | 2021-12-29 01:01:00+00:00 | 2021-12-29 05:30:00+00:00 | 2982750.0 | 2993760.0 | -1.327113e+06 | -1.333276e+06 | 1.660484e+06 | 1 | 0 | 2993760.0 | ... | 0.0 | 487 | 2021-12 | 0.232850 | 0.0 | 0.0 | 0.660484 | None | None | 1.243176 |
2021-12-30 05:30:00+00:00 | 2021-12-30 01:01:00+00:00 | 2021-12-30 05:30:00+00:00 | 2993760.0 | 2995050.0 | -1.333276e+06 | -1.339430e+06 | 1.655620e+06 | 1 | 0 | 2995050.0 | ... | 0.0 | 488 | 2021-12 | 0.232629 | 0.0 | 0.0 | 0.655620 | None | None | 1.235305 |
488 rows × 38 columns
Common errors
- NotSessionError : The date of algorithm start date or end date is not available in trading algorithm.
- Solution : Adjust start date or end date to align trading calendar.
- DateOutOfBounds : The trading calendar would update every day, but it would be fixed on the FIRST TIME executed date in Jupyter Notebook.
- Solution : Restart Jupyter Notebook kernel.
More Zipline Tutorials
- For more tutorials
Suggestions
- To get TEJAPI_KEY (link)
- TEJ Official Website
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file zipline-tej-0.0.47.tar.gz
.
File metadata
- Download URL: zipline-tej-0.0.47.tar.gz
- Upload date:
- Size: 11.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.16
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8392aa9a0e60334e9a2bcfe59460c1a8876b5edc7b41b633d99d2238d6e0193a |
|
MD5 | 40c6c48a401f117cb1ccb686cba7a2f4 |
|
BLAKE2b-256 | 71cb3d99306941ef7f4ba53760ccd16ff74d8a002976a124ed9e6f2c5f56fc18 |
File details
Details for the file zipline_tej-0.0.47-cp38-cp38-win_amd64.whl
.
File metadata
- Download URL: zipline_tej-0.0.47-cp38-cp38-win_amd64.whl
- Upload date:
- Size: 4.1 MB
- Tags: CPython 3.8, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.16
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a638a774b06bf0697a46f8eb30408a6c97278b4916a301f9ff9d1fd42f8a834a |
|
MD5 | 0f030fe4967257f17342e2a844518ac5 |
|
BLAKE2b-256 | c3fddb0a8f32038cedfcab3c57d72f3dc6894f6817ec847e80b1e4511c08c7d5 |