Portfolio Risk Management

Institutional-Grade Risk Control | Protect Your Capital


Learning Objectives

After this module, you will:

  • Calculate and interpret Value at Risk (VaR) using multiple methods
  • Implement stress testing and scenario analysis
  • Design position sizing frameworks for options portfolios
  • Manage Greeks across multi-position portfolios
  • Identify and mitigate concentration and correlation risks
  • Build risk monitoring dashboards
  • Apply capital allocation strategies
  • Measure risk-adjusted performance properly
  • Learn from catastrophic risk failures

Prerequisites:

Time to Master: 10-15 hours | Difficulty: Expert


Why Risk Management Matters

The Harsh Reality

Trading Without Risk Management:

Month 1-11: +5%, +7%, +3%, +8%, +6%, +4%, +9%, +5%, +7%, +6%, +8%
Cumulative: +88% (Amazing!)

Month 12: -95% (One bad trade)
Final Result: -60% (Account devastated)

Trading With Risk Management:

Month 1-11: +4%, +5%, +2%, +6%, +4%, +3%, +7%, +4%, +5%, +4%, +6%
Cumulative: +59% (Good, not amazing)

Month 12: -8% (Controlled risk, stopped out)
Final Result: +46% (Survived and profitable)

The Difference: Risk management keeps you in the game


The Iron Law of Risk Management

“Rule #1: Don’t lose money. Rule #2: Never forget Rule #1.” - Warren Buffett

For Options Traders:

  1. You WILL be wrong
  2. You WILL face tail events
  3. Survival > Performance
  4. Compound gains require surviving losses
  5. One blow-up erases years of gains

The Goal: Maximize risk-adjusted returns, not absolute returns


Value at Risk (VaR)

What Is VaR?

Definition: Maximum expected loss over a time horizon at a given confidence level

English Translation: “I’m 95% confident I won’t lose more than $10,000 tomorrow”

Components:

  1. Confidence Level: 95%, 99% (how sure?)
  2. Time Horizon: 1 day, 10 days, 1 month
  3. Loss Amount: Dollar value

Method 1: Parametric VaR

Assumption: Returns are normally distributed

Formula:

VaR = Portfolio Value × σ × Z

Where:
- σ = Portfolio standard deviation (daily)
- Z = Z-score for confidence level
  - 95% confidence: Z = 1.65
  - 99% confidence: Z = 2.33

Example:

Portfolio: $100,000
Daily volatility: 3%
Confidence: 95%

VaR(95%, 1-day) = $100,000 × 3% × 1.65
                = $4,950

Interpretation: 95% confident we won't lose more than $4,950 tomorrow
Or: Expect to lose more than $4,950 once every 20 days

Python Implementation:

import numpy as np
from scipy import stats
 
def parametric_var(portfolio_value, daily_volatility, confidence=0.95, horizon=1):
    """
    Calculate parametric VaR
    """
    z_score = stats.norm.ppf(1 - confidence)  # Negative for losses
    var = portfolio_value * daily_volatility * abs(z_score) * np.sqrt(horizon)
 
    return var
 
# Usage
port_value = 100000
daily_vol = 0.03  # 3%
var_95 = parametric_var(port_value, daily_vol, 0.95, 1)
var_99 = parametric_var(port_value, daily_vol, 0.99, 1)
 
print(f"1-Day VaR (95%): ${var_95:,.0f}")
print(f"1-Day VaR (99%): ${var_99:,.0f}")
 
# Output:
# 1-Day VaR (95%): $4,950
# 1-Day VaR (99%): $6,990

Limitations:

  • Assumes normal distribution (crypto/options are NOT normal!)
  • Underestimates tail risk
  • Ignores skewness and kurtosis
  • Dangerous for options (non-linear payoffs)

Method 2: Historical VaR

Concept: Use actual historical returns

Steps:

  1. Collect historical portfolio returns (e.g., 250 days)
  2. Sort from worst to best
  3. Find the loss at the desired percentile

Example:

Historical returns (250 days sorted):
Day 1 (worst): -8.2%
Day 2: -6.5%
Day 3: -5.8%
...
Day 13: -2.1% ← 5th percentile (95% VaR)
...
Day 250 (best): +9.1%

For $100,000 portfolio:
VaR(95%) = $100,000 × 2.1% = $2,100

Interpretation: In the past year, 95% of days had losses smaller than $2,100

Python Implementation:

import numpy as np
import pandas as pd
 
def historical_var(returns, portfolio_value, confidence=0.95):
    """
    Calculate historical VaR from returns series
    """
    # Sort returns (worst to best)
    sorted_returns = np.sort(returns)
 
    # Find percentile
    index = int((1 - confidence) * len(sorted_returns))
    var_return = abs(sorted_returns[index])
 
    var = portfolio_value * var_return
 
    return var
 
# Usage
# Assume daily_returns is a pandas Series of historical returns
daily_returns = pd.Series([...])  # Your historical data
 
var_95_hist = historical_var(daily_returns, 100000, 0.95)
var_99_hist = historical_var(daily_returns, 100000, 0.99)
 
print(f"Historical VaR (95%): ${var_95_hist:,.0f}")
print(f"Historical VaR (99%): ${var_99_hist:,.0f}")

Advantages:

  • No distribution assumptions
  • Captures actual tail behavior
  • Simple to understand

Limitations:

  • Assumes future like past (rarely true)
  • Limited by sample size
  • Doesn’t capture unprecedented events

