SPX is not found, but is supposed to be available on the QC cloud platformI'm having trouble accessing index data (SPX in this example) on QC cloud while backtesting. Sharing my code below:
from datetime import time, timedelta
from AlgorithmImports import *
class BankNiftyStraddleSuperTrend(QCAlgorithm):
def initialize(self):
self.set_start_date(2025, 1, 1)
# self.set_end_date(2025, 1, 15)
self.set_cash(1000000) # 10 Lakh INR
# Set the brokerage model for Indian markets
# self.set_brokerage_model(BrokerageName.INTERACTIVE_BROKERS_BROKERAGE, AccountType.CASH)
# === User-configurable parameters ===
self.entry_time = time(9, 49)
self.exit_time = time(15, 45)
self.initial_sl_percent = 0.15 # 15% individual SL
# === Index and Option setup ===
self.index_symbol = self.add_index("SPX", Resolution.MINUTE).symbol
self.option = self.add_index_option(self.index_symbol, Resolution.MINUTE)
self.option.set_filter(-5, 5, timedelta(0), timedelta(7)) # Filter for near-expiry options
# === SuperTrend Indicator on a 3-minute consolidated chart ===
self.supertrend = self.str(self.index_symbol, 10, 3, MovingAverageType.SIMPLE, Resolution.MINUTE)
self.consolidator = TradeBarConsolidator(timedelta(minutes=3))
self.consolidator.data_consolidated += self.on_three_minute_bar_update
self.register_indicator(self.index_symbol, self.supertrend, self.consolidator)
# === Scheduled events for entry and exit ===
self.schedule.on(self.date_rules.every_day(self.index_symbol),
self.time_rules.at(self.entry_time.hour, self.entry_time.minute),
self.enter_straddle)
self.schedule.on(self.date_rules.every_day(self.index_symbol),
self.time_rules.at(self.exit_time.hour, self.exit_time.minute),
self.liquidate_positions)
# === State management variables ===
self.call_contract = None
self.put_contract = None
self.call_premium = 0
self.put_premium = 0
self.trailing_stop_active = False
def on_data(self, data: Slice):
# 1. Subscribe to option contracts data once we have sold them
if self.call_contract and not data.contains_key(self.call_contract.symbol):
self.add_index_option_contract(self.call_contract.symbol, Resolution.MINUTE)
if self.put_contract and not data.contains_key(self.put_contract.symbol):
self.add_index_option_contract(self.put_contract.symbol, Resolution.MINUTE)
# 2. Check for initial stop loss (only if trailing stop is not active)
if not self.trailing_stop_active:
self.check_initial_stop_loss()
def enter_straddle(self):
# Do not enter a new position if we already have one
if self.portfolio.invested:
return
# Get the options chain
chain = self.option_chain_provider.get_option_contract_list(self.index_symbol, self.current_slice.time)
if not chain:
return
# Find the ATM strike price
underlying_price = self.securities[self.index_symbol].price
atm_strike = sorted(chain, key=lambda x: abs(x.id.strike_price - underlying_price))[0].id.strike_price
# Select ATM call and put contracts for the nearest expiry
contracts = [c for c in chain if c.id.strike_price == atm_strike]
if len(contracts) < 2: return
expiry = sorted([x.id.date for x in contracts])[0]
atm_call = [c for c in contracts if c.id.option_right == OptionRight.CALL and c.id.date == expiry]
atm_put = [c for c in contracts if c.id.option_right == OptionRight.PUT and c.id.date == expiry]
if not atm_call or not atm_put:
self.log("Could not find ATM Call or Put.")
return
self.call_contract = atm_call[0]
self.put_contract = atm_put[0]
# Sell the straddle
self.market_order(self.call_contract, -1)
self.market_order(self.put_contract, -1)
self.log(f"Sold BANKNIFTY Straddle at Strike: {atm_strike} | Expiry: {expiry.date()}")
def on_order_event(self, order_event: OrderEvent):
# Store the premium received when the sell orders are filled
if order_event.status == OrderStatus.FILLED:
order = self.transactions.get_order_by_id(order_event.order_id)
if order.type == OrderType.MARKET and order.direction == OrderDirection.SELL:
if order_event.symbol == self.call_contract.symbol:
self.call_premium = order.price
self.log(f"Sold Call @ {self.call_premium}")
elif order_event.symbol == self.put_contract.symbol:
self.put_premium = order.price
self.log(f"Sold Put @ {self.put_premium}")
# Check if this fill was due to a stop loss, if so, activate trailing
if self.portfolio[order_event.symbol].quantity == 0 and (self.call_premium > 0 or self.put_premium > 0):
self.trailing_stop_active = True
self.log(f"One leg SL hit. Activating SuperTrend trailing stop for the other leg.")
def check_initial_stop_loss(self):
# Check call leg SL
if self.call_contract and self.portfolio[self.call_contract.symbol].invested:
current_price = self.securities[self.call_contract.symbol].price
sl_price = self.call_premium * (1 + self.initial_sl_percent)
if current_price >= sl_price:
self.liquidate(self.call_contract.symbol, "Initial SL Hit on Call")
return
# Check put leg SL
if self.put_contract and self.portfolio[self.put_contract.symbol].invested:
current_price = self.securities[self.put_contract.symbol].price
sl_price = self.put_premium * (1 + self.initial_sl_percent)
if current_price >= sl_price:
self.liquidate(self.put_contract.symbol, "Initial SL Hit on Put")
return
def on_three_minute_bar_update(self, sender, bar):
# Only run this logic if the trailing stop is active and the indicator is ready
if not self.trailing_stop_active or not self.supertrend.is_ready:
return
# If price closes above the SuperTrend, it's a bullish signal. Exit short positions.
if bar.close > self.supertrend.current.value:
if self.portfolio.invested:
self.log(f"SuperTrend trailing stop hit. Price {bar.close} > SuperTrend {self.supertrend.current.value}")
self.liquidate_positions("SuperTrend Trailing Stop Hit")
def liquidate_positions(self, reason="End of Day Exit"):
if self.portfolio.invested:
self.log(f"Liquidating all positions: {reason}")
# Liquidate in a specific order to avoid margin errors
if self.call_contract and self.portfolio[self.call_contract.symbol].invested:
self.liquidate(self.call_contract.symbol)
if self.put_contract and self.portfolio[self.put_contract.symbol].invested:
self.liquidate(self.put_contract.symbol)
# Reset state for the next day
self.call_contract = None
self.put_contract = None
self.call_premium = 0
self.put_premium = 0
self.trailing_stop_active = False
Appreciate any help with this!
Â
Mia Alissi
Here's a minimal example that checks SPX index data access on QuantConnect Cloud. This algorithm adds SPX as an index, requests historical data for the last 10 days, and logs whether the data is available—no trading or options logic included:
How to use:
Successfully retrieved 10 rows of SPX historical data.), then SPX data is working.Let me know the result—it will help pinpoint the root cause!
Sources: docs writing algorithms datasets quantconnect cash indices, docs writing algorithms datasets algoseek us index options, Index - QuantConnect.com, Basic Template Index Daily Algorithm, Getting Started - QuantConnect.com
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Shinchan
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!