Files
quantconnect--lean/Algorithm.Python/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.py
2026-07-13 13:02:50 +08:00

71 lines
3.3 KiB
Python

### QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
### Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
###
### Licensed under the Apache License, Version 2.0 (the "License");
### you may not use this file except in compliance with the License.
### You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
###
### Unless required by applicable law or agreed to in writing, software
### distributed under the License is distributed on an "AS IS" BASIS,
### WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
### See the License for the specific language governing permissions and
### limitations under the License.
from AlgorithmImports import *
### <summary>
### This regression test tests for the loading of futures options contracts with a contract month of 2020-03 can live
### and be loaded from the same ZIP file that the 2020-04 contract month Future Option contract lives in.
### </summary>
class FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm(QCAlgorithm):
def initialize(self):
self.expected_symbols = {
self._create_option(datetime(2020, 3, 26), OptionRight.CALL, 1650.0): False,
self._create_option(datetime(2020, 3, 26), OptionRight.PUT, 1540.0): False,
self._create_option(datetime(2020, 2, 25), OptionRight.CALL, 1600.0): False,
self._create_option(datetime(2020, 2, 25), OptionRight.PUT, 1545.0): False
}
# Required for FOPs to use extended hours, until GH #6491 is addressed
self.universe_settings.extended_market_hours = True
self.set_start_date(2020, 1, 4)
self.set_end_date(2020, 1, 6)
gold_futures = self.add_future("GC", Resolution.MINUTE, Market.COMEX, extended_market_hours=True)
gold_futures.set_filter(0, 365)
self.add_future_option(gold_futures.symbol)
def on_data(self, data: Slice):
for symbol in data.quote_bars.keys():
# Check that we are in regular hours, we can place a market order (on extended hours, limit orders should be used)
if symbol in self.expected_symbols and self.is_in_regular_hours(symbol):
invested = self.expected_symbols[symbol]
if not invested:
self.market_order(symbol, 1)
self.expected_symbols[symbol] = True
def on_end_of_algorithm(self):
not_encountered = [str(k) for k,v in self.expected_symbols.items() if not v]
if any(not_encountered):
raise AssertionError(f"Expected all Symbols encountered and invested in, but the following were not found: {', '.join(not_encountered)}")
if not self.portfolio.invested:
raise AssertionError("Expected holdings at the end of algorithm, but none were found.")
def is_in_regular_hours(self, symbol):
return self.securities[symbol].exchange.exchange_open
def _create_option(self, expiry: datetime, option_right: OptionRight, strike_price: float) -> Symbol:
return Symbol.create_option(
Symbol.create_future("GC", Market.COMEX, datetime(2020, 4, 28)),
Market.COMEX,
OptionStyle.AMERICAN,
option_right,
strike_price,
expiry
)