Files
vault-dash/docs/STRATEGIES.md
Bu5hm4nn 00a68bc767 Initial commit: Vault Dashboard for options hedging
- FastAPI + NiceGUI web application
- QuantLib-based Black-Scholes pricing with Greeks
- Protective put, laddered, and LEAPS strategies
- Real-time WebSocket updates
- TradingView-style charts via Lightweight-Charts
- Docker containerization
- GitLab CI/CD pipeline for VPS deployment
- VPN-only access configuration
2026-03-21 19:21:40 +01:00

10 KiB

Strategy Documentation

Overview

Vault Dashboard currently documents and compares hedging approaches for a Lombard-style loan backed by gold exposure. The implementation focuses on paper analysis using option pricing, LTV protection metrics, and scenario analysis.

The strategy subsystem currently includes:

  • protective puts
  • laddered puts
  • lease/LEAPS duration analysis

This document focuses on the two primary hedge structures requested here:

  • protective put
  • laddered put

Common portfolio assumptions

The default research engine in app/strategies/engine.py uses:

  • portfolio value: 1,000,000
  • loan amount: 600,000
  • margin-call threshold: 0.75
  • spot price: 460
  • volatility: 0.16
  • risk-free rate: 0.045

From these values, the portfolio is modeled as a LombardPortfolio:

  • gold ounces = portfolio_value / spot_price
  • initial LTV = loan_amount / portfolio_value
  • margin call price = loan_amount / (margin_call_ltv * gold_ounces)

These assumptions create the common basis used to compare all strategies.


Protective put

What it is

A protective put is the simplest downside hedge in the project.

Structure:

  • long the underlying collateral exposure implicitly represented by the gold-backed portfolio
  • buy one put hedge sized to the portfolio's underlying units

In this codebase, ProtectivePutStrategy creates a single long put whose strike is defined as a percentage of spot.

Examples currently used by the engine:

  • ATM protective put: strike = 100% of spot
  • 95% OTM protective put: strike = 95% of spot
  • 90% OTM protective put: strike = 90% of spot

Why use it

A protective put sets a floor on downside beyond the strike, helping reduce the chance that falling collateral value pushes the portfolio above the margin-call LTV.

How it is implemented

File: app/strategies/protective_put.py

Main properties:

  • hedge_units: portfolio.gold_value / spot_price
  • strike: spot_price * strike_pct
  • term_years: months / 12

A put contract is priced with Black-Scholes inputs:

  • current spot
  • strike
  • time to expiry
  • risk-free rate
  • volatility
  • option type = put

The resulting OptionContract uses:

  • quantity = 1.0
  • contract_size = hedge_units

That means one model contract covers the full portfolio exposure in underlying units.

Protective put payoff intuition

At expiry:

  • if spot is above strike, the put expires worthless
  • if spot is below strike, payoff rises linearly as strike - spot

Total gross payoff is:

max(strike - spot, 0) * hedge_units

Protective put trade-offs

Advantages:

  • simple to explain
  • clear downside floor
  • strongest protection when strike is high

Costs:

  • premium can be expensive, especially at-the-money and for longer tenor
  • full notional protection may overspend relative to a client's risk budget
  • upside is preserved, but cost drags returns

Laddered put

What it is

A laddered put splits the hedge across multiple put strikes instead of buying the full hedge at one strike.

Structure:

  • multiple long put legs
  • each leg covers a weighted fraction of the total hedge
  • lower strikes usually reduce premium while preserving some tail protection

Examples currently used by the engine:

  • 50/50 ATM + 95% OTM
  • 33/33/33 ATM + 95% OTM + 90% OTM

Why use it

A ladder can reduce hedge cost versus a full ATM protective put, while still providing meaningful protection as the underlying falls.

This is useful when:

  • full-cost protection is too expensive
  • some drawdown can be tolerated before the hedge fully engages
  • the client wants a better cost/protection balance

How it is implemented

File: app/strategies/laddered_put.py

A LadderSpec defines:

  • weights
  • strike_pcts
  • months

Validation rules:

  • number of weights must equal number of strikes
  • weights must sum to 1.0

Each leg is implemented by internally creating a ProtectivePutStrategy, then weighting its premium and payoff.

Ladder payoff intuition

Each leg pays off independently:

max(leg_strike - spot, 0) * hedge_units * weight

Total ladder payoff is the sum across legs.

Relative to a single-strike hedge:

  • protection turns on in stages
  • blended premium is lower when some legs are farther OTM
  • downside support is smoother but less absolute near the first loss zone than a full ATM hedge

Ladder trade-offs

Advantages:

  • lower blended hedge cost
  • more flexible cost/protection shaping
  • better fit for cost-sensitive clients

Costs and limitations:

  • weaker immediate protection than a fully ATM hedge
  • more complex to explain to users
  • floor value depends on weight distribution across strikes

Cost calculations

Protective put cost calculation

ProtectivePutStrategy.calculate_cost() returns:

  • premium_per_share
  • total_cost
  • cost_pct_of_portfolio
  • term_months
  • annualized_cost
  • annualized_cost_pct

Formula summary

Let:

  • P = option premium per underlying unit
  • U = hedge units
  • T = term in years
  • V = portfolio value

Then:

total_cost = P * U
cost_pct_of_portfolio = total_cost / V
annualized_cost = total_cost / T
annualized_cost_pct = annualized_cost / V

Because the model contract size equals the full hedge units, the total premium directly represents the whole-portfolio hedge cost.

Laddered put cost calculation

LadderedPutStrategy.calculate_cost() computes weighted leg costs.

For each leg i:

  • weight_i
  • premium_i
  • hedge_units

Leg cost:

leg_cost_i = premium_i * hedge_units * weight_i

Blended totals:

blended_cost = sum(leg_cost_i)
blended_premium_per_share = sum(premium_i * weight_i)
annualized_cost = blended_cost / term_years
cost_pct_of_portfolio = blended_cost / portfolio_value
annualized_cost_pct = annualized_cost / portfolio_value

Why annualized cost matters

The engine compares strategies with different durations, especially in LeaseStrategy. Annualizing allows the system to compare short-dated and long-dated hedges on a common yearly basis.


Protection calculations

Margin-call threshold price

The project defines the collateral price that would trigger a margin call as:

margin_call_price = loan_amount / (margin_call_ltv * gold_ounces)

This is a key reference point for all protection calculations.

Protective put protection calculation

At the threshold price:

  1. compute the put payoff
  2. add that payoff to the stressed collateral value
  3. recompute LTV on the hedged collateral

Formulas:

payoff_at_threshold = max(strike - threshold_price, 0) * hedge_units
hedged_value_at_threshold = gold_value_at_threshold + payoff_at_threshold
hedged_ltv_at_threshold = loan_amount / hedged_value_at_threshold

The strategy is flagged as maintaining a margin buffer when:

hedged_ltv_at_threshold < margin_call_ltv

Laddered put protection calculation

For a ladder, threshold payoff is the weighted sum of all leg payoffs:

weighted_payoff_i = max(strike_i - threshold_price, 0) * hedge_units * weight_i
payoff_at_threshold = sum(weighted_payoff_i)
hedged_value_at_threshold = gold_value_at_threshold + payoff_at_threshold
hedged_ltv_at_threshold = loan_amount / hedged_value_at_threshold

The ladder's implied floor value is approximated as the weighted strike coverage:

portfolio_floor_value = sum(strike_i * hedge_units * weight_i)

Scenario analysis methodology

Scenario grid

The current scenario engine in ProtectivePutStrategy uses a fixed price-change grid:

-60%, -50%, -40%, -30%, -20%, -10%, 0%, +10%, +20%, +30%, +40%, +50%

For each change:

scenario_price = spot_price * (1 + change)

Negative or zero prices are ignored.

Metrics produced per scenario

For each scenario, the strategy computes:

  • scenario spot price
  • unhedged gold value
  • option payoff
  • hedge cost
  • net portfolio value after hedge cost
  • unhedged LTV
  • hedged LTV
  • whether a margin call occurs without the hedge
  • whether a margin call occurs with the hedge

Protective put scenario formulas

Let S be scenario spot.

gold_value = gold_ounces * S
option_payoff = max(strike - S, 0) * hedge_units
hedged_collateral = gold_value + option_payoff
net_portfolio_value = gold_value + option_payoff - hedge_cost
unhedged_ltv = loan_amount / gold_value
hedged_ltv = loan_amount / hedged_collateral

Margin-call flags:

margin_call_without_hedge = unhedged_ltv >= margin_call_ltv
margin_call_with_hedge = hedged_ltv >= margin_call_ltv

Laddered put scenario formulas

For ladders:

option_payoff = sum(max(strike_i - S, 0) * hedge_units * weight_i)
hedged_collateral = gold_value + option_payoff
net_portfolio_value = gold_value + option_payoff - blended_cost

All other LTV and margin-call logic is the same.

Interpretation methodology

Scenario analysis is used to answer four practical questions:

  1. Cost: How much premium is paid upfront?
  2. Activation: At what downside level does protection meaningfully start?
  3. Buffer: Does the hedge keep LTV below the margin-call threshold under stress?
  4. Efficiency: How much protection is obtained per dollar of annualized hedge cost?

This is why each strategy exposes both:

  • a calculate_protection() summary around the threshold price
  • a full get_scenarios() table across broad upside/downside moves

Comparing protective puts vs laddered puts

Dimension Protective put Laddered put
Structure Single put strike Multiple weighted put strikes
Simplicity Highest Moderate
Upfront cost Usually higher Usually lower
Near-threshold protection Stronger if ATM-heavy Depends on ladder weights
Tail downside protection Strong Strong, but blended
Customization Limited High
Best fit conservative protection balanced or cost-sensitive protection

Important limitations

  • The strategy engine is currently research-oriented, not an execution engine
  • Black-Scholes assumptions simplify real-world market behavior
  • Transaction costs, slippage, taxes, liquidity, and early exercise effects are not modeled here
  • The API payloads should be treated as analytical outputs, not trade recommendations
  • For non-GLD symbols, the engine currently still uses research-style assumptions rather than a complete live instrument-specific calibration

Future strategy extensions

Natural follow-ups for this subsystem:

  • collars and financed hedges
  • partial notional hedging
  • dynamic re-hedging rules
  • volatility surface-based pricing
  • broker-native contract sizing and expiries
  • user-configurable scenario grids