Overall Statistics
Total Orders
19
Average Win
0.02%
Average Loss
-0.03%
Compounding Annual Return
-0.075%
Drawdown
0.100%
Expectancy
-0.642
Start Equity
10000000
End Equity
9999344
Net Profit
-0.007%
Sharpe Ratio
-0.641
Sortino Ratio
-0.767
Probabilistic Sharpe Ratio
35.096%
Loss Rate
78%
Win Rate
22%
Profit-Loss Ratio
0.61
Alpha
-0.005
Beta
0.025
Annual Standard Deviation
0.005
Annual Variance
0
Information Ratio
-0.464
Tracking Error
0.135
Treynor Ratio
-0.121
Total Fees
$19.00
Estimated Strategy Capacity
$13000.00
Lowest Capacity Asset
GOOCV 31K516AN36IVA|GOOCV VP83T1ZUHROL
Portfolio Turnover
0.20%
from AlgorithmImports import *

class USEquityOptionsUniverseAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2021, 1, 1)
        self.set_end_date(2021, 2, 1)
        self.set_cash(10000000)

        # Asynchronous can use computational resources efficiently
        self.universe_settings.asynchronous = True
        # Subscribe to the underlying for the underlying position
        # Set the data normalization mode to raw for strike price comparability
        self.equity = self.add_equity("GOOG", data_normalization_mode=DataNormalizationMode.RAW).symbol
        # Requesting option data and filter for the hedge candidates
        option = self.add_option(self.equity)
        option.set_filter(self.option_filter)
        self.option_symbol = option.symbol

        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
        self.schedule.on(
            self.date_rules.every_day(self.equity),
            self.time_rules.after_market_open(self.equity, 1),
            self.buy_hedge_contract
        )

        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
        # Leave 2 minutes contingency to fill
        self.schedule.on(
            self.date_rules.every_day(self.equity),
            self.time_rules.before_market_close(self.equity, 2),
            self.sell_hedge_contract
        )

        self.hedge = None
        
    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
        # Select the contracts with delta very close to -1 and high open interest
        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
        # Make sure the contract is expiring close for its tradbility
        return universe.include_weeklys().puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)

    def buy_hedge_contract(self) -> None:
        chain = self.current_slice.option_chains.get(self.option_symbol)
        if chain:
            # Order the underlying if not hold, the order size should match the option contract
            # Order only if option chain data ready for hedging
            if not self.portfolio[self.equity].invested:
                self.market_order(self.equity, self.securities[self.option_symbol].symbol_properties.contract_multiplier)

            # Get the contract with delta closest to -1 (lowest possible delta)
            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
            self.hedge = contract.symbol
            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
            self.market_order(self.hedge, 1)
        
    def sell_hedge_contract(self) -> None:
        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
        if self.hedge:
            self.liquidate(self.hedge)
            self.hedge = None