| Overall Statistics |
|
Total Orders 13611 Average Win 0.03% Average Loss -0.02% Compounding Annual Return 9.570% Drawdown 40.500% Expectancy 0.117 Start Equity 1000000 End Equity 1729953.92 Net Profit 72.995% Sharpe Ratio 0.326 Sortino Ratio 0.335 Probabilistic Sharpe Ratio 4.494% Loss Rate 51% Win Rate 49% Profit-Loss Ratio 1.28 Alpha -0.013 Beta 1.028 Annual Standard Deviation 0.198 Annual Variance 0.039 Information Ratio -0.11 Tracking Error 0.095 Treynor Ratio 0.063 Total Fees $21708.55 Estimated Strategy Capacity $40000000.00 Lowest Capacity Asset TRU W1O47LFNB1PH Portfolio Turnover 5.48% |
# 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(2018, 1, 1) # Set Start Date
self.SetEndDate(2024, 1, 1) # Set End Date
self.SetCash(1000000) # 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)
shares = 10000 / current_close
self.MarketOrder(symbol, shares)
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")