| 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)