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.
Install with pip:
$ pip install filib
Proposed workflow contains three steps. Here's an example:
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
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", "U
73BC
SD_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
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
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.