Overall Statistics
Total Orders
4167
Average Win
115.16%
Average Loss
-4.07%
Compounding Annual Return
147.895%
Drawdown
70.100%
Expectancy
9.344
Start Equity
10000000
End Equity
61605054.27
Net Profit
516.051%
Sharpe Ratio
1.821
Sortino Ratio
1.219
Probabilistic Sharpe Ratio
62.272%
Loss Rate
65%
Win Rate
35%
Profit-Loss Ratio
28.31
Alpha
1.78
Beta
-2.148
Annual Standard Deviation
0.767
Annual Variance
0.589
Information Ratio
1.343
Tracking Error
0.908
Treynor Ratio
-0.651
Total Fees
$56870.64
Estimated Strategy Capacity
$11000000.00
Lowest Capacity Asset
BRKA R735QTJ8XC9X
Portfolio Turnover
4.28%
# from AlgorithmImports import *

# class FlipCountTradingAlgorithm(QCAlgorithm):
#     def Initialize(self):
#         self.SetStartDate(2020, 1, 1)  # Set Start Date
#         self.SetEndDate(2023, 1, 1)    # Set End Date
#         self.SetCash(100000)           # Set Strategy Cash
#         self.UniverseSettings.Resolution = Resolution.Daily

#         # Add universe selection based on the top 1000 stocks by dollar volume
#         self.AddUniverse(self.CoarseSelectionFunction)

#         # Dictionary to store stock data including the rolling window
#         self.data = {}
    
#     def CoarseSelectionFunction(self, coarse):
#         sorted_by_dollar_volume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
#         return [x.Symbol for x in sorted_by_dollar_volume[:1000]]

#     def OnSecuritiesChanged(self, changes):
#         for security in changes.RemovedSecurities:
#             if security.Symbol in self.data:
#                 del self.data[security.Symbol]
        
#         for security in changes.AddedSecurities:
#             symbol = security.Symbol
#             # Initialize a RollingWindow for each added security to store the last 5 close prices
#             self.data[symbol] = {
#                 'price_window': RollingWindow[Decimal](5) ,
#                 'buy_count': 0,
#                 'position_opened': False
#             }

#     def OnData(self, data):
#         for symbol, stock_data in self.data.items():
#             if data.Bars.ContainsKey(symbol):
#                 bar = data.Bars[symbol]
#                 stock_data['price_window'].Add(Decimal(bar.Close))
                
#                 if stock_data['price_window'].IsReady:
#                     current_close = stock_data['price_window'][0]
#                     past_close = stock_data['price_window'][4]

#                     if current_close < past_close:
#                         stock_data['buy_count'] += 1
#                     else:
#                         stock_data['buy_count'] = 0  # Reset if the condition breaks

#                     if stock_data['buy_count'] > 9 and not stock_data['position_opened']:
#                         self.SetHoldings(symbol, 1 / len(self.data))
#                         stock_data['position_opened'] = True
#                         self.Debug(f"Bought {symbol} at {current_close}")
                    
#                     elif current_close < past_close and stock_data['position_opened']:
#                         self.Liquidate(symbol)
#                         stock_data['position_opened'] = False
#                         self.Debug(f"Sold {symbol} at {current_close}")


# #################################################################################################

from AlgorithmImports import *

class FlipCountTradingAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020, 1, 1)  # Set Start Date
        self.SetEndDate(2022, 1, 1)    # Set End Date
        self.SetCash(10000000)           # Set Strategy Cash
        self.UniverseSettings.Resolution = Resolution.Daily

        # Add universe selection based on the top 1000 stocks by dollar volume
        self.AddUniverse(self.CoarseSelectionFunction)

        # Dictionary to store stock data including the rolling window
        self.data = {}
    
    def CoarseSelectionFunction(self, coarse):
        sorted_by_dollar_volume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in sorted_by_dollar_volume[:1000]]

    def OnSecuritiesChanged(self, changes):
        for security in changes.RemovedSecurities:
            if security.Symbol in self.data:
                del self.data[security.Symbol]
        
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            # Initialize a RollingWindow for each added security to store the last 5 close prices
            self.data[symbol] = {
                'price_window': RollingWindow[Decimal](5) ,
                'buy_count': 0,
                'position_opened': False
            }

    def OnData(self, data):
        for symbol, stock_data in self.data.items():
            if data.Bars.ContainsKey(symbol):
                bar = data.Bars[symbol]
                stock_data['price_window'].Add(Decimal(bar.Close))
                
                if stock_data['price_window'].IsReady:
                    current_close = stock_data['price_window'][0]
                    past_close = stock_data['price_window'][4]

                    if current_close < past_close:
                        stock_data['buy_count'] += 1
                    else:
                        stock_data['buy_count'] = 0  # Reset if the condition breaks

                    # Attempt to buy $10,000 worth of stock
                    if stock_data['buy_count'] > 9 and not stock_data['position_opened']:
                        if self.Portfolio.Cash > 10000:
                            self.SetHoldings(symbol, 10000 / current_close)
                            stock_data['position_opened'] = True
                            #self.Debug(f"Bought {symbol} at {current_close}")
                        # else:
                        #     # Find and liquidate the most profitable stock
                        #     pass
                        #     #self.LiquidateMostProfitable()

                    elif current_close < past_close and stock_data['position_opened']:
                        self.Liquidate(symbol)
                        stock_data['position_opened'] = False
                        #self.Debug(f"Sold {symbol} at {current_close}")

    def LiquidateMostProfitable(self):
        max_profit = 0
        max_symbol = None
        for symbol, holding in self.Portfolio.items():
            profit = holding.UnrealizedProfit
            if profit > max_profit:
                max_profit = profit
                max_symbol = symbol

        if max_symbol is not None:
            self.Liquidate(max_symbol)
            self.Debug(f"Liquidated {max_symbol} to free up funds")