| Overall Statistics |
|
Total Trades 394 Average Win 14.11% Average Loss -4.79% Compounding Annual Return 192.780% Drawdown 96.000% Expectancy 1.003 Net Profit 2980.860% Sharpe Ratio 2.513 Sortino Ratio 4.023 Probabilistic Sharpe Ratio 66.355% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 2.95 Alpha 2.785 Beta 1.898 Annual Standard Deviation 1.155 Annual Variance 1.335 Information Ratio 2.574 Tracking Error 1.104 Treynor Ratio 1.529 Total Fees $221625.49 Estimated Strategy Capacity $0 Lowest Capacity Asset TSLA Y6URRGCB7VXI|TSLA UNU3P8Y3WFAD Portfolio Turnover 2.82% |
# region imports
from AlgorithmImports import *
# endregion
class VAlgorithm(QCAlgorithmFramework):
def Initialize(self):
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2023,3,11)
self.SetCash(1000000)
#set Tesla equity
equity = self.AddEquity("TSLA",Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.tesla = equity.Symbol
option = self.AddOption("TSLA", Resolution.Minute)
option.SetFilter(-3,3,timedelta(50), timedelta(70))
self.call = None
def OnData(self,data):
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type == SecurityType.Option]
if option_invested:
if self.Time + timedelta(30) > option_invested[0].ID.Date:
self.Liquidate(option_invested[0],"too close to expiration")
self.call = None
else: #not invested in an option
for i in data.OptionChains:
chains = i.Value
self.BuyCall(chains)
self.Log(f"Call symbol : {self.call.Symbol}")
self.HedgeDelta(chains)
if self.Time.hour == 10 and self.Time.minute == 0:
for i in data.OptionChains:
chains = i.Value
self.HedgeDelta(chains)
def HedgeDelta(self,chains):
# Get the option position
if self.call:
option_position = self.Portfolio[self.call.Symbol]
if option_position is not None:
# Calculate the delta of the option position
# Extract the delta from the Greeks
call = next((x for x in chains if x.Symbol == self.call.Symbol), None)
if call:
self.call = call
# Calculate the delta of the option position using the updated data
option_delta = self.call.Greeks.Delta
# Calculate the quantity of the underlying asset needed to offset the delta
underlying_quantity = -option_delta * option_position.Quantity
underlying_price = self.Securities[self.tesla].Price
# Calculate the percentage of the portfolio value to set as holdings
portfolio_value = self.Portfolio.TotalPortfolioValue
target_percentage = (underlying_quantity * underlying_price) / portfolio_value
# Place an order to hedge the delta
self.SetHoldings(self.tesla, target_percentage)
return
def BuyCall(self,chains):
#we buy calls that are near at the money 60 days till expiration
expiry = sorted(chains, key = lambda x: abs((x.Expiry-self.Time).days-60))[0].Expiry#60 DTE
calls = [i for i in chains if i.Right == OptionRight.Call and i.Expiry == expiry ]
call_contracts = sorted(calls, key = lambda x: abs(x.Strike - x.UnderlyingLastPrice))
if len(call_contracts) == 0:
return
self.call = call_contracts[0]
quantity = self.Portfolio.TotalPortfolioValue / self.call.AskPrice
quantity = int(quantity*0.4/100)
self.Buy(self.call.Symbol, quantity)
return