Overall Statistics
Total Trades
3
Average Win
0%
Average Loss
0%
Compounding Annual Return
0.465%
Drawdown
19.700%
Expectancy
0
Net Profit
0.698%
Sharpe Ratio
0.083
Probabilistic Sharpe Ratio
8.848%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0.003
Beta
0.769
Annual Standard Deviation
0.145
Annual Variance
0.021
Information Ratio
0.013
Tracking Error
0.063
Treynor Ratio
0.016
Total Fees
$4.05
Estimated Strategy Capacity
$7600000.00
Lowest Capacity Asset
BND TRO5ZARLX6JP
Portfolio Turnover
0.18%
# region imports
from AlgorithmImports import *
# endregion

class DancingApricotCamel(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 1, 14)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        self.AddEquity("SPY", Resolution.Minute)
        self.AddEquity("BND", Resolution.Minute)
        self.AddEquity("AAPL", Resolution.Minute)

    def OnData(self, data: Slice):
        if not self.Portfolio.Invested:
            self.SetHoldings("SPY", 0.33)
            self.SetHoldings("BND", 0.33)
            self.SetHoldings("AAPL", 0.33)
#region imports
from AlgorithmImports import *
from datetime import timedelta
import datetime as dt

#endregion
def getOIHist(qb, contract_symbol, startDate=datetime(2023, 2, 10), endDate=datetime(2023, 2, 10)):
    history = qb.History(OpenInterest, contract_symbol, startDate, endDate)
    if not history.empty:
        history.index = history.index.droplevel([0, 1, 2])
        oi_df = history['openinterest'].droplevel(level=0)
        oi_df.index = oi_df.index.date
        return oi_df
    else:
        return pd.DataFrame()

def GetNearestSymbols(qb, symbol, dDate, up, nearness=8):
    contract_symbols = qb.OptionChainProvider.GetOptionContractList(symbol, dDate)
    # Get nearest 20 strikes on both sides of underlying price at start date
    allStrikes = sorted(set([x.ID.StrikePrice for x in contract_symbols]),key=lambda x: abs(up-x))
    nearStrikes = allStrikes[:nearness]
    nearExpiries = set([x.ID.Date for x in contract_symbols if x.ID.Date.date() <= dDate+dt.timedelta(days=180)])
    nearSymbols = [s for s in contract_symbols 
        if s.ID.StrikePrice in nearStrikes and s.ID.Date in nearExpiries]
    # print(f'Filtered {len(nearSymbols)} near ones out of total {len(contract_symbols)} contracts')
    return nearSymbols

def getGreeksForAll(qb):
    all_slices = qb.History(timedelta(days=180),Resolution.Daily)
    df = pd.DataFrame()
    for slice in all_slices:
        underlying_price = None
        underlying_volatility = None

        # Update the security with QuoteBar information
        for bar in slice.QuoteBars.Values:
            qb.Securities[bar.Symbol].SetMarketPrice(bar)

        # Update the security with TradeBar information
        for bar in slice.Bars.Values:
            symbol = bar.Symbol
            security = qb.Securities[symbol]
            security.SetMarketPrice(bar)

            if security.Type == SecurityType.Equity:
                underlying_volatility = security.VolatilityModel.Volatility
                underlying_price = security.Price
                continue
            
            # Create the Option contract
            contract = OptionContract.Create(symbol, symbol.Underlying, bar.EndTime, security, underlying_price)
            contract.LastPrice = bar.Close

            # Evaluate the price model to get the IV, Greeks, and theoretical price
            result = security.PriceModel.Evaluate(security, None, contract)
            greeks = result.Greeks
            
            # Append the data to the DataFrame
            data = {
                # "IV" : result.ImpliedVolatility,
                "Delta": greeks.Delta,
                "Gamma": greeks.Gamma,
                # "Vega": greeks.Vega,
                # "Rho": greeks.Rho,
                # "Theta": greeks.Theta,
                # "LastPrice": contract.LastPrice,
                # "Close": security.Close,
                # "theoreticalPrice" : result.TheoreticalPrice,
                "underlyingPrice": underlying_price,
                # "underlyingVolatility": underlying_volatility
            }
            right = "Put" if symbol.ID.OptionRight == 1 else "Call"
            index = pd.MultiIndex.from_tuples([(symbol.ID.Date, symbol.ID.StrikePrice, right, symbol.Value, bar.EndTime)], names=["expiry", "strike", "type", "symbol", "endTime"])
            df = pd.concat([df, pd.DataFrame(data, index=index)])
            
    # df.reset_index(level=[0,1,2])
    return df