| Overall Statistics |
|
Total Trades 94 Average Win 0.37% Average Loss -0.09% Compounding Annual Return 1.848% Drawdown 1.600% Expectancy 0.222 Net Profit 0.912% Sharpe Ratio 0.451 Probabilistic Sharpe Ratio 32.884% Loss Rate 77% Win Rate 23% Profit-Loss Ratio 4.22 Alpha 0.016 Beta 0.002 Annual Standard Deviation 0.035 Annual Variance 0.001 Information Ratio -1.994 Tracking Error 0.128 Treynor Ratio 9.243 Total Fees $94.00 Estimated Strategy Capacity $7800000.00 Lowest Capacity Asset SPCE 324FMVN88B9T2|SPCE X91R7VLCNM91 |
class AlgoSeekDataDemoAlgorithm(QCAlgorithm):
max_option_contract_expiry = timedelta(days=30)
profit_target = 5000
option_contract_symbol_by_equity_symbol = {}
hit_profit_target_symbols = []
def Initialize(self):
self.SetStartDate(2021, 1, 1)
self.SetEndDate(2021, 6, 30)
self.SetCash(1000000)
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.Universe.DollarVolume.Top(5))
def OnData(self, data):
# Subscribe to an Option contract for each underlying Equity if one isn't currently selected
for symbol, option_contract in self.option_contract_symbol_by_equity_symbol.items():
if option_contract is not None or symbol in self.hit_profit_target_symbols:
continue
# Fetch the contracts from the OptionChainProvider
contract_symbols = self.OptionChainProvider.GetOptionContractList(symbol, data.Time)
# Find the latest contract expiry
expiries = [symbol.ID.Date for symbol in contract_symbols if symbol.ID.Date.date() > data.Time.date() + self.max_option_contract_expiry]
if len(expiries) == 0:
continue
furthest_expiry = max(expiries)
# Select the put Option contracts with the furthest expiry and in the money
selected_contract_symbols = []
for contract_symbol in contract_symbols:
if contract_symbol.ID.Date == furthest_expiry and \
contract_symbol.ID.OptionRight == OptionRight.Put and \
contract_symbol.ID.StrikePrice < self.Securities[symbol].Price:
selected_contract_symbols.append(contract_symbol)
if len(selected_contract_symbols) == 0:
continue
# Select the put Option contract with the lowest strike price
contract_symbol = sorted(selected_contract_symbols, key=lambda contract: contract.ID.StrikePrice)[0]
self.option_contract_symbol_by_equity_symbol[symbol] = contract_symbol
# Subscribe to the Option contract
self.AddOptionContract(contract_symbol)
# Place entry orders
for symbol, option_contract in self.option_contract_symbol_by_equity_symbol.items():
if symbol in self.hit_profit_target_symbols:
continue
# Buy underlying Equity if not already invested
if data.ContainsKey(symbol) and data[symbol] is not None and \
not self.Portfolio[symbol].Invested and not data[symbol].IsFillForward:
self.MarketOrder(symbol, 100)
# Buy the put Option
if option_contract is not None and \
data.ContainsKey(option_contract) and \
data[option_contract] is not None and \
not self.Portfolio[option_contract].Invested and \
self.Securities[option_contract].IsTradable:
self.MarketOrder(option_contract, 1)
# Close the position if we've hit the take-profit level
for symbol, option_contract in self.option_contract_symbol_by_equity_symbol.items():
if self.Portfolio[symbol].Invested and \
self.Portfolio[symbol].UnrealizedProfit > self.profit_target and \
symbol not in self.hit_profit_target_symbols:
self.hit_profit_target_symbols.append(symbol)
self.Liquidate(symbol)
self.Liquidate(option_contract)
def OnOrderEvent(self, order_event):
# Remove the selected Option contract from our dictionary if it has expired
if order_event.Status == OrderStatus.Filled and \
order_event.Symbol in self.option_contract_symbol_by_equity_symbol.values() and \
order_event.Direction == OrderDirection.Sell:
self.option_contract_symbol_by_equity_symbol[order_event.Symbol.Underlying] = None
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
if security.Type == SecurityType.Equity:
self.option_contract_symbol_by_equity_symbol[security.Symbol] = None
for security in changes.RemovedSecurities:
if security.Type == SecurityType.Equity:
if security.Symbol in self.hit_profit_target_symbols:
self.hit_profit_target_symbols.remove(security.Symbol)
self.Liquidate(security.Symbol)
option_contract = self.option_contract_symbol_by_equity_symbol.pop(security.Symbol, None)
if option_contract:
self.Liquidate(option_contract)