Overall Statistics |
Total Orders 426 Average Win 0.47% Average Loss -0.38% Compounding Annual Return 2.878% Drawdown 7.600% Expectancy 0.190 Start Equity 1000000 End Equity 1159540.23 Net Profit 15.954% Sharpe Ratio -0.181 Sortino Ratio -0.115 Probabilistic Sharpe Ratio 8.148% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.24 Alpha -0.005 Beta -0.032 Annual Standard Deviation 0.041 Annual Variance 0.002 Information Ratio -0.454 Tracking Error 0.183 Treynor Ratio 0.229 Total Fees $7387.16 Estimated Strategy Capacity $1300000.00 Lowest Capacity Asset SNDK YQ9V5TFTJSKL Portfolio Turnover 2.22% |
# region imports from AlgorithmImports import * from sklearn.cluster import KMeans from sklearn.preprocessing import MinMaxScaler # endregion class MuscularFluorescentPinkPanda(QCAlgorithm): def initialize(self): self.set_start_date(2020, 1, 1) self.set_cash(1_000_000) self.universe_settings.extended_market_hours = True self._etf = self.add_equity('SPY') self.add_universe(self.universe.etf(self._etf.symbol, universe_filter_func=self._select_assets)) self._previous_symbols = set() self._hold_duration = 3 # Trading days self._trades = [] self.schedule.on(self.date_rules.every_day(self._etf.symbol), self.time_rules.before_market_open(self._etf.symbol, 30), self._rebalance) self.set_warm_up(timedelta(7)) def _select_assets(self, constituents): symbols = set([c.symbol for c in constituents]) if not (400 < len(symbols) < 600): return [] # To avoid data issues. self._etf_additions = list(symbols - self._previous_symbols) self._previous_symbols = symbols return self._etf_additions def _rebalance(self): if self.is_warming_up: return # Scan for exits. closed_trades = [] for i, trade in enumerate(self._trades): trade.scan(self) if trade.closed: closed_trades.append(i) # Delete closed trades for i in closed_trades[::-1]: del self._trades[i] # Scan for entries. for symbol in self._etf_additions: self._trades.append(Trade(self, symbol, self._hold_duration)) self._etf_additions = [] self.plot('Trades', 'Open', len(self._trades)) class Trade: def __init__(self, algorithm, symbol, hold_duration): self._symbol = symbol # Determine position size self.closed = True price = algorithm.securities[symbol].price if not price: return self._quantity = -int(0.1 * algorithm.portfolio.total_portfolio_value / algorithm.securities[symbol].price) if self._quantity == 0: return self.closed = False # Enter trade algorithm.market_order(symbol, self._quantity) # Set variable for exit logic self._hold_duration = hold_duration def scan(self, algorithm): if self.closed: return self._hold_duration -= 1 if self._hold_duration <= 0: algorithm.market_order(self._symbol, -self._quantity) self.closed = True