/pytrading

Algorithmic Trading in Python

Primary LanguagePythonMIT LicenseMIT

pytrading

GitHub license Code Climate

Python-library for algorithmic trading based on technical indicators with backtesting ability. Data is pulled from the Yahoo Finance API.

Installation

Clone repository, setup virtual environment, and install dependencies:

git clone git@github.com:tuinvest/pytrading.git
cd pytrading/
python3 -m venv venv/
source venv/bin/activate
pip install -r requirements.txt

Basics

To create a PyTrading strategy you only have to subclass the AbstractStrategy class from the pytrading.entities module. You are required to implement two methods: initialize and handle_data. The initialize method requires you to set a few configuration variables that specify how the strategy is executed. Below we create a strategy whose asset universe include Pepsi (PEP) and Coca-Cola (KO).

from pytrading.entities import AbstractStrategy

class ExampleStrategy(AbstractStrategy):
    def initialize(self):
        self.universe = ['PEP', 'KO']

    def handle_data(self, data, indicators=None):
		pass

strategy = ExampleStrategy()
strategy.run()

The handle_data will be called for every trading day with a data dictionary that uses the security tickers as keys and pandas.DataFrame objects as values. These pandas.DataFrame objects contain Low, High, Open, Close and Adj Close as columns. PyTrading relies heavily on the data structures provided by pandas.

Indicators

Since no behavior is defined for the handle_data method the above strategy will do nothing. Indicators can be used to generate trading signals. They can be utilized by passing a dictionary of the form {'INDICATOR_NAME': indicator_method} to the context constructor. INDICATOR_NAME is the name by which the indicator data can be accessed later on. indicator_method is a method which takes a security's DataFrame object as an input and returns the calculated indicator. The indicator data is provided to a strategy's handle_data method as well.

from pytrading.entities import AbstractStrategy
from pytrading.indicators import with_series


@with_series('Adj Close')
def momentum(series):
    return series - series.shift()  # Change to previous day


class ExampleStrategy(AbstractStrategy):
    def initialize(self):
        self.universe=['PEP', 'KO']
        self.indicators={ 'MOMENTUM': momentum }

    def handle_data(self, data, indicators=None):
        pass

Simply passing the momentum method as an indicator method will not work since it takes a series instead of data frame as an argument. The with_series decorator can be used to create a method that will call the indicator method with only the data from the specified column label (in this case Adj Close).

The indicators can be used to define a simple strategy:

from pytrading.entities import AbstractStrategy
from pytrading.indicators import with_series


@with_series('Adj Close')
def momentum(series):
    return series - series.shift()  # Change to previous day


class MomentumStrategy(AbstractStrategy):
    def initialize(self):
        self.universe=['PEP', 'KO']
        self.skip_days=1  # Skip the first day
        self.indicators={ 'MOMENTUM': momentum }

    def handle_data(self, data, indicators=None):
        sec_weight = 1 / len(self.universe)

        for sec in self.universe:
            if indicators[sec]['MOMENTUM'][-1] > 0.0:
                # Buy at next price, if security closed with an uptick
                self.environment.order_target_percent(sec, sec_weight)
            else:
                # Sell at next price, if security closed with a downtick
                self.environment.order_target_percent(sec, 0.0)

strategy = MomentumStrategy()
strategy.run()

We buy the stocks that performed well and sell those that did perform well during the last day. We additionally set the variable skip_days since we cannot calculate momentum data for the first day since that would require the closing price of the day before the first day.