在 Quant Connect 中编码回测策略

问题描述 投票:0回答:1

我正在尝试在 Quant Connect 中回测以下策略

  1. 每天在东部时间上午 9:35 使用 0DTE 以中间价差价格开立空头 SPY 跨式期权
  2. 盈利10%就平仓
  3. 如果未达到利润,请在东部时间中午 12 点平仓。不要持仓过夜。
  4. 这是连续的,意味着一次一个位置

当我运行策略时,头寸并不是每天都开仓和平仓。例如,某天上午 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
python algorithmic-trading back-testing
1个回答
0
投票

我认为问题在于这个条件:

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日午夜“自然”关闭。

© www.soinside.com 2019 - 2024. All rights reserved.