How the AI Hedge Fund Risk Manager Calculates Position Limits
The Risk Manager calculates position limits by combining volatility-adjusted portfolio percentages with correlation-based multipliers, then converting the result into a dollar-denominated cap that respects both portfolio value and available cash.
In the virattt/ai-hedge-fund repository, the risk_management_agent enforces capital allocation discipline through a quantitative risk model. This agent determines how much capital can be safely deployed to each ticker by analyzing historical volatility and cross-asset correlations, ensuring no single position or correlated cluster threatens overall portfolio stability.
The Two-Factor Risk Model: Volatility and Correlation
The position limit logic rests on two pillars: volatility-adjusted limits and correlation-based adjustments. High-volatility assets receive smaller allocation percentages, while assets that correlate heavily with existing holdings face additional reduction through a multiplier. This dual approach prevents concentration risk in both volatile individual securities and highly correlated groups.
Step-by-Step Calculation Workflow
The calculation follows a rigorous pipeline defined in src/agents/risk_manager.py, processing market data through eleven distinct stages before emitting a tradable limit.
Data Collection and Volatility Metrics
First, the agent gathers historical price data for every ticker in the watchlist and all currently held positions. In src/agents/risk_manager.py at lines 27-36, the system iterates through all_tickers to fetch prices via get_prices and stores the latest close price for each symbol.
At line 54, the system computes volatility_metrics by calling calculate_volatility_metrics(prices_df), which returns daily volatility, annualized volatility, a percentile rank, and the count of data points. These metrics form the foundation for the volatility-adjusted limit calculation.
Correlation Matrix Construction
To assess diversification benefits, the agent builds a correlation matrix from close-to-close daily returns. Lines 81-84 in src/agents/risk_manager.py construct returns_df = pd.DataFrame(returns_by_ticker).dropna(), creating a pandas correlation matrix when two or more tickers have return histories. This matrix enables the system to detect when new positions would increase portfolio-wide correlation risk.
Portfolio Valuation
The agent calculates the Net Liquidation Value by combining cash with the market value of all long and short positions using the latest prices. This occurs at lines 94-102: total_portfolio_value = portfolio.get("cash", 0.0) plus the summed value of all positions. This total serves as the baseline for percentage-based limit calculations.
Risk Adjustments and Limit Calculation
The core logic applies two sequential adjustments:
-
Volatility Adjustment: The function
calculate_volatility_adjusted_limit(lines 70-99) maps the ticker's annualized volatility to a portfolio allocation percentage. Low volatility assets receive higher percentages; high volatility assets receive lower percentages. -
Correlation Adjustment: Using the correlation matrix from earlier, the agent computes the average correlation between the target ticker and currently active positions (lines 140-162). The
calculate_correlation_multiplierfunction (lines 301-317) transforms this average into a multiplier where high correlation yields a lower multiplier, reducing the allowable position size.
At line 164, these factors combine: combined_limit_pct = vol_adjusted_limit_pct * corr_multiplier. The dollar limit is calculated at line 166: position_limit = total_portfolio_value * combined_limit_pct.
Cash and Position Enforcement
The final steps ensure practical tradability. At line 169, the agent calculates remaining_position_limit = position_limit - current_position_value, subtracting the absolute exposure of existing longs and shorts. Finally, at lines 172-173, the agent enforces the cash constraint by setting the final allowable size to the smaller of the remaining limit and available cash.
Key Implementation Details in risk_manager.py
The risk management agent stores comprehensive diagnostics for each ticker. Lines 174-195 populate a dictionary containing the calculated limit, current price, volatility metrics, correlation data, and human-readable reasoning.
To execute the risk manager within the system:
from src.agents.risk_manager import risk_management_agent
# state is the shared AgentState defined in src/graph/state.py
result = risk_management_agent(state)
# Access per-ticker risk analysis
risk_analysis = result["data"]["analyst_signals"]["risk_management_agent"]
for ticker, info in risk_analysis.items():
print(f"{ticker}:")
print(f" • Remaining position limit: ${info['remaining_position_limit']:.0f}")
print(f" • Annualized volatility: {info['volatility_metrics']['annualized_volatility']:.1%}")
print(f" • Correlation multiplier: {info['reasoning']['correlation_multiplier']:.2f}")
print(f" • Adjustment rationale: {info['reasoning']['risk_adjustment']}")
This output reveals exactly how much additional exposure is permitted and whether volatility or correlation drove the constraint.
Summary
- The Risk Manager in
virattt/ai-hedge-fundimplements a volatility-adjusted, correlation-aware position sizing system insrc/agents/risk_manager.py. - Volatility metrics computed via
calculate_volatility_metricsinversely scale the base allocation percentage—high volatility reduces the limit. - Correlation multipliers from
calculate_correlation_multiplierfurther reduce limits for assets that move with existing holdings. - The final dollar limit respects both the Net Liquidation Value and available cash constraints.
- All calculations include full audit trails stored in the agent state for transparency and debugging.
Frequently Asked Questions
How does the Risk Manager handle single-stock portfolios?
When only one ticker exists in the portfolio, the correlation matrix cannot be constructed. In this case, the correlation multiplier defaults to neutral (1.0), and the position limit depends solely on volatility adjustments and cash constraints.
What happens if a stock's volatility is extremely high?
High annualized volatility triggers an aggressive reduction in the base allocation percentage through calculate_volatility_adjusted_limit (lines 70-99). The function maps volatility percentiles to allocation caps, ensuring high-beta assets never receive disproportionate capital regardless of available cash.
Does the correlation calculation distinguish between long and short positions?
The correlation adjustment uses absolute exposure values when calculating average correlations (lines 140-162), meaning the directional exposure matters less than the magnitude of correlation. Highly correlated shorts and longs both trigger the multiplier reduction to prevent net exposure concentration in similar risk factors.
Where is the final position limit stored after calculation?
The final remaining_position_limit and all intermediate metrics are stored in the risk_analysis dictionary within AgentState, specifically at result["data"]["analyst_signals"]["risk_management_agent"] as implemented in lines 174-195 of src/agents/risk_manager.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →