Overall Statistics
Total Orders
3454
Average Win
0.59%
Average Loss
-0.28%
Compounding Annual Return
1.851%
Drawdown
23.400%
Expectancy
0.008
Start Equity
100000
End Equity
109608.33
Net Profit
9.608%
Sharpe Ratio
-0.147
Sortino Ratio
-0.181
Probabilistic Sharpe Ratio
1.233%
Loss Rate
67%
Win Rate
33%
Profit-Loss Ratio
2.09
Alpha
-0.019
Beta
0.015
Annual Standard Deviation
0.12
Annual Variance
0.014
Information Ratio
-0.469
Tracking Error
0.183
Treynor Ratio
-1.14
Total Fees
$8470.50
Estimated Strategy Capacity
$73000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
376.14%
Drawdown Recovery
122
# 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)) 

    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)