Overall Statistics |
Total Trades 37 Average Win 9.14% Average Loss -0.19% Compounding Annual Return 24.007% Drawdown 18.000% Expectancy 29.520 Net Profit 197.857% Sharpe Ratio 1.688 Probabilistic Sharpe Ratio 86.366% Loss Rate 39% Win Rate 61% Profit-Loss Ratio 49.14 Alpha 0.191 Beta 0.322 Annual Standard Deviation 0.151 Annual Variance 0.023 Information Ratio 0.299 Tracking Error 0.188 Treynor Ratio 0.793 Total Fees $1111.45 Estimated Strategy Capacity $120000000.00 Lowest Capacity Asset TLT SGNKIKYGE9NP |
import numpy as np import pandas as pd class NaturalResources(QCAlgorithm): def Initialize(self): self.SetStartDate(2016, 7, 1) self.SetCash(1000000) self.SetBrokerageModel(BrokerageName.AlphaStreams) rebalance_period = timedelta(days=7) self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel(rebalance_period)) self.Settings.RebalancePortfolioOnInsightChanges = False self.SetExecution(ImmediateExecutionModel()) res = Resolution.Hour self.UniverseSettings.Resolution = res market = ['SPY'] bonds = ['TLT'] signals = ['IGE'] self.market = [self.AddEquity(ticker, res).Symbol for ticker in market] self.bonds = [self.AddEquity(ticker, res).Symbol for ticker in bonds] self.signals = [self.AddEquity(ticker, res).Symbol for ticker in signals] self.AddAlpha(NaturalResourcesEvent(self.market, self.bonds, self.signals, )) class NaturalResourcesEvent(AlphaModel): """ """ def __init__(self, market, bonds, signals): self.Name = 'Natural Resources Event' self.market = market self.bonds = bonds self.signals = signals # Rolling mean of signal: self.rolling_mean = 55 self.past_days = 365 # Out of market waiting days: self.wait_days = 15 # Percentiles of extreme: self.extreme_p = 5 self.be_in = True self.hold_days = timedelta(days=1) self.gain = 0.02 self.dcount = False def Update(self, algorithm, data): if algorithm.Time.hour != 10 or algorithm.Time.minute != 0: return [] insights = [] # Sample to detect extreme observations: hist = algorithm.History(self.signals, self.past_days, Resolution.Daily)['close'] hist = hist.unstack(level=0).dropna() # Rolling mean smoothing out of values: hist_shift = hist.rolling(window=self.rolling_mean).mean().dropna() # As returns: returns_sample = (hist / hist_shift - True) # Extreme observations at given percentile pctl_b = np.nanpercentile(returns_sample, self.extreme_p, axis=int(False)) extreme_b = returns_sample.iloc[-True] < pctl_b alarms_on = extreme_b[self.signals].any() # Determine whether 'in' or 'out' of the market if alarms_on: self.be_in = False if self.dcount >= self.wait_days: self.be_in = True if self.be_in: for symbol in self.market: weight = int(True) insights.append(Insight(symbol, self.hold_days, InsightType.Price, InsightDirection.Up, self.gain, int(True), self.Name, weight)) self.dcount = False return insights else: algorithm.Log('Market Event incoming. Entering safe positions.') for symbol in self.bonds: insights.append(Insight(symbol, self.hold_days, InsightType.Price, InsightDirection.Up, self.gain, int(True), self.Name, int(True))) self.dcount += True return insights