Files
strategy-lab/to_explore/pyquantnews/34_ZiplineBacktesting.ipynb
David Brazda e3da60c647 daily update
2024-10-21 20:57:56 +02:00

10 KiB

No description has been provided for this image

This code implements a trading algorithm using Zipline, simulating trades on Apple Inc. (AAPL) stock based on moving average crossovers. It initializes the trading environment, defines trading logic, and records relevant data. The algorithm is backtested over a specified time period, and performance metrics are analyzed and visualized using Pyfolio. This is useful for developing and evaluating trading strategies in a systematic manner.

In [ ]:
import pandas as pd
import pandas_datareader.data as web
In [ ]:
import matplotlib.pyplot as plt
In [ ]:
from zipline import run_algorithm
from zipline.api import order_target, record, symbol
from zipline.finance import commission, slippage
In [ ]:
import pyfolio as pf
In [ ]:
import warnings
warnings.filterwarnings('ignore')

Load the Zipline extension for Jupyter notebooks

In [ ]:
%load_ext zipline

Ingest historical data from Quandl for Zipline to use

In [ ]:
! zipline ingest -b quandl
In [ ]:
def initialize(context):
    """Initialize the trading algorithm

    Sets up initial parameters and trading environment.

    Parameters
    ----------
    context : zipline.assets.context
        The algorithm's context, including variables and state.
    """

    context.i = 0
    context.asset = symbol("AAPL")

    context.set_commission(commission.PerShare(cost=0.01))
    context.set_slippage(slippage.FixedSlippage(spread=0.01))
In [ ]:
def handle_data(context, data):
    """Handle the trading logic

    Executes trading logic based on moving averages.

    Parameters
    ----------
    context : zipline.assets.context
        The algorithm's context, including variables and state.
    data : zipline.protocol.BarData
        Contains current and historical market data.
    """

    context.i += 1
    if context.i < 50:
        return

    short_mavg = data.history(
        context.asset, 
        "price", 
        bar_count=14,
        frequency="1d"
    ).mean()
    
    long_mavg = data.history(
        context.asset,
        "price",
        bar_count=50,
        frequency="1d"
    ).mean()

    if short_mavg > long_mavg:
        order_target(context.asset, 100)
    elif short_mavg < long_mavg:
        order_target(context.asset, 0)

    record(
        AAPL=data.current(context.asset, "price"),
        short_mavg=short_mavg,
        long_mavg=long_mavg,
    )
In [ ]:
def analyze(context, perf):
    """Analyze the performance of the algorithm

    Visualizes the portfolio and stock performance.

    Parameters
    ----------
    context : zipline.assets.context
        The algorithm's context, including variables and state.
    perf : pandas.DataFrame
        A dataframe containing the performance metrics.
    """

    fig = plt.figure()
    ax1 = fig.add_subplot(211)
    perf.portfolio_value.plot(ax=ax1)
    ax1.set_ylabel("portfolio value in $")

    ax2 = fig.add_subplot(212)
    perf["AAPL"].plot(ax=ax2)
    perf[["short_mavg", "long_mavg"]].plot(ax=ax2)

    perf_trans = perf.loc[
        [t != [] for t in perf.transactions]
    ]
    buys = perf_trans.loc[
        [t[0]["amount"] > 0 for t in perf_trans.transactions]
    ]
    sells = perf_trans.loc[
        [t[0]["amount"] < 0 for t in perf_trans.transactions]
    ]
    ax2.plot(
        buys.index,
        perf.short_mavg.loc[buys.index],
        "^",
        markersize=10,
        color="m"
    )
    ax2.plot(
        sells.index,
        perf.short_mavg.loc[sells.index],
        "v",
        markersize=10,
        color="k"
    )
    ax2.set_ylabel("price in $")
    plt.legend(loc=0)
    plt.show()

Define the start and end dates for the backtesting period

In [ ]:
start = pd.Timestamp('2000')
end = pd.Timestamp('2018')

Fetch the benchmark returns for the S&P 500 index from the Federal Reserve Economic Data (FRED)

In [ ]:
sp500 = web.DataReader('SP500', 'fred', start, end).SP500
benchmark_returns = sp500.pct_change()

Run the algorithm with the specified parameters and historical data

In [ ]:
perf = run_algorithm(
    start=start,
    end=end,
    initialize=initialize,
    handle_data=handle_data,
    analyze=analyze,
    capital_base=100000,
    benchmark_returns=benchmark_returns,
    bundle="quandl",
    data_frequency="daily",
)

Display the performance metrics of the algorithm

In [ ]:
perf.info()

Extract returns, positions, and transactions from the performance DataFrame for analysis

In [ ]:
returns, positions, transactions = \
    pf.utils.extract_rets_pos_txn_from_zipline(perf)

Create a full tear sheet using Pyfolio to analyze the trading strategy's performance

In [ ]:
pf.create_full_tear_sheet(
    returns,
    positions=positions,
    transactions=transactions,
    live_start_date="2016-01-01",
    round_trips=True,
)
In [ ]:
 

PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.