Skip to content
All library documents

Building Long and Short Option Straddles with Strategy Helpers

Article Strategy library · Author: QuantConnect

Summary

This example demonstrates how an options strategy helper can submit a straddle as a grouped trade. It searches the option chain for a strike and expiry that have both a call and a put, selecting contracts near the underlying price and favoring later expiries in its ordering. It then constructs long and short straddle definitions and buys two units of the long straddle.

The example checks that the resulting position group contains one call and one put, each with quantity two. Its liquidation method buys two units of the short straddle as the inverse strategy to close the long position. The code is an order-construction example rather than a signal-based trading system: it gives no entry timing, volatility view, pricing analysis, backtest results, or risk controls. A long straddle generally depends on a sufficiently large move to offset the premiums paid, while a short straddle has substantial exposure if the underlying moves sharply; those trade-offs are not analyzed in the example.

Key ideas

  • A straddle pairs a call and a put with the same strike and expiry.
  • The example searches for a strike and expiry where both option types are available.
  • It submits two units of the long straddle and expects two contracts on each leg.
  • The inverse short straddle is used to liquidate the long position group.
  • The code demonstrates order construction and position checks, not trade signals or performance analysis.

Tags

Full text
# LongAndShortStraddleStrategiesAlgorithm


# LongAndShortStraddleStrategiesAlgorithm









This algorithm demonstrate how to use OptionStrategies helper class to batch send orders for common strategies. In this case, the algorithm tests the Straddle and Short Straddle strategies.

## Source (Apache-2.0)

```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.

import itertools
from AlgorithmImports import *

from OptionStrategyFactoryMethodsBaseAlgorithm import *

### <summary>
### This algorithm demonstrate how to use OptionStrategies helper class to batch send orders for common strategies.
### In this case, the algorithm tests the Straddle and Short Straddle strategies.
### </summary>
class LongAndShortStraddleStrategiesAlgorithm(OptionStrategyFactoryMethodsBaseAlgorithm):

    def expected_orders_count(self) -> int:
        return 4

    def trade_strategy(self, chain: OptionChain, option_symbol: Symbol):
        contracts = sorted(sorted(chain, key=lambda x: abs(chain.underlying.price - x.strike)),
                           key=lambda x: x.expiry, reverse=True)
        grouped_contracts = [list(group) for _, group in itertools.groupby(contracts, lambda x: (x.strike, x.expiry))]
        filtered_grouped_contracts = (group
                            for group in grouped_contracts
                            if (any(contract.right == OptionRight.CALL for contract in group) and
                                any(contract.right == OptionRight.PUT for contract in group)))
        contracts = next(filtered_grouped_contracts, [])

        if len(contracts) == 0:
            return

        contract = contracts[0]
        if contract is not None:
            self._straddle = OptionStrategies.straddle(option_symbol, contract.strike, contract.expiry)
            self._short_straddle = OptionStrategies.short_straddle(option_symbol, contract.strike, contract.expiry)
            self.buy(self._straddle, 2)

    def assert_strategy_position_group(self, position_group: IPositionGroup, option_symbol: Symbol):
        positions = list(position_group.positions)
        if len(positions) != 2:
            raise AssertionError(f"Expected position group to have 2 positions. Actual: {len(positions)}")

        call_position = next((position for position in positions if position.symbol.id.option_right == OptionRight.CALL), None)
        if call_position is None:
            raise AssertionError("Expected position group to have a call position")

        put_position = next((position for position in positions if position.symbol.id.option_right == OptionRight.PUT), None)
        if put_position is None:
            raise AssertionError("Expected position group to have a put position")

        expected_call_position_quantity = 2
        expected_put_position_quantity = 2

        if call_position.quantity != expected_call_position_quantity:
            raise AssertionError(f"Expected call position quantity to be {expected_call_position_quantity}. Actual: {call_position.quantity}")

        if put_position.quantity != expected_put_position_quantity:
            raise AssertionError(f"Expected put position quantity to be {expected_put_position_quantity}. Actual: {put_position.quantity}")

    def liquidate_strategy(self):
        # We should be able to close the position using the inverse strategy (a short straddle)
        self.buy(self._short_straddle, 2)

```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.