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 *

### <summary>
### Basic template algorithm simply initializes the date range and cash. This is a skeleton
### framework you can use for designing an algorithm.
### </summary>
class VIX_SPY_ALGO(QCAlgorithm):
    '''Basic template algorithm simply initializes the date range and cash'''

    def Initialize(self):
        '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

        self.SetStartDate(2015,8,20)  #Set Start Date
        self.SetEndDate(2015,8,30)    #Set End Date
        self.SetCash(10000)           #Set Strategy Cash
    
        self.vix = 'CBOE/VIX'
        self.spy = "SPY"
        
        equity = self.AddEquity("SPY", Resolution.Minute)
        equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        
        self.underlyingsymbol = equity.Symbol
        
         # Add Quandl VIX price (daily)
        self.AddData(QuandlVix, "CBOE/VIX", Resolution.Minute)
        
         # 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)
        option = self.AddOption("SPY", Resolution.Minute)
        option.SetFilter(-10, +10, timedelta(0), timedelta(250))
        self.symbol = option.Symbol
        self.order_times = {}
     
        self.buy_spy = None
        self.SetBenchmark(equity.Symbol)
        #self.Plot("VIX", self.vix_price)
        
        self.Debug("numpy test >>> print numpy.pi: " + str(np.pi))
    
        self.date_first_level = (self.Time)
        
        self.buy_ticket = None
        self.number_of_spy_transactions = 0
        # Add differents EMA for SPY 
        self.ema_50 = self.EMA(self.spy, 50, Resolution.Daily)
        self.ema_100 = self.EMA(self.spy, 100, Resolution.Daily)
        self.ema_200 = self.EMA(self.spy, 200, Resolution.Daily)
        self.ema_365 = self.EMA(self.spy, 365, Resolution.Daily)
        
        self.ema_50 = self.EMA("SPY", 50)
        self.ema_100 = self.EMA("SPY", 100)
        self.ema_200 = self.EMA("SPY", 200)
        self.ema_365 = self.EMA("SPY", 365)
       
       # self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(timedelta(minutes=60)), Action(self.sell_intraday))

        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(timedelta(minutes=60)), self.LiquidateUnrealizedProfits)
    
    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.

        Arguments:
            data: Slice object keyed by symbol containing the stock data
        '''
        if not data.ContainsKey(self.vix): return
            
        #self.Debug(self.Time + timedelta(days=7)) #current_date = datetime.strptime(self.Time, '%Y-%m-%d') 
        
        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, data.Time,self.Securities[self.spy].Price))
            quantity = int(2500 / self.Securities[self.spy].Price)
            self.Debug('Margin Remaining is %s' % self.Portfolio.MarginRemaining)
            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,data.Time,self.Securities[self.spy].Price))
            quantity = int(2500 / self.Securities[self.spy].Price)
            self.Debug('Margin Remaining is %s' % self.Portfolio.MarginRemaining)
            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,data.Time,self.Securities[self.spy].Price))
            quantity = int(2500 / self.Securities[self.spy].Price)
            self.Debug('Margin Remaining is %s' % self.Portfolio.MarginRemaining)
            self.MarketOrder("SPY", quantity)
            self.buy_third_level = True
            self.buy_day = data.Time
            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 > 35 and self.Securities[self.vix].Price < 42:# and not self.buy_option:
            self.Debug('buy option with vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,data.Time,self.Securities[self.spy].Price))
            option_contract = self.BuyCall()[0]
            self.AddOptionContract(option_contract, Resolution.Minute)
            self.Buy(option_contract, 2)
            
            #self.buy_option = True
        #    #limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
            #self.sell_intraday(self)   
        
        elif self.Securities[self.vix].Price > 42:# and not self.buy_option:
            self.Debug('buy option with vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,data.Time,self.Securities[self.spy].Price))
            option_contract = self.BuyCall()[1]
            self.AddOptionContract(option_contract, Resoluation.Minute)
            self.Buy(option_contract, 3)
            self.TradeOptions(slice)
            #self.buy_option = True
            #limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
            
        elif self.Securities[self.vix].Price > 53:# and not self.buy_option:
            self.Debug('buy option with vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,data.Time,self.Securities[self.spy].Price))
            option_contract = self.BuyCall()[2]
            self.AddOptionContract(option_contract, Resoluation.Minute)
            self.Buy(option_contract, 2)
            #self.buy_option = True
            #limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
            
        elif self.Securities[self.vix].Price > 75:# and not self.buy_option:
            self.Debug('vix price is %s on date %s spy price is %s' % (self.Securities[self.vix].Price,data.Time,self.Securities[self.spy].Price))
            option_contract = self.BuyCall()[3]
            self.AddOptionContract(option_contract, Resoluation.Minute)
            self.Buy(option_contract, 2)
            #self.buy_option = True
            #self.LimitOrder('SPY',1, decimal.Decimal(.999))
        
        self.Debug('vix price is %s vix 10 SMA is %s , vix 15 SMA is %s on date %s' % (self.Securities[self.vix].Price, self.sma_10.Current.Value,self.sma_15.Current.Value,self.Time))
        
        
        # Track the value of the SPY ETF and the Portfolio instrument invested 
      #  if self.Portfolio["SPY"].Invested:
      #      self.Debug('Unrealized Profits on SPY is %s on time %s' % (self.Portfolio["SPY"].UnrealizedProfit, data.Time))
      #      self.Debug('Number of transactions is %s' % self.number_of_transactions)
        if self.Portfolio.Invested:
            self.Debug('Total Value of the Portfolio is %s' % self.Portfolio.TotalHoldingsValue)
            self.Debug('Number of transactions %s' % self.number_of_spy_transactions)
       
    
        if self.buy_spy == True:
            if self.Portfolio['SPY'].HoldingsValue < 200 and (self.sma_10.Current.Value < 11):
                put_contract = self.Buy_Put()[0]
                self.AddOptionContract(put_contract, Resolution.Minute)
                self.Buy(put_contract, 2)
            
            elif self.Portfolio['SPY'].HoldingsValue < 200 and (self.sma_15.Current.Value < 10):
                put_contract = self.Buy_Put()[1]
                self.AddOptionContract(put_contract, Resolution.Minute)
                self.Buy(put_contract, 3)
    
    def BuyCall(self):
        contracts = self.OptionChainProvider.GetOptionContractList(self.underlyingsymbol, self.Time.date())
        
        # if there is no contracts in this optionchain, pass the instance
        if len(contracts) == 0 : return
        
        filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, -3, 3, 30, 300)
        
        # Get call options
        call = [x for x in filtered_contracts if x.ID.OptionRight == 0] 

        # sorted the contracts according to their expiration dates and the difference between strike price and current price
        
        call_contracts_first_entry = [x for x in call if ((x.ID.StrikePrice - self.Securities[self.spy].Price) / (self.Securities[self.spy].Price)) >= 0.08 and ((x.ID.Date.date() - self.Time.date()).days) >= 90]
        call_contracts_first_entry_sorted = sorted(call_contracts_first_entry,
                            key = lambda x: abs(x.ID.StrikePrice - self.Securities[self.underlyingsymbol].Price))#[0]#.ID.StrikePrice
        contract_first_entry = call_contracts_first_entry_sorted[0]
        self.Debug('first entry contract is %s' % contract_first_entry.ID.StrikePrice)
        self.Debug('first entry contract expire in %s' % contract_first_entry.ID.Date.date())
     
        call_contracts_second_entry = [x for x in call if ((x.ID.StrikePrice - self.Securities[self.spy].Price) / (self.Securities[self.spy].Price)) >= 0.14 and ((x.ID.Date.date() - self.Time.date()).days) >= 120]
        call_contracts_second_entry_sorted = sorted(call_contracts_second_entry,
                            key = lambda x: abs(x.ID.StrikePrice - self.Securities[self.underlyingsymbol].Price))#[0]#.ID.StrikePrice
        
        contract_second_entry = call_contracts_second_entry_sorted[0]
        self.Debug('second entry contract is %s' % contract_second_entry.ID.StrikePrice)
        self.Debug('second entry contract expiry in %s' % contract_second_entry.ID.Date.date())
        
        call_contracts_third_entry = [x for x in call if ((x.ID.StrikePrice - self.Securities[self.spy].Price) / (self.Securities[self.spy].Price)) >= 0.2 and ((x.ID.Date.date() - self.Time.date()).days) >= 150]
        call_contracts_third_entry_sorted = sorted(call_contracts_third_entry, key = lambda x: abs(x.ID.StrikePrice - self.Securities[self.underlyingsymbol].Price))#[0]#.ID.StrikePrice
        contract_third_entry = call_contracts_third_entry_sorted[0]
        self.Debug('third entry contract is %s' % contract_third_entry.ID.StrikePrice)
        self.Debug('third entry contract expire in %s' % contract_third_entry.ID.Date.date())
        
        
        call_contracts_forth_entry = [x for x in call if ((x.ID.StrikePrice - self.Securities[self.spy].Price) / (self.Securities[self.spy].Price)) >= 0.2 and ((x.ID.Date.date() - self.Time.date()).days) >= 180]
        call_contracts_forth_entry_sorted = sorted(call_contracts_forth_entry, key = lambda x: abs(x.ID.StrikePrice - self.Securities[self.underlyingsymbol].Price))#[0]#.ID.StrikePrice
        contract_forth_entry = call_contracts_forth_entry_sorted[0]
        self.Debug('forth entry contract is %s' % contract_forth_entry.ID.StrikePrice)
        self.Debug('forth entry contract expire in %s' % contract_forth_entry.ID.Date.date())
        
        
        return contract_first_entry ,contract_second_entry,contract_third_entry ,contract_forth_entry
    
    def BuyPut(self):
        contracts = self.OptionChainProvider.GetOptionContractList(self.underlyingsymbol, self.Time.date())
        
        # if there is no contracts in this optionchain, pass the instance
        if len(contracts) == 0: return
        
        filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, -10, 10, 30, 300)
        
        # Select put contracts from the filtered_contracts list 
        puts = [x for x in filtered_contracts if x.ID.OptionRight == 1] 
        
        put_contracts_first_entry = [x for x in call if ((self.Securities[self.spy].Price - x.ID.StrikePrice) / (self.Securities[self.spy].Price)) >= 0.1 and ((x.ID.Date.date() - self.Time.date()).days) >= 120]
        put_contracts_first_entry_sorted = sorted(put_contracts_first_entry,
                            key = lambda x: abs(self.Securities[self.underlyingsymbol].Price - x.ID.StrikePrice))#[0]#.ID.StrikePrice
        
        put_contract_first_entry = put_contracts_first_entry_sorted[0]
        self.Debug('put contract first entry is %s' % put_contract_first_entry.ID.StrikePrice)
        self.Debug('put first entry contract expire in %s' % put_contract_first_entry.ID.Date.date())
        
        put_contracts_second_entry = [x for x in call if ((self.Securities[self.spy].Price - x.ID.StrikePrice) / (self.Securities[self.spy].Price)) >= 0.1 and ((x.ID.Date.date() - self.Time.date()).days) >= 180]
        put_contracts_second_entry_sorted = sorted(put_contracts_second_entry,
                            key = lambda x: abs(self.Securities[self.underlyingsymbol].Price - x.ID.StrikePrice))#[0]#.ID.StrikePrice
    
        put_contract_second_entry = put_contracts_second_entry_sorted[0]
        self.Debug('put contract second entry is %s' % put_contract_second_entry.ID.StrikePrice)
 
        self.Debug('put second entry contract expire in %s' % put_contract_second_entry.ID.Date.date())
        
        return put_contract_first_entry, put_contract_second_entry
    
    def InitialFilter(self, underlyingsymbol, symbol_list, min_strike_rank, max_strike_rank, min_expiry, max_expiry):
        
        ''' This method is an initial filter of option contracts
            according to the range of strike price and the expiration date '''
            
        if len(symbol_list) == 0 : return
        #fitler the contracts based on the expiry range
        contract_list = [i for i in symbol_list if min_expiry < (i.ID.Date.date() - self.Time.date()).days < max_expiry]
        
        return contract_list 
    

    
    #    self.Log(str("sell intraday function has triggered"))
    #    self.Debug("sell intraday function has triggered")
        
        
        #filledSpyOrders = [x for x in orders  if x.Symbol == "SPY" and  x.Status == OrderStatus.Filled]     
                #orderTime = filledSpyOrders.Last().Time
        #self.Debug('order time is %s' % orderTime)
        #self.Log('order time is %s' % orderTime)
    #    if self.Portfolio["SPY"].Invested:
            
            #if self.buy_first_level == True:
                #orders  = self.Transactions.GetOrders()
                #if orders:
                #    self.Log(str(orders))

     #           if (self.Portfolio["SPY"].UnrealizedProfit > 200):
     #               quantity = self.Portfolio['SPY'].Quantity
     #               quantity_to_sell = quantity * 0.60
     #               self.Debug('sell SPY in the same day with a profit of %s' % self.Portfolio["SPY"].UnrealizedProfit)
     #               self.MarketOrder('SPY',-quantity_to_sell)
                
     #       elif self.buy_second_level == True:
     # 
        
    def sell_intraday(self):
        if (self.Time.year == self.year) and (self.Time.day == self.day) and (self.Time.hour > self.hour):
            if (self.Portfolio["SPY"].UnrealizedProfit > 200):
                    quantity = self.quantity
                    quantity_to_sell = quantity * 0.60
                    self.Debug('sell SPY in the same day with a profit of %s' % self.Portfolio["SPY"].UnrealizedProfit)
                    self.MarketOrder('SPY',-quantity_to_sell)
                
            
        
   
    def LiquidateUnrealizedProfits(self):
        ''' if we have over 1500 dollars in unrealized profits, liquidate'''
        if self.Portfolio["SPY"].Invested:
            if (self.sma_15.Current.Value <= 13) and (self.Portfolio['SPY'].UnrealizedProfit > 1000):
                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 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)
       
        if order.Status == OrderStatus.Filled:
            self.order_times['time'] = order.Time
            self.Debug('order times are %s' % self.order_times)
            self.Debug('Info from OrderEvent object')
            self.Debug('order status is %s' % order.Status)
            self.Debug('order time is %s' % order.Time)
            self.Debug('order quantity is %s' % order.Quantity)
            self.Debug('order time hour is %s' % order.Time.hour)
            self.Debug('order time day is %s' % order.Time.day)
            self.Debug('order time year is %s' % order.Time.year)
            self.Debug('order id is %s' % order.Id)
            self.Debug('order type is %s' % order.Type)
            self.Debug('order symbol is %s' % order.Symbol)
            self.Debug('order direction is %s' % orderEvent.Direction)
            self.Debug('filled price of the order is %s' % order.Price)
            self.year = order.Time.year
            self.month = order.Time.month
            self.day = order.Time.day
            self.hour = order.Time.hour
            self.quantity = order.Quantity
                
                #self.Debug('next day of trading is %s' % datetime.strptime(order.Time,'m%/d%/Y% %H:%M:%S') + timedelta(days=1))
        self.Log("{0}: {1}: {2}".format(self.Time, order.Type, OrderEvent))
        
                
                
        #if self.Portfolio['SPY'].Invested:
        #    orders  = self.Transactions.GetOrders()
        #    if orders:
        #        self.Log(str(orders))
      #  if OrderEvent.FillQuantity == 0:
       #     return

      #  fetched = self.Transactions.GetOrderById(OrderEvent.OrderId)

      #  self.Debug("{} was filled. Symbol: {}. Quantity: {}. Direction: {}"
       #            .format(str(fetched.Type),
    #                       str(OrderEvent.Symbol),
     #                      str(OrderEvent.FillQuantity),
      #                     str(OrderEvent.Direction)))
          
        
class QuandlVix(PythonQuandl):
    def __init__(self):
        self.ValueColumnName = "vix Close"