← Back to Skills Marketplace
zhaocaixia888

Portfolio Risk Manager

by zhaocaixia888 · GitHub ↗ · v1.0.3 · MIT-0
cross-platform ✓ Security Clean
46
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install zcx-portfolio-risk-manager
Description
Calculate portfolio risk metrics — Value at Risk (VaR), Sharpe ratio, max drawdown, correlation matrix, position sizing, and scenario analysis. Supports mult...
README (SKILL.md)

Portfolio Risk Manager — 投资组合风险管理

Calculate key risk metrics for multi-asset portfolios using pure math (no third-party financial libraries). Supports equities, crypto, futures, and mixed portfolios.

Risk Metrics

1. Value at Risk (VaR)

Historical simulation — the worst expected loss over a given confidence level and time horizon.

import numpy as np

def calculate_var(returns, confidence=0.95):
    """Historical VaR."""
    sorted_returns = np.sort(returns)
    index = int((1 - confidence) * len(sorted_returns))
    return sorted_returns[index]

def calculate_cvar(returns, confidence=0.95):
    """Conditional VaR (Expected Shortfall) — average of losses beyond VaR."""
    sorted_returns = np.sort(returns)
    index = int((1 - confidence) * len(sorted_returns))
    tail = sorted_returns[:index]
    return np.mean(tail) if len(tail) > 0 else sorted_returns[0]

Interpretation:

  • 95% VaR of -2% → 5% chance of losing >2% in a day
  • CVaR is stricter than VaR (looks at the tail, not just the threshold)

2. Sharpe Ratio

Risk-adjusted return measure. Annualized.

def sharpe_ratio(returns, risk_free_rate=0.05, periods_per_year=252):
    """Annualized Sharpe Ratio."""
    excess = np.mean(returns) - risk_free_rate / periods_per_year
    return excess / np.std(returns) * np.sqrt(periods_per_year) if np.std(returns) > 0 else 0

def sortino_ratio(returns, risk_free_rate=0.05, periods_per_year=252):
    """Sortino Ratio — only penalizes downside volatility."""
    excess = np.mean(returns) - risk_free_rate / periods_per_year
    downside = np.std(returns[returns \x3C 0]) if np.any(returns \x3C 0) else 0.001
    return excess / downside * np.sqrt(periods_per_year)

Interpretation:

Sharpe Rating
> 2.0 Excellent
1.0 - 2.0 Good
0.5 - 1.0 Average
\x3C 0.5 Poor
\x3C 0 Underperforming risk-free

3. Maximum Drawdown

Largest peak-to-trough decline.

def max_drawdown(prices):
    """Calculate max drawdown from price series."""
    peak = np.maximum.accumulate(prices)
    drawdown = (prices - peak) / peak
    max_dd = np.min(drawdown)
    # Also return duration: how long to recover
    trough_idx = np.argmin(drawdown)
    recovery_idx = np.argmax(prices[trough_idx:] >= prices[:len(prices)-trough_idx][0])
    recovery_days = recovery_idx if recovery_idx > 0 else None
    return {"drawdown": max_dd, "trough_index": trough_idx, "recovery_days": recovery_days}

4. Correlation Matrix

def correlation_matrix(returns_dict):
    """Correlation matrix from multiple return series."""
    assets = list(returns_dict.keys())
    n = len(assets)
    matrix = np.ones((n, n))
    for i in range(n):
        for j in range(i+1, n):
            r = np.corrcoef(returns_dict[assets[i]], returns_dict[assets[j]])[0, 1]
            matrix[i, j] = round(r, 3)
            matrix[j, i] = round(r, 3)
    return {"assets": assets, "matrix": matrix}

Interpretation: Correlation of 1 = move together, -1 = move opposite, 0 = no relationship. During crises, correlations converge toward 1 (everything sells off together).

5. Position Sizing (Kelly Criterion)

def kelly_criterion(win_rate, avg_win, avg_loss):
    """Full Kelly — aggressive. Most traders use fractional Kelly."""
    b = avg_win / abs(avg_loss) if avg_loss != 0 else 1
    p = win_rate
    q = 1 - p
    full_kelly = (p * b - q) / b if b > 0 else 0
    return {
        "full_kelly": max(0, full_kelly),
        "quarter_kelly": max(0, full_kelly * 0.25),
        "half_kelly": max(0, full_kelly * 0.5),
    }

6. Scenario Analysis

def scenario_analysis(positions, scenario_returns):
    """Analyze portfolio under different market scenarios.
    
    positions: {"BTC": 50000, "ETH": 30000, "CASH": 20000}
    scenario_returns: {"crash": {"BTC": -0.3, "ETH": -0.4, "CASH": 0},
                       "rally": {"BTC": 0.2, "ETH": 0.25, "CASH": 0}}
    """
    results = {}
    for scenario, returns in scenario_returns.items():
        pnl = 0
        for asset, exposure in positions.items():
            if asset in returns:
                pnl += exposure * returns[asset]
        total = sum(positions.values())
        results[scenario] = {"pnl": round(pnl, 2), "return_pct": round(pnl / total * 100, 2) if total > 0 else 0}
    return results

Complete Usage Example

import numpy as np

# Daily returns for 3 assets (1 year = 252 days)
portfolio = {
    "BTC": np.random.normal(0.001, 0.03, 252),
    "ETH": np.random.normal(0.001, 0.04, 252),
    "BOND": np.random.normal(0.0003, 0.005, 252),
}
weights = {"BTC": 0.5, "ETH": 0.3, "BOND": 0.2}
portfolio_returns = sum(weights[a] * portfolio[a] for a in weights)

print(f"95% VaR: {calculate_var(portfolio_returns):.2%}")
print(f"CVaR:    {calculate_cvar(portfolio_returns):.2%}")
print(f"Sharpe:  {sharpe_ratio(portfolio_returns):.2f}")
print(f"Sortino: {sortino_ratio(portfolio_returns):.2f}")

# Simulated price series
prices = 100 * np.exp(np.cumsum(portfolio_returns))
dd = max_drawdown(prices)
print(f"Max DD:  {dd['drawdown']:.2%}  (recovery: {dd['recovery_days'] or 'N/A'} days)")

print(f"Correlation:\
{correlation_matrix(portfolio)}")

# Scenario analysis
scenarios = {
    "crash": {"BTC": -0.3, "ETH": -0.4, "BOND": 0.02},
    "mild_dip": {"BTC": -0.05, "ETH": -0.08, "BOND": 0.01},
    "rally": {"BTC": 0.15, "ETH": 0.2, "BOND": -0.02},
}
positions = {"BTC": 50000, "ETH": 30000, "BOND": 20000}
print(f"Scenario: {scenario_analysis(positions, scenarios)}")

Format Output

📊 投资组合风险报告

组合总值: $100,000
持仓: BTC 50% | ETH 30% | BOND 20%

🛡️ 风险指标
• VaR (95%):    -2.3%  → 日最大亏损 $2,300
• CVaR (95%):   -3.1%  → 尾部平均亏损 $3,100
• VaR (99%):    -3.8%  → 日最大亏损 $3,800
• Sharpe:        1.25  🟢
• Sortino:       1.52  🟢 (更好,只看下行)
• 最大回撤:     -15.4%  (恢复期: 45天)

🔗 相关性矩阵
        BTC    ETH   BOND
BTC     1.00   0.65  0.10
ETH     0.65   1.00  0.08
BOND    0.10   0.08  1.00

📈 情景分析
• 崩盘 (-30%):   PnL -$27,000 (-27.0%) 🔴
• 温和回调 (-5%): PnL -$4,900 (-4.9%)  🟡
• 大涨 (+15%):   PnL +$13,500 (+13.5%) 🟢

💰 仓位建议 (Kelly)
• BTC:  35% (全Kelly)  → 17.5% (半Kelly)  → 8.7% (¼Kelly)
• ETH:  20% → 10% → 5%
• 现金: 45% → 72.5% → 86.3%

⚠️ 回测不代表未来,Kelly建议保守使用半仓或¼仓

Notes

  • All calculations use NumPy only — no external financial libraries needed
  • Historical VaR/CVaR assumes past patterns persist (they often don't in crises)
  • Kelly Criterion is aggressive — most professional traders use fractional Kelly (25-50%)
  • Correlation is NOT constant — it spikes during market stress (correlations converge to 1)
  • Sortino > Sharpe when returns are asymmetric (typical in options trading)
  • Always stress-test with scenario analysis — don't rely on VaR alone
Usage Guidance
Safe to install from a security perspective. Use care with private portfolio data, verify formulas before relying on outputs, and treat the results as educational risk analysis rather than financial advice.
Capability Tags
crypto
Capability Assessment
Purpose & Capability
The stated purpose is portfolio risk analysis, and the artifact content matches that purpose with formulas and NumPy examples for VaR, CVaR, Sharpe, Sortino, drawdown, correlations, Kelly sizing, and scenarios.
Instruction Scope
Instructions are limited to user-directed calculations and report formatting; there are no role overrides, hidden commands, unrelated data requests, or automatic actions.
Install Mechanism
The package contains only SKILL.md, declares no required binaries, and includes no executable scripts or install-time behavior.
Credentials
The skill may handle user-supplied portfolio positions or return data, which can be financially sensitive, but that data use is expected for the stated risk-analysis purpose.
Persistence & Privilege
No persistence, background workers, privilege escalation, credential handling, local indexing, API calls, or network behavior are present.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install zcx-portfolio-risk-manager
  3. After installation, invoke the skill by name or use /zcx-portfolio-risk-manager
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.3
Initial release on ClawHub
Metadata
Slug zcx-portfolio-risk-manager
Version 1.0.3
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Portfolio Risk Manager?

Calculate portfolio risk metrics — Value at Risk (VaR), Sharpe ratio, max drawdown, correlation matrix, position sizing, and scenario analysis. Supports mult... It is an AI Agent Skill for Claude Code / OpenClaw, with 46 downloads so far.

How do I install Portfolio Risk Manager?

Run "/install zcx-portfolio-risk-manager" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Portfolio Risk Manager free?

Yes, Portfolio Risk Manager is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Portfolio Risk Manager support?

Portfolio Risk Manager is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Portfolio Risk Manager?

It is built and maintained by zhaocaixia888 (@zhaocaixia888); the current version is v1.0.3.

💬 Comments