Back to Community
XIV/VXX pair trade

seems too good to be true . the period between jan 2012 and August 2015

the sharpe seems too high

Clone Algorithm
129
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
''' 
    This algorithm defines a target long-only diversified portfolio and rebalances 
    it at a user-specified frequency. 
'''

import datetime
import pytz
import pandas as pd
from zipline.utils.tradingcalendar import get_early_closes

def initialize(context):
    
    # Define the instruments in the portfolio:
    set_symbol_lookup_date('2012-1-1')
    context.stocks = {
                              symbol('xiv'): -.40,
                              symbol('vxx'): -.60,
    }
    
    # Define the benchmark (used to get early close dates for reference).
    context.spy           = sid(8554)
    
    start_date = context.spy.security_start_date
    end_date   = context.spy.security_end_date
    
    # Initialize context variables the define rebalance logic:
    context.rebalance_date = None
    context.next_rebalance_Date = None
    context.rebalance_days = 60
    
    # Get the dates when the market closes early:
    context.early_closes = get_early_closes(start_date, end_date).date

    set_commission(commission.PerTrade(cost=1))

def handle_data(context, data):
    # Get the current exchange time, in local timezone: 
    exchange_time = pd.Timestamp(get_datetime()).tz_convert('US/Eastern')
    
    # If it is rebalance day, rebalance:
    if context.rebalance_date == None or exchange_time >= context.next_rebalance_date:
       # If we are in rebalance window but there are open orders, wait til next minute
       if has_open_orders(data,context) == True:
            log.info('Has open orders, not rebalancing.')
       else:
           # If there are no open orders we can rebalance.
           rebalance(context, data, exchange_time) 
           log.info('Rebalanced portfolio to target weights at %s' % exchange_time)

           # Update the current and next rebalance dates
           context.rebalance_date = exchange_time 
           context.next_rebalance_date = context.rebalance_date + datetime.timedelta(days=context.rebalance_days)      
           print(context.next_rebalance_date)

def rebalance(context,data,exchange_time):    
    for stock in context.stocks:
        if stock in data:
            order_target_percent(stock, context.stocks[stock])

def has_open_orders(data,context):               
    # Only rebalance when we have zero pending orders.
    has_orders = False
    for stk in data:
        orders = get_open_orders(stk)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=stk)  
            has_orders = True
    return has_orders           
There was a runtime error.
5 responses

Why not just short VXX?

Clone Algorithm
41
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
''' 
    This algorithm defines a target long-only diversified portfolio and rebalances 
    it at a user-specified frequency. 
'''

import datetime
import pytz
import pandas as pd
from zipline.utils.tradingcalendar import get_early_closes

def initialize(context):
    
    # Define the instruments in the portfolio:
    set_symbol_lookup_date('2012-1-1')
    context.stocks = {
                              symbol('xiv'): 0,
                              symbol('vxx'): -1,
    }
    
    # Define the benchmark (used to get early close dates for reference).
    context.spy           = sid(8554)
    
    start_date = context.spy.security_start_date
    end_date   = context.spy.security_end_date
    
    # Initialize context variables the define rebalance logic:
    context.rebalance_date = None
    context.next_rebalance_Date = None
    context.rebalance_days = 60
    
    # Get the dates when the market closes early:
    context.early_closes = get_early_closes(start_date, end_date).date

    set_commission(commission.PerTrade(cost=1))

def handle_data(context, data):
    # Get the current exchange time, in local timezone: 
    exchange_time = pd.Timestamp(get_datetime()).tz_convert('US/Eastern')
    
    # If it is rebalance day, rebalance:
    if context.rebalance_date == None or exchange_time >= context.next_rebalance_date:
       # If we are in rebalance window but there are open orders, wait til next minute
       if has_open_orders(data,context) == True:
            log.info('Has open orders, not rebalancing.')
       else:
           # If there are no open orders we can rebalance.
           rebalance(context, data, exchange_time) 
           log.info('Rebalanced portfolio to target weights at %s' % exchange_time)

           # Update the current and next rebalance dates
           context.rebalance_date = exchange_time 
           context.next_rebalance_date = context.rebalance_date + datetime.timedelta(days=context.rebalance_days)      
           print(context.next_rebalance_date)

def rebalance(context,data,exchange_time):    
    for stock in context.stocks:
        if stock in data:
            order_target_percent(stock, context.stocks[stock])

def has_open_orders(data,context):               
    # Only rebalance when we have zero pending orders.
    has_orders = False
    for stk in data:
        orders = get_open_orders(stk)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=stk)  
            has_orders = True
    return has_orders           
There was a runtime error.

Obviously, quantopian is calculating these sharpes wrong. it's nowhere near that high

If we just short the vix, the max draw down is quite high.

The problem s that you cannot trade the Vix index but only Vix futures.
That is why your backtest seems so beautiful.

I stumbled to this thread and thought it would be a good idea to post a longer term backtest. I can only guess what 2007 would look like if both etfs would have been available then...

Clone Algorithm
9
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
''' 
    This algorithm defines a target long-only diversified portfolio and rebalances 
    it at a user-specified frequency. 
'''

import datetime
import pytz
import pandas as pd
from zipline.utils.tradingcalendar import get_early_closes

def initialize(context):
    
    # Define the instruments in the portfolio:
    set_symbol_lookup_date('2012-1-1')
    context.stocks = {
                              symbol('xiv'): -.40,
                              symbol('vxx'): -.60,
    }
    
    # Define the benchmark (used to get early close dates for reference).
    context.spy           = sid(8554)
    
    start_date = context.spy.security_start_date
    end_date   = context.spy.security_end_date
    
    # Initialize context variables the define rebalance logic:
    context.rebalance_date = None
    context.next_rebalance_Date = None
    context.rebalance_days = 60
    
    # Get the dates when the market closes early:
    context.early_closes = get_early_closes(start_date, end_date).date

    set_commission(commission.PerTrade(cost=1))

def handle_data(context, data):
    # Get the current exchange time, in local timezone: 
    exchange_time = pd.Timestamp(get_datetime()).tz_convert('US/Eastern')
    
    # If it is rebalance day, rebalance:
    if context.rebalance_date == None or exchange_time >= context.next_rebalance_date:
       # If we are in rebalance window but there are open orders, wait til next minute
       if has_open_orders(data,context) == True:
            log.info('Has open orders, not rebalancing.')
       else:
           # If there are no open orders we can rebalance.
           rebalance(context, data, exchange_time) 
           log.info('Rebalanced portfolio to target weights at %s' % exchange_time)

           # Update the current and next rebalance dates
           context.rebalance_date = exchange_time 
           context.next_rebalance_date = context.rebalance_date + datetime.timedelta(days=context.rebalance_days)      
           print(context.next_rebalance_date)

def rebalance(context,data,exchange_time):    
    for stock in context.stocks:
        if stock in data:
            order_target_percent(stock, context.stocks[stock])

def has_open_orders(data,context):               
    # Only rebalance when we have zero pending orders.
    has_orders = False
    for stk in data:
        orders = get_open_orders(stk)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=stk)  
            has_orders = True
    return has_orders           
There was a runtime error.