pxtrade
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",
)
columns = ["Portfolio", "Benchmark"]
df[columns].iplot(
title="Portfolio Value",
)
Metadata
Release files for pxtrade 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pxtrade-0.2.0.tar.gz | 18.1 kB | Without provenance | Details for pxtrade-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pxtrade-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for pxtrade-0.2.0-py3-none-any.whl |
Total release size: 43.7 kB
Release files / pxtrade-0.2.0.tar.gz
| Download URL | pxtrade-0.2.0.tar.gz |
|---|---|
| Size | 18.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
53588b760df9e304ee39e1f146461bec84a62f589fa0842d645f98f60ac22af9
|
|
BLAKE2b-256 checksum How to use checksums |
a63f3e4c4d2296a82d8a225c67273f110130d8f9517717074e19212a0158f49e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.8.3
|
Release files / pxtrade-0.2.0-py3-none-any.whl
| Download URL | pxtrade-0.2.0-py3-none-any.whl |
|---|---|
| Size | 25.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7f6e553d22a9c20f9b899e2353120a383745550bcb4e7d4179c0a2a751c550cd
|
|
BLAKE2b-256 checksum How to use checksums |
a44e8758ef3cd649bf60791ce4bb424b34dc3e989201bf4536ed6612a09c2e68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.8.3
|
Security for pxtrade 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.