Overall Statistics
Total Trades
436
Average Win
8.59%
Average Loss
-6.32%
Compounding Annual Return
0%
Drawdown
100.500%
Expectancy
-0.128
Net Profit
-100.793%
Sharpe Ratio
-0.362
Probabilistic Sharpe Ratio
0.093%
Loss Rate
63%
Win Rate
37%
Profit-Loss Ratio
1.36
Alpha
0
Beta
0
Annual Standard Deviation
2.346
Annual Variance
5.505
Information Ratio
-0.362
Tracking Error
2.346
Treynor Ratio
0
Total Fees
$1132.50
Estimated Strategy Capacity
$31000.00
Lowest Capacity Asset
VXXB 31XQECQPCLGIU|VXXB WRBPJAJZ2Q91
Portfolio Turnover
12.54%
# region imports
from AlgorithmImports import *
from datetime import timedelta
# endregion

class Vxx(QCAlgorithm):

    def Initialize(self):

        # # Series A expired on 30 January 2019
        # self.SetStartDate(2010, 1, 1)  # Set Start Date
        # self.SetEndDate(2019, 1, 1)  # Set End Date
        # self.vxx = self.AddEquity("VXX.1", Resolution.Daily)

        # # new VXX
        self.SetStartDate(2021, 1, 1)  
        # self.SetEndDate(2022, 2, 1)
        self.vxx = self.AddEquity("VXX", Resolution.Daily)

        self.option = self.AddOption(self.vxx.Symbol, Resolution.Daily)
        # self.option.SetFilter(lambda option_filter_universe: option_filter_universe.Strikes(-1, 1).Expiration(1, 90))
        self.option.SetFilter(-1, 1, timedelta(days=15), timedelta(days=45))
        
        self.SetCash(100000)  # Set Strategy Cash

        # subscribe to VXX ETF, VIX and VIX3M date on daily resolution
        self.vix = self.AddData(CBOE, "VIX", Resolution.Daily)
        self.vix3m = self.AddData(CBOE, "VIX3M", Resolution.Daily)

        # set ib brokerage model
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)

        self.Schedule.On(self.DateRules.MonthEnd(), self.TimeRules.At(0, 0), self.log_profit)
        # self.Schedule.On(self.DateRules.MonthStart(), self.TimeRules.At(0, 0), self.log_profit())

    def log_profit(self):
        try:
            if self.Portfolio.Invested:
                for symbol, holding in self.Portfolio.items():
                    if holding.Invested:
                        self.Debug(f"{symbol}: {holding.UnrealizedProfit}")
        except:
           self.Debug("Error logging profit")
        
        # self.side = 'none'
        


    def OnData(self, data: Slice):
        # self.Log("VXX: " + str(self.vxx.Close) + " VIX: " + str(self.vix.Close) + " VIX3M: " + str(self.vix3m.Close))
        self.side = 'none'

        
        # we don't ever want to own shares after assignment
        if self.Portfolio[self.vxx.Symbol].Quantity != 0:
            self.SetHoldings(self.vxx.Symbol, 0)
            self.Log('owned VXX shares, liquidating')
            self.side = 'none'
        # some funny business with automatic execution due to dividends
        if not self.Portfolio.Invested:
            self.side = 'none'
        # if we have value of > 10k in options, do nothing
        if self.Portfolio.TotalMarginUsed > 10000:
            return
        

        if self.vix.Close > self.vix3m.Close and self.side != 'long':            
            self.Log('entered call block')
            self.Debug("Long VXX")
            option = buy_option(self, 'call', data, self.option)
            if not option:
                return
            # buy $1000 of the call
            qty = 1000 // (option.AskPrice * 100) if option.AskPrice != 0 else 1
            self.Log("Buy call: " + str(option.Symbol) + "qty: " + str(qty) + " calls at: " + str(option.AskPrice) + 'VXX spot: ' + str(self.vxx.Close) + 'strike is: ' + (str(option.Strike) if hasattr(option, 'Strike') else '') + 'expiry is: ' + str(option.Expiry))
            most_recent_call = self.MarketOrder(option.Symbol, qty)
            self.side = 'long'
            # log_profit(self)
            return
        
        if self.vix.Close < self.vix3m.Close and self.side != 'short':
            self.Log('entered put block')
            self.Debug("Short VXX")
            option = buy_option(self, 'put', data, self.option)
            if not option:
                return
            # buy $1000 of the put
            qty = 1000 // (option.AskPrice * 100) if option.AskPrice != 0 else 1
            self.Log("Buy put: " + str(option.Symbol) + "qty: " + str(qty) + " puts at: " + str(option.AskPrice) + 'VXX spot: ' + str(self.vxx.Close) + 'strike is: ' + (str(option.Strike) if hasattr(option, 'Strike') else '') + 'expiry is: ' + str(option.Expiry))
            most_recent_put = self.MarketOrder(option.Symbol, qty)
            self.side = 'short'
            # log_profit(self)
            return
            
        pass


        
def buy_option(self, option_type: str, data: Slice, option: Option):
    chain = data.OptionChains.get(option.Symbol)
    if not chain:
        # log no chain at this time
        self.Log('No option chain for ' + str(option.Symbol) + ' at ' + str(self.Time))
        return None

    side = OptionRight.Call if option_type == 'call' else OptionRight.Put if option_type == 'put' else None
    contracts = [c for c in chain if c.Right == side]
    try:
        expiry = max([c.Expiry for c in contracts]) if option_type == 'put' else min([c.Expiry for c in contracts])
    except:
        return None
    contracts = sorted([c for c in contracts if c.Expiry == expiry], key=lambda c: c.Strike, reverse=False)
    option = contracts[0]

    return option



##############################


# # region imports
# from AlgorithmImports import *
# # endregion

# class Vxx(QCAlgorithm):

#     def Initialize(self):

#         # Series A expired on 30 January 2019
#         # self.SetStartDate(2010, 1, 1)  # Set Start Date
#         # self.SetEndDate(2019, 1, 30)  # Set End Date
#         # self.vxx = self.AddEquity("VXX.1", Resolution.Daily)

#         # new VXX
#         self.SetStartDate(2019, 1, 31)  #
#         self.vxx = self.AddEquity("VXX", Resolution.Daily)
        
#         self.SetCash(100000)  # Set Strategy Cash

#         # subscribe to VXX ETF, VIX and VIX3M date on daily resolution
#         self.vix = self.AddData(CBOE, "VIX", Resolution.Daily)
#         self.vix3m = self.AddData(CBOE, "VIX3M", Resolution.Daily)

#         # set ib brokerage model
#         self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)



#     def OnData(self, data: Slice):

#         self.Log("VXX: " + str(self.vxx.Close) + " VIX: " + str(self.vix.Close) + " VIX3M: " + str(self.vix3m.Close))

#         if not self.Portfolio.Invested:
#             if self.vix.Close < self.vix3m.Close:
#                 self.SetHoldings(self.vxx.Symbol, -0.1)
#                 self.Log("Short VXX")
#             else:
#                 self.SetHoldings(self.vxx.Symbol, 0.1)
#                 self.Log("Long VXX")
#                 return

#         #if vix < vix3m, short vxx ... Contango
#         if (self.Portfolio['VXX'].Quantity > 0) and self.vix.Close < self.vix3m.Close :
#             self.Liquidate()
#             self.SetHoldings(self.vxx.Symbol, -0.1)
#             self.Log("Short VXX")
#             return
            

#         #if vix > vix3m, long vxx ... Backwardation
#         if (self.Portfolio['VXX'].Quantity < 0) and self.vix.Close > self.vix3m.Close :
#             self.Liquidate()
#             self.SetHoldings(self.vxx.Symbol, 0.1)
#             self.Debug("Long VXX")
#             return

#         pass
        
# region imports
from AlgorithmImports import *
# endregion

class Vxx(QCAlgorithm):

    def Initialize(self):

        # Series A expired on 30 January 2019
        self.SetStartDate(2010, 1, 1)  # Set Start Date
        self.SetEndDate(2019, 1, 30)  # Set End Date
        self.vxx = self.AddEquity("VXX.1", Resolution.Daily)

        # new VXX
        # self.SetStartDate(2019, 1, 31)  #
        # self.vxx = self.AddEquity("VXX", Resolution.Daily)
        
        self.SetCash(100000)  # Set Strategy Cash

        # subscribe to VXX ETF, VIX and VIX3M date on daily resolution
        self.vix = self.AddData(CBOE, "VIX", Resolution.Daily)
        self.vix3m = self.AddData(CBOE, "VIX3M", Resolution.Daily)

        # set ib brokerage model
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)



    def OnData(self, data: Slice):

        self.Log("VXX: " + str(self.vxx.Close) + " VIX: " + str(self.vix.Close) + " VIX3M: " + str(self.vix3m.Close))

        chain = data.OptionChains.get(self.optionSymbol)
        if not chain:
            return

        if not self.Portfolio.Invested:
            if self.vix.Close < self.vix3m.Close:
                self.SetHoldings(self.vxx.Symbol, -0.1)
                self.Log("Short VXX")
            else:
                self.SetHoldings(self.vxx.Symbol, 0.1)
                self.Log("Long VXX")
                return

        #if vix < vix3m, short vxx ... Contango
        if (self.Portfolio['VXX'].Quantity > 0) and self.vix.Close < self.vix3m.Close :
            self.Liquidate()
            self.SetHoldings(self.vxx.Symbol, -0.1)
            self.Log("Short VXX")
            return
            

        #if vix > vix3m, long vxx ... Backwardation
        if (self.Portfolio['VXX'].Quantity < 0) and self.vix.Close > self.vix3m.Close :
            self.Liquidate()
            self.SetHoldings(self.vxx.Symbol, 0.1)
            self.Debug("Long VXX")
            return

        pass