Overall Statistics |
Total Orders 4 Average Win 0% Average Loss 0% Compounding Annual Return -0.113% Drawdown 0.000% Expectancy 0 Start Equity 100000 End Equity 99997 Net Profit -0.003% Sharpe Ratio -43.667 Sortino Ratio -861.468 Probabilistic Sharpe Ratio 37.637% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.05 Beta -0.003 Annual Standard Deviation 0.001 Annual Variance 0 Information Ratio 2.524 Tracking Error 0.182 Treynor Ratio 15.48 Total Fees $4.00 Estimated Strategy Capacity $1300000.00 Lowest Capacity Asset SPY Y6URRHKSRX7Q|SPY R735QTJ8XC9X Portfolio Turnover 0.22% |
# region imports from AlgorithmImports import * # endregion def _get_iron_condor_legs(chain): if not 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) < 3 or len(put_contracts) < 3: return [] # Select the strategy legs near_call = call_contracts[-3] far_call = call_contracts[-1] near_put = put_contracts[2] far_put = [x for x in put_contracts if x.Strike == near_put.strike - far_call.strike + near_call.strike][0] return [ Leg.create(far_put.symbol, 1), Leg.create(near_put.symbol, -1), Leg.create(far_call.symbol, 1), Leg.create(near_call.symbol, -1) ] class CalmSkyBlueCobra(QCAlgorithm): def initialize(self): self.set_start_date(2023, 3, 1) self.set_end_date(2023, 3, 12) self._symbol = self.add_option("SPY").Symbol self.tickets = self.legs = [] def on_data(self, slice: Slice) -> None: if self.portfolio[self._symbol.underlying].invested: self.liquidate() if self.portfolio.invested or not self.is_market_open(self._symbol) or self.tickets: prices = [self.get_value(x) for x in self.legs] self.log(f'{self.time} :: Price of the combo: {sum(prices)}') return legs = _get_iron_condor_legs(slice.option_chains.get(self._symbol)) if not legs: return self.legs = legs prices = [self.get_value(x) for x in legs] price = sum(prices) limit_price = -2 self.tickets = self.combo_limit_order(legs, 1, limit_price, tag=f'Price={price:.2f}, Limit Price={limit_price:.2f}') def on_order_event(self, order_event): if order_event.status != OrderStatus.FILLED: return prices = [self.get_value(x) for x in self.legs] price = sum([x.average_fill_price * x.quantity_filled for x in self.tickets]) self.log(f'Fill price: {order_event.fill_price*order_event.fill_quantity:.2f}. Combo fill price: {price:.2f}') def get_value(self, leg): quote_bar = self.securities[leg.symbol].cache.get_data[QuoteBar]() price = quote_bar.ask.low if leg.quantity > 0 else quote_bar.bid.low return price * leg.quantity