| Overall Statistics |
|
Total Trades 20 Average Win 0.02% Average Loss -0.03% Compounding Annual Return -0.081% Drawdown 0.100% Expectancy -0.359 Net Profit -0.093% Sharpe Ratio -0.938 Probabilistic Sharpe Ratio 0.160% Loss Rate 60% Win Rate 40% Profit-Loss Ratio 0.60 Alpha 0 Beta 0 Annual Standard Deviation 0.001 Annual Variance 0 Information Ratio -0.938 Tracking Error 0.001 Treynor Ratio 0 Total Fees $20.00 Estimated Strategy Capacity $410000.00 Lowest Capacity Asset AAPL 3250B9MJXFZ3A|AAPL R735QTJ8XC9X |
# region imports
from AlgorithmImports import *
from datetime import datetime
from datetime import timedelta
# endregion
class FatBlueAlligator(QCAlgorithm):
def Initialize(self):
self.ticker = "AAPL"
self.SetStartDate(2022, 1, 1)
self.MIN_DAYS_TO_EXP = 3 # don't consider contracts less than X days to expiry
self.CALENDAR_CAL_FAR_EXPIRY = 21 # at least DAYS away from near term for calendar
self.STRATEGY_TYPE = 2 # 1 - stock; 2 - straddle; 3 - calendar ;
datesToWatchStr = '27/01/2022,28/04/2022,28/07/2022,27/10/2022,02/02/2023'
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.SetWarmUp(30, Resolution.Daily)
self.SetCash(1000000)
self.AddEquity(self.ticker, Resolution.Minute)
self.option = self.AddOption(self.ticker, Resolution.Minute)
self.symbol = self.option.Symbol
self.option.SetFilter( lambda option_filter_universe: option_filter_universe.IncludeWeeklys().Strikes(-1, 1).Expiration(self.MIN_DAYS_TO_EXP, 90))
self.datesToWatch = []
for i in datesToWatchStr.split(","):
self.datesToWatch.append(datetime.strptime(i, '%d/%m/%Y').date())
self.dateSell = None
self.invested = False
def OnData(self, slice: Slice) -> None:
if not self.IsWarmingUp and self.Time.hour == 10 and self.Time.minute == 00 and self.dateSell == None:
if self.Time.date()+timedelta(1) in self.datesToWatch:
self.Log(f"signal is triggered on\t {self.ticker}")
chain = slice.OptionChains.get(self.symbol, None)
if not chain:
self.Log("options chain is not ready")
return
contract_days = [] # collecting contracts dates list for custom far term selection
for i in chain:
if i.Expiry.date() not in contract_days:
contract_days.append(i.Expiry.date())
contract_days = sorted(contract_days)
self.Log(f"Contracts are with following expiry dates\t{contract_days}")
expiry = sorted(chain, key=lambda contract: contract.Expiry, reverse=False)[0].Expiry
underlyingLastPrice = sorted(chain, key=lambda contract: contract.Expiry, reverse=False)[0].UnderlyingLastPrice # perhaps there is a better way to get underlyng price
far_expiry=''
for i in contract_days:
if (expiry.date() + timedelta(self.CALENDAR_CAL_FAR_EXPIRY)) <= i:
far_expiry = i
break
strikes = [contract.Strike for contract in chain if contract.Expiry == expiry]
strike = sorted(strikes, key=lambda strike: abs(strike - chain.Underlying.Price))[0]
self.Log(f"{self.symbol}\tstrategy is based on\t\t Stock Price:{underlyingLastPrice}\tstrike:{strike}\tnear term:{str(expiry.date())}\tfar term:{far_expiry}")
if self.STRATEGY_TYPE == 1: # cash
self.Buy(self.ticker, 100)
if self.STRATEGY_TYPE == 2: # straddle
staddle_option_strategy = OptionStrategies.Straddle(self.symbol, strike, expiry)
self.Buy(staddle_option_strategy, 1)
if self.STRATEGY_TYPE == 3: # calendar
calendar_option_strategy = OptionStrategies.CallCalendarSpread(self.symbol, strike, expiry, far_expiry)
self.Buy(calendar_option_strategy, 1)
self.Log("Call Spread 'Buy' has been completed")
self.dateSell = self.Time.date() + timedelta(1) # sell the next day after earnings announced
self.invested = True
if self.invested and self.Time.date() > self.dateSell:
self.Liquidate()
self.invested = False
self.dateSell = None
self.Log(f"position has been liquidated")