我正在尝试在 Quant Connect 中回测以下策略
当我运行策略时,头寸并不是每天都开仓和平仓。例如,某天上午 9:35 开仓,但几天甚至一个月后平仓。
好像不一致。我不确定我的代码中做错了什么。
这是代码:
from AlgorithmImports import *
from QuantConnect.DataSource import *
import datetime
class USEquityOptionsDataAlgorithm(QCAlgorithm):
def Initialize(self) -> None:
self.SetStartDate(2022, 1, 1)
self.SetEndDate(2022, 12, 31)
self.SetCash(100000)
# Requesting data
self.underlying = self.AddEquity("SPY").Symbol
option = self.AddOption("SPY")
self.option_symbol = option.Symbol
# Set our strike/expiry filter for this option chain
option.SetFilter(0, 0)
self.contract_call = None
self.contract_put = None
self.entry_time = datetime.time(hour=9, minute=35)
self.exit_time = datetime.time(hour=12)
self.profit_target = 0.1
self.position_open = False
self.entry_price = None
def OnData(self, slice: Slice) -> None:
if self.Portfolio[self.underlying].Invested:
self.Liquidate(self.underlying)
if self.contract_call is not None and self.Portfolio[self.contract_call.Symbol].Invested:
return
chain = slice.OptionChains.get(self.option_symbol)
if chain:
# Select call and put contracts with zero days to expiration
zero_expiry_calls = [contract for contract in chain if contract.Expiry.date() == self.Time.date() and contract.Right == OptionRight.Call]
zero_expiry_puts = [contract for contract in chain if contract.Expiry.date() == self.Time.date() and contract.Right == OptionRight.Put]
if len(zero_expiry_calls) == 0 or len(zero_expiry_puts) == 0:
return
# Select the call and put contracts with the nearest strike to the underlying price
nearest_strike_call = min(zero_expiry_calls, key=lambda x: abs(chain.Underlying.Price - x.Strike))
nearest_strike_put = min(zero_expiry_puts, key=lambda x: abs(chain.Underlying.Price - x.Strike))
self.contract_call = nearest_strike_call
self.contract_put = nearest_strike_put
current_time = self.Time
current_price = self.Securities[self.contract_call.Symbol].Price
if current_time.time() == self.entry_time and not self.position_open and self.contract_call.Expiry.date() == self.Time.date():
# Open short straddle position
self.entry_price = current_price
self.position_open = True
self.MarketOrder(self.contract_call.Symbol, -1) # Short the call option
self.MarketOrder(self.contract_put.Symbol, -1) # Short the put option
if (current_time.time() >= self.exit_time or self.is_profit_target_met(self.entry_price, current_price)) and self.position_open:
# Close position if profit target is met or it's after 12pm ET
self.exit_price = current_price
self.profit = self.calculate_profit(self.entry_price, self.exit_price)
self.Liquidate(self.contract_call.Symbol) # Close the call option
self.Liquidate(self.contract_put.Symbol) # Close the put option
self.Debug(f"Closed position at {current_time}: Profit = {self.profit}")
self.position_open = False
def calculate_profit(self, entry_price, exit_price):
if entry_price is None or exit_price is None:
return 0.0
return exit_price - entry_price
def is_profit_target_met(self, entry_price, exit_price):
profit = self.calculate_profit(entry_price, exit_price)
return profit >= self.profit_target
我认为问题在于这个条件:
if self.contract_call is not None and self.Portfolio[self.contract_call.Symbol].Invested:
return
它运行到你的
OnData()
方法的顶部。问题是,当您执行交易时,您正在为 self.contract_call
设置一个值。因此,当下一个数据滴答到来并且调用 OnData()
方法时,它会过早返回。它永远不会达到检查是否在中午关闭交易的条件。
例如,一笔交易于 2022 年 1 月 21 日 09:35 开仓,但由于上述原因,当天中午并未平仓。 2022年1月21日午夜“自然”关闭。