Crypto fund risk reporting system development
Crypto funds operate under conditions that traditional risk management simply didn't account for: 24/7 market without circuit breakers, positions simultaneously in on-chain protocols and centralized exchanges, liquidation risks with nonlinear price dependency, counterparty risk of custodian and smart-contract simultaneously. Standard tools (Bloomberg, Advent) don't understand DeFi. You need to build the system from scratch — or adapt existing risk frameworks to crypto reality.
Data sources: where fund positions live
The first and main complexity — aggregation. Fund positions can be in:
CeFi: Binance, OKX, Bybit, Kraken — each exchange has its own API. REST for position snapshots, WebSocket for real-time P&L. Problem: API rate limits, non-standard margin account formats, different models for cross/isolated margin.
DeFi on-chain:
- Lending: Aave v3, Compound v3, Morpho — positions through smart-contract view functions or subgraph
- Perps: GMX, dYdX v4, Hyperliquid — each has its own account model
- LP positions: Uniswap v3 (concentrated liquidity = nonlinear payoff), Curve, Balancer
- Yield: EigenLayer, Pendle (tokenized yield), Convex
- Structured products: Ribbon, Lyra — option strategies on-chain
Custody: Fireblocks, Copper, Anchorage — usually REST API for balances. MPC wallets appear as normal on-chain addresses.
Total: data aggregator is 5-15 different integrations with varying API quality and source reliability.
System architecture
Data layer
[CeFi APIs] [On-chain nodes] [Price feeds]
↓ ↓ ↓
[Kafka / message queue]
↓
[Normalizer Service] ← unified Position, Balance, Trade model
↓
[Time-series DB] ← TimescaleDB or ClickHouse
↓
[Risk Engine] ← metric calculation
↓
[Reporting API + UI]
Normalized position model:
interface Position {
id: string;
fund_id: string;
venue: 'binance' | 'aave_v3' | 'gmx' | string;
venue_type: 'cex' | 'dex_perp' | 'lending' | 'lp' | 'spot';
asset: string; // base asset (ETH, BTC, SOL)
quote_asset: string; // USDT, USDC, USD
size: Decimal; // in base asset
size_usd: Decimal; // USD equivalent
side: 'long' | 'short' | 'neutral';
entry_price?: Decimal;
mark_price: Decimal;
unrealized_pnl_usd: Decimal;
// for lending
health_factor?: Decimal;
liquidation_price?: Decimal;
// for LP
tick_lower?: number;
tick_upper?: number;
in_range?: boolean;
snapshot_ts: Date;
}
Risk Engine: key metrics
Net Delta. Total exposure per base asset accounting for all positions:
delta_ETH = Σ(position.size × sign × delta_multiplier)
For linear positions delta = 1, for options — greeks, for LP in Uniswap v3 — derivative of liquidity function (nonlinearly depends on current price in range).
Portfolio VaR (Value at Risk). Several approaches for crypto:
- Historical simulation — based on actual P&L history for 1-2 years. Problem: bitcoin history is short, crypto correlations unstable (especially in crises).
- Parametric VaR — normal distribution return model. Works poorly for crypto: heavy tails, skew. Used only as grounding estimate.
- Monte Carlo — price path simulation with given volatility and correlation parameters. Most flexible but computationally heavy.
import numpy as np
from scipy import stats
def historical_var(returns: np.ndarray, confidence: float = 0.99) -> float:
"""
returns: daily portfolio returns in USD
confidence: 0.99 → 1% worst case
"""
return -np.percentile(returns, (1 - confidence) * 100)
def conditional_var(returns: np.ndarray, confidence: float = 0.99) -> float:
"""Expected Shortfall / CVaR — average loss worse than VaR"""
var = historical_var(returns, confidence)
tail_returns = returns[returns <= -var]
return -tail_returns.mean() if len(tail_returns) > 0 else var
Stress testing. Scenarios specific to crypto:
| Scenario | Parameters |
|---|---|
| BTC -30% in 24 hours | Historical precedent: May 2021, Nov 2022 |
| Stablecoin depeg | USDC -5%, USDT -10% (like SVB event) |
| DeFi exploit | Instant loss of positions in specific protocol |
| CEX withdrawal halt | FTX scenario: loss of access to CeFi assets |
| Gas spike on Ethereum | > 500 gwei — impossible to close positions |
| Liquidation cascade | Price shock → chained liquidations → flash crash |
Liquidation distance. For each lending position:
def liquidation_distance(
health_factor: Decimal,
liquidation_threshold: Decimal,
collateral_price: Decimal,
) -> dict:
"""
Aave v3 liquidation: health_factor < 1
health_factor = Σ(collateral_i × LT_i) / total_debt
"""
# What price drop triggers liquidation
price_drop_to_liquidation = 1 - (1 / health_factor)
return {
'current_hf': health_factor,
'price_drop_pct': price_drop_to_liquidation * 100,
'liquidation_price': collateral_price * (1 - price_drop_to_liquidation),
}
Concentration risk. Share of each asset/protocol/counterparty in portfolio. Herfindahl-Hirschman Index for concentration:
HHI = Σ(s_i²) where s_i — share of i-th asset
HHI = 1 — full concentration, HHI → 0 — full diversification.
Counterparty risk score. Subjective but necessary metric:
| Counterparty | Factors |
|---|---|
| CeFi exchange | Reserve volume (PoR), regulatory status, history |
| DeFi protocol | TVL, audit history, upgrade mechanism (multisig? timelock?), age |
| Custodian | Insurance coverage, MPC vs multisig, SLA |
Alerts and triggers
Real-time monitoring with thresholds:
alerts:
- name: health_factor_critical
condition: health_factor < 1.2
severity: critical
channels: [telegram, pagerduty]
- name: net_delta_breach
condition: abs(net_delta_usd) > max_allowed_delta
severity: high
- name: var_limit_breach
condition: daily_var > var_limit * portfolio_nav
severity: high
- name: concentration_limit
condition: single_asset_pct > 0.4
severity: medium
- name: exchange_withdrawal_anomaly
condition: cex_balance_change > 0.1 * cex_total
severity: medium
Alert delivery: Telegram Bot API for operational notifications, PagerDuty for critical, email for daily reports.
Reporting
Daily risk report
Structure (automatically generated as PDF or sent to Telegram/email):
- Snapshot NAV — total portfolio value with venue breakdown
- Delta exposure — net exposure per asset
- VaR metrics — 1-day VaR at 95%/99%, CVaR
- Liquidation watchlist — positions with HF < 1.5, distance to liquidation
- Concentration — top-5 assets and protocols by share
- Realized PnL — for day/week/month with strategy attribution
- Stress scenarios — results of standard scenarios
Compliance reporting
For institutional investors (LP) often need:
- ILPA-compliant reports — standard formats for private funds
- Risk disclosure — risk description in plain language for non-technical LP
- Exposure limits compliance — confirmation of investment mandate adherence
If fund is regulated (e.g., through MiCA in EU or as VASP), reporting must comply with regulatory requirements.
Technology stack
| Component | Technology |
|---|---|
| Data ingestion | Python (ccxt for CeFi, web3.py + viem for on-chain) |
| Message queue | Kafka / Redpanda |
| Time-series DB | TimescaleDB (positions) + ClickHouse (trade history) |
| Risk engine | Python (numpy, scipy, pandas) |
| API backend | FastAPI + PostgreSQL |
| Frontend | React + Recharts/TradingView widgets |
| Alerts | Prometheus Alertmanager → Telegram/PagerDuty |
| Reports | WeasyPrint (PDF) / custom HTML templates |
Implementation phases
Phase 1 — Integrations (3-5 weeks). Connect to CeFi API and on-chain sources for fund venues. Normalize into unified position model. Historical backfill.
Phase 2 — Risk engine (2-3 weeks). Delta calculation, VaR, liquidation distance, concentration metrics. Stress tests. Validation on historical data.
Phase 3 — Alerts (1-2 weeks). Real-time monitoring, configurable thresholds, Telegram/PagerDuty integration.
Phase 4 — Reporting UI (2-3 weeks). Portfolio manager dashboard, auto-generated reports, LP export.
Total: 8-13 weeks for fund with standard venue set (2-3 CeFi + 3-5 DeFi protocols). Each new non-standard integration adds 3-7 days.







