Overall Statistics
Total Trades
87
Average Win
0.87%
Average Loss
-0.38%
Compounding Annual Return
8.557%
Drawdown
16.300%
Expectancy
0.688
Net Profit
21.559%
Sharpe Ratio
0.561
Probabilistic Sharpe Ratio
19.917%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
2.31
Alpha
0.043
Beta
0.399
Annual Standard Deviation
0.117
Annual Variance
0.014
Information Ratio
0.065
Tracking Error
0.136
Treynor Ratio
0.164
Total Fees
$205.03
Estimated Strategy Capacity
$5100000.00
Lowest Capacity Asset
PE R735QTJ8XC9X
Portfolio Turnover
0.80%
# region imports
from AlgorithmImports import *

from QuantConnect.Data.Market import TradeBar
from QuantConnect.Orders import *
# endregion


class StrongVolumeAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2021, 1, 1)
        self.SetCash(100000) 
        self.AddEquity("SPY", Resolution.Daily)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction)
        self.trailingStopPercent = 0.03
        self.previous_spy_price = None
        self.previous_prices = {}
        self.symbols_to_invest = []
        self.SetWarmUp(100, Resolution.Daily)
        self.SetHoldings("SPY", 0.1)

    def CoarseSelectionFunction(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        
        selected = []
        for x in sortedByDollarVolume[:500]: 
            if x.Symbol not in self.previous_prices or (x.Volume > 5000000 and x.AdjustedPrice > self.previous_prices[x.Symbol]):
                selected.append(x.Symbol)
            self.previous_prices[x.Symbol] = x.AdjustedPrice
        
        self.Debug(f"{self.Time} - Selected securities: {selected}")
        self.symbols_to_invest = selected
        return selected

    def OnData(self, data):
        if self.previous_spy_price is not None and self.Securities["SPY"].Price < self.previous_spy_price:
            for symbol in self.symbols_to_invest:
                if data.ContainsKey(symbol) and data[symbol] is not None:
                    if self.Securities.ContainsKey(symbol) and data[symbol].Close > self.previous_prices[symbol]:
                        self.SetHoldings(symbol, 0.1)
                        self.StopMarketOrder(symbol, -self.Portfolio[symbol].Quantity, self.Securities[symbol].Price * (1-self.trailingStopPercent))
                        self.Debug(f"{self.Time} - Placed order for: {symbol}")
        self.previous_spy_price = self.Securities["SPY"].Price

    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status != OrderStatus.Filled:
            return

        order = self.Transactions.GetOrderById(orderEvent.OrderId)
        if order.Type == OrderType.Market and order.Direction == OrderDirection.Buy:
            self.StopMarketOrder(order.Symbol, -order.Quantity, orderEvent.FillPrice * (1-self.trailingStopPercent))
            self.Debug(f"{self.Time} - Filled order for: {order.Symbol}")