| Overall Statistics |
|
Total Trades 27683 Average Win 0.36% Average Loss -0.07% Compounding Annual Return 11.573% Drawdown 19.100% Expectancy 0.042 Net Profit 89.501% Sharpe Ratio 0.466 Sortino Ratio 0.56 Probabilistic Sharpe Ratio 11.195% Loss Rate 82% Win Rate 18% Profit-Loss Ratio 4.86 Alpha 0 Beta 0 Annual Standard Deviation 0.15 Annual Variance 0.022 Information Ratio 0.606 Tracking Error 0.15 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $8700000.00 Lowest Capacity Asset QQQ RIWIV7K5Z9LX Portfolio Turnover 2233.05% |
# region imports
from AlgorithmImports import *
from QuantConnect.Data import Slice
# endregion
# Fee model to test zero fees
class CustomFeeModel(FeeModel):
def __init__(self):
pass
def GetOrderFee(self, parameters: OrderFeeParameters) -> OrderFee:
return OrderFee.Zero
# Buying power model so that we can aoivd trading single shares
class MinimumOrderSizeBuyingPowerModel(BuyingPowerModel):
def __init__(self, min_order_size):
self.min_order_size = min_order_size
def GetMinimumOrderQuantityForResolution(self, security, targetOrderValue):
return OrderQuantity(self.min_order_size, 0)
def GetBuyingPower(self, parameters):
return BuyingPower(self.Portfolio.Cash, 0)
class Vwaptrend(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 1, 1)
self.SetEndDate(2023, 11, 1)
self.SetCash(25000)
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) # Equal weighting with assets
self.SetExecution(ImmediateExecutionModel())
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.asset1 = self.AddEquity("QQQ", Resolution.Minute)
self.asset1.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.asset1.SetBuyingPowerModel(MinimumOrderSizeBuyingPowerModel(10)) # Set minimum order size to 10 so that insights don't trade single shares
self.asset1_vwap = self.VWAP(self.asset1.Symbol)
self.asset1_long = None
self.period = timedelta(days=1) # Insight period, but we're not using it here as the execution model is with market orders
# turn off fees
self.asset1.SetFeeModel(CustomFeeModel())
def OnData(self, slice: Slice) -> None:
if not self.asset1_vwap.IsReady or (self.Time.hour == 9 and self.Time.minute == 30) or (self.Time.hour == 16 and self.Time.minute == 0):
return
# exit position EOD
if self.Time.hour == 15 and self.Time.minute == 59:
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Flat)
self.EmitInsights(asset1_insight)
self.Log(f'Exiting position at EOD')
self.asset1_long = None
return
# if getting second data but don't want to trade every second
# if not self.Time.second == 0:
# return
# if we want to trade every 5 minutes
# if not self.Time.minute % 5 == 0:
# return
price = self.asset1.Close
if price > self.asset1_vwap.Current.Value and (not self.asset1_long or self.asset1_long is None):
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Up)
self.EmitInsights(asset1_insight)
self.asset1_long = True
self.Log(f'vwap: {round(self.asset1_vwap.Current.Value, 2)} price: {price} Flipping to long')
if price < self.asset1_vwap.Current.Value and (self.asset1_long or self.asset1_long is None):
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Down)
self.EmitInsights(asset1_insight)
self.asset1_long = False
self.Log(f'vwap: {round(self.asset1_vwap.Current.Value, 2)} price: {price} Flipping to short')
# do this every few minutes
# if self.Time.minute % 1 == 0:
# self.Plot("IntradayVwap", "vwap", self.asset1_vwap.Current.Value)
# self.Plot("IntradayVwap", "price", price)
# self.Log(f"vwap: {self.asset1_vwap.Current.Value} price: {price}")
# region imports
from AlgorithmImports import *
from QuantConnect.Data import Slice
# endregion
class CustomFeeModel(FeeModel):
def __init__(self):
pass
def GetOrderFee(self, parameters: OrderFeeParameters) -> OrderFee:
return OrderFee.Zero
class MinimumOrderSizeBuyingPowerModel(BuyingPowerModel):
def __init__(self, min_order_size):
self.min_order_size = min_order_size
def GetMinimumOrderQuantityForResolution(self, security, targetOrderValue):
return OrderQuantity(self.min_order_size, 0)
def GetBuyingPower(self, parameters):
return BuyingPower(self.Portfolio.Cash, 0)
class Vwaptrend(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 1, 1)
self.SetEndDate(2023, 11, 1)
self.SetCash(30000)
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.asset1 = self.AddEquity("QQQ", Resolution.Minute)
self.asset1.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.asset1.SetBuyingPowerModel(MinimumOrderSizeBuyingPowerModel(10)) # Set minimum order size to 100
self.asset1_vwap = self.VWAP(self.asset1.Symbol)
self.asset1_long = None
self.period = timedelta(days=1)
self.asset1.SetFeeModel(CustomFeeModel())
def OnData(self, slice: Slice) -> None:
if not self.asset1_vwap.IsReady or (self.Time.hour == 9 and self.Time.minute == 30) or (self.Time.hour == 16 and self.Time.minute == 0):
return
if not self.Time.second == 0:
return
# exit position EOD
if self.Time.hour == 15 and self.Time.minute == 59:
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Flat)
self.EmitInsights(asset1_insight)
self.Log(f'Exiting position at EOD')
self.asset1_long = None
return
# if not self.Time.minute % 5 == 0:
# return
price = self.asset1.Close
if price > self.asset1_vwap.Current.Value and (not self.asset1_long or self.asset1_long is None):
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Up)
self.EmitInsights(asset1_insight)
self.asset1_long = True
self.Log(f'vwap: {round(self.asset1_vwap.Current.Value, 2)} price: {price} Flipping to long')
if price < self.asset1_vwap.Current.Value and (self.asset1_long or self.asset1_long is None):
asset1_insight = Insight.Price(self.asset1.Symbol, self.period, InsightDirection.Down)
self.EmitInsights(asset1_insight)
self.asset1_long = False
self.Log(f'vwap: {round(self.asset1_vwap.Current.Value, 2)} price: {price} Flipping to short')
# do this every few minutes
# if self.Time.minute % 1 == 0:
# self.Plot("IntradayVwap", "vwap", self.asset1_vwap.Current.Value)
# self.Plot("IntradayVwap", "price", price)
# self.Log(f"vwap: {self.asset1_vwap.Current.Value} price: {price}")