| Overall Statistics |
|
Total Trades 6231 Average Win 0.11% Average Loss -0.03% Compounding Annual Return 10.874% Drawdown 16.800% Expectancy 1.114 Net Profit 180.898% Sharpe Ratio 0.835 Probabilistic Sharpe Ratio 24.135% Loss Rate 55% Win Rate 45% Profit-Loss Ratio 3.69 Alpha 0.1 Beta -0.035 Annual Standard Deviation 0.115 Annual Variance 0.013 Information Ratio -0.13 Tracking Error 0.18 Treynor Ratio -2.723 Total Fees $6875.14 |
from datetime import timedelta
import numpy as np
from scipy import stats
from collections import deque
class FrameworkAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetEndDate(2019, 12, 31)
self.SetCash(100000)
self.tickers = ["QQQ","PQSC","IYC","IYK","IGV","IHI","ITA","ITB","SMH","GLD","SBUG","TLH","TLT","EDV","CWB"]
self.UniverseSettings.Resolution = Resolution.Daily
self.sym=[]
for x in self.tickers:
self.sym.append(Symbol.Create(x, SecurityType.Equity, Market.USA))
self.SetUniverseSelection( ManualUniverseSelectionModel(self.sym) )
# Alpha Model
self.SetAlpha(MOMAlphaModel())
# PortfolioConstruction Model
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
# RiskManagement Model
self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(1))
# Execution Model
self.SetExecution(ImmediateExecutionModel())
class MOMAlphaModel(AlphaModel):
def __init__(self):
self.mom = []
self.slopy={}
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
self.slopy[symbol] = custom_slope(symbol, 100)
history = algorithm.History(symbol, 100, Resolution.Daily)
self.slopy[symbol].Warmup(history)
algorithm.RegisterIndicator(symbol, self.slopy[symbol], Resolution.Daily)
self.mom.append({"symbol":symbol, "indicator": self.slopy[symbol]})
def Update(self, algorithm, data):
insights = []
ordered = sorted(self.mom, key=lambda kv: kv["indicator"].Current.Value, reverse=True)[:4]
for x in ordered:
symbol = x['symbol']
#if self.slopy[symbol].IsReady :
insights.append( Insight.Price(symbol, timedelta(1), InsightDirection.Up) )
return insights
class custom_slope(PythonIndicator):
def __init__(self,symbol, periods):
self.symbol=symbol
self.queue = deque(maxlen=periods)
self.Value = 0
self.Time=None
#self.IsReady=False
def Update(self,input):
self.queue.appendleft(input.Close)
count = len(self.queue)
if count == self.queue.maxlen:
y = np.log(self.queue)
x = [range(len(y))]
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
self.Value=slope * 10000
#self.IsReady=True
def Warmup(self,history):
if self.symbol not in history:
return
for index, row in history.loc[self.symbol].iterrows():
self.queue.Add(row["close"])
self.Time=index