Back to Community
The Importance of the Gold:Silver Ratio

One of the most meaningful metrics in the market is the gold:silver ratio. It not only provides information about how to trade gold and silver, but offers signals for the stock market as well.

The ratio has meaning because of what the out-performance of one or the other means for the economy and investor sentiment, in general. When gold is outperforming, it normally means investors are risk-averse. When silver is outperforming, investors are risk-taking and the economy has moved into high gear because silver actually has some industrial use, unlike gold. Therefore, we'd expect the gold:silver ratio to be low at market highs and high at market lows.

Besides that, the ratio can offer direction about which you should be buying if you happen to be bullish or bearish on gold or silver. If the ratio is too high, you should buy silver or short gold. If the ratio is too low, you should buy gold or short silver.

I extended the use of the gold:silver ratio to also be something you can actually trade via a pairs trade. This strategy buys gold 50%/shorts silver 50% when the ratio is under 4.9 for GLD:SLV (the actual spot prices of gold and silver are not available on this platform). It then reverses the trade when the ratio > 8 and buys silver 50%/shorts gold 50%. These levels are fairly obvious by investigating a gold:silver ratio chart, which oscillates at regular intervals between those values.

The results are market beating. There was one nasty draw-down that I might consider unacceptable, except that if this were actually trading, I might implement some kind of trailing stop to maximize profits on winning trades and prevent entering before the ratio turns up or down. Even with the draw-down this still does well.

Clone Algorithm
47
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 is a template algorithm on Quantopian for you to adapt and fill in.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from datetime import timedelta, datetime, tzinfo
 
def initialize(context):
    """
    Called once at the start of the algorithm.
    """   
    # Rebalance every day, 1 hour after market open.
    #schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(hours=1))
     
    # Record tracking variables at the end of each day.
    #schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())
     
    # Create our dynamic stock selector.
    #attach_pipeline(my_pipeline(context), 'my_pipeline')
    
    # Variable initialization
    context.gold = sid(26807) 
    context.silver = sid(28368) 
    context.in_trade1 = False
    context.in_trade2 = False
         
def my_pipeline(context):
    """
    A function to create our dynamic stock selector (pipeline). Documentation on
    pipeline can be found here: https://www.quantopian.com/help#pipeline-title
    """
    #pipe = Pipeline()
     
    # Create a dollar volume factor.
    #dollar_volume = AverageDollarVolume(window_length=1)
    #pipe.add(dollar_volume, 'dollar_volume')
 
    # Pick the top 1% of stocks ranked by dollar volume.
    #high_dollar_volume = dollar_volume.percentile_between(99, 100)
    #pipe.set_screen(high_dollar_volume)
     
    return pipe
 
def before_trading_start(context, data):
    """
    Called every day before market open.
    """
    #context.output = pipeline_output('my_pipeline')
  
    # These are the securities that we are interested in trading each day.
    #context.security_list = context.output.index
     
def my_assign_weights(context, data):
    """
    Assign weights to securities that we want to order.
    """
    pass
 
def my_rebalance(context,data):
    """
    Execute orders according to our schedule_function() timing. 
    """
    pass
 
def my_record_vars(context, data):
    """
    Plot variables at the end of each day.
    """
    pass
 
def handle_data(context,data):
    """
    Called every minute.
    """ 
    # Get price data
    hist_gold = data.history(context.gold, 'close', 1, '1d')
    hist_silver = data.history(context.silver, 'close', 1, '1d')
    
    # Calculate gold/silver ratio
    gold_silver_ratio = hist_gold[0]/hist_silver[0]
    
    if (gold_silver_ratio > 8) & (context.in_trade2 == True):
            # Exit
            order_target_percent(context.silver, 0)
            order_target_percent(context.gold,0)
            context.in_trade2 = False
            print 'Exiting long gold/short silver pair trade'     
              
    elif (gold_silver_ratio < 4.9)  & (context.in_trade1 == True):
            # Exit
            order_target_percent(context.silver, 0)
            order_target_percent(context.gold,0)
            context.in_trade1 = False
            print 'Exiting long silver/short gold pair trade'   
            
    elif (gold_silver_ratio > 8) & (context.in_trade1 == False):
            # 50% long silver, 50% short gold
            order_target_percent(context.silver, 0.5)
            order_target_percent(context.gold,-0.5)
            context.in_trade1 = True
            print 'Entering long silver/short gold pair trade'
            
    elif (gold_silver_ratio < 4.9) & (context.in_trade2 == False):
             # 50% long silver, 50% short gold
            order_target_percent(context.gold, 0.5)
            order_target_percent(context.silver,-0.5)
            context.in_trade2 = True        
            print 'Entering long gold/short silver pair trade'
            

    pass
There was a runtime error.
3 responses

Welcome to Q.

I did not really dig into the code yet because I'm on my iPad today but I'm curious as to how you came up with the inputs 4.9 and 8. Maybe there's a more dynamic way of setting this threshold.

@jeffrey.. how came your code wont work at different time frame like 2013-to present or 2015 to present it only execute... on 2007 start ?? I'd like to backtest it different starting point like 2013.. to see... if it can still.. outperform... and how come it only have few trades does this really really re-balance everyday...? or every month? thanks....

@jeffrey... is there a rolling chart for 8 and 4.9 greater than or less than... on the drawn... on screen... it would be a great help... thanks.....