Master essential risk management techniques to protect your capital and minimize losses in MEV trading
By the end of this course, you will be able to:
Calculate optimal position sizes using the Kelly Criterion and risk management principles
Real-time monitoring of your portfolio risk metrics
import numpy as np
import pandas as pd
from typing import Dict, List, Tuple
class PortfolioRiskManager:
def __init__(self, initial_balance: float, max_drawdown: float = 0.15):
self.initial_balance = initial_balance
self.current_balance = initial_balance
self.peak_balance = initial_balance
self.max_drawdown = max_drawdown
self.positions = {}
self.trade_history = []
self.daily_pnl = []
def calculate_position_size(self,
account_balance: float,
risk_percentage: float,
win_rate: float,
win_loss_ratio: float) -> float:
"""Calculate position size using Kelly Criterion"""
if win_rate <= 0 or win_loss_ratio <= 0:
return 0
# Kelly Criterion formula
kelly_percentage = (win_rate * win_loss_ratio - (1 - win_rate)) / win_loss_ratio
kelly_percentage = max(0, min(kelly_percentage, 0.25)) # Cap at 25%
# Apply risk management multiplier (typically 0.25 of Kelly)
position_risk = kelly_percentage * 0.25 * risk_percentage / 100
return account_balance * position_risk
def check_risk_limits(self, proposed_position_size: float) -> Tuple[bool, str]:
"""Check if proposed position meets risk criteria"""
max_position = self.current_balance * 0.1 # Max 10% per position
max_portfolio_risk = self.current_balance * 0.02 # Max 2% total risk
if proposed_position_size > max_position:
return False, f"Position size exceeds 10% of portfolio (${max_position:,.2f})"
if self.get_total_exposure() + proposed_position_size > max_portfolio_risk:
return False, "Total portfolio risk would exceed 2%"
return True, "Position approved"
def update_drawdown(self, new_balance: float):
"""Update current drawdown metrics"""
self.current_balance = new_balance
self.peak_balance = max(self.peak_balance, new_balance)
current_drawdown = (self.peak_balance - new_balance) / self.peak_balance
if current_drawdown > self.max_drawdown:
raise ValueError(f"Maximum drawdown exceeded: {current_drawdown:.2%}")
return current_drawdown
def get_risk_metrics(self) -> Dict:
"""Calculate comprehensive risk metrics"""
total_exposure = self.get_total_exposure()
current_drawdown = (self.peak_balance - self.current_balance) / self.peak_balance
# Calculate Sharpe ratio (simplified)
if len(self.daily_pnl) > 1:
returns = np.array(self.daily_pnl)
sharpe_ratio = np.mean(returns) / np.std(returns) * np.sqrt(365) if np.std(returns) > 0 else 0
else:
sharpe_ratio = 0
# Value at Risk (95% confidence)
var_95 = np.percentile(self.daily_pnl, 5) if self.daily_pnl else 0
return {
'total_exposure': total_exposure,
'current_drawdown': current_drawdown,
'portfolio_utilization': total_exposure / self.current_balance,
'sharpe_ratio': sharpe_ratio,
'var_95': var_95,
'max_drawdown_limit': self.max_drawdown
}
def get_total_exposure(self) -> float:
"""Calculate total portfolio exposure"""
return sum(abs(position.get('value', 0)) for position in self.positions.values())
# Usage Example
risk_manager = PortfolioRiskManager(initial_balance=10000, max_drawdown=0.15)
# Calculate optimal position size
position_size = risk_manager.calculate_position_size(
account_balance=10000,
risk_percentage=2,
win_rate=0.7,
win_loss_ratio=1.5
)
# Check risk limits
approved, message = risk_manager.check_risk_limits(position_size)
print(f"Position size: ${position_size:,.2f}")
print(f"Risk check: {message}")
# Get current risk metrics
metrics = risk_manager.get_risk_metrics()
print(f"Current drawdown: {metrics['current_drawdown']:.2%}")
print(f"Sharpe ratio: {metrics['sharpe_ratio']:.2f}")
print(f"VaR (95%): ${metrics['var_95']:,.2f}")