Zipline

repository·master·Indexed 12 days ago

https://github.com/quantopian/zipline

A Pythonic, event-driven algorithmic trading library for backtesting trading strategies. It integrates with Pandas and NumPy and features a Pipeline API for data processing, a comprehensive set of order management functions (such as order, order_target, and order_value), and tools for managing data bundles and trading calendars. It supports execution via CLI, IPython Notebooks, and the zipline.run_algorithm entry point.

Tokens
17.1K
Snippets
62
Records
84
Agent score
97%

What's inside Zipline

  1. What is a Trading Calendar in Zipline

    master

    A TradingCalendar represents the timing information of a single market exchange. It is the parent class for all exchange calendars in Zipline. A calendar consists of two primary components:

    1. Sessions: A contiguous set of minutes. Sessions are labeled using midnight UTC (used for convenience, not as a specific point in time).
    2. Opens/Closes: The specific times the market opens and closes.

    Crucial Requirement: The dates accounted for in your data bundle must match the dates in your TradingCalendar. If they do not match (e.g., your calendar says the market is closed on a Saturday, but your data bundle contains Saturday price data), you will encounter errors during backtesting.

  2. Properties of the TradingCalendar class

    master

    When implementing a custom TradingCalendar by subclassing zipline.utils.calendars.trading_calendar.TradingCalendar, you can define several key properties to model an exchange:

    • name: The identifier for the exchange.
    • tz: The timezone of the exchange.
    • open_time: The daily opening time.
    • close_time: The daily closing time.
    • regular_holidays: A collection of holiday objects.
    • Special opens and closes (ad hoc sessions).
  3. Use the Algorithm API in initialize, handle_data, and before_trading_start

    master
    The following API categories provide methods available within the core algorithm lifecycle functions: initialize, handle_data, and before_trading_start. In these functions, the self argument refers to the currently-executing zipline.algorithm.TradingAlgorithm instance.
  4. Use the Pipeline API for data processing

    master

    The Pipeline API allows for efficient data processing and factor calculation.

    Core Pipeline Components:

    • Pipeline: The main container for factor calculations.
    • CustomFactor: Allows defining custom logic for factors.
    • Filter: Used to filter assets (supports __and__, __or__, if_else).
    • Term: Represents a single component of a factor.
    • DataSet & Column: Access data points.

    Pipeline Engine:

    • PipelineEngine: Executes the pipeline via run_pipeline or run_chunked_pipeline.
    • SimplePipelineEngine: A basic implementation of the engine.

    Integration:

    • attach_pipeline: Attach a pipeline to a simulation.
    • pipeline_output: Retrieve results from a pipeline.
  5. How to define a custom metric

    master

    A metric is an object that implements one or more of the following lifecycle methods to collect and report data during a simulation:

    • start_of_simulation: Initialize caches for the simulation.
    • end_of_simulation: Finalize and write end-of-simulation values.
    • start_of_session: Handle changes occurring between sessions (e.g., futures price moves).
    • end_of_session: Report daily or cumulative performance.
    • end_of_bar: Report minute-level performance (only called if emission_rate is minute).

    Metrics should be reusable; a single instance of a metric class should be able to be used across multiple backtests by resetting its internal state in start_of_simulation.

  6. Understand the core structure of a Zipline algorithm

    master

    Every Zipline algorithm is built around two mandatory functions that the simulator calls automatically:

    1. initialize(context): Called once before the simulation starts. It receives a context object, which serves as a persistent namespace. You should use context to store variables that need to persist across multiple iterations of the algorithm (e.g., state, parameters, or custom objects).

    2. handle_data(context, data): Called once for every event (e.g., every minute or day, depending on your data frequency). It receives the same context object and a data object (the event-frame). The data object contains the current trading bar (OHLC prices and volume) for all assets in your universe.

    All common trading functions are imported from zipline.api.

    from zipline.api import order, record, symbol
    
    def initialize(context):
        # Set up persistent state here
        pass
    
    def handle_data(context, data):
        # Logic executed at every event
        pass
  7. How to build a custom TradingCalendar

    master

    To create a custom exchange calendar, subclass TradingCalendar and implement the required properties. You can use pandas.tseries.holiday.Holiday to define specific holiday rules and pandas.tseries.offsets.CustomBusinessDay to define which days of the week the exchange is open.

    Example of a 24/7 exchange calendar using UTC:

    from datetime import time
    import pandas as pd
    from pandas.tseries.offsets import CustomBusinessDay
    from pytz import timezone
    from trading_calendars import register_calendar, TradingCalendar
    from zipline.utils.memoize import lazyval
    
    class TFSExchangeCalendar(TradingCalendar):
        """
        An exchange calendar for trading assets 24/7.
    
        Open Time: 12AM, UTC
        Close Time: 11:59PM, UTC
        """
    
        @property
        def name(self):
          """
          The name of the exchange, which Zipline will look for
          when we run our algorithm and pass TFS to
          the --trading-calendar CLI flag.
          """
          return "TFS"
    
        @property
        def tz(self):
          """
          The timezone in which we'll be running our algorithm.
          """
          return timezone("UTC")
    
        @property
        def open_time(self):
          """
          The time in which our exchange will open each day.
          """
          return time(0, 0)
    
        @property
        def close_time(self):
          """
          The time in which our exchange will close each day.
          """
          return time(23, 59)
    
        @lazyval
        def day(self):
          """
          The days on which our exchange will be open.
          """
          weekmask = "Mon Tue Wed Thu Fri Sat Sun"
          return CustomBusinessDay(
            weekmask=weekmask
          )
    class TFSExchangeCalendar(TradingCalendar):
        @property
        def name(self):
          return "TFS"
    
        @property
        def tz(self):
          return timezone("UTC")
    
        @property
        def open_time(self):
          return time(0, 0)
    
        @property
        def close_time(self):
          return time(23, 59)
    
        @lazyval
        def day(self):
          weekmask = "Mon Tue Wed Thu Fri Sat Sun"
          return CustomBusinessDay(weekmask=weekmask)
  8. Manage Zipline environments with Conda

    master

    It is recommended to install Zipline in an isolated conda environment to prevent conflicts with your global Python installation.

    Note on Python versions: The conda-forge channel provides Zipline 1.4.0+ for Python 3.6. For older versions of Zipline on Python 2.7, 3.5, or 3.6, you can use the Quantopian channel, though it is no longer being updated.

    # 1. Create an isolated environment (e.g., for Python 3.6)
    $ conda create -n env_zipline python=3.6
    
    # 2. Activate the environment
    $ conda activate env_zipline
    
    # 3. Install Zipline from conda-forge
    (env_zipline) $ conda install -c conda-forge zipline
    
    # OR: Install older versions from the Quantopian channel
    (env_zipline) $ conda install -c Quantopian zipline
    
    # 4. Deactivate when finished
    (env_zipline) $ conda deactivate
  9. Install binary dependencies for Zipline on OSX

    master

    It is recommended to use a separate Python installation (e.g., via Homebrew) rather than the system Python. If using Homebrew, install the following packages to satisfy Zipline's dependencies:

    $ brew install freetype pkg-config gcc openssl hdf5
  10. Run Zipline style checks and tests

    master

    Zipline uses flake8 for style enforcement and nosetests for running the test suite. Before submitting any pull requests, ensure your code passes style checks and all tests.

    Prerequisite: TA-lib installation To run tests locally, you must have TA-lib installed on your system.

    Linux Installation:

    $ wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
    $ tar -xvzf ta-lib-0.4.0-src.tar.gz
    $ cd ta-lib/
    $ ./configure --prefix=/usr
    $ make
    $ sudo make install

    macOS Installation:

    $ brew install ta-lib

    Python Package Installation: After the system library is installed, install the Python bindings:

    $ pip install -r ./etc/requirements_talib.in -c ./etc/requirements_locked.txt
    # Check style
    $ flake8 zipline tests
    
    # Run tests
    $ nosetests
  11. Update Zipline dependencies

    master

    Zipline manages dependencies using .in files and a requirements_locked.txt lockfile via pip-compile.

    Bumping a dependency lower bound

    If a code change requires a newer version of a library, update the lower bound in etc/requirements.in (or etc/requirements_dev.in) and re-run the pip-compile command found in the header of etc/requirements_locked.txt.

    Updating a dependency in CI without changing the lower bound

    To update a library to a newer version in CI environments without changing the minimum required version in the source, use the --upgrade-package or -P flag with pip-compile:

    $ pip-compile --output-file=etc/reqs.txt etc/reqs.in ... -P six==1.13.0 -P "click>4.0.0"