Metadata-Version: 2.1
Name: zipline-tej
Version: 0.0.11
Summary: A Pythonic backtester for trading algorithms
Author: tej
Author-email: tej@tej.com.tw
Maintainer: tej api Development Team
Maintainer-email: tej@tej.com.tw
License: MIT
Project-URL: homepage, https://api.tej.com.tw
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: System :: Distributed Computing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: alembic (>=0.7.7)
Requires-Dist: bcolz-zipline (>=1.2.6)
Requires-Dist: bottleneck (>=1.0.0)
Requires-Dist: click (>=4.0.0)
Requires-Dist: empyrical-reloaded (>=0.5.7)
Requires-Dist: h5py (>=2.7.1)
Requires-Dist: intervaltree (>=2.1.0)
Requires-Dist: iso3166 (>=2.1.1)
Requires-Dist: iso4217 (>=1.6.20180829)
Requires-Dist: lru-dict (>=1.1.4)
Requires-Dist: multipledispatch (>=0.6.0)
Requires-Dist: networkx (>=2.0)
Requires-Dist: numexpr (>=2.6.1)
Requires-Dist: numpy (<1.24,>=1.14.5)
Requires-Dist: pandas (<1.6,>=1.3)
Requires-Dist: patsy (>=0.4.0)
Requires-Dist: python-dateutil (>=2.4.2)
Requires-Dist: python-interface (>=1.5.3)
Requires-Dist: pytz (>=2018.5)
Requires-Dist: requests (>=2.9.1)
Requires-Dist: scipy (>=0.17.1)
Requires-Dist: six (>=1.10.0)
Requires-Dist: sqlalchemy (<2,>=1.0.8A)
Requires-Dist: statsmodels (>=0.6.1)
Requires-Dist: ta-lib (>=0.4.09)
Requires-Dist: tables (>=3.4.3)
Requires-Dist: toolz (>=0.8.2)
Requires-Dist: exchange-calendars (==3.3.0)
Requires-Dist: tejapi
Provides-Extra: dev
Requires-Dist: flake8 (>=3.9.1) ; extra == 'dev'
Requires-Dist: black ; extra == 'dev'
Requires-Dist: pre-commit (>=2.12.1) ; extra == 'dev'
Requires-Dist: Cython (<3,>=0.29.21) ; extra == 'dev'
Provides-Extra: docs
Requires-Dist: Cython ; extra == 'docs'
Requires-Dist: Sphinx (>=1.3.2) ; extra == 'docs'
Requires-Dist: numpydoc (>=0.5.0) ; extra == 'docs'
Requires-Dist: sphinx-autobuild (>=0.6.0) ; extra == 'docs'
Requires-Dist: pydata-sphinx-theme ; extra == 'docs'
Requires-Dist: sphinx-markdown-tables ; extra == 'docs'
Requires-Dist: m2r2 ; extra == 'docs'
Provides-Extra: test
Requires-Dist: tox ; extra == 'test'
Requires-Dist: pytest (>=7.2.0) ; extra == 'test'
Requires-Dist: pytest-cov (>=3.0.0) ; extra == 'test'
Requires-Dist: pytest-xdist (>=2.5.0) ; extra == 'test'
Requires-Dist: pytest-timeout (>=1.4.2) ; extra == 'test'
Requires-Dist: parameterized (>=0.6.1) ; extra == 'test'
Requires-Dist: testfixtures (>=4.1.2) ; extra == 'test'
Requires-Dist: flake8 (>=3.9.1) ; extra == 'test'
Requires-Dist: matplotlib (>=1.5.3) ; extra == 'test'
Requires-Dist: responses (>=0.9.0) ; extra == 'test'
Requires-Dist: pandas-datareader (>=0.2.1) ; extra == 'test'
Requires-Dist: click (<8.1.0) ; extra == 'test'
Requires-Dist: coverage ; extra == 'test'
Requires-Dist: pytest-rerunfailures ; extra == 'test'

# Installation

## Requirements
* Zipline-reloaded 2.2.0
* Python 3.8 or above
* Microsoft Windows OS
* Python 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](https://www.anaconda.com/data-science-platform) as development environment.

* Download dependency packages. [(zipline-tej.yml)](/uploads/04b6deacb4850e807e28e9f0dcc82833/zipline-tej.yml)

* Start an Anaconda (base) prompt, create an virtual environment and install the appropriate versions of packages:

```
# create virtual env
$ conda env create -f zipline-tej.yml

# activate virtual env
$ conda activate zipline-tej

# install required packages
$ pip install zipline-tej

```
## Exchange Calendar Issues

We're now developing specfic on Taiwan securities backtesting strategy, so we're using the unique trading calendar created by ourselves.  [download]()

After downloaded the calendar file above, overwrite them into exchange_calendars folder.

\* Navigate to the exchange_calendars folder within site packages. This is typically located at C:\Users\\< your username >\Anaconda3\envs\zipline-tej\Lib\site-packages\exchange_calendars


# Quick start

## CLI Interface

The following code implements a simple buy_and_hold trading algorithm.

```python
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>

# 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.

## Jupyter Notebook 

### 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.

```python
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

```python
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

```python
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

```python
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]:
```
![output_3_0](/uploads/90b6240acf50bc0a6435edf09b86c3e8/output_3_0.png)


### Show trading process
```python
In[5]: 
result
[Out]:
```
<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>period_open</th>
      <th>period_close</th>
      <th>starting_value</th>
      <th>ending_value</th>
      <th>starting_cash</th>
      <th>ending_cash</th>
      <th>portfolio_value</th>
      <th>longs_count</th>
      <th>shorts_count</th>
      <th>long_value</th>
      <th>...</th>
      <th>treasury_period_return</th>
      <th>trading_days</th>
      <th>period_label</th>
      <th>algo_volatility</th>
      <th>benchmark_period_return</th>
      <th>benchmark_volatility</th>
      <th>algorithm_period_return</th>
      <th>alpha</th>
      <th>beta</th>
      <th>sharpe</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2020-01-03 05:30:00+00:00</th>
      <td>2020-01-03 01:01:00+00:00</td>
      <td>2020-01-03 05:30:00+00:00</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.000000e+06</td>
      <td>1.000000e+06</td>
      <td>1.000000e+06</td>
      <td>0</td>
      <td>0</td>
      <td>0.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>1</td>
      <td>2020-01</td>
      <td>NaN</td>
      <td>0.0</td>
      <td>NaN</td>
      <td>0.000000</td>
      <td>None</td>
      <td>None</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2020-01-06 05:30:00+00:00</th>
      <td>2020-01-06 01:01:00+00:00</td>
      <td>2020-01-06 05:30:00+00:00</td>
      <td>0.0</td>
      <td>3320.0</td>
      <td>1.000000e+06</td>
      <td>9.966783e+05</td>
      <td>9.999983e+05</td>
      <td>1</td>
      <td>0</td>
      <td>3320.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>2</td>
      <td>2020-01</td>
      <td>0.000019</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>-0.000002</td>
      <td>None</td>
      <td>None</td>
      <td>-11.224972</td>
    </tr>
    <tr>
      <th>2020-01-07 05:30:00+00:00</th>
      <td>2020-01-07 01:01:00+00:00</td>
      <td>2020-01-07 05:30:00+00:00</td>
      <td>3320.0</td>
      <td>6590.0</td>
      <td>9.966783e+05</td>
      <td>9.933817e+05</td>
      <td>9.999717e+05</td>
      <td>1</td>
      <td>0</td>
      <td>6590.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>3</td>
      <td>2020-01</td>
      <td>0.000237</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>-0.000028</td>
      <td>None</td>
      <td>None</td>
      <td>-10.038514</td>
    </tr>
    <tr>
      <th>2020-01-08 05:30:00+00:00</th>
      <td>2020-01-08 01:01:00+00:00</td>
      <td>2020-01-08 05:30:00+00:00</td>
      <td>6590.0</td>
      <td>9885.0</td>
      <td>9.933817e+05</td>
      <td>9.900850e+05</td>
      <td>9.999700e+05</td>
      <td>1</td>
      <td>0</td>
      <td>9885.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>4</td>
      <td>2020-01</td>
      <td>0.000203</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>-0.000030</td>
      <td>None</td>
      <td>None</td>
      <td>-9.298128</td>
    </tr>
    <tr>
      <th>2020-01-09 05:30:00+00:00</th>
      <td>2020-01-09 01:01:00+00:00</td>
      <td>2020-01-09 05:30:00+00:00</td>
      <td>9885.0</td>
      <td>13500.0</td>
      <td>9.900850e+05</td>
      <td>9.867083e+05</td>
      <td>1.000208e+06</td>
      <td>1</td>
      <td>0</td>
      <td>13500.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>5</td>
      <td>2020-01</td>
      <td>0.001754</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.000208</td>
      <td>None</td>
      <td>None</td>
      <td>5.986418</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>2021-12-24 05:30:00+00:00</th>
      <td>2021-12-24 01:01:00+00:00</td>
      <td>2021-12-24 05:30:00+00:00</td>
      <td>2920920.0</td>
      <td>2917320.0</td>
      <td>-1.308854e+06</td>
      <td>-1.314897e+06</td>
      <td>1.602423e+06</td>
      <td>1</td>
      <td>0</td>
      <td>2917320.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>484</td>
      <td>2021-12</td>
      <td>0.232791</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.602423</td>
      <td>None</td>
      <td>None</td>
      <td>1.170743</td>
    </tr>
    <tr>
      <th>2021-12-27 05:30:00+00:00</th>
      <td>2021-12-27 01:01:00+00:00</td>
      <td>2021-12-27 05:30:00+00:00</td>
      <td>2917320.0</td>
      <td>2933040.0</td>
      <td>-1.314897e+06</td>
      <td>-1.320960e+06</td>
      <td>1.612080e+06</td>
      <td>1</td>
      <td>0</td>
      <td>2933040.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>485</td>
      <td>2021-12</td>
      <td>0.232577</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.612080</td>
      <td>None</td>
      <td>None</td>
      <td>1.182864</td>
    </tr>
    <tr>
      <th>2021-12-28 05:30:00+00:00</th>
      <td>2021-12-28 01:01:00+00:00</td>
      <td>2021-12-28 05:30:00+00:00</td>
      <td>2933040.0</td>
      <td>2982750.0</td>
      <td>-1.320960e+06</td>
      <td>-1.327113e+06</td>
      <td>1.655637e+06</td>
      <td>1</td>
      <td>0</td>
      <td>2982750.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>486</td>
      <td>2021-12</td>
      <td>0.233086</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.655637</td>
      <td>None</td>
      <td>None</td>
      <td>1.237958</td>
    </tr>
    <tr>
      <th>2021-12-29 05:30:00+00:00</th>
      <td>2021-12-29 01:01:00+00:00</td>
      <td>2021-12-29 05:30:00+00:00</td>
      <td>2982750.0</td>
      <td>2993760.0</td>
      <td>-1.327113e+06</td>
      <td>-1.333276e+06</td>
      <td>1.660484e+06</td>
      <td>1</td>
      <td>0</td>
      <td>2993760.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>487</td>
      <td>2021-12</td>
      <td>0.232850</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.660484</td>
      <td>None</td>
      <td>None</td>
      <td>1.243176</td>
    </tr>
    <tr>
      <th>2021-12-30 05:30:00+00:00</th>
      <td>2021-12-30 01:01:00+00:00</td>
      <td>2021-12-30 05:30:00+00:00</td>
      <td>2993760.0</td>
      <td>2995050.0</td>
      <td>-1.333276e+06</td>
      <td>-1.339430e+06</td>
      <td>1.655620e+06</td>
      <td>1</td>
      <td>0</td>
      <td>2995050.0</td>
      <td>...</td>
      <td>0.0</td>
      <td>488</td>
      <td>2021-12</td>
      <td>0.232629</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.655620</td>
      <td>None</td>
      <td>None</td>
      <td>1.235305</td>
    </tr>
  </tbody>
</table>
<p>488 rows × 38 columns</p>
</div>


## 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
* Any [suggestions]()
* To get TEJAPI_KEY [(link)](https://api.tej.com.tw/trial.html)
* [TEJ Official Website](https://www.tej.com.tw/)
