Add GLD vs gold futures basis research for dashboard implementation
This commit is contained in:
170
docs/GLD_BASIS_RESEARCH.md
Normal file
170
docs/GLD_BASIS_RESEARCH.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
# 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"
|
||||||
Reference in New Issue
Block a user