Files
vault-dash/docs/GLD_BASIS_RESEARCH.md

170 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:**
```python
# 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
```python
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
```python
# 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:
```python
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"