| Overall Statistics |
|
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -0.712 Tracking Error 0.143 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
#region imports
from AlgorithmImports import *
#endregion
from QuantConnect.Indicators import MovingAverageConvergenceDivergence
class BootCampTask(QCAlgorithm):
"""
BootCampTask algorithm trades the most liquid future contract of S&P 500 E-mini based on the MACD signal.
It takes a long position when the MACD value is significantly less than the signal (suggesting an upward trend),
and a short position when the MACD value is significantly greater than the signal (suggesting a downward trend).
It places corresponding stop loss and take profit orders for risk management.
"""
def Initialize(self):
"""
Initialize the algorithm with necessary parameters.
"""
self.SetStartDate(2013, 12, 20) # Set the algorithm start date
self.SetEndDate(2014, 6, 21) # Set the algorithm end date
self.SetCash(1000000) # Set the starting cash
# Add the future contract for the S&P 500 E-mini and set filters for expiration range.
self.spy = self.AddFuture(Futures.Indices.SP500EMini)
self.spy.SetFilter(5, 120) # Only include contracts expiring in 5 to 120 days
# Initialize variables to store the most liquid contract, the MACD indicator,
# and order tickets for take profit and stop loss.
self.oi_contract = None # Most liquid contract based on open interest
self.macd = None # MACD indicator
self.takeProfit = None # Take profit order ticket
self.stopLoss = None # Stop loss order ticket
def OnData(self, slice):
"""
Event handler for new data.
"""
# Iterate through each future chain in the data slice.
for chain in slice.FutureChains:
# Select contracts from the chain and sort them by open interest.
contracts = sorted([contract for contract in chain.Value],
key=lambda k: k.OpenInterest, reverse=True)
# If there are no contracts, reset variables and break the loop.
if len(contracts) == 0:
self.oi_contract = None
self.macd = None
break
# Pick the most liquid contract.
contract = contracts[0]
# If we have already stored the most liquid contract and it is unchanged, skip updates.
if self.oi_contract is not None and contract.Symbol == self.oi_contract.Symbol:
break
# Update the most liquid contract and initialize the MACD indicator.
self.oi_contract = contract
self.macd = self.MACD(contract.Symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Minute)
# If the MACD indicator is not ready, return early.
if self.macd is None or not self.macd.IsReady:
return
# Define the trade logic for new positions.
symbol = self.oi_contract.Symbol
security = self.Securities[symbol]
# Do not trade if we're already invested in this contract.
if security.Invested:
return
price = security.Price
tolerance = 0.003 # Tolerance for MACD signal deviation
signalDeltaPercent = self.macd.Current.Value - self.macd.Signal.Current.Value
# Determine the trading signal based on MACD and tolerance.
if signalDeltaPercent < -tolerance:
# If MACD is significantly below the signal line, go long.
self.MarketOrder(symbol, 1)
# Set take profit and stop loss orders.
self.takeProfit = self.LimitOrder(symbol, -1, price * 1.01)
self.stopLoss = self.StopMarketOrder(symbol, -1, price * 0.99)
elif signalDeltaPercent > tolerance:
# If MACD is significantly above the signal line, go short.
self.MarketOrder(symbol, -1)
# Set take profit and stop loss orders.
self.takeProfit = self.LimitOrder(symbol, 1, price * 0.99)
self.stopLoss = self.StopMarketOrder(symbol, 1, price * 1.01)
def OnOrderEvent(self, orderEvent):
"""
Event handler for order events.
"""
# Only act on filled orders.
if orderEvent.Status != OrderStatus.Filled:
return
# Attempt to cancel the opposite order when one is filled.
self.Cancel(orderEvent.OrderId)
def Cancel(self, orderId):
"""
Cancel the opposite pending order when one of the take profit or stop loss orders is filled.
Args:
orderId: The ID of the filled order to identify the opposite order to cancel.
"""
# If the filled order is the take profit order, cancel the stop loss.
if self.takeProfit is not None and orderId == self.takeProfit.OrderId:
self.stopLoss.Cancel()
# If the filled order is the stop loss order, cancel the take profit.
elif self.stopLoss is not None and orderId == self.stopLoss.OrderId:
self.takeProfit.Cancel()
# Reset the order tickets to None after cancellation.
self.takeProfit = None
self.stopLoss = None
from AlgorithmImports import *
class MultiTimeframeTrendStrategy(QCAlgorithm):
def Initialize(self):
# Initialize algorithm parameters
self.SetStartDate(2010, 1, 1)
# self.SetEndDate(2015, 1, 1)
self.SetCash(100000)
# Add SPY Equity with hourly resolution
spy = self.AddEquity("SPY", Resolution.Hour)
spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.spySymbol = spy.Symbol
# Set Benchmark
self.SetBenchmark("SPY")
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
# Initialize opening and previous bar prices for multiple time frames
self.weeklyOpenPrice = None
self.dailyOpenPrice = None
self.hourlyOpenPrice = None
self.lastDailyHigh = None
self.lastDailyLow = None
self.lastHourlyHigh = None
self.lastHourlyLow = None
# Schedule functions to update weekly, daily, and hourly opening prices
self.lastTradeWeek = -1 # Initialize to an invalid week number
self.Schedule.On(self.DateRules.EveryDay(self.spySymbol), self.TimeRules.AfterMarketOpen(self.spySymbol, 1), self.CheckIfNewWeek)
self.Schedule.On(self.DateRules.EveryDay(self.spySymbol), self.TimeRules.At(9, 30), self.DailyOpen)
# Initialize last hour
self.lastHour = self.Time.hour
def OnData(self, data):
# Ensure the algorithm isn't warming up and that SPY data is available.
if self.IsWarmingUp or self.spySymbol not in data or data[self.spySymbol] is None:
return
# Update hourly price data and track high/low for Inside Bar detection.
if self.Time.hour != self.lastHour:
if data.Bars.ContainsKey(self.spySymbol):
bar = data.Bars[self.spySymbol]
self.hourlyOpenPrice = bar.Open
self.lastHourlyHigh = bar.High
self.lastHourlyLow = bar.Low
self.lastHour = self.Time.hour
self.insideBarDetected = False # Reset inside bar detection for the new hour
# Detect an Inside Bar based on the last hourly high and low.
if self.lastHourlyHigh is not None and self.lastHourlyLow is not None:
if self.hourlyOpenPrice < self.lastHourlyHigh and self.hourlyOpenPrice > self.lastHourlyLow:
self.Debug("Detected an Inside Bar at the hourly time frame")
self.insideBarDetected = True
# Ensure all necessary prices are set before proceeding.
if None in [self.weeklyOpenPrice, self.dailyOpenPrice, self.hourlyOpenPrice]:
return
# Current price from the data.
price = data[self.spySymbol].Price
# Execute trades based on Inside Bar breakout and trend continuity.
if self.insideBarDetected:
# Entry condition for a long position when current price breaks above the Inside Bar's high
if price > self.lastHourlyHigh and price > self.weeklyOpenPrice and price > self.dailyOpenPrice and price > self.hourlyOpenPrice:
if not self.Portfolio[self.spySymbol].Invested:
self.Log("Inside Bar broken upwards, aligning with TFC for a long position")
self.SetHoldings(self.spySymbol, 1)
# Exit condition if the price breaks below the Inside Bar's low
elif price < self.lastHourlyLow:
if self.Portfolio[self.spySymbol].Invested:
self.Log("Inside Bar broken downwards, exiting position.")
self.Liquidate(self.spySymbol)
def CheckIfNewWeek(self):
currentWeek = self.Time.isocalendar()[1]
if currentWeek != self.lastTradeWeek:
self.lastTradeWeek = currentWeek
self.WeeklyOpen()
def WeeklyOpen(self):
self.weeklyOpenPrice = self.Securities[self.spySymbol].Price
self.Log(f"Weekly open price updated on {self.Time.strftime('%Y-%m-%d')}: {self.weeklyOpenPrice}")
def DailyOpen(self):
bar = self.Securities[self.spySymbol]
self.dailyOpenPrice = bar.Price
self.lastDailyHigh = bar.High
self.lastDailyLow = bar.Low
self.Log(f"Daily open price updated on {self.Time.strftime('%Y-%m-%d')}: {self.dailyOpenPrice}")
from AlgorithmImports import *
from QuantConnect.DataSource import *
class USFuturesSecurityMasterDataClassicAlgorithm (QCAlgorithm):
"""
This algorithm demonstrates the use of the US futures security master to trade a continuous futures contract
based on its price relative to a simple moving average (SMA). It goes long when the price is above the SMA
by a certain threshold and goes short when the price is below the SMA by the same threshold. The algorithm
also handles contract rollovers and logs when these events occur.
"""
threshold = 0.01 # Define a threshold for price deviation from the SMA (1%)
def Initialize(self) -> None:
"""
Initialize the algorithm settings, add the future contract, and set up the indicators.
"""
self.SetCash(1000000) # Set starting cash
self.SetStartDate(2019, 2, 1) # Set start date for the backtest
self.SetEndDate(2021, 6, 1) # Set end date for the backtest
# Request continuous future data for Crude Oil WTI with specific data normalization and mapping modes.
self.continuous_contract = self.AddFuture(Futures.Energies.CrudeOilWTI,
dataNormalizationMode=DataNormalizationMode.BackwardsRatio,
dataMappingMode=DataMappingMode.OpenInterest,
contractDepthOffset=0)
self.symbol = self.continuous_contract.Symbol # Get the continuous contract symbol
# Request historical data to warm up the SMA indicator
history = self.History(self.symbol, 500, Resolution.Minute)
self.Debug(f"We got {len(history)} items from our history request")
# Initialize a 10-period SMA indicator with daily resolution
self.sma = self.SMA(self.symbol, 10, Resolution.Daily)
# Warm up the SMA with historical data
if not history.empty:
for time, row in history.droplevel(0).loc[self.symbol].iterrows():
self.sma.Update(IndicatorDataPoint(time, row.close))
def OnData(self, slice: Slice) -> None:
"""
Event handler for new data. Checks for rollover events and trading signals based on the SMA.
"""
# Check for contract rollover events and handle them
for symbol, changed_event in slice.SymbolChangedEvents.items():
old_symbol = changed_event.OldSymbol # The symbol of the old contract
new_symbol = changed_event.NewSymbol # The symbol of the new contract
tag = f"Rollover - Symbol changed at {self.Time}: {old_symbol} -> {new_symbol}"
quantity = self.Portfolio[old_symbol].Quantity # Quantity held of the old contract
# Liquidate the old contract position and open a new position in the new contract if necessary
self.Liquidate(old_symbol, tag=tag)
if quantity != 0: self.MarketOrder(new_symbol, quantity, tag=tag)
self.Log(tag)
mapped_symbol = self.continuous_contract.Mapped # The currently mapped contract symbol
# Check if there is a price update for the continuous contract and the SMA is ready
if not (slice.Bars.ContainsKey(self.symbol) and self.sma.IsReady and mapped_symbol):
return
# Trading logic based on the relationship between the current price and the SMA
current_price = slice.Bars[self.symbol].Price # The current price of the continuous contract
sma_value = self.sma.Current.Value # The current value of the SMA
# If the current price is significantly above the SMA, and we're not already long, go long
if current_price > sma_value * (1 + self.threshold) and not self.Portfolio[mapped_symbol].IsLong:
self.MarketOrder(mapped_symbol, 1)
# If the current price is significantly below the SMA, and we're not already short, go short
elif current_price < sma_value * (1 - self.threshold) and not self.Portfolio[mapped_symbol].IsShort:
self.MarketOrder(mapped_symbol, -1)
from AlgorithmImports import *
class MultiTimeframeTrendStrategy(QCAlgorithm):
def Initialize(self):
# Initialize algorithm parameters
self.SetStartDate(2010, 1, 1)
# self.SetEndDate(2015, 1, 1)
self.SetCash(100000)
# Add SPY Equity with hourly resolution
spy = self.AddEquity("SPY", Resolution.Hour)
spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.spySymbol = spy.Symbol
# Set Benchmark
self.SetBenchmark("SPY")
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
# Initialize opening and previous bar prices for multiple time frames
self.weeklyOpenPrice = None
self.dailyOpenPrice = None
self.hourlyOpenPrice = None
self.lastDailyHigh = None
self.lastDailyLow = None
self.lastHourlyHigh = None
self.lastHourlyLow = None
# Schedule functions to update weekly, daily, and hourly opening prices
self.lastTradeWeek = -1 # Initialize to an invalid week number
self.Schedule.On(self.DateRules.EveryDay(self.spySymbol), self.TimeRules.AfterMarketOpen(self.spySymbol, 1), self.CheckIfNewWeek)
self.Schedule.On(self.DateRules.EveryDay(self.spySymbol), self.TimeRules.At(9, 30), self.DailyOpen)
# Initialize last hour
self.lastHour = self.Time.hour
def OnData(self, data):
# Check for necessary conditions
if self.IsWarmingUp or self.spySymbol not in data or data[self.spySymbol] is None:
return
# Update hourly open and track high/low
if self.Time.hour != self.lastHour:
if data.Bars.ContainsKey(self.spySymbol):
bar = data.Bars[self.spySymbol]
self.hourlyOpenPrice = bar.Open
self.lastHourlyHigh = bar.High
self.lastHourlyLow = bar.Low
self.lastHour = self.Time.hour
else:
self.Debug(f"No hourly open data for {self.spySymbol} at {self.Time}")
# Check for Inside Bar at the hourly time frame
if self.hourlyOpenPrice and self.lastHourlyHigh and self.lastHourlyLow:
if self.hourlyOpenPrice < self.lastHourlyHigh and self.hourlyOpenPrice > self.lastHourlyLow:
self.Debug("Detected an Inside Bar at the hourly time frame")
# Ensure all opening prices are set
if None in [self.weeklyOpenPrice, self.dailyOpenPrice, self.hourlyOpenPrice]:
return
# Trading logic based on trend continuity and Inside Bar detection
price = data[self.spySymbol].Price
if price > self.weeklyOpenPrice and price > self.dailyOpenPrice and price > self.hourlyOpenPrice:
if not self.Portfolio[self.spySymbol].Invested:
self.Log("Timeframes aligned for long position")
self.SetHoldings(self.spySymbol, 1) # Long position
elif price < self.weeklyOpenPrice and price < self.dailyOpenPrice and price < self.hourlyOpenPrice:
self.Log("Timeframes down, exiting.")
self.Liquidate(self.spySymbol) # Exit position
def CheckIfNewWeek(self):
currentWeek = self.Time.isocalendar()[1]
if currentWeek != self.lastTradeWeek:
self.lastTradeWeek = currentWeek
self.WeeklyOpen()
def WeeklyOpen(self):
self.weeklyOpenPrice = self.Securities[self.spySymbol].Price
self.Log(f"Weekly open price updated on {self.Time.strftime('%Y-%m-%d')}: {self.weeklyOpenPrice}")
def DailyOpen(self):
bar = self.Securities[self.spySymbol]
self.dailyOpenPrice = bar.Price
self.lastDailyHigh = bar.High
self.lastDailyLow = bar.Low
self.Log(f"Daily open price updated on {self.Time.strftime('%Y-%m-%d')}: {self.dailyOpenPrice}")