Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -0.421 Tracking Error 0.191 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
from datetime import timedelta from AlgorithmImports import * class SimpleOptionStrategy(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) # Setting start date self.SetCash(100000) # Setting initial cash # Add equity data for the underlying stock self.equity = self.AddEquity("TSLA", Resolution.Minute) self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) # Add option data self.option = self.AddOption("TSLA", Resolution.Minute) # Set our option filter self.option.SetFilter(self.UniverseFunc) # Flag to determine if we've invested in options self.invested = False def UniverseFunc(self, universe): return universe.IncludeWeeklys() \ .Strikes(-2, 2) \ .Expiration(timedelta(14), timedelta(15)) def OnData(self, slice): # Check if we have any option data if slice.OptionChains.Count == 0: return if not self.invested: for kvp in slice.OptionChains: chain = kvp.Value # Logging the underlying equity price self.Log(f"Underlying equity price: {chain.Underlying.Price}") # We're sorting the contracts to find at the money option (with minimum difference from current price) and volume > 0 contracts = sorted([i for i in chain if i.Volume > 0], key = lambda x: abs(chain.Underlying.Price - x.Strike)) if len(contracts) == 0: self.Log("No tradable contracts available.") continue # Selecting the first contract (which is the nearest ATM) contract = contracts[0] self.Log(f"Selected contract: {contract.Symbol}, Strike: {contract.Strike}, LastPrice: {contract.LastPrice}") # Buy the contract self.Buy(contract.Symbol, 10) # Logging the purchase self.Log(f"Purchased contract: {contract.Symbol}") # Setting our invested flag to True self.invested = True else: for kvp in slice.OptionChains: chain = kvp.Value for contract in chain: if self.Portfolio[contract.Symbol].IsLong: unrealizedProfitPercent = self.Portfolio[contract.Symbol].UnrealizedProfitPercent # Logging unrealized profit percent self.Log(f"Unrealized Profit %: {unrealizedProfitPercent*100}") if unrealizedProfitPercent > 0.10 or unrealizedProfitPercent < -0.05: self.Liquidate(contract.Symbol) # Logging the liquidation self.Log(f"Liquidated contract: {contract.Symbol}") self.invested = False
from AlgorithmImports import * from datetime import timedelta class StrangleStrategy(QCAlgorithm): OtmPercentage = 0.10 OtmSellContracts = 35 OtmBuyContracts = 10 ExpiryDays = 10 def Initialize(self): self.SetStartDate(2020, 1, 1) self.SetCash(100000) self.equity = self.AddEquity("TSLA", Resolution.Minute) self.equitySymbol = self.equity.Symbol self.option = self.AddOption("TSLA", Resolution.Minute) # Set the filter for options data self.option.SetFilter(-100, +100) self.option.SetFilter(lambda x: x.Expiration(timedelta(days=4), timedelta(days=7))) self.initialPositionValue = 0 self.underlyingEquityValueAtPurchase = 0 # Member variable to store the underlying equity value def OnData(self, data): self.Log(f"OnData triggered for date: {self.Time}") if not self.Portfolio.Invested: if self.equitySymbol in data.OptionChains: chain = data.OptionChains[self.equitySymbol] self.Log(f"Option chain fetched. Total contracts: {len(chain)}") callsAtTheMoney = [contract for contract in chain if contract.Right == OptionRight.Call and contract.Expiry < self.Time + timedelta(days=self.ExpiryDays) and contract.Expiry > self.Time + timedelta(days=self.ExpiryDays - 5)] self.Log(f"Number of ATM Call contracts: {len(callsAtTheMoney)}") putsOutOfTheMoney = [contract for contract in chain if contract.Right == OptionRight.Put and contract.Strike < self.equity.Price * (1 - self.OtmPercentage) and contract.Expiry < self.Time + timedelta(days=self.ExpiryDays) and contract.Expiry > self.Time + timedelta(days=self.ExpiryDays - 5)] self.Log(f"Number of OTM Put contracts: {len(putsOutOfTheMoney)}") sentiment = self.DetermineSentiment() self.Log(f"Determined sentiment: {sentiment}") if sentiment == "bullish": atms = self.GetAtTheMoneyOptions(callsAtTheMoney) atmCallCost = 0 if atms: atmCallCost = atms.AskPrice * self.OtmBuyContracts * 100 self.Log(f"Buying ATM calls. Symbol: {atms.Symbol}, Ask Price: {atms.AskPrice}, Cost: {atmCallCost}") else: self.Log("ATM calls not found.") otmCallProceeds = 0 otmsCalls = self.GetOutOfTheMoneyOptionsForCalls(callsAtTheMoney, atmCallCost) if otmsCalls: otmCallProceeds = otmsCalls.BidPrice * self.OtmSellContracts * 100 self.Log(f"Selling OTM calls. Symbol: {otmsCalls.Symbol}, Bid Price: {otmsCalls.BidPrice}") else: self.Log("Suitable OTM calls for selling not found.") otmsPuts = self.GetOutOfTheMoneyOptionsForPuts(putsOutOfTheMoney, atmCallCost, otmCallProceeds) if otmsPuts: self.Log(f"Selling OTM puts. Symbol: {otmsPuts.Symbol}, Bid Price: {otmsPuts.BidPrice}") else: self.Log("Suitable OTM puts for selling not found.") else: self.Log("Failed to fetch option chain.") else: self.Log("Portfolio already invested.") def DetermineSentiment(self): return "bullish" def GetAtTheMoneyOptions(self, options): sorted_options = sorted(options, key=lambda x: abs(x.Strike - self.equity.Price)) return sorted_options[0] if sorted_options else None def GetOutOfTheMoneyOptionsForCalls(self, options, atmCallCost): otmCalls = [option for option in options if option.Strike > self.equity.Price] otmCalls = sorted(otmCalls, key=lambda x: x.Strike) for otmCall in otmCalls: proceedsFromOtmCall = otmCall.BidPrice * self.OtmSellContracts * 100 netProceeds = proceedsFromOtmCall - atmCallCost if netProceeds > 0.015 * self.equity.Price * 1000: return otmCall return None def GetOutOfTheMoneyOptionsForPuts(self, options, atmCallCost, otmCallProceeds): otmPuts = [option for option in options if option.Strike < self.equity.Price] otmPuts = sorted(otmPuts, key=lambda x: x.Strike) for otmPut in otmPuts: proceedsFromOtmPut = otmPut.BidPrice * self.OtmBuyContracts * 100 netProceeds = otmCallProceeds + proceedsFromOtmPut - atmCallCost if netProceeds > 0.015 * self.equity.Price * 1000: return otmPut return None def AdjustPosition(self): if self.underlyingEquityValueAtPurchase == 0: return currentProfitPercentage = (self.Portfolio.TotalPortfolioValue - self.initialPositionValue) / self.underlyingEquityValueAtPurchase if currentProfitPercentage > 0.01: self.Liquidate() self.initialPositionValue = 0 self.underlyingEquityValueAtPurchase = 0
from AlgorithmImports import * class SquareMagentaHamster(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 1, 1) # Set Start Date self.SetEndDate(2019, 1, 1) self.SetCash(1000000) # Set Strategy Cash index = self.AddIndex("SPX", Resolution.Minute) self.spx = index.Symbol option = self.AddOption(index.Symbol, Resolution.Minute) option.SetFilter(self.UniverseFunc) self.symbol = option.Symbol self.indicator = SimpleMovingAverage(200) self.RegisterIndicator(self.spx, self.indicator, Resolution.Daily) self.entryTicket = None self.SLTicket = None self.TPTicket = None self.entryTime = datetime.min self.AddRiskManagement(TrailingStopRiskManagementModel(0.15)) def UniverseFunc(self, universe: OptionFilterUniverse) -> OptionFilterUniverse: return universe.IncludeWeeklys().Strikes(1, 2).Expiration(timedelta(45), timedelta(50)) def OnData(self, data: Slice): if not(data.ContainsKey(self.spx) and data[self.spx] is not None): return if not self.indicator.IsReady: return option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option] if option_invested: for option in option_invested: if self.Time + timedelta(1) > option.ID.Date: self.Liquidate(option, "Option too close to expiration.") lvl = self.indicator.Current.Value atSMA = self.Securities[self.spx].AskPrice > lvl - 2 and self.Securities[self.spx].AskPrice < lvl + 2 if atSMA and not self.Portfolio.Invested: self.BuyCall(data) self.BuyPut(data) def BuyCall(self, data: Slice) -> None: # Get the OptionChain chain = data.OptionChains.get(self.symbol, None) if not chain: return # Get the furthest expiry date of the contracts expiry = sorted(chain, key = lambda x: x.Expiry, reverse=True)[0].Expiry # Select the call Option contracts with the furthest expiry calls = [i for i in chain if i.Expiry == expiry and i.Right == OptionRight.Call] if len(calls) == 0: return call_contracts = sorted(calls, key = lambda x: abs(x.Strike - x.UnderlyingLastPrice)) if len(call_contracts) == 0: return self.call = call_contracts[0] self.entryTicket = self.MarketOrder(self.call.Symbol, 5) def BuyPut(self, data: Slice) -> None: # Get the OptionChain chain = data.OptionChains.get(self.symbol, None) if not chain: return # Get the furthest expiry date of the contracts expiry = sorted(chain, key = lambda x: x.Expiry, reverse=True)[0].Expiry # Select the call Option contracts with the furthest expiry puts = [i for i in chain if i.Expiry == expiry and i.Right == OptionRight.Put] if len(puts) == 0: return put_contracts = sorted(puts, key = lambda x: abs(x.Strike - x.UnderlyingLastPrice)) if len(put_contracts) == 0: return self.put = put_contracts[0] self.entryTicket = self.MarketOrder(self.put.Symbol, 5)