| Overall Statistics |
|
Total Trades 1 Average Win 0% Average Loss 0% Compounding Annual Return 3.797% Drawdown 12.900% Expectancy 0 Net Profit 2.251% Sharpe Ratio 0.266 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.035 Beta 0.938 Annual Standard Deviation 0.168 Annual Variance 0.028 Information Ratio 1.829 Tracking Error 0.019 Treynor Ratio 0.048 Total Fees $1.00 |
import numpy as np
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(2016,3,26) #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.Daily)
# 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)
# set strike/expiry filter for this option chain
#option.SetFilter(-10, +10, timedelta(0), timedelta(180))
self.symbol = option.Symbol
#self.vix_price = self.Securities[self.vix].Price
self.SetBenchmark(equity.Symbol)
#self.Plot("VIX", self.vix_price)
self.Debug("numpy test >>> print numpy.pi: " + str(np.pi))
self.buy_spy = None
self.buy_day = None
self.buy_option = None
# 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=5)), 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
if self.Securities[self.vix].Price > 19 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))
self.SetHoldings("SPY", 1.0)
self.buy_spy = True
self.buy_day = data.Time
self.Debug('time is %s' % self.Time)
elif self.Securities[self.vix].Price > 25 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))
self.SetHoldings("SPY", 1)
self.buy_spy = True
self.buy_day = data.Time
#limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
elif 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))
self.SetHoldings("SPY", 1)
self.buy_spy = True
self.buy_day = data.Time
#limit_order_ticker = self.LimitOrder('SPY',1, decimal.Decimal(.999))
elif self.Securities[self.vix].Price > 35 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))
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.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 two instrument invested
if self.Portfolio["SPY"].Invested:
self.Debug('Unrealized Profits on SPY is %s on time %s' % (self.Portfolio["SPY"].UnrealizedProfit, data.Time))
if self.Portfolio[self.symbol].Invested:
self.Debug('Unrealized Profits on SPY option is %s on time %s' % (self.Portfolio[self.symbol].UnrealizedProfit, data.Time))
#self.Debug('SMA 50 SPY is %s and SPY price is %s on data %s' % (self.ema_50, self.Securities['SPY'].Price, data.Time))
if self.buy_spy == True:
if self.Portfolio['SPY'].HoldingsValue < 1000 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 < 1000 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 sell_intraday(self):
while self.Time == self.buy_day:
if (self.Portfolio["SPY"].UnrealizedProfit > 200):
self.Debug('sell SPY in the same day with a profit of %s' % self.Portfolio["SPY"].UnrealizedProfit)
self.Liquidate('SPY',0.5)
def LiquidateUnrealizedProfits(self):
''' if we have over 1500 dollars in unrealized profits, liquidate'''
if self.buy_spy == True:
if (self.sma_15.Current.Value <= 13) and (self.Portfolio['SPY'].UnrealizedProfit > 1500):
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):
contracts = self.OptionChainProvider.GetOptionContractList(self.underlyingsymbol, self.Time.date())
# if there is no contracts in this optionchain, pass the instance
if (len(contracts) == 0) or (contracts == None):
return
filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, -10, 10, 30, 300)
call = [x for x in filtered_contracts if x.ID.OptionRight == 0]
# sorted the contracts according to their expiration dates and choose the ATM options
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) or (contracts == None):
return
filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, -10, 10, 30, 300)
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
def OnOrderEvent(self, orderEvent):
self.Log(str(orderEvent))
class QuandlVix(PythonQuandl):
def __init__(self):
self.ValueColumnName = "vix Close"