| Overall Statistics |
|
Total Orders 4201 Average Win 0.23% Average Loss -0.29% Compounding Annual Return 1.998% Drawdown 5.900% Expectancy 0.002 Start Equity 100000 End Equity 110411.67 Net Profit 10.412% Sharpe Ratio -0.062 Sortino Ratio -0.071 Probabilistic Sharpe Ratio 4.683% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 0.81 Alpha -0.006 Beta 0.034 Annual Standard Deviation 0.038 Annual Variance 0.001 Information Ratio -0.648 Tracking Error 0.156 Treynor Ratio -0.069 Total Fees $4444.40 Estimated Strategy Capacity $31000000.00 Lowest Capacity Asset BRKB R735QTJ8XC9X Portfolio Turnover 69.49% |
from AlgorithmImports import *
from QuantConnect.DataSource import *
class ETFConstituentUniverseAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2016, 1, 1)
self.set_end_date(2021, 1, 1)
self.set_cash(100000)
self.universe_settings.asynchronous = True
self.universe_settings.resolution = Resolution.MINUTE
# Requesting data
self.spy = self.add_equity("SPY").symbol
self._universe = self.add_universe(self.universe.etf(self.spy, self.universe_settings, self.etf_constituents_filter))
# Historical Universe data
history = self.history(self._universe, 30, Resolution.DAILY)
for (universe_symbol, time), constituents in history.items():
for constituent in constituents:
self.debug(f'{constituent.symbol}: {constituent.weight}')
self.weight_by_symbol = {}
self.schedule.on(
self.date_rules.every_day(self.spy),
self.time_rules.after_market_open(self.spy, 1),
self.rebalance)
def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
# Get the 10 securities with the largest weight in the index
selected = sorted([c for c in constituents if c.weight],
key=lambda c: c.weight, reverse=True)[:10]
self.weight_by_symbol = {c.symbol: c.weight for c in selected}
return list(self.weight_by_symbol.keys())
def rebalance(self) -> None:
spy_weight = sum(self.weight_by_symbol.values())
if spy_weight > 0:
for symbol in self.portfolio.Keys:
if symbol not in self.weight_by_symbol:
self.liquidate(symbol)
for symbol, weight in self.weight_by_symbol.items():
self.set_holdings(symbol, 0.5 * weight / spy_weight)
self.set_holdings(self.spy, -0.5)
def on_securities_changed(self, changes: SecurityChanges) -> None:
for security in changes.removed_securities:
if security.invested:
self.liquidate(security.symbol, 'Removed From Universe')
for security in changes.added_securities:
# Historical data
history = self.history(security.symbol, 7, Resolution.DAILY)
self.debug(f'We got {len(history)} from our history request for {security.symbol}')