Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/simongarisch/pxtrade
A multi currency, event driven backtester written in Python.
https://github.com/simongarisch/pxtrade
backtest bitcoin event fx python stock trade trading
Last synced: 29 days ago
JSON representation
A multi currency, event driven backtester written in Python.
- Host: GitHub
- URL: https://github.com/simongarisch/pxtrade
- Owner: simongarisch
- License: mit
- Created: 2020-09-07T04:08:11.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-03-01T02:55:55.000Z (almost 4 years ago)
- Last Synced: 2024-11-27T09:01:57.579Z (about 2 months ago)
- Topics: backtest, bitcoin, event, fx, python, stock, trade, trading
- Language: Python
- Homepage:
- Size: 4.78 MB
- Stars: 2
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## pxtrade
[![Python](https://img.shields.io/badge/python-v3-brightgreen.svg)](https://www.python.org/)
[![Build Status](https://travis-ci.org/simongarisch/pxtrade.svg?branch=master)](https://travis-ci.org/simongarisch/pxtrade)
[![Coverage Status](https://coveralls.io/repos/github/simongarisch/pxtrade/badge.svg)](https://coveralls.io/github/simongarisch/pxtrade?branch=master)
[![PyPI version](https://badge.fury.io/py/pxtrade.svg)](https://badge.fury.io/py/pxtrade)
[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
[![Codestyle](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Maintainability](https://api.codeclimate.com/v1/badges/22d56bf02ecbd8ccea22/maintainability)](https://codeclimate.com/github/simongarisch/pxtrade/maintainability)A multi currency, event driven backtester written in Python.
### Installation
```bash
pip install pxtrade
```### Examples
[Notebooks](https://github.com/simongarisch/pxtrade/tree/master/notes) are available to cover the main concepts and examples.
- [equities buy and hold](https://github.com/simongarisch/pxtrade/blob/master/notes/06%20Example%20-%20Buy%20And%20Hold.ipynb)
- [fx trading](https://github.com/simongarisch/pxtrade/blob/master/notes/08%20Example%20-%20FX.ipynb)
- [bitcoin](https://github.com/simongarisch/pxtrade/blob/master/notes/09%20Example%20-%20Bitcoin.ipynb)
- [Intraday trading](https://github.com/simongarisch/pxtrade/blob/master/notes/11%20Example%20-%20FX%20Intraday%20with%20Benchmark.ipynb)### Assets and Portfolios
Before we can run a backtest we need to define the assets and portfolios involved.
```python
from pxtrade.assets import reset, Cash, Stock, FxRate, Portfolioreset()
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')
```python
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
```python
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](https://github.com/simongarisch/pxtrade/blob/master/notes/02%20The%20Trade%20Lifecycle.ipynb).```python
from pxtrade.compliance import Compliance, UnitLimitfor 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](https://github.com/simongarisch/pxtrade/blob/master/pxtrade/broker/execution.py#L6) or [AbstractCharges](https://github.com/simongarisch/pxtrade/blob/master/pxtrade/broker/charges.py#L8). Note that backtesting supports multiple currencies. The portfolio could be denominated in USD, for example, but broker charges defined in AUD terms.```python
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 of trades.```python
from pxtrade import Strategy, Tradeclass 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.```python
from pxtrade import Backtest, Historybacktest = Backtest(ExampleStrategy())
history = History(
portfolios=[portfolio, benchmark],
backtest=backtest
)
```### [Loading event data](https://github.com/simongarisch/pxtrade/blob/master/notes/05%20Bulk%20Event%20Loads.ipynb)
Events can be loaded either from yahoo finance or from an existing data frame.```python
from datetime import date
from pxtrade.events.yahoo import load_yahoo_pricesstart_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
```python
backtest.run()df = history.get()
``````python
df.columns
```
Index(['AUD', 'AUDUSD', 'Benchmark', 'Benchmark_AUD', 'Benchmark_SPY',
'Benchmark_USD', 'Portfolio', 'Portfolio_AUD', 'Portfolio_SPY',
'Portfolio_USD', 'SPY', 'USD'],
dtype='object')```python
import cufflinks as cfcolumns = ["Portfolio_SPY", "Benchmark_SPY", "SPY"]
df[columns].iplot(
secondary_y="SPY",
title="Portfolio Holdings of SPY",
)
```
![holdings](https://github.com/simongarisch/pxtrade/blob/master/notes/portfolio_holdings_of_spy.png?raw=true)```python
columns = ["Portfolio", "Benchmark"]
df[columns].iplot(
title="Portfolio Value",
)
```
![holdings](https://github.com/simongarisch/pxtrade/blob/master/notes/portfolio_value.png?raw=true)***