| Overall Statistics |
|
Total Orders 5462 Average Win 0.39% Average Loss -0.23% Compounding Annual Return 9.271% Drawdown 13.900% Expectancy 0.045 Start Equity 100000 End Equity 155806.31 Net Profit 55.806% Sharpe Ratio 0.31 Sortino Ratio 0.383 Probabilistic Sharpe Ratio 18.597% Loss Rate 61% Win Rate 39% Profit-Loss Ratio 1.70 Alpha 0.028 Beta 0.042 Annual Standard Deviation 0.098 Annual Variance 0.01 Information Ratio -0.226 Tracking Error 0.167 Treynor Ratio 0.734 Total Fees $11785.04 Estimated Strategy Capacity $120000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 458.52% Drawdown Recovery 444 |
# region imports
from AlgorithmImports import *
# endregion
class SPY_SMA(QCAlgorithm):
def initialize(self):
self.set_start_date(self.end_date - timedelta(5*365))
self.set_cash(100_000)
self._can_trade = True
# Add SPY to trade.
self._spy = self.add_equity("SPY")
# Consolidate SPY data into 5-minute bars.
consolidator = self.consolidate(self._spy, timedelta(minutes=5), self._consolidation_handler)
# Create some indicators to detect trading opportunities.
self._sma_fast = SimpleMovingAverage(5)
self._sma_slow = SimpleMovingAverage(30)
# Hook up the indicators to be updated with the 5-min bars.
for indicator in [self._sma_slow, self._sma_fast]:
self.register_indicator(self._spy.symbol, indicator, consolidator)
# Add a warm-up period to warm up the indicators.
self.set_warm_up(timedelta(7))
# Add a Scheduled Event to liquidate positions before the market closes.
self.schedule.on(
self.date_rules.every_day(self._spy),
self.time_rules.before_market_close(self._spy, 1),
self.liquidate
)
def on_end_of_day(self, symbol):
self._yesterday_aum = self.portfolio.total_portfolio_value
self._can_trade = True
def _consolidation_handler(self, bar):
if (self.is_warming_up or
not self._can_trade or
not self._sma_slow.is_ready or
not self._spy.exchange.hours.is_open(self.time, False)):
return
# If the portfolio value has dropped 5% or more today,
# stop trading for the rest of the day.
if self.portfolio.total_portfolio_value / self._yesterday_aum - 1 <= -0.05:
self.liquidate()
self._can_trade = False
return
# Scan for long trades.
sma_fast = self._sma_fast.current.value
sma_slow = self._sma_slow.current.value
if not self._spy.holdings.is_long and bar.close > sma_fast > sma_slow:
self.set_holdings(self._spy, 1)
# Scan for short trades.
elif not self._spy.holdings.is_short and bar.close < sma_fast < sma_slow:
self.set_holdings(self._spy, -1)