| Overall Statistics |
|
Total Trades 133 Average Win 0.06% Average Loss -0.04% Compounding Annual Return 0.334% Drawdown 1.200% Expectancy 0.090 Net Profit 0.234% Sharpe Ratio 0.211 Probabilistic Sharpe Ratio 21.747% Loss Rate 57% Win Rate 43% Profit-Loss Ratio 1.51 Alpha 0.007 Beta -0.024 Annual Standard Deviation 0.011 Annual Variance 0 Information Ratio -1.568 Tracking Error 0.114 Treynor Ratio -0.097 Total Fees $76.20 Estimated Strategy Capacity $3000.00 Lowest Capacity Asset SPY YB1F5SRQ7R6U|SPY R735QTJ8XC9X Portfolio Turnover 3.22% |
#region imports
from AlgorithmImports import *
import datetime
#endregion
class IronCondorAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 1, 1)
self.SetCash(100000)
option = self.AddOption("SPY")
self.symbol = option.Symbol
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
option.SetFilter(lambda universe:
universe.Strikes(-15, 15).Expiration(0, 0))
# use the underlying instrument as the benchmark
self.SetBenchmark(self.symbol.Underlying)
self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol, 30), self.OpenIronCondor)
def OpenIronCondor(self):
# Print the underlying price
underlying_price = self.Securities[self.symbol.Underlying].Price
self.Debug(f"Opening Iron Condor position. Underlying Price: {underlying_price}")
# Get the Option chain
chain = self.CurrentSlice.OptionChains.get(self.symbol)
if not chain:
self.Debug(f"No Option Chain")
return
# Find put and call contracts with the farthest expiry
expiry = max([x.Expiry for x in chain])
chain = sorted([x for x in chain if x.Expiry == expiry], key = lambda x: x.Strike)
put_contracts = [x for x in chain if x.Right == OptionRight.Put]
call_contracts = [x for x in chain if x.Right == OptionRight.Call]
if len(call_contracts) < 10 or len(put_contracts) < 10:
return
# Select the strikes in the strategy legs
far_put = put_contracts[0].Strike
near_put = put_contracts[10].Strike
near_call = call_contracts[-10].Strike
far_call = call_contracts[-1].Strike
self.Debug(f"Strike Price -> {far_put}/{near_put}/{near_call}/{far_call}")
iron_condor = OptionStrategies.IronCondor(
self.symbol,
far_put,
near_put,
near_call,
far_call,
expiry)
self.Buy(iron_condor, 2)
def OnData(self,slice):
# If there is underlying assets in portfolio at expiration, liquidate the stocks in order to roll into new contracts
if self.Portfolio[self.symbol.Underlying].Invested:
self.Liquidate()
if self.Portfolio.Invested or not self.IsMarketOpen(self.symbol):
return