Overall Statistics
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Python import PythonQuandl
from datetime import datetime, timedelta
import numpy as np
import math
import time
#https://www.quantconnect.com/tutorials/strategy-library/exploiting-term-structure-of-vix-futures


class VerticalNadionRadiator(QCAlgorithm):

    def Initialize(self):
        self.es_liq = self.start_time = self.Time
        self.SetStartDate(2010, 1, 1)  # Set Start Date
        self.SetEndDate(2013,3,1)
        self.SetCash(100000)  # Set Strategy Cash

        self.es = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Minute)
        self.es.SetFilter(timedelta(3), timedelta(200))
        self.ty = self.AddFuture(Futures.Financials.Y10TreasuryNote, Resolution.Minute)
        self.ty.SetFilter(timedelta(3), timedelta(200))
        self.vx = self.AddFuture(Futures.Indices.VIX, Resolution.Minute)
        self.vx.SetFilter(timedelta(0), timedelta(100))
        self.spy = self.AddEquity("SPY",Resolution.Minute)
        self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.vx_contracts = []
        self.es_contracts = []
        self.ty_contracts = []
        self.contango = []
        self.CONTANGO = False
        self.SPY_sma_period = 20 #self.GetParameter("ma_length")
        self.SPY_prices = []
        self.SPY_sma = []
        self.downward_sloping_ma = False
            
    def OnData(self, data):

        es_leverage = 5
        ty_leverage = 8
        ty_stop_pc = 0.015
        
        if self.Time.hour == 15 and self.Time.minute == 0:
            
            self.SPY_prices.append(self.spy.Close)
            if len(self.SPY_prices)>self.SPY_sma_period:
                self.SPY_prices.pop(0)
                self.SPY_sma.append(np.mean(self.SPY_prices))
                if len(self.SPY_sma)>5:
                    self.SPY_sma.pop(0)
                    if self.SPY_sma[-1] < self.SPY_sma[-2]*1.00025:
                        self.downward_sloping_ma = True
                    else:
                        self.downward_sloping_ma = False
                    #self.Debug("Today's SMA: "+str(self.SPY_sma[-1])+" vs 
                    #yesterday's: "+str(self.SPY_sma[-2]))
            
            for chain in data.FutureChains:
                contracts = [contract for contract in chain.Value]
                for j in contracts:
                    if Futures.Indices.VIX in str(j):
                        self.vx_contracts = []
                    elif Futures.Indices.SP500EMini in str(j):
                        self.es_contracts = []
                    elif Futures.Financials.Y10TreasuryNote in str(j):
                        self.ty_contracts = []
                for i in contracts:
                    if Futures.Indices.VIX in str(i):
                        self.vx_contracts.append(i)
                    elif Futures.Indices.SP500EMini in str(i):
                        self.es_contracts.append(i)
                    elif Futures.Financials.Y10TreasuryNote in str(i):
                        self.ty_contracts.append(i)
                        
            self.vx_contracts = self.ContractSorter(self.vx_contracts)
            self.es_contracts = self.ContractSorter(self.es_contracts)
            self.ty_contracts = self.ContractSorter(self.ty_contracts)
            
            if len(self.es_contracts) < 0.5 or len(self.ty_contracts)<0.5:
                return
            
            if (self.es_contracts[0].Expiry - self.Time).days <5:
                
                if self.Portfolio[self.es_contracts[0].Symbol].Quantity != 0:
                    quantity = self.Portfolio[self.es_contracts[0].Symbol].Quantity
                    self.SetHoldings(self.es_contracts[0].Symbol,0)
                    self.MarketOrder(self.es_contracts[1].Symbol,quantity)
                    self.Debug("Rolled ES contract forward")
                    
                self.es_contracts.pop(0)
                
            if (self.ty_contracts[0].Expiry - self.Time).days <5:
                
                if self.Portfolio[self.ty_contracts[0].Symbol].Quantity != 0:
                    quantity = self.Portfolio[self.ty_contracts[0].Symbol].Quantity
                    self.SetHoldings(self.ty_contracts[0].Symbol,0)
                    self.MarketOrder(self.ty_contracts[1].Symbol,quantity)
                    self.ty_stop_price = self.ty_stop_price * \
                            self.ty_contracts[1].AskPrice/self.ty_contracts[0].AskPrice
                    self.Debug("Rolled TY contract forward")
                    
                self.ty_contracts.pop(0)
                
        if (self.Time - self.start_time).days < 10 or len(self.vx_contracts)<1.5:
        #or len(self.es_contracts)<0.5 or len(self.ty_contracts)<0.5:
            return

        if self.vx_contracts[0].AskPrice > 0 and self.vx_contracts[1].AskPrice >0:
            self.contango.append(self.vx_contracts[1].AskPrice - self.vx_contracts[0].AskPrice)
        if len(self.contango)>1440:
            self.contango.pop(0)
        
            if np.min(self.contango)>0.5:
                self.CONTANGO = True
            else:
                self.CONTANGO = False
            
        if not self.Securities["SPY"].Exchange.ExchangeOpen:
            return
        else:
            if self.Portfolio.Invested:
    
                if self.CONTANGO == True and self.downward_sloping_ma == False:
                    
                    if self.Portfolio[self.ty_contracts[0].Symbol].Quantity !=0:
                        self.SetHoldings(self.ty_contracts[0].Symbol,0)
                        
                    if (self.Time - self.es_liq).days > 5 and \
                    self.Portfolio[self.es_contracts[0].Symbol].Quantity == 0:
                        
                        es_notional = self.es_contracts[0].AskPrice * \
                                    self.es.SymbolProperties.ContractMultiplier
                        #self.Debug("ES notional is :" +str(es_notional))
                        es_to_buy = math.floor(self.Portfolio.Cash*es_leverage / es_notional)
                        #self.Debug("ES to buy is :" +str(es_to_buy))
                        #self.Debug("Port cash is : "+str(self.Portfolio.Cash))
                        self.MarketOrder(self.es_contracts[0].Symbol,es_to_buy)
                        self.Debug("VX1 and VX2 spread is: "+str(self.contango[-1]))
                        self.Debug("1. Bought ES @ "+str(self.es_contracts[0].AskPrice))
                
                elif self.CONTANGO == False or self.downward_sloping_ma:
                    if self.Portfolio[self.es_contracts[0].Symbol].Quantity !=0:
                        self.SetHoldings(self.es_contracts[0].Symbol,0)
                        self.es_liq = self.Time
                        ty_notional = self.ty_contracts[0].AskPrice * \
                                    self.ty.SymbolProperties.ContractMultiplier
                        ty_to_buy = math.floor(self.Portfolio.Cash*ty_leverage / ty_notional)
                        self.MarketOrder(self.ty_contracts[0].Symbol,ty_to_buy)
                        self.ty_stop_price = self.ty_contracts[0].AskPrice * (1-ty_stop_pc)
                        self.Debug("2. Sold ES @ "+str(self.es_contracts[0].AskPrice))
                        self.Debug("Bought TY @ "+str(self.ty_contracts[0].AskPrice))
                        
                    if self.Portfolio[self.ty_contracts[0].Symbol].Quantity !=0 \
                    and self.ty_contracts[0].AskPrice < self.ty_stop_price:
                        
                        self.SetHoldings(self.ty_contracts[0].Symbol,0)
                        self.Debug("3. Stopped out of TY @ "+str(self.ty_contracts[0].AskPrice))
                    
                # elif self.downward_sloping_ma:
                #     self.SetHoldings(self.es_contracts[0].Symbol,0)
                        
            elif not self.Portfolio.Invested:
                if self.CONTANGO == True and (self.Time - self.es_liq).days > 5\
                and self.downward_sloping_ma == False:
                    es_notional = self.es_contracts[0].AskPrice * \
                                self.es.SymbolProperties.ContractMultiplier
                    #self.Debug("ES notional is :" +str(es_notional))
                    es_to_buy = math.floor(self.Portfolio.Cash*es_leverage / es_notional)
                    #self.Debug("ES to buy is :" +str(es_to_buy))
                    #self.Debug("Port cash is : "+str(self.Portfolio.Cash))
                    self.MarketOrder(self.es_contracts[0].Symbol,es_to_buy)
                    
                    self.Debug("VX1 and VX2 spread is: "+str(self.contango[-1]))
                    self.Debug("4. Bought ES @ "+str(self.es_contracts[0].AskPrice))
                    
                elif self.CONTANGO == False or self.downward_sloping_ma:
                    return
                
    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status != OrderStatus.Filled:
            #time.sleep(3)
            self.Transactions.CancelOpenOrders()

    def ContractSorter(self,contract_list):
        if len(contract_list)>1.5:
            return sorted(contract_list, key = lambda x: x.Expiry,reverse = False)
        else:
            return contract_list