Original paper
Trading rules
- Investment universe: All U.S. equity options
- Straddle formation: Day following standard monthly options expiration (third Friday of each month)
- Exclusions: Options violating arbitrage conditions, underlying equity price less than 10 USD, non-ATM options (delta not between 0.35 (-0.35) and 0.65 (-0.65) for call (put))
- Maturity range: One to six months
- Portfolio formation: Based on slope of implied volatility term structure
- Decile buckets:
- Decile 1: Most upward-sloping term structure (positive slope)
- Decile 10: Most downward-sloping term structure (negative slope)
- Strategy: Buy decile 1, sell decile 10 of one-month ATM straddles
- Holding period: Until expiration (one month)
- Portfolio weighting: Equally weighted
- Investment allocation: 20% of total portfolio value due to leptokurtic skewness
Python code
Backtrader
Here’s a skeleton code for the Backtrader trading strategy based on the given rules. Please note that this code assumes you have the necessary data for U.S. equity options, including implied volatilities and deltas, which are not available in the default Backtrader dataset. You will need to import this data and create custom indicators to calculate the slopes of implied volatility term structures.
import backtrader as bt
import pandas as pd
import numpy as np
from datetime import timedelta
class StraddleStrategy(bt.Strategy):
def __init__(self):
# Custom indicators and calculations for slope and deciles will be required
pass
def next(self):
# Check if today is the day after the third Friday of the month
if (self.datetime.date(0).day > 21) and (self.datetime.date(0) - timedelta(days=1)).weekday() == 4:
# Filter options and calculate slopes, deciles, etc.
# This will require custom data processing and indicators
# Create equal weights for selected options
weights = 1.0 / len(selected_options)
# Enter positions for selected options
for option in selected_options:
self.order_target_percent(data=option, target=weights * 0.2) # 20% of total portfolio value
# Exit positions at expiration (one month holding period)
for option in self.getpositions():
if self.datetime.date(0) >= option.expiration_date:
self.sell(data=option)
if __name__ == '__main__':
cerebro = bt.Cerebro()
cerebro.addstrategy(StraddleStrategy)
# Add U.S. equity options data feed here
cerebro.run()
This code provides a basic framework for the StraddleStrategy. You will need to implement the custom data processing and indicators to filter options based on the given rules, calculate the slopes of implied volatility term structures, and assign deciles. Additionally, you will need to provide a custom data feed containing the necessary U.S. equity options data.