| Overall Statistics |
|
Total Trades 1643 Average Win 0.12% Average Loss -0.24% Compounding Annual Return -14.163% Drawdown 57.600% Expectancy -0.105 Net Profit -21.022% Sharpe Ratio -0.215 Probabilistic Sharpe Ratio 3.424% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 0.50 Alpha -0.126 Beta 1.211 Annual Standard Deviation 0.289 Annual Variance 0.083 Information Ratio -0.493 Tracking Error 0.233 Treynor Ratio -0.051 Total Fees $1704.62 Estimated Strategy Capacity $3400000.00 Lowest Capacity Asset LNTH W1O47LFNB1PH |
# region imports
from AlgorithmImports import *
# endregion
class PensiveSkyBlueBison(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 5, 17) # Set Start Date
self.SetEndDate(2022, 12, 1)
self.SetCash(100000) # Set Strategy Cash
self.SetBenchmark("VHT")
self.factor_by_symbol = {}
self.universe_symbols = []
self.market_cap_threshold = int(self.GetParameter("market_cap_threshold"))
self.universe_size = int(self.GetParameter("universe_size"))
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseFilterFunction, self.FineFundamentalFunction)
# 300-day warm
self.SetWarmUp(300, Resolution.Daily)
def CoarseFilterFunction(self, coarse):
for item in coarse:
symbol = item.Symbol
if symbol not in self.factor_by_symbol:
self.factor_by_symbol[symbol] = Factor()
self.factor_by_symbol[symbol].Update(item.EndTime, item.AdjustedPrice)
if self.IsWarmingUp:
return Universe.Unchanged
return [c.Symbol for c in coarse if c.HasFundamentalData]
def FineFundamentalFunction(self, fine):
selected = {}
for item in fine:
if item.MarketCap > self.market_cap_threshold and item.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Healthcare:
symbol = item.Symbol
factor = self.factor_by_symbol[symbol]
if factor.IsReady and factor.ScaledDelta > 0:
selected[symbol] = factor
self.universe_symbols = [kvp[0] for kvp in sorted(selected.items(), key = lambda kvp: kvp[1].ScaledDelta, reverse=True)[:self.universe_size]]
return self.universe_symbols
def OnData(self, slice):
weight = 1 / len(self.universe_symbols)
self.SetHoldings([PortfolioTarget(symbol, weight) for symbol in self.universe_symbols])
def OnSecuritiesChanged(self, changes):
for security in changes.RemovedSecurities:
self.Liquidate(security.Symbol)
class Factor:
def __init__(self):
self.IsReady = False
self.ScaledDelta = -999
self.fast_ema = ExponentialMovingAverage(100)
self.slow_ema = ExponentialMovingAverage(300)
def Update(self, time, value):
self.IsReady = self.slow_ema.Update(time, value) & self.fast_ema.Update(time, value)
if self.IsReady:
fast = self.fast_ema.Current.Value
slow = self.slow_ema.Current.Value
self.ScaledDelta = (fast - slow) / ((fast + slow) / 2)
return self.IsReady