Overall Statistics
import numpy as np
from datetime import datetime
from datetime import timedelta 
import decimal 
import time 
from QuantConnect.Algorithm import *
from QuantConnect.Data import *

class vixSpyExample(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2015,8,20)  #Set Start Date
        self.SetEndDate(2015,8,30)    #Set End Date
        self.SetCash(10000)           #Set Strategy Cash

        # Quandl id    
        self.vix = 'CBOE/VIX'
        self.spy = 'SPY'
        
        self.date_first_level = self.Time
        self.number_of_spy_transactions = 0
        
        # Add Quandl VIX
        self.AddData(QuandlVix, "CBOE/VIX", Resolution.Daily)
        equity = self.AddEquity("SPY", Resolution.Daily)
        equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        
        # Add VIX 10 and 15 SMA
        self.sma_10 = self.SMA(self.vix, 10, Resolution.Daily)
        self.sma_15 = self.SMA(self.vix, 15, Resolution.Daily)
        
        # Add SPY options
        option = self.AddOption("SPY", Resolution.Minute)
        option.SetFilter(-10, +10, timedelta(30), timedelta(60))
        
        self.symbol = option.Symbol

        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(timedelta(minutes=60)), self.LiquidateUnrealizedProfits)

    def OnData(self, slice):
        
        if (self.Securities[self.vix].Price > 19) and (self.Securities[self.vix].Price < 25) and (self.Time >= self.date_first_level):
            self.Debug('vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price, self.Time,self.Securities[self.spy].Price))
            quantity = (self.Portfolio.Cash * 0.25) / self.Securities[self.spy].Price  #int(2500 / )
            self.MarketOrder("SPY", quantity)
            self.buy_first_level = self.Time
            self.Debug('time is %s' % self.Time)
            self.date_first_level = self.Time + timedelta(days=7)
            
            self.number_of_spy_transactions +=1
        
           # self.sell_intraday()
        
        
        elif self.Securities[self.vix].Price > 25 and self.Securities[self.vix].Price < 30:# and not self.buy_spy:
            self.Debug('vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,self.Time,self.Securities[self.spy].Price))
            quantity = (self.Portfolio.Cash * 0.25) / self.Securities[self.spy].Price 
            self.MarketOrder("SPY", quantity)
            self.buy_second_level = True
            self.number_of_spy_transactions +=1
            #self.sell_intraday()
            #limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
        
        elif self.Securities[self.vix].Price > 30 and self.Securities[self.vix].Price < 35:# and not self.buy_spy:
            self.Debug('vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,self.Time,self.Securities[self.spy].Price))
            quantity = (self.Portfolio.Cash * 0.25) / self.Securities[self.spy].Price 
            self.MarketOrder("SPY", quantity)
            self.buy_third_level = True
            self.buy_day = self.Time
            self.number_of_spy_transactions +=1
            #self.sell_intraday()
            #limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
         
        optionchain = slice.OptionChains
        for i in slice.OptionChains:
            if i.Key != self.symbol: continue
        
            # Return if holding option contracts
            if self.Portfolio.Invested: return
        
            # Buy OTM call option if the VIX is between 35 and 42
            if self.Securities[self.vix].Price > 35 and self.Securities[self.vix].Price < 42:
                option_contract = self.BuyCall(optionchain)
                self.Buy(option_contract, 2)
    
    def LiquidateUnrealizedProfits(self):
        ''' if we have over 1500 dollars in unrealized profits, liquidate'''
        if self.Portfolio["SPY"].Invested:
            if (self.sma_15.Current.Value <= 16) and (self.Portfolio['SPY'].UnrealizedProfit > 100):
                self.Log("Liquidated unrealized profits at: {0}".format(self.Time))
                self.Debug("Liquidated unrealized profits at %s" % self.Time)
                self.Liquidate('SPY')
                #self.buy_spy = False
    
    def BuyCall(self,optionchain):
        for i in optionchain:
            if i.Key != self.symbol: continue

            # Retrieve option chain
            chain = i.Value
            
            # sorted the optionchain by expiration date and choose the furthest date
            expiry = sorted(chain,key = lambda x: x.Expiry, reverse=True)[0].Expiry
        
            # filter the call options from the contracts expires on that date
            call = [i for i in chain if i.Expiry == expiry and i.Right == 0]

            # sorted the contracts according to their strike prices 
            call_contracts = sorted(call,key = lambda x: x.Strike)
            
            if len(call_contracts) == 0: continue
            
            # choose the deep OTM call option
            self.call = call_contracts[-1]
            self.Debug('call options is %s' % self.call)
            return self.call.Symbol
        
    def OnOrderEvent(self, orderEvent):
        ''' Event when the order is filled. Debug log the order fill. :OrderEvent:'''
        self.Log(str(orderEvent))
        order = self.Transactions.GetOrderById(orderEvent.OrderId)
       
        
class QuandlVix(PythonQuandl):
    def __init__(self):
        self.ValueColumnName = "vix Close"