Overall Statistics
Total Orders
6
Average Win
12.04%
Average Loss
-5.94%
Compounding Annual Return
35.514%
Drawdown
17.800%
Expectancy
1.018
Start Equity
100000
End Equity
111030.12
Net Profit
11.030%
Sharpe Ratio
0.799
Sortino Ratio
1.109
Probabilistic Sharpe Ratio
41.658%
Loss Rate
33%
Win Rate
67%
Profit-Loss Ratio
2.03
Alpha
0.343
Beta
0.132
Annual Standard Deviation
0.423
Annual Variance
0.179
Information Ratio
0.678
Tracking Error
0.56
Treynor Ratio
2.55
Total Fees
$7.41
Estimated Strategy Capacity
$3400000.00
Lowest Capacity Asset
GC XFO1EI4768PP
Portfolio Turnover
3.71%
from AlgorithmImports import *
from QuantConnect.DataSource import *

class FutureOptionDataAlgorithm(QCAlgorithm):
    
    option_contract_by_underlying_future_contract = {}
    
    def initialize(self) -> None:
        self.set_start_date(2020, 1, 28)
        self.set_end_date(2020, 6, 1)
        self.set_cash(100000)
        self.universe_settings.asynchronous = True
        # Requesting data
        gold_futures = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
        gold_futures.set_filter(0, 90)
        self.add_future_option(gold_futures.symbol, lambda universe: universe.strikes(-5, +5)
                                                                           .calls_only()
                                                                           .back_month())
        
    def on_data(self, slice: Slice) -> None:
        for kvp in slice.option_chains:
            # Liquidate underlying Future contract after Option assignment
            underlying_future_contract = kvp.Key.underlying
            if self.portfolio[underlying_future_contract].invested:
                self.liquidate(underlying_future_contract)
                self.option_contract_by_underlying_future_contract.pop(underlying_future_contract)
            
            chain = kvp.Value
            chain = [contract for contract in chain if self.securities[contract.symbol].is_tradable]
            
            # Continue if chain is empty or already invested in an Option on this Futures contract
            if not chain or underlying_future_contract in self.option_contract_by_underlying_future_contract:
                continue

            # Select the Option contract with the lowest strike price
            contract = sorted(chain, key = lambda x: x.strike)[0]
            
            self.market_order(contract.symbol, 1)
            self.option_contract_by_underlying_future_contract[kvp.Key.underlying] = contract
        
        
    def on_securities_changed(self, changes: SecurityChanges) -> None:
        for security in changes.added_securities:
            if security.type == SecurityType.FUTURE_OPTION:
                # Historical data
                history = self.history(security.symbol, 10, Resolution.MINUTE)
                self.debug(f"We got {len(history)} from our history request for {security.symbol}")