| Overall Statistics |
|
Total Trades 28803 Average Win 0.06% Average Loss -0.06% Compounding Annual Return -3.321% Drawdown 20.200% Expectancy -0.021 Net Profit -18.275% Sharpe Ratio -0.335 Probabilistic Sharpe Ratio 0.005% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.06 Alpha -0.021 Beta -0.003 Annual Standard Deviation 0.063 Annual Variance 0.004 Information Ratio -0.89 Tracking Error 0.163 Treynor Ratio 7.366 Total Fees $53974.34 Estimated Strategy Capacity $250000000.00 Lowest Capacity Asset AXP R735QTJ8XC9X |
#region imports
from AlgorithmImports import *
import math
#endregion
class MeanReversion(AlphaModel):
def __init__(self):
self.symbolData = []
self.lastDay = -1
def Update(self, algorithm, data):
time = algorithm.Time
day = algorithm.Time.day
insights = []
#Near the market close of each day
for symbol in self.symbolData:
isClosingSoon = algorithm.Securities[symbol].Exchange.IsClosingSoon(1)
if isClosingSoon == True:
break
else:
return insights
if algorithm.Time.day == self.lastDay:
return insights
self.lastDay = algorithm.Time.day
startdate = time-timedelta(days=1)
enddate = time
history = algorithm.History(self.symbolData, startdate, enddate, Resolution.Minute)
#Hvis vi får nul data, så returnerer vi
if history.empty:
return insights
#Vi får vores tickers
tickers = history.index.levels[0]
returns = {}
#Looper over vores tickers, hvis nogle af dem har tomme data eller close ikke er der, så dropper vi dem
for ticker in tickers:
ticker_history = history.loc[ticker]
symbol = SymbolCache.GetSymbol(ticker)
if ticker_history.empty or "close" not in ticker_history or ticker_history.close.isnull().values.any() == True or algorithm.Securities[symbol].HasData == False or algorithm.Securities[symbol].Price == 0:
history.drop(ticker, level=0)
continue
ticker_history = ticker_history.close
dailyreturn = ticker_history[-2]-ticker_history[0]
if math.isnan(dailyreturn) == True:
continue
returns[symbol] = dailyreturn
#algorithm.Securities[symbol].IsTradable
rj = sum(returns.values())/len(returns.keys())
weights = {}
sum123 = 0
for key, value in returns.items():
sum123 += abs(value-rj)
for key, value in returns.items():
weight = -(value-rj)/sum123
weights[key] = weight
for key,value in weights.items():
if value > 0:
direction = InsightDirection.Up
else:
direction = InsightDirection.Down
insights.append(Insight.Price(key, Expiry.EndOfDay(time+timedelta(days=1)), direction, weight = value))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
for added in changes.AddedSecurities:
self.symbolData.append(added.Symbol)
for removed in changes.RemovedSecurities:
self.symbolData.remove(removed.Symbol)
# Your New Python File
#region imports
from AlgorithmImports import *
from QuantConnect import Resolution, Extensions
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from itertools import groupby
from datetime import datetime, timedelta
from pytz import utc
UTCMIN = datetime.min.replace(tzinfo=utc)
#endregion
class WeightedPortfolio(PortfolioConstructionModel):
def __init__(self):
self.insightCollection = InsightCollection()
self.removedSymbols = []
self.nextRebalance = None
def CreateTargets(self, algorithm, insights):
targets = []
if len(insights) == 0:
return targets
# here we get the new insights and add them to our insight collection
for insight in insights:
self.insightCollection.Add(insight)
# create flatten target for each security that was removed from the universe
if len(self.removedSymbols) > 0:
universeDeselectionTargets = [ PortfolioTarget(symbol, 0) for symbol in self.removedSymbols ]
targets.extend(universeDeselectionTargets)
algorithm.Log('(Portfolio module) liquidating: ' + str([x.Value for x in self.removedSymbols]) + ' if they are active, due to not being in the universe')
self.removedSymbols = []
expiredInsights = self.insightCollection.RemoveExpiredInsights(algorithm.UtcTime)
expiredTargetsLog = []
expiredTargets = []
for symbol, f in groupby(expiredInsights, lambda x: x.Symbol):
if not self.insightCollection.HasActiveInsights(symbol, algorithm.UtcTime):
expiredTargets.append(PortfolioTarget(symbol, 0))
expiredTargetsLog.append(symbol)
continue
algorithm.Log(f'(Portfolio module) sold {expiredTargetsLog} due to insight being expired')
targets.extend(expiredTargets)
# get insight that have not expired of each symbol that is still in the universe
activeInsights = self.insightCollection.GetActiveInsights(algorithm.UtcTime)
# get the last generated active insight for each symbol
lastActiveInsights = []
for symbol, g in groupby(activeInsights, lambda x: x.Symbol):
lastActiveInsights.append(sorted(g, key = lambda x: x.GeneratedTimeUtc)[-1])
# determine target percent for the given insights
boughtTargetsLog = []
for insight in lastActiveInsights:
allocationPercent = insight.Weight * abs(insight.Direction)
target = PortfolioTarget.Percent(algorithm, insight.Symbol, allocationPercent)
boughtTargetsLog.append(insight.Symbol)
targets.append(target)
algorithm.Log(f'(Portfolio module) Bought {boughtTargetsLog} stocks, that expires at {Expiry.EndOfMonth}')
return targets
def OnSecuritiesChanged(self, algorithm, changes):
newRemovedSymbols = [x.Symbol for x in changes.RemovedSecurities if x.Symbol not in self.removedSymbols]
# get removed symbol and invalidate them in the insight collection
self.removedSymbols.extend(newRemovedSymbols)
self.insightCollection.Clear(self.removedSymbols)
removedList = [x.Value for x in self.removedSymbols]
algorithm.Log('(Portfolio module) securities removed from Universe: ' + str(removedList))# region imports
from AlgorithmImports import *
from MeanReversionAlpha import MeanReversion
from WeightedPortfolioConstructionModel import WeightedPortfolio
# endregion
class EmotionalYellowGull(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016, 1, 1) # Set Start Date'
self.SetEndDate(2021, 12, 20)
self.SetCash(500000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Minute
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
seeder = FuncSecuritySeeder(self.GetLastKnownPrices)
self.SetSecurityInitializer(lambda security: seeder.SeedSecurity(security))
self.SetBenchmark('SPY')
etf_symbol = "XLF"
universe = self.Universe.ETF(etf_symbol, Market.USA,
self.UniverseSettings, self.ETFConstituentsFilter)
self.AddUniverse(universe)
self.AddAlpha(MeanReversion())
self.SetPortfolioConstruction(WeightedPortfolio())
self.SetExecution(ImmediateExecutionModel())
self.lastMonth = -1
self.num_coarse = 20
def ETFConstituentsFilter(self, constituents: List[ETFConstituentData]) -> List[Symbol]:
if self.Time.month == self.lastMonth:
return Universe.Unchanged
self.lastMonth = self.Time.month
selected = sorted([c for c in constituents if c.Weight],
key=lambda c: c.Weight, reverse=True)[:self.num_coarse]
return [c.Symbol for c in selected]