Skip to content

prmkowalski/filib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

filib

PyPI - Python Version

PyPI

PyPI - Status

GitHub

CI - Status

Black

Factor Investing LIBrary is a lightweight algorithmic trading Python library built for easy testing of predictive factors and portfolio rebalance via Oanda. Inspired by and compatible with Quantopian Open Source.

NOTE: This library is currently in alpha stage. Until it becomes stable I strongly recommend using practice account for testing and trading. You can also expect major changes without warnings, mostly responses to Issues.

Changelog »

Installation

Install with pip:

$ pip install filib

Usage

Proposed workflow contains three steps. Here's an example:

1. Assemble

Begin with imports, create hypotheses and write functions with predictive factors:

from filib.oanda import Oanda  # Currently only Oanda FOREX is available
from filib.helpers import *  # Optional, useful for factor generation


class MyFactors(Oanda):
    def momentum(self):  # THEORY: Persistence in asset performance
        factor = self.returns  # Write down your factor formula
        return factor  # By default split factor data to 3 quantiles

    @swap_sign  # Short high and long low factor values
    def relative_strenght_index(self):  # THEORY: Oversold / overbought indicator
        factor = rsi(self.close, 14)
        split = [0, 30, 70, 100]  # List of thresholds or int to split equally
        return factor, split  # Follow this order: factor, split

    def big_mac_index(self):  # THEORY: Simplified Purchasing Power Parity
        import quandl  # Financial, Economic and Alternative Data

        iso_codes = get_iso_codes(self.price_data)
        codes = [f"ECONOMIST/BIGMAC_{COUNTRY}.5" for COUNTRY in iso_codes]
        factor = quandl.get(codes).dropna(how="all", axis=1)
        factor.columns = [iso_codes[c.split("_")[1].split()[0]] for c in factor]
        factor.index = factor.index.tz_localize("UTC")  # Convert time zone to UTC
        return factor

2. Research

Initialize parameters (during the first run you will be asked to provide credentials):

model = MyFactors(
    instruments=["EUR_USD", "GBP_USD", "USD_JPY", "AUD_USD", "NZD_USD", "USD_CAD",
                 "USD_CHF", "USD_NOK", "USD_SEK"],  # Define universe
    symbol="USD",  # Optional, specify symbol to arrange price data
    granularity="D",  # Time period between each candle and between each rebalance
    count=500,  # Number of historical OHLCV candles to return for analysis
    periods=(1, 2, 3),  # Optional, specify periods for factor decay analysis
    split=3,  # Number of quantiles to split combined factor data
    long_short=True,  # Trade only top and bottom factor quantile
    combination="sum_of_weights",  # Formula for combining factors together
    leverage=3,  # Multiplier for the portfolio positions
)

Check the performance of factors combined together:

>>> model.performance()
Collecting price data: |██████████████████████████████| 9/9 [100%] in 4.0 s
Preparing factor data: |██████████████████████████████| 3/3 [100%] in 12.0 s

MyFactors - INFO - Factor `MyFactors_combined` Analytics:

                Min    Max    Mean   Size    Returns (bps)
                factor factor factor factor            1D     2D     3D
factor_quantile
1.0             -1.003  0.000 -0.237   1499        -1.337 -2.068 -2.320
2.0             -0.243  0.210  0.005   1461        -2.582 -3.299 -5.138
3.0             -0.027  0.973  0.238   1459         0.892 -0.835 -2.266

                            1D     2D     3D
- Information Coefficient:  0.037  0.001  0.0
- Factor Rank Autocorrelation: 0.05

- Annualized Sharpe Ratio: 0.76
- Annualized Alpha (Beta): 0.080 (0.042)
- Win Rate: 52.55%
- Risk / Reward: 1.02
- Profit Factor: 1.15

- Start Date: 2018-07-11
- End Date: 2020-05-27
- Duration: 686 days 00:00:00 (1.9 years)
- Rebalance every: 1D

- Compound Annual Growth Rate: 7.78%
- Annualized Volatility: 10.44%
- Maximum Drawdown: -11.49%
- Maximum Drawdown Duration: 434 days 00:00:00
...

Alternatively set selection rules with a query string to evaluate. Available metrics:

  • ic: Information Coefficient based on Spearman Rank Correlation
  • autocorr: Factor Rank Autocorrelation
  • sharpe: Annualized Sharpe Ratio
  • beta: Annualized Beta as exposure to trading universe
  • alpha: Annualized Alpha as excess returns over trading universe
  • win: Win Rate
  • rr: Risk / Reward Ratio
  • profit: Profit Factor = (sum of earnings) / (sum of losses)
  • cagr: Compound Annual Growth Rate

Then analyze the performance of individual factors and select those that meet the rules:

>>> model.select(
...     rules="abs(ic) > .01 or profit > 1",  # Example query expression
...     swap_to="cagr",  # Align the signs of selected factors to specified metric
...     inplace=True,  # Modify model to contain only selected factors
... )
Preparing performance: |██████████████████████████████| 3/3 [100%] in 6.2 s

MyFactors - INFO - Factors with signs that meet the rules `abs(ic) > .01 or profit > 1`:

big_mac_index             -1.0
momentum                   1.0
relative_strenght_index    1.0

3. Trade

Check portfolio positions based on selected factors and generated submitted orders:

PLEASE USE AT YOUR OWN RISK - THIS CAN TRADE REAL MONEY - NO WARRANTY IS GIVEN

>>> model.rebalance(
...     accountID="",  # Your Oanda Account Identifier
...     live=True,  # Actually place orders
... )
MyFactors - INFO - Portfolio from `2020-05-28 00:00:00+00:00`:

NOK    -19.5%
SEK    -15.3%
CHF    -15.2%
AUD      0.0%
EUR      0.0%
GBP      0.0%
NZD      9.0%
CAD     15.3%
JPY     25.8%

- Account NAV: 8423.77 EUR
- Position Value: 25382.12
- Submitted Orders:

USD_JPY   -7240
NZD_USD    4050
USD_CAD   -4280
USD_CHF    4260
USD_NOK    5490
USD_SEK    4280

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.