| Overall Statistics |
|
Total Orders 4998 Average Win 0.00% Average Loss 0.00% Compounding Annual Return -65.022% Drawdown 13.700% Expectancy -0.235 Start Equity 2000000 End Equity 1904505.61 Net Profit -4.775% Sharpe Ratio -0.272 Sortino Ratio -0.461 Probabilistic Sharpe Ratio 37.625% Loss Rate 51% Win Rate 49% Profit-Loss Ratio 0.55 Alpha -1.765 Beta 3.323 Annual Standard Deviation 0.666 Annual Variance 0.444 Information Ratio -1.206 Tracking Error 0.545 Treynor Ratio -0.054 Total Fees $6834.40 Estimated Strategy Capacity $36000.00 Lowest Capacity Asset QQQ 31TIRIE31K486|QQQ RIWIV7K5Z9LX Portfolio Turnover 1015.12% |
from AlgorithmImports import *
import pandas as pd
import numpy as np
class FormalAsparagusFrog(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 12, 1)
self.SetEndDate(2021, 12, 17)
self.SetCash(2000000)
equity = self.AddEquity('QQQ', Resolution.Minute)
option = self.AddOption('QQQ', Resolution.Minute)
self.symbol = option.Symbol
self.stock = equity.Symbol
option.SetFilter(-30, 30, 0, 500)
self.trade = True
self.contract = None
self.size = 203
self.sign = -1
self.highest_pnl = 0 # Track the highest PnL
def OnData(self, slice: Slice) -> None:
if self.trade:
chain = slice.OptionChains.get(self.symbol)
if chain:
# Change to target put options (Right == 1 for puts)
contract_list = [x for x in chain if x.Expiry == DateTime(2021, 12, 17) and x.Right == 1 and x.Strike <= x.UnderlyingLastPrice]
self.highest_put = sorted(contract_list, key=lambda x: x.Strike, reverse=True)[0].Strike
self.contract = [contract for contract in contract_list if contract.Strike == self.highest_put][0]
# Calculate historical volatility based on the last 25 trading days
daily_returns = self.History(self.stock, 25, Resolution.Daily)['close'].pct_change()[1:]
self.sign = -1
volatility = daily_returns.std() * 252**0.5 # Annualized volatility based on 252 trading days
self.Log(volatility)
self.Log(self.contract.ImpliedVolatility)
# Decide to go long or short based on implied volatility and historical volatility
if volatility > self.contract.ImpliedVolatility:
self.sign = 1
# Check available margin before placing the trade
margin_remaining = self.Portfolio.MarginRemaining
required_margin = self.contract.LastPrice * self.size # Use LastPrice for margin calculation
if margin_remaining > required_margin:
self.trade = False
self.size = self.size * self.sign
self.MarketOrder(self.contract.Symbol, self.size)
self.MarketOrder(self.stock, 100 * self.size * self.contract.Greeks.Delta) # Delta for puts is positive when short
self.Debug(str(self.contract.Greeks.Delta))
self.previous = self.contract.Greeks.Delta
else:
chain = slice.OptionChains.get(self.symbol)
if chain:
# Change to target put options (Right == 1 for puts)
contract_list = [x for x in chain if x.Expiry == DateTime(2021, 12, 17) and x.Right == 1 and x.Strike <= x.UnderlyingLastPrice]
self.highest_put = sorted(contract_list, key=lambda x: x.Strike, reverse=True)[0].Strike
self.contract = [contract for contract in contract_list if contract.Strike == self.highest_put][0]
self.MarketOrder(self.stock, 100 * self.size * (self.contract.Greeks.Delta - self.previous)) # Adjust for put's delta
self.previous = self.contract.Greeks.Delta
# Track highest PnL
current_pnl = self.Portfolio.TotalProfit
if current_pnl > self.highest_pnl:
self.highest_pnl = current_pnl
self.Debug(f"New highest PnL: {self.highest_pnl}")