| Overall Statistics |
|
Total Trades 7 Average Win 0% Average Loss -0.35% Compounding Annual Return -15.633% Drawdown 1.100% Expectancy -1 Net Profit -0.310% Sharpe Ratio -7.213 Probabilistic Sharpe Ratio 1.216% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.191 Beta 0.068 Annual Standard Deviation 0.025 Annual Variance 0.001 Information Ratio -3.347 Tracking Error 0.11 Treynor Ratio -2.598 Total Fees $7.00 |
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Securities.Option import OptionPriceModels
from QuantConnect.Securities.Option import OptionStrategies
import pandas as pd
import numpy as np
import math
class QuantumVerticalInterceptor(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2020, 1, 7)
self.SetCash(10000)
self.DELTA_TARGET=0.5
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)
self.df_calls = None
#set a risk limit of 1% of portfolio value
self.investment_limit = self.Portfolio.TotalPortfolioValue * 0.01
# Add the option
option = self.AddOption("SPY")
self.optionSymbol = option.Symbol
# Add the initial contract filter
option.SetFilter(-5, +5, 5, 10)
# Define the Option Price Model
option.PriceModel = OptionPriceModels.CrankNicolsonFD()
#option.PriceModel = OptionPriceModels.BlackScholes()
#option.PriceModel = OptionPriceModels.AdditiveEquiprobabilities()
#option.PriceModel = OptionPriceModels.BaroneAdesiWhaley()
#option.PriceModel = OptionPriceModels.BinomialCoxRossRubinstein()
#option.PriceModel = OptionPriceModels.BinomialJarrowRudd()
#option.PriceModel = OptionPriceModels.BinomialJoshi()
#option.PriceModel = OptionPriceModels.BinomialLeisenReimer()
#option.PriceModel = OptionPriceModels.BinomialTian()
#option.PriceModel = OptionPriceModels.BinomialTrigeorgis()
#option.PriceModel = OptionPriceModels.BjerksundStensland()
#option.PriceModel = OptionPriceModels.Integral()
# Set warm up with 30 trading days to warm up the underlying volatility model
self.SetWarmUp(30, Resolution.Daily)
def OnData(self,slice):
self.Plot("Portfolio", "Margin Remaining", self.Portfolio.MarginRemaining) # Remaining margin on the account
self.Plot("Portfolio", "Margin Used", self.Portfolio.TotalMarginUsed) # Sum of margin used across all securities
if self.IsWarmingUp or not slice.OptionChains.ContainsKey(self.optionSymbol):
return
chain = slice.OptionChains[self.optionSymbol]
#set float format so delta displays correctly
pd.set_option('display.float_format', lambda x: '%.5f' % x)
#put the relevant data into the dataframe
df = pd.DataFrame([[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice),x.Greeks.Delta,x.UnderlyingLastPrice] for x in chain],
index=[x.Symbol.Value for x in chain],
columns=['type', 'strike', 'expiry', 'ask price', 'bid price', 'delta','underlyinglast'])
#ensure expiry column is in datetime format
df['expiry'] = pd.to_datetime(df['expiry'])
# sort by expiry, descending
df.sort_values(by=['expiry'],ascending=False)
# get the most future date
furthest_date = df['expiry'].iloc[0]
# keep only those rows which have that furthest date
df = df[df.expiry == furthest_date]
#split the dataframe into calls and puts (calls are 0, puts are 1)
self.df_calls = df[df.type==0]
#sort by delta
self.df_calls.sort_values(by=['delta'],ascending=False)
#select the closest two records to the DELTA TARGET
#try:
uppercall_ind = self.df_calls[self.df_calls.delta<self.DELTA_TARGET].delta.idxmax()
lowercall_ind = self.df_calls[self.df_calls.delta>self.DELTA_TARGET].delta.idxmin()
self.df_calls = self.df_calls[self.df_calls.index.isin([lowercall_ind,uppercall_ind])]
spread_value = self.df_calls.at[lowercall_ind,'bid price'] - self.df_calls.at[uppercall_ind,'ask price']
max_risk = self.df_calls.at[uppercall_ind,'strike'] - self.df_calls.at[lowercall_ind,'strike']
max_risk_contract = max_risk * 100
max_investment = math.trunc(self.investment_limit / max_risk_contract)
self.Sell(OptionStrategies.BearCallSpread(self.optionSymbol, self.df_calls.at[lowercall_ind,'strike'], self.df_calls.at[uppercall_ind,'strike'] , self.df_calls.at[uppercall_ind,'expiry']), max_investment)
#except:
# return