Skip to main content

A multi currency, event driven backtester written in Python.

Project description

pxtrade

Build Status Coverage Status

A multi currency, event driven backtester written in Python.

Installation

pip install pxtrade

Examples

Notebooks are available to cover the main concepts and examples.

Assets and Portfolios

Before we can run a backtest we need to define the assets and portfolios involved.

from pxtrade.assets import reset, Cash, Stock, FxRate, Portfolio


reset()
aud = Cash("AUD")
usd = Cash("USD")
audusd = FxRate("AUDUSD")
spy = Stock("SPY")
portfolio = Portfolio("USD", code="Portfolio")  # a portfolio denominated in USD
benchmark = Portfolio("USD", code="Benchmark")

print(portfolio)

Portfolio('USD')

portfolio.transfer(usd, 1e6)  # start both with 1M USD
benchmark.transfer(usd, 1e6)

print(portfolio)

Portfolio('USD'): Cash('USD', 1.0, currency_code='USD'): 1,000,000

portfolio.value

1000000.0

Imposing portfolio constraints through compliance

Ideally there will be risk limits in place when running a backtest. Some concrete compliance rules are provided, but you can also define your own by inheriting from ComplianceRule.

from pxtrade.compliance import Compliance, UnitLimit


for port in [portfolio, benchmark]:
    port.compliance = Compliance().add_rule(
        UnitLimit(spy, 1000)
    )

Defining a portfolio broker

Different portfolios / strategies are likely to vary materially in broker charges. All portfolios have a default broker that executes trades at the last price with no charge (or slippage). Brokers have separate execution and charges strategies. You can use the classes available or define custom strategies by inheriting from AbstractExecution or AbstractCharges. Note that backtesting supports multiple currencies. The portfolio could be denominated in USD, for example, but broker charges defined in AUD terms.

from pxtrade.broker import (
    Broker, 
    FillAtLastWithSlippage,
    FixedRatePlusPercentage,
)


portfolio.broker = Broker(
    execution_strategy=FillAtLastWithSlippage(0),  # no slippage, just fill at last
    charges_strategy=FixedRatePlusPercentage(20, 0, currency_code="AUD")  # fixed charge of AUD 20 per trade.
)

Defining a trading strategy

All strategy classes must inherit from pxtrade.Strategy and implement a generate_trades method. Note that the trades returned can either be None, a trade instance or list or trades.

from pxtrade import Strategy, Trade 


class ExampleStrategy(Strategy):
    def generate_trades(self):
        trades = list()

        # get the portfolio trades first
        if spy.price < 330:
            trades.append(Trade(portfolio, spy, +100))

        trades.append(Trade(benchmark, spy, +1000))

        return trades

The backtest instance and trade history

A backtest takes a strategy instance as its argument. Any instances of History then record state through time as events are processed.

from pxtrade import Backtest, History


backtest = Backtest(ExampleStrategy())

history = History(
    portfolios=[portfolio, benchmark],
    backtest=backtest
)

Loading event data

Events can be loaded either from yahoo finance or from an existing data frame.

from datetime import date
from pxtrade.events.yahoo import load_yahoo_prices


start_date = date(2020, 6, 30)
end_date = date(2020, 9, 30)

load_yahoo_prices(
    [spy, audusd], backtest,
    start_date=start_date,
    end_date=end_date,
)

Running the backtest and collecting history

backtest.run()

df = history.get()
df.columns
Index(['AUD', 'AUDUSD', 'Benchmark', 'Benchmark_AUD', 'Benchmark_SPY',
       'Benchmark_USD', 'Portfolio', 'Portfolio_AUD', 'Portfolio_SPY',
       'Portfolio_USD', 'SPY', 'USD'],
      dtype='object')
import cufflinks as cf


columns = ["Portfolio_SPY", "Benchmark_SPY", "SPY"]
df[columns].iplot(
    secondary_y="SPY",
    title="Portfolio Holdings of SPY",
)

holdings

columns = ["Portfolio", "Benchmark"]
df[columns].iplot(
    title="Portfolio Value",
)

holdings


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pxtrade-0.2.0.tar.gz (18.1 kB view hashes)

Uploaded Source

Built Distribution

pxtrade-0.2.0-py3-none-any.whl (25.7 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page