Method 3: Monte Carlo VaR

Concept: Simulate thousands of possible futures

Steps:

  1. Model asset price process (GBM, etc.)
  2. Generate 10,000 scenarios for tomorrow
  3. Calculate portfolio value in each scenario
  4. Sort outcomes, find 5th percentile

Example:

Simulate 10,000 possible tomorrows:
- Scenario 1: BTC +5%, ETH +3% → Portfolio +$4,200
- Scenario 2: BTC -2%, ETH +1% → Portfolio -$800
- ...
- Scenario 500 (5th percentile): Portfolio -$6,300 ← VaR(95%)
- ...
- Scenario 10,000: BTC +8%, ETH +7% → Portfolio +$7,500

VaR(95%) = $6,300

Python Implementation:

import numpy as np
 
def monte_carlo_var(portfolio_positions, n_simulations=10000, confidence=0.95):
    """
    Monte Carlo VaR for multi-asset portfolio
 
    portfolio_positions = {
        'BTC': {'quantity': 2, 'price': 50000, 'volatility': 0.80},
        'ETH': {'quantity': 10, 'price': 3000, 'volatility': 0.85}
    }
    """
    # Calculate initial portfolio value
    initial_value = sum(p['quantity'] * p['price'] for p in portfolio_positions.values())
 
    # Simulate scenarios
    portfolio_values = []
 
    for _ in range(n_simulations):
        simulated_value = 0
 
        for asset, position in portfolio_positions.items():
            # Generate random return
            daily_vol = position['volatility'] / np.sqrt(365)
            random_return = np.random.normal(0, daily_vol)
 
            # Calculate new price
            new_price = position['price'] * (1 + random_return)
            simulated_value += position['quantity'] * new_price
 
        portfolio_values.append(simulated_value)
 
    # Calculate VaR
    portfolio_values = np.array(portfolio_values)
    losses = initial_value - portfolio_values
    var = np.percentile(losses, confidence * 100)
 
    return var, portfolio_values
 
# Usage
positions = {
    'BTC': {'quantity': 2, 'price': 50000, 'volatility': 0.80},
    'ETH': {'quantity': 10, 'price': 3000, 'volatility': 0.85}
}
 
var_mc, simulated_values = monte_carlo_var(positions, 10000, 0.95)
print(f"Monte Carlo VaR (95%): ${var_mc:,.0f}")
 
# Analyze distribution
print(f"Expected Portfolio Value: ${np.mean(simulated_values):,.0f}")
print(f"Worst 1% outcome: ${np.percentile(simulated_values, 1):,.0f}")

Advantages:

  • Handles complex portfolios (options, multi-asset)
  • Captures non-linear payoffs
  • Can model correlations
  • Most flexible method

Limitations:

  • Computationally intensive
  • Model assumptions matter (garbage in, garbage out)
  • Requires good volatility/correlation estimates

Conditional VaR (CVaR) / Expected Shortfall

Problem with VaR: Doesn’t tell you HOW BAD it gets beyond VaR

CVaR: Average loss in the worst X% of cases

Example:

VaR(95%) = $5,000 (5% of days exceed this)

But what's the average loss on those bad days?

CVaR(95%) = Average of worst 5% losses
          = ($8,000 + $7,500 + $12,000 + ...) / N
          = $9,200

Interpretation: When things go bad (5% of the time), expect to lose $9,200 on average

Why CVaR is Better:

  • Captures tail risk severity
  • More conservative
  • Preferred by regulators
  • Actually measures “how bad is bad”

Python Implementation:

def cvar(returns, portfolio_value, confidence=0.95):
    """
    Calculate CVaR (Expected Shortfall)
    """
    sorted_returns = np.sort(returns)
    cutoff_index = int((1 - confidence) * len(sorted_returns))
 
    # Average of worst cases
    worst_returns = sorted_returns[:cutoff_index]
    cvar_return = abs(np.mean(worst_returns))
 
    cvar = portfolio_value * cvar_return
 
    return cvar
 
# Usage
cvar_95 = cvar(daily_returns, 100000, 0.95)
print(f"CVaR (95%): ${cvar_95:,.0f}")

Stress Testing

What Is Stress Testing?

Definition: “What if the worst happens?”

vs VaR:

  • VaR: “What’s normal bad?”
  • Stress Test: “What’s catastrophic?”

Historical Scenario Analysis

Replay Historical Crises:

Scenario 1: COVID Crash (Feb-Mar 2020)
- BTC: -50% in 2 weeks
- Vol spike: 60% → 150%
- Correlations → 1.0

Apply to current portfolio:
- Long 2 BTC at $50k
- Short 5 BTC puts at $45k

Result:
BTC drops to $25k:
- Long BTC: -$50,000
- Short puts: -$100,000 (deep ITM)
- Total loss: -$150,000

Stress test reveals: Position is massively exposed to crash

Key Historical Scenarios:

  1. 2020 COVID Crash: -35% in 3 weeks, vol explosion
  2. 2021 Crypto Crash: -50% from peak
  3. 2018 Crypto Winter: -80% over 12 months
  4. 2008 Financial Crisis: Liquidity freeze
  5. Flash Crash: -10% in minutes, instant recovery

Custom Scenario Design

Build Your Own Nightmare Scenarios:

Scenario Design Template:

Scenario Name: "Bitcoin Regulation Ban"
Probability: Low (5% chance)
Impact: Catastrophic

Parameters:
- BTC: -60% overnight
- Volatility: +200%
- Liquidity: Dries up (can't exit)
- Correlations: ETH follows (0.95 correlation)

Portfolio Impact: [Calculate]

Python Implementation:

def stress_test_portfolio(portfolio, scenarios):
    """
    Apply stress scenarios to portfolio
 
    scenarios = {
        'COVID Crash': {'BTC': -0.50, 'ETH': -0.45, 'vol_spike': 2.5},
        'Flash Crash': {'BTC': -0.15, 'ETH': -0.18, 'vol_spike': 1.8},
        'Regulation Ban': {'BTC': -0.60, 'ETH': -0.55, 'vol_spike': 3.0}
    }
    """
    initial_value = calculate_portfolio_value(portfolio)
    results = {}
 
    for scenario_name, shocks in scenarios.items():
        # Apply shocks to portfolio
        stressed_portfolio = apply_shocks(portfolio, shocks)
        stressed_value = calculate_portfolio_value(stressed_portfolio)
 
        loss = initial_value - stressed_value
        loss_pct = (loss / initial_value) * 100
 
        results[scenario_name] = {
            'loss': loss,
            'loss_pct': loss_pct,
            'surviving': loss < initial_value * 0.5  # Can survive 50% loss
        }
 
    return results
 
# Usage
portfolio = {
    'BTC_long': {'quantity': 2, 'price': 50000},
    'BTC_put_short': {'quantity': -5, 'strike': 45000, 'price': 2000}
}
 
scenarios = {
    'COVID Crash': {'BTC': -0.50, 'vol_spike': 2.5},
    'Flash Crash': {'BTC': -0.15, 'vol_spike': 1.8},
}
 
stress_results = stress_test_portfolio(portfolio, scenarios)
 
for scenario, result in stress_results.items():
    print(f"{scenario}:")
    print(f"  Loss: ${result['loss']:,.0f} ({result['loss_pct']:.1f}%)")
    print(f"  Survivable: {result['surviving']}")

Reverse Stress Testing

Concept: “What would it take to blow me up?”

Process:

  1. Define unacceptable loss (e.g., -80% of capital)
  2. Work backwards to find scenarios that cause it
  3. Assess probability of those scenarios
  4. Adjust position if probability too high

Example:

Portfolio: $100,000
Unacceptable Loss: -$80,000 (80%)

Positions:
- Long 2 BTC at $50k
- Short 10 ATM straddles

Reverse engineer:
What price movement causes -$80k loss?

Analysis:
- If BTC stays flat: Straddles expire worthless (+$20k profit) ✓
- If BTC moves 20%: Straddles lose $60k, BTC gains $20k = -$40k ✗
- If BTC moves 40%: Straddles lose $150k, BTC gains $40k = -$110k ✗✗

Conclusion: Any move &gt;25% causes unacceptable loss
Recent history: BTC moves &gt;25% about 4x per year

Action: Position is too risky, reduce short straddles!

Position Sizing Frameworks

Fixed Fractional Position Sizing

Concept: Risk fixed % of capital per trade

Formula:

Position Size = (Account Size × Risk %) / Risk per Unit

Example:
Account: $100,000
Risk per trade: 2%
Risk per unit: $1,000 (stop loss)

Position Size = ($100,000 × 2%) / $1,000
              = $2,000 / $1,000
              = 2 units

For Options:

Example: Buying straddles
Account: $100,000
Risk per trade: 5% = $5,000
Straddle cost: $3,000 (max risk)

Position Size = $5,000 / $3,000 = 1.67 straddles
Round down to 1 straddle

Kelly Criterion

Concept: Optimal position size for maximum long-term growth

Formula:

Kelly % = (Win Rate × Avg Win - Loss Rate × Avg Loss) / Avg Win

Example:
Win Rate: 40%
Avg Win: $2,000
Loss Rate: 60%
Avg Loss: $800

Kelly % = (0.40 × $2,000 - 0.60 × $800) / $2,000
        = ($800 - $480) / $2,000
        = 0.16 or 16%

Size next trade at 16% of capital

Practical Adjustment: Use Half-Kelly or Quarter-Kelly

Full Kelly: 16% (very aggressive)
Half Kelly: 8% (reasonable)
Quarter Kelly: 4% (conservative)

Python Implementation:

def kelly_criterion(win_rate, avg_win, avg_loss):
    """
    Calculate Kelly optimal position size
    """
    loss_rate = 1 - win_rate
    kelly = (win_rate * avg_win - loss_rate * avg_loss) / avg_win
 
    # Also calculate fractional Kelly
    half_kelly = kelly * 0.5
    quarter_kelly = kelly * 0.25
 
    return {
        'full_kelly': kelly,
        'half_kelly': half_kelly,
        'quarter_kelly': quarter_kelly
    }
 
# Usage
kelly = kelly_criterion(win_rate=0.40, avg_win=2000, avg_loss=800)
print(f"Full Kelly: {kelly['full_kelly']:.1%}")
print(f"Half Kelly: {kelly['half_kelly']:.1%}")
print(f"Quarter Kelly: {kelly['quarter_kelly']:.1%}")
 
# Output:
# Full Kelly: 16.0%
# Half Kelly: 8.0%
# Quarter Kelly: 4.0%

Warning: Kelly assumes you know win rate and avg win/loss accurately. Overestimating leads to ruin!


Risk Parity Position Sizing

Concept: Size positions so each contributes equal risk

Formula:

Position Weight = 1 / Volatility

Example:
Asset A: 20% vol → Weight = 1/20 = 0.05 (5%)
Asset B: 40% vol → Weight = 1/40 = 0.025 (2.5%)
Asset C: 60% vol → Weight = 1/60 = 0.017 (1.7%)

Normalize to 100%:
Total = 0.05 + 0.025 + 0.017 = 0.092
Asset A: 54.3% of portfolio
Asset B: 27.2%
Asset C: 18.5%

Result: Each asset contributes ~equal risk despite different volatilities

Python Implementation:

def risk_parity_weights(assets_volatility):
    """
    Calculate risk parity weights
 
    assets_volatility = {
        'BTC': 0.80,  # 80% annual vol
        'ETH': 0.90,
        'Stocks': 0.20
    }
    """
    # Inverse volatility weights
    inv_vol = {asset: 1/vol for asset, vol in assets_volatility.items()}
 
    # Normalize to 100%
    total_inv_vol = sum(inv_vol.values())
    weights = {asset: inv/total_inv_vol for asset, inv in inv_vol.items()}
 
    return weights
 
# Usage
vols = {'BTC': 0.80, 'ETH': 0.90, 'Stocks': 0.20}
weights = risk_parity_weights(vols)
 
for asset, weight in weights.items():
    print(f"{asset}: {weight:.1%}")
 
# Output:
# BTC: 28.6%
# ETH: 25.4%
# Stocks: 46.0%

Greeks-Based Portfolio Risk

Portfolio Greeks Aggregation

Concept: Sum Greeks across all positions

Example Portfolio:

Position 1: Long 10 BTC calls ($50k strike)
- Delta: +400
- Gamma: +50
- Theta: -$500
- Vega: +$8,000

Position 2: Short 5 BTC puts ($45k strike)
- Delta: +250
- Gamma: -30
- Theta: +$300
- Vega: -$5,000

Position 3: Long 2 BTC (spot)
- Delta: +200
- Gamma: 0
- Theta: 0
- Vega: 0

Portfolio Totals:
- Net Delta: +850 (bullish)
- Net Gamma: +20 (slightly long vol)
- Net Theta: -$200 (bleeding daily)
- Net Vega: +$3,000 (long vol)

Interpretation:

  • Directionally bullish (net delta +850)
  • Slightly long volatility (gamma +20, vega +$3k)
  • Small theta bleed (-$200/day)
  • Needs BTC to rise or vol to increase

Greeks Risk Limits

Set Portfolio Limits:

Delta Limits: -500 to +500 (nearly market-neutral)
Gamma Limits:
  - Long vol: 0 to +100
  - Short vol: -100 to 0
Theta Limits: -$1,000 to +$1,000 per day
Vega Limits: -$10,000 to +$10,000 per vol point

Monitoring:

def check_greeks_limits(portfolio_greeks, limits):
    """
    Check if portfolio Greeks exceed limits
    """
    violations = []
 
    for greek, value in portfolio_greeks.items():
        if greek in limits:
            min_limit, max_limit = limits[greek]
            if value < min_limit or value > max_limit:
                violations.append({
                    'greek': greek,
                    'value': value,
                    'limit': (min_limit, max_limit),
                    'breach_amount': max(0, value - max_limit, min_limit - value)
                })
 
    return violations
 
# Usage
portfolio_greeks = {
    'delta': 850,  # Exceeds limit!
    'gamma': 20,
    'theta': -200,
    'vega': 3000
}
 
limits = {
    'delta': (-500, 500),
    'gamma': (-100, 100),
    'theta': (-1000, 1000),
    'vega': (-10000, 10000)
}
 
violations = check_greeks_limits(portfolio_greeks, limits)
 
if violations:
    print("Greek violations detected:")
    for v in violations:
        print(f"  {v['greek']}: {v['value']} (limit: {v['limit']})")
        print(f"  Breach: {v['breach_amount']}")

Delta-Gamma-Vega Hedging

Multi-Dimensional Hedging:

Scenario: Portfolio with complex Greeks

Current Greeks:
- Delta: +300 (too bullish)
- Gamma: +80 (want to keep)
- Vega: +$5,000 (want to keep)

Goal: Neutralize delta, keep gamma/vega

Solution: Use underlying (delta-only instrument)

Hedge: Short 300 delta of underlying

After hedge:
- Delta: 0 ✓
- Gamma: +80 ✓ (unchanged, underlying has no gamma)
- Vega: +$5,000 ✓ (unchanged)

Result: Pure volatility exposure, no directional risk

Correlation and Concentration Risk

Correlation Risk

Problem: Assets move together, less diversification than expected

Example:

Portfolio:
- 50% Bitcoin
- 50% Ethereum

Expected: 50% diversification benefit
Reality: BTC-ETH correlation = 0.85 (move together!)

Actual diversification: Much less than 50%

Measuring Correlation Risk:

import numpy as np
 
def portfolio_correlation_risk(positions, correlation_matrix):
    """
    Calculate portfolio variance accounting for correlations
 
    positions = {'BTC': 0.5, 'ETH': 0.5}  # Weights
    correlation_matrix = [[1.0, 0.85], [0.85, 1.0]]
    volatilities = [0.80, 0.90]
    """
    weights = np.array(list(positions.values()))
    vols = np.array([0.80, 0.90])  # BTC, ETH vols
 
    # Covariance matrix
    cov_matrix = correlation_matrix * np.outer(vols, vols)
 
    # Portfolio variance
    portfolio_var = np.dot(weights, np.dot(cov_matrix, weights))
    portfolio_vol = np.sqrt(portfolio_var)
 
    return portfolio_vol
 
# Usage
positions = {'BTC': 0.5, 'ETH': 0.5}
corr_matrix = np.array([[1.0, 0.85], [0.85, 1.0]])
 
portfolio_vol = portfolio_correlation_risk(positions, corr_matrix)
print(f"Portfolio Volatility: {portfolio_vol:.1%}")
 
# Compare to average:
avg_vol = (0.80 + 0.90) / 2
print(f"Average Vol (no correlation): {avg_vol:.1%}")
print(f"Diversification benefit: {(avg_vol - portfolio_vol)/avg_vol:.1%}")

Concentration Risk

Problem: Too much in one position

Herfindahl Index (Concentration Measure):

HHI = Σ (weight_i)²

Example 1: Diversified
- 10 positions, each 10%
- HHI = 10 × (0.10)² = 0.10 (low concentration)

Example 2: Concentrated
- 1 position 60%, 4 positions 10%
- HHI = (0.60)² + 4×(0.10)² = 0.36 + 0.04 = 0.40 (high!)

Threshold: HHI > 0.25 = Too concentrated

Risk Limits:

Single Position Limits:
- Max 20% in any single asset
- Max 30% in any single strategy
- Max 40% in any single asset class

Monitoring:
- Daily concentration checks
- Rebalance if limits breached
- Force diversification

Liquidity Risk

What Is Liquidity Risk?

Definition: Risk you can’t exit when needed

Manifestations:

  1. Bid-ask spreads widen: Lose 5-10% on execution
  2. No buyers: Can’t sell at any price
  3. Slippage: Moving the market against yourself

Measuring Liquidity

Metrics:

  1. Bid-Ask Spread:
Bid: $49,500
Ask: $50,500
Spread: $1,000 (2%)

Cost to round-trip: 2% (ouch!)
  1. Volume:
Daily volume: $10M
Your position: $2M (20% of volume)

Risk: Liquidating would move market significantly
  1. Market Depth:
Order Book:
$50,000: 5 BTC available
$49,500: 3 BTC
$49,000: 2 BTC
$48,500: 1 BTC

To sell 10 BTC, average price: ~$49,300 (1.4% slippage)

Liquidity-Adjusted VaR

Concept: Account for liquidity constraints in VaR

Formula:

Liquidity-Adjusted VaR = VaR + Liquidity Cost

Liquidity Cost = Position Size × (Spread/2 + Slippage %)

Example:
VaR (95%): $5,000
Position: $100,000
Spread: 2%
Slippage: 1%

Liquidity Cost = $100,000 × (2%/2 + 1%) = $2,000

Liquidity-Adjusted VaR = $5,000 + $2,000 = $7,000

Lesson: Illiquid positions have higher effective risk


Risk-Adjusted Performance

Sharpe Ratio

Formula:

Sharpe = (Return - Risk-Free Rate) / Volatility

Example:
Annual Return: 25%
Risk-Free Rate: 3%
Volatility: 30%

Sharpe = (25% - 3%) / 30% = 0.73

Interpretation:
- Sharpe &lt; 0.5: Poor
- Sharpe 0.5-1.0: Okay
- Sharpe 1.0-2.0: Good
- Sharpe &gt; 2.0: Excellent

Sortino Ratio

Improvement on Sharpe: Only penalize downside volatility

Formula:

Sortino = (Return - Risk-Free Rate) / Downside Deviation

Downside Deviation = Std Dev of negative returns only

Example:
Annual Return: 25%
Risk-Free Rate: 3%
Downside Deviation: 18% (vs 30% total vol)

Sortino = (25% - 3%) / 18% = 1.22 (better than Sharpe!)

Why Better: Upside volatility is good! Don’t penalize it.


Calmar Ratio

Focus on Max Drawdown:

Formula:

Calmar = Annual Return / Max Drawdown

Example:
Annual Return: 40%
Max Drawdown: -25%

Calmar = 40% / 25% = 1.6

Interpretation:
- Calmar &lt; 1.0: Return doesn't justify risk
- Calmar 1.0-3.0: Reasonable
- Calmar &gt; 3.0: Excellent risk-adjusted returns

Python Risk Metrics Suite

import numpy as np
import pandas as pd
 
class RiskMetrics:
    def __init__(self, returns, risk_free_rate=0.03):
        self.returns = returns
        self.rf = risk_free_rate
 
    def sharpe_ratio(self):
        excess_return = np.mean(self.returns) - self.rf / 252
        volatility = np.std(self.returns)
        return (excess_return * 252) / (volatility * np.sqrt(252))
 
    def sortino_ratio(self):
        excess_return = np.mean(self.returns) - self.rf / 252
        downside_returns = self.returns[self.returns < 0]
        downside_std = np.std(downside_returns)
        return (excess_return * 252) / (downside_std * np.sqrt(252))
 
    def max_drawdown(self):
        cumulative = (1 + self.returns).cumprod()
        running_max = cumulative.expanding().max()
        drawdown = (cumulative - running_max) / running_max
        return drawdown.min()
 
    def calmar_ratio(self):
        annual_return = np.mean(self.returns) * 252
        max_dd = abs(self.max_drawdown())
        return annual_return / max_dd
 
    def generate_report(self):
        return {
            'Sharpe Ratio': self.sharpe_ratio(),
            'Sortino Ratio': self.sortino_ratio(),
            'Max Drawdown': self.max_drawdown(),
            'Calmar Ratio': self.calmar_ratio(),
            'Annual Return': np.mean(self.returns) * 252,
            'Annual Volatility': np.std(self.returns) * np.sqrt(252)
        }
 
# Usage
daily_returns = pd.Series([...])  # Your returns
metrics = RiskMetrics(daily_returns)
report = metrics.generate_report()
 
for metric, value in report.items():
    print(f"{metric}: {value:.2f}")

Real-World Risk Failures

Case Study 1: Long-Term Capital Management (LTCM, 1998)

Background:

  • Nobel Prize-winning team
  • Sophisticated arbitrage strategies
  • $1.25B capital, $125B balance sheet (100x leverage!)

The Strategy:

  • Convergence trades (bond spreads)
  • High Sharpe ratio (2.0+)
  • Worked for years

What Went Wrong:

Russian Default (Aug 1998):
- Bonds crashed globally
- Spreads widened (opposite of expected)
- Liquidity disappeared
- Forced liquidations accelerated losses

Timeline:
Week 1: -$500M
Week 2: -$1.5B
Week 3: -$3B
Fed intervenes to prevent systemic collapse

Lessons:

  1. Leverage kills: 100x leverage = no room for error
  2. Liquidity risk: Can’t exit when everyone exits
  3. Tail risk: “6-sigma event” (but they happen!)
  4. Model risk: Assumed correlations → 1.0 in crisis
  5. Overconfidence: “Our models are perfect”

For Us:

  • Never use extreme leverage
  • Stress test for liquidity crises
  • Assume correlations go to 1.0 in crashes
  • Stay humble

Case Study 2: Archegos Capital (2021)

Background:

  • Family office (less regulated)
  • Equity swaps (synthetic leverage)
  • ~5-6x leverage hidden via swaps

The Positions:

Concentrated bets on:
- ViacomCBS
- Discovery
- Chinese tech stocks

Total exposure: ~$100B on $10B capital (10x leverage!)

What Went Wrong:

ViacomCBS announces stock offering (dilutive)

Stock drops 10%

Margin call from broker

Can't meet margin (overleveraged)

Forced liquidation (massive size)

Stock drops another 40%

Other positions cascade

Total loss: $20B in 2 days

Lessons:

  1. Concentration risk: Too much in few stocks
  2. Leverage risk: 10x leverage = instant death
  3. Correlation risk: All positions fell together
  4. Liquidity risk: Couldn’t exit without destroying prices
  5. Transparency: Swaps hid true exposure

For Us:

  • Diversify (max 20% per position)
  • Limit leverage (2-3x max)
  • Maintain liquidity buffers
  • Track total exposure honestly

Case Study 3: Amaranth Advisors (2006)

Background:

  • Natural gas trader
  • Exploited seasonal spreads
  • Made billions in 2005

The Trade:

Strategy: Calendar spreads in nat gas futures
- Long winter delivery
- Short summer delivery
- Bet on seasonal spread widening

Position size: $9B exposure on $4B capital
Leverage: ~2x (reasonable!)

What Went Wrong:

September 2006:
- Mild hurricane season (less supply disruption)
- Spread collapsed (opposite of expected)
- Massive positions couldn't be exited
- Week 1: -$1B
- Week 2: -$3B
- Week 3: -$6B
- Total: Lost $6B in 2 weeks (fund collapsed)

Lessons:

  1. Liquidity: Big positions can’t exit in small markets
  2. Concentration: 90% of capital in one strategy
  3. Timing: Seasonal trades require patience
  4. Market depth: Position size exceeded market capacity
  5. No diversification: All eggs in one basket

For Us:

  • Check market depth vs position size
  • Diversify strategies
  • Never put >50% in one trade
  • Maintain exit plans

Building a Risk Dashboard

Daily Risk Report Template

=== DAILY RISK REPORT ===
Date: 2024-03-15
Portfolio Value: $487,200

POSITION SUMMARY:
- Long BTC: 5 units @ $50,000
- Short BTC Puts: 10 contracts @ $45k strike
- Long ETH: 20 units @ $3,000

GREEKS:
- Net Delta: +720 (BULLISH - Above limit!)
- Net Gamma: -45 (Short vol)
- Net Theta: +$450/day
- Net Vega: -$12,000 per vol point (SHORT VOL)

RISK METRICS:
- VaR (95%, 1-day): $18,400 (3.8% of portfolio)
- CVaR (95%): $29,200 (6.0%)
- Max Drawdown (30d): -12.3%
- Current Drawdown: -3.2%

STRESS TESTS:
- COVID Crash (-50%): -$198,000 (-41%) ⚠️
- Flash Crash (-15%): -$42,000 (-9%) ✓
- Regulation Ban (-60%): -$285,000 (-58%) ⚠️⚠️

CONCENTRATION:
- BTC exposure: 68% (OVER LIMIT!) ⚠️
- ETH exposure: 32%
- HHI: 0.57 (HIGH CONCENTRATION) ⚠️

VIOLATIONS:
1. Net delta exceeds limit (+720 vs +500 max)
2. BTC concentration exceeds 60% limit
3. Stress test losses exceed 50% in 2 scenarios

RECOMMENDED ACTIONS:
1. Sell 200 delta of BTC to neutralize
2. Add uncorrelated positions (reduce HHI)
3. Buy OTM puts for tail protection

Automated Risk Monitoring

class RiskMonitor:
    def __init__(self, portfolio, limits):
        self.portfolio = portfolio
        self.limits = limits
        self.alerts = []
 
    def check_all_risks(self):
        """Run all risk checks"""
        self.check_greeks()
        self.check_concentration()
        self.check_var()
        self.run_stress_tests()
 
        return self.generate_report()
 
    def check_greeks(self):
        """Check Greeks against limits"""
        greeks = self.portfolio.calculate_greeks()
 
        for greek, value in greeks.items():
            if greek in self.limits['greeks']:
                min_val, max_val = self.limits['greeks'][greek]
                if value < min_val or value > max_val:
                    self.alerts.append({
                        'type': 'GREEK_VIOLATION',
                        'severity': 'HIGH',
                        'greek': greek,
                        'value': value,
                        'limit': (min_val, max_val)
                    })
 
    def check_concentration(self):
        """Check position concentration"""
        weights = self.portfolio.get_weights()
        hhi = sum(w**2 for w in weights.values())
 
        if hhi > self.limits['max_hhi']:
            self.alerts.append({
                'type': 'CONCENTRATION',
                'severity': 'MEDIUM',
                'hhi': hhi,
                'limit': self.limits['max_hhi']
            })
 
    def check_var(self):
        """Check VaR against limits"""
        var = self.portfolio.calculate_var()
        var_pct = var / self.portfolio.value
 
        if var_pct > self.limits['max_var_pct']:
            self.alerts.append({
                'type': 'VAR_BREACH',
                'severity': 'HIGH',
                'var': var,
                'var_pct': var_pct
            })
 
    def run_stress_tests(self):
        """Run stress scenarios"""
        scenarios = self.limits['stress_scenarios']
        results = self.portfolio.stress_test(scenarios)
 
        for scenario, loss in results.items():
            if loss > self.limits['max_stress_loss']:
                self.alerts.append({
                    'type': 'STRESS_TEST_FAIL',
                    'severity': 'CRITICAL',
                    'scenario': scenario,
                    'loss': loss
                })
 
    def generate_report(self):
        """Generate formatted report"""
        report = {
            'timestamp': datetime.now(),
            'portfolio_value': self.portfolio.value,
            'alerts': self.alerts,
            'risk_metrics': self.portfolio.calculate_all_metrics()
        }
        return report
 
# Usage
limits = {
    'greeks': {'delta': (-500, 500), 'gamma': (-100, 100)},
    'max_hhi': 0.30,
    'max_var_pct': 0.05,
    'max_stress_loss': 50000
}
 
monitor = RiskMonitor(portfolio, limits)
daily_report = monitor.check_all_risks()
 
if daily_report['alerts']:
    print("⚠️ RISK ALERTS:")
    for alert in daily_report['alerts']:
        print(f"  [{alert['severity']}] {alert['type']}: {alert}")

Practice Exercises

Exercise 1: VaR Calculation

Scenario: Your portfolio is worth $250,000 with daily volatility of 4%.

Questions:

  1. Calculate 95% VaR (1-day)
  2. Calculate 99% VaR (1-day)
  3. Calculate 95% VaR (10-day)
  4. Interpret each result
Solution

1. VaR (95%, 1-day):

VaR = Portfolio × σ × Z
    = $250,000 × 4% × 1.65
    = $16,500

Interpretation: 95% confident we won't lose more than $16,500 tomorrow

2. VaR (99%, 1-day):

VaR = $250,000 × 4% × 2.33
    = $23,300

Interpretation: 99% confident we won't lose more than $23,300 tomorrow
(But 1% of the time—about 2.5 trading days/year—we'll lose more)

3. VaR (95%, 10-day):

VaR = $250,000 × 4% × 1.65 × √10
    = $16,500 × 3.16
    = $52,140

Interpretation: Over a 2-week period, 95% confident loss won't exceed $52,140

4. Key Insights:

  • VaR scales with √time (10-day VaR ≠ 10× 1-day VaR)
  • Higher confidence = higher VaR
  • These are parametric VaR (assume normal distribution—crypto is NOT normal!)
  • Real tail risk likely higher than calculated

Exercise 2: Position Sizing

Scenario:

  • Account size: $100,000
  • Risk tolerance: 3% per trade
  • You want to buy ATM straddles on Bitcoin
  • Each straddle costs $5,000

Questions:

  1. How many straddles should you buy?
  2. What if you use 2x leverage?
  3. What’s your max loss?
Solution

1. Position Size (No Leverage):

Risk per trade = $100,000 × 3% = $3,000
Max risk per straddle = $5,000 (paid premium)

Position size = $3,000 / $5,000 = 0.6 straddles
Round down to 0 straddles

Alternative: Increase risk tolerance to 5%
$5,000 / $5,000 = 1 straddle ✓

2. With 2x Leverage:

Effective capital = $100,000 × 2 = $200,000
Risk per trade = $200,000 × 3% = $6,000

Position size = $6,000 / $5,000 = 1.2 straddles
Round to 1 straddle

But remember: Leverage amplifies losses!

3. Max Loss:

Without leverage: $5,000 (premium paid)
With leverage: $5,000 + interest costs

Since long options have defined risk (premium), max loss is known
This is why long options are safer than short options for leverage

Exercise 3: Stress Test Analysis

Scenario: Portfolio:

  • Long 3 BTC at $50,000 = $150,000
  • Short 5 BTC puts ($45k strike) collected $2,000 each = $10,000 credit

Questions:

  1. What’s your max profit potential?
  2. Calculate P&L if BTC drops to $40,000
  3. At what price do you lose 50% of initial capital?
  4. Should you hedge?
Solution

1. Max Profit:

Unlimited upside from long BTC
Best case for puts: Expire worthless (keep $10k credit)

Max profit: Unlimited (as BTC rises)
Collected income: $10,000

2. BTC at $40,000 P&L:

Long BTC: 3 × ($40k - $50k) = -$30,000
Short puts: 5 × ($45k - $40k) = -$25,000 (in-the-money)
Less premium: +$10,000

Total P&L = -$30,000 - $25,000 + $10,000 = -$45,000

Loss: $45,000 on $160,000 initial = -28% 😬

3. 50% Loss Point:

Initial capital: $160,000
50% loss: $80,000

Need: -$80,000 = 3×(P - 50k) - 5×max(0, 45k - P) + 10k

Solving:
If P < $45k:
-80k = 3×(P - 50k) - 5×(45k - P) + 10k
-80k = 3P - 150k - 225k + 5P + 10k
-80k = 8P - 365k
8P = 285k
P = $35,625

At $35,625, you've lost 50% of capital (DANGER ZONE!)

4. Should You Hedge?:

YES! Here's why:
- Exposed to 20% drop before 50% loss
- Bitcoin commonly moves 20-40%
- Short puts without protection = disaster potential

Recommended hedges:
1. Buy OTM puts at $40k (tail protection)
2. Reduce short put position (cut exposure)
3. Sell some long BTC (reduce concentration)

Cost: $2,000-$3,000 for $40k puts
Benefit: Caps max loss at ~25% instead of potential wipeout

Key Takeaways

  1. Survival > Performance

    • Staying in the game is #1 priority
    • One catastrophic loss can erase years of gains
    • Risk management is not optional
  2. Know Your Risk

    • VaR quantifies normal risk
    • Stress tests quantify catastrophic risk
    • Both are necessary
  3. Position Sizing is Everything

    • Never risk more than 2-5% per trade
    • Size by max loss, not credit received
    • Kelly Criterion provides mathematical framework
  4. Greeks Tell You Everything

    • Portfolio delta: Directional exposure
    • Portfolio gamma: Convexity risk
    • Portfolio theta: Time decay impact
    • Portfolio vega: Volatility exposure
    • Monitor and set limits for each
  5. Diversification is Real

    • Don’t put >20% in any single position
    • Low correlation assets provide true diversification
    • But correlations → 1.0 in crises!
  6. Liquidity Matters

    • Can’t profit if you can’t exit
    • Check bid-ask spreads and market depth
    • Size positions relative to liquidity
  7. Leverage Kills

    • LTCM: 100x leverage → bankruptcy
    • Archegos: 10x leverage → $20B loss
    • Keep leverage <2-3x maximum
  8. Stress Test Everything

    • Historical scenarios (COVID, 2008)
    • Custom scenarios (regulation, black swans)
    • Reverse stress test: “What blows me up?”
  9. Risk-Adjusted Returns > Absolute Returns

    • Sharpe ratio: Risk per unit return
    • Sortino: Penalize only downside
    • Calmar: Return vs max drawdown
    • Optimize for risk-adjusted, not absolute
  10. Automate Monitoring

    • Daily risk reports
    • Automated limit checks
    • Alert systems for violations
    • Discipline beats discretion

Final Thoughts

Risk Management Hierarchy:

Level 1 (Beginner): Don't blow up
- Use stop losses
- Never risk &gt;5% per trade
- Understand max loss

Level 2 (Intermediate): Quantify risk
- Calculate VaR
- Monitor Greeks
- Track correlations

Level 3 (Advanced): Optimize risk
- Risk parity allocation
- Dynamic hedging
- Tail risk management
- Kelly sizing

Level 4 (Professional): Portfolio construction
- Multi-dimensional risk budgeting
- Stress testing infrastructure
- Real-time risk monitoring
- Automated compliance

Start Simple:

  1. Set position size limits (start with 2% per trade)
  2. Calculate portfolio Greeks daily
  3. Run weekly stress tests
  4. Measure Sharpe ratio monthly
  5. Increase sophistication gradually

Remember: The goal isn’t to eliminate risk—it’s to take calculated risks that you can survive and profit from over the long term. Master risk management, and you’ll outlast 95% of traders who eventually blow up.


Next Steps

Master Prerequisites:

Related Advanced Topics:

Practical Application:

Real-World Learning:

  • Case Studies - Learn from failures
  • Study historical crises (2008, 2020, LTCM, Archegos)
  • Paper trade with strict risk limits
  • Build your own risk dashboard

You’ve completed the Advanced Level! You now have institutional-grade knowledge of structured products, volatility trading, exotic options, and professional risk management. The next step is practice: apply these frameworks to real markets, make mistakes with small size, and build the discipline that separates professionals from gamblers.

Welcome to the top 1% of derivatives traders. 🎓

2025 © FORGE Structured Products - Demo Only