Files
vault-dash/docs/GLD_BASIS_RESEARCH.md

5.4 KiB
Raw Blame History

GLD ETF vs Gold Futures Basis: Implementation Guide

Executive Summary

GLD (SPDR Gold Shares ETF) does not track gold at a simple 10:1 ratio. Two mechanical factors affect the conversion between GLD and physical gold/futures.

Key Findings for Dashboard Implementation

1. Expense Ratio Decay (Permanent, Predictable)

Metric Launch (2004) Current (2026)
Gold per share 0.1000 oz ~0.0919 oz
Effective ratio 10:1 10.9:1
Cumulative decay 8.1%

Formula:

ounces_per_share = 0.10 * e^(-0.004 * years_since_2004)

Dashboard Implementation:

# Current GLD backing (as of 2026)
GLD_OUNCES_PER_SHARE = 0.0919

def gld_price_to_gold_spot(gld_price: float) -> float:
    """Convert GLD price to implied gold spot price."""
    return gld_price / GLD_OUNCES_PER_SHARE

def gold_spot_to_gld_price(gold_spot: float) -> float:
    """Convert gold spot price to GLD equivalent."""
    return gold_spot * GLD_OUNCES_PER_SHARE

# Example: At $4,600/oz gold
# GLD ≈ $4,600 × 0.0919 ≈ $423 (NOT $460)

2. Futures-Spot Basis (Variable, Market-Dependent)

Market State Futures vs. Spot GLD vs. GC=F÷10
Contango (normal) Futures > Spot by $10-15/oz GLD appears at "discount"
Backwardation (stress) Spot > Futures GLD appears at "premium"

During stress events:

  • March 2020 COVID: COMEX futures $50-70 above London spot
  • GLD holders benefited (physical-backed)
  • Futures traders suffered negative roll yield

3. After-Hours Pricing Gap

Instrument Trading Hours
GLD US market hours (9:30 AM - 4 PM ET)
GC=F (futures) 23 hours/day, 6 days/week

Implication: GLD opens with gaps after weekend/overnight gold moves. Dashboard should show "last regular session close" vs. "current futures indication."

Dashboard Recommendations

Data Display

class GoldPriceDisplay:
    """Recommended price display for vault-dash."""
    
    def __init__(self, gld_price: float, gold_futures_price: float):
        self.gld_price = gld_price
        self.gold_futures_price = gold_futures_price
        self.ounces_per_share = 0.0919  # Current GLD backing
        
    @property
    def implied_spot_from_gld(self) -> float:
        """Gold spot implied from GLD price."""
        return self.gld_price / self.ounces_per_share
    
    @property
    def gld_fair_value(self) -> float:
        """What GLD 'should' trade at based on futures."""
        # Adjust for contango (~$10/oz typically)
        spot_estimate = self.gold_futures_price - 10
        return spot_estimate * self.ounces_per_share
    
    @property
    def basis_bps(self) -> float:
        """Basis between GLD and fair value in basis points."""
        diff_bps = (self.gld_price / self.gld_fair_value - 1) * 10000
        return diff_bps

Warning Thresholds

# Raise warnings when basis exceeds normal bounds
BASIS_WARNING_THRESHOLD = 50  # 50 bps = 0.5%

if abs(basis_bps) > BASIS_WARNING_THRESHOLD:
    # GLD trading at unusual premium/discount
    # Possible causes: after-hours gap, physical stress, AP arb failure
    show_warning(f"GLD basis elevated: {basis_bps:.0f} bps")

Options Pricing

For Lombard hedge calculations:

def calculate_hedge_strikes(
    portfolio_gold_ounces: float,
    margin_call_price: float,
    current_gold_spot: float
) -> dict:
    """
    Calculate appropriate GLD option strikes for hedge.
    
    IMPORTANT: Use GLD price directly, not converted from futures.
    """
    # Convert gold price thresholds to GLD strikes
    gld_current = current_gold_spot * GLD_OUNCES_PER_SHARE
    gld_margin_call = margin_call_price * GLD_OUNCES_PER_SHARE
    
    # Recommended strikes
    atm_strike = round(gld_current)  # e.g., $423
    otm_10_strike = round(gld_current * 0.90)  # 10% OTM: ~$381
    otm_5_strike = round(gld_current * 0.95)  # 5% OTM: ~$402
    
    return {
        "current_gld": gld_current,
        "margin_call_gld": gld_margin_call,
        "atm_strike": atm_strike,
        "otm_5pct_strike": otm_5_strike,
        "otm_10pct_strike": otm_10_strike,
        "contracts_needed": math.ceil(portfolio_gold_ounces / (100 * GLD_OUNCES_PER_SHARE))
    }

Data Sources

Data Point Source Notes
GLD NAV/ounce spdrgoldshares.com Daily updated
GLD price Market data API Real-time
GC=F price CME/futures API Extended hours
Contango estimate Futures curve Calculate from term structure

Key Takeaways for Vault-Dash

  1. Never use a fixed 10:1 ratio — always use current GLD backing (~0.092 oz/share)

  2. Display both measures:

    • GLD implied spot = GLD ÷ 0.0919
    • GC=F adjusted = GC=F ÷ 10 (naive) for comparison
  3. Show basis indicator:

    • Green: basis within ±25 bps (normal)
    • Yellow: basis ±25-50 bps (elevated)
    • Red: basis > 50 bps (unusual — possible stress)
  4. For hedging:

    • Use GLD's actual price for strike selection
    • Contract count = gold ounces ÷ (100 × 0.0919)
    • Don't convert from GC=F to GLD — use GLD directly

References

  • SEC GLD Registration Statement (2004)
  • SPDR Gold Shares: GLDM methodology updates
  • CME Gold Futures specifications
  • Research paper: "Optimal Hedging Strategies for Gold-Backed Lombard Loans"