Source profileQuality 90/100

HKUDS/Vibe-Trading/agent/src/skills/risk-analysis/SKILL.md

risk-analysis

Risk measurement and stress testing — VaR/CVaR/max drawdown calculation, Monte Carlo simulation, extreme-value tail-risk analysis, and historical scenario stress testing.

Source repository stars
31,714
Declared platforms
0
Static risk flags
0
Last source update
2026-08-25
Source checked
2026-08-26

Decision brief

What it does: where it fits

Risk measurement and stress testing — VaR/CVaR/max drawdown calculation, Monte Carlo simulation, extreme-value tail-risk analysis, and historical scenario stress testing.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/HKUDS/Vibe-Trading --skill "agent/src/skills/risk-analysis"
    Safe inspection promptEditorial

    Inspect the Agent Skill "risk-analysis" from https://github.com/HKUDS/Vibe-Trading/blob/5cd08ee1bd5c28e856b20acae3d077ed9bd919ce/agent/src/skills/risk-analysis/SKILL.md at commit 5cd08ee1bd5c28e856b20acae3d077ed9bd919ce. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Stress-Test Implementation Steps

      1. Select a scenario: either historical or hypothetical 2. Apply shocks: multiply scenario shocks by the current positions 3. Compute portfolio loss: portfolioloss = Σ(weighti × shocki × positioni) 4. Assess adequacy: compare loss vs risk budget and whether stop-loss thresholds…

      Select a scenario: either historical or hypotheticalApply shocks: multiply scenario shocks by the current positionsCompute portfolio loss: portfolioloss = Σ(weighti × shocki × positioni)
    2. 02

      Sign convention

      A loss is a positive number, uniformly, across every function in the module:

      A loss is a positive number, uniformly, across every function in the module:Quantities that are returns rather than losses keep their natural sign and are named return (meanreturn, worst5pctreturn, best5pctreturn), so a bad outcome there is negative. Report VaR to the user with the sign the use…cvar = var holds by construction whenever both come from the same sample at the same confidence level. If you ever compute a CVaR below its VaR, the tail mask is wrong.
    3. 03

      Risk Measurement Methods

      Definition: the maximum expected loss over a given horizon at a specified confidence level.

      Recovery means reaching the peak value again, not merely bouncing off the trough; recoverydate is None and recovered is False if it never happens.underwaterdays / recoverydays are calendar days and require a DatetimeIndex; on any other index they come back None and you should use the periods counts, which are always populated.Non-positive equity raises — a drawdown ratio is undefined at or below zero. Rebase a signed PnL series to a positive net value first.
    4. 04

      1. VaR (Value at Risk)

      Definition: the maximum expected loss over a given horizon at a specified confidence level.

      Definition: the maximum expected loss over a given horizon at a specified confidence level.Reads the loss straight off the sorted sample, so it inherits whatever fat tails the history actually had. horizon scales by the square-root-of-time rule, which is only valid under i.i.d. returns.The quantile is a non-interpolating lower order statistic: element ceil((1 - confidence) n) - 1 of the ascending-sorted returns, negated. The result is therefore always a return that was actually observed, never a blend…
    5. 05

      Three Calculation Methods

      Review the “Three Calculation Methods” section in the pinned source before continuing.

      Review and apply the “Three Calculation Methods” source section.

    Permission review

    Static risk signals and limitations

    No configured static risk pattern was detected

    This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars31,714SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    HKUDS/Vibe-Trading
    Skill path
    agent/src/skills/risk-analysis/SKILL.md
    Commit
    5cd08ee1bd5c28e856b20acae3d077ed9bd919ce
    License
    MIT
    Collected
    2026-08-26
    Default branch
    main
    View the original SKILL.md

    Risk Measurement and Stress Testing

    Overview

    Systematic risk-measurement methodology covering VaR/CVaR calculation, Monte Carlo simulation, stress-test design, and tail-risk analysis. It provides risk evaluation for backtest results and risk-control constraints for asset allocation.

    The measures below are implemented once, with tests, in src/quantlib/risk.py. Call them; do not retype the formulas, because a hand-retyped VaR is where the sign convention silently flips.

    from src.quantlib.risk import (
        historical_var, parametric_var, historical_cvar,
        max_drawdown_analysis, monte_carlo_gbm, analyze_mc_results, fit_gpd_tail,
    )
    

    Sign convention

    A loss is a positive number, uniformly, across every function in the module:

    ValueReads as
    historical_var(...) == 0.028a 2.8% loss
    historical_cvar(...) == 0.042a 4.2% average loss in the tail
    max_drawdown_analysis(...)["max_drawdown"] == 0.325a 32.5% peak-to-trough decline
    analyze_mc_results(...)["var"] == 0.224a 22.4% loss

    Quantities that are returns rather than losses keep their natural sign and are named *_return (mean_return, worst_5pct_return, best_5pct_return), so a bad outcome there is negative. Report VaR to the user with the sign the user expects, but never re-derive it — flip it at the presentation layer only.

    cvar >= var holds by construction whenever both come from the same sample at the same confidence level. If you ever compute a CVaR below its VaR, the tail mask is wrong.

    This is not cvar >= var >= 0. The magnitudes are never clipped, so a sample whose tail contains no actual loss reports a negative loss — a gain. That is deliberate and informative; do not assert non-negativity on a VaR and do not clip it, or you destroy the distinction between "small loss" and "no loss at all".

    Risk Measurement Methods

    1. VaR (Value at Risk)

    Definition: the maximum expected loss over a given horizon at a specified confidence level.

    Three Calculation Methods

    MethodFormula / StepsAdvantagesDisadvantages
    Historical simulationSort historical returns and take the quantileNo distribution assumptionDepends on historical samples
    Parametric (normal)VaR = μ - z_α × σEasy to computeAssumes a normal distribution
    Monte CarloSimulate N paths and take the quantileFlexibleComputationally intensive

    Historical Simulation

    Reads the loss straight off the sorted sample, so it inherits whatever fat tails the history actually had. horizon scales by the square-root-of-time rule, which is only valid under i.i.d. returns.

    historical_var(returns, confidence=0.95)              # 1-day 95% VaR
    historical_var(returns, confidence=0.99, horizon=10)  # 10-day 99% VaR
    

    The quantile is a non-interpolating lower order statistic: element ceil((1 - confidence) * n) - 1 of the ascending-sorted returns, negated. The result is therefore always a return that was actually observed, never a blend of two neighbours.

    Parametric (normal)

    parametric_var(returns, confidence=0.95)
    

    Fits mu and the sample sigma (ddof=1) and returns -(mu + z*sigma) with z = norm.ppf(1 - confidence). Needs at least 2 observations.

    Do not assume the parametric figure is the lower one. The direction of the gap depends on the confidence level. A fat tail inflates the fitted sigma, which pushes the normal quantile outward at moderate confidence, where the empirical quantile is still sitting in the well-behaved body. Measured over 300 t(4) samples of 750 daily returns:

    ConfidenceParametric reads above historical
    90%100% of samples
    95%92.7%
    97.5%40.3%
    99%5.3%

    So the familiar "parametric understates risk" result only appears at 99% and deeper. At the 95% default it is normally the higher of the two, and that is not a sign your code is wrong. Quote both at 99% when the point is to expose the tail.

    2. CVaR / ES (Conditional VaR / Expected Shortfall)

    Definition: the average loss beyond the VaR threshold, more conservative than VaR.

    historical_cvar(returns, confidence=0.95)
    historical_cvar(returns, confidence=0.99, horizon=10)
    

    Averages the VaR order statistic together with everything worse than it (inclusive), which is the standard expected shortfall and is what makes cvar >= var structural rather than incidental.

    VaR vs CVaR comparison:

    MetricVaR(95%)CVaR(95%)Meaning
    Typical value2.1%3.4%CVaR is usually 1.3-1.8x VaR
    SubadditivityNot satisfiedSatisfiedCVaR can be used for portfolio risk decomposition
    RegulationBasel IIBasel IIIRegulatory trend is shifting toward CVaR

    3. Maximum Drawdown Analysis

    dd = max_drawdown_analysis(equity)   # equity = a strictly positive net-value Series
    dd["max_drawdown"]        # 0.325 -> fell 32.5% below its running peak (POSITIVE)
    dd["peak_date"], dd["trough_date"], dd["recovery_date"]
    dd["recovered"]           # False when the series ends still underwater
    

    Full return keys: max_drawdown, peak_date, trough_date, recovery_date, recovered, peak_to_trough_periods, trough_to_recovery_periods, underwater_days, recovery_days.

    • Recovery means reaching the peak value again, not merely bouncing off the trough; recovery_date is None and recovered is False if it never happens.
    • underwater_days / recovery_days are calendar days and require a DatetimeIndex; on any other index they come back None and you should use the *_periods counts, which are always populated.
    • Non-positive equity raises — a drawdown ratio is undefined at or below zero. Rebase a signed PnL series to a positive net value first.

    4. Monte Carlo Simulation

    Geometric Brownian Motion (GBM)

    paths = monte_carlo_gbm(
        s0=100.0, mu=0.10, sigma=0.20,   # mu/sigma are ANNUALISED
        n_steps=252, n_paths=10_000,
        seed=42,                          # keyword-only; required for a reproducible run
    )
    paths.shape        # (10000, 253) -- n_steps + 1 columns
    paths[:, 0]        # exactly s0 on every path
    

    Always pass seed. It is keyword-only so it cannot be supplied by accident, and leaving it None draws fresh OS entropy — the run is then unreproducible and the numbers in your report cannot be regenerated. Use steps_per_year if the step is not a 252-day trading day.

    Column 0 is the starting price, so paths[:, -1] / paths[:, 0] - 1 is the total return over the whole simulation. Terminal expectation is s0 * exp(mu * n_steps / steps_per_year); the median sits lower, at s0 * exp((mu - 0.5*sigma**2) * T), and that gap is the volatility drag, not a bug.

    Simulation Result Analysis

    summary = analyze_mc_results(paths, confidence=0.95)
    summary["var"], summary["cvar"]                 # positive loss magnitudes
    summary["mean_return"], summary["prob_loss"]
    summary["worst_5pct_return"], summary["best_5pct_return"]   # signed returns
    

    var / cvar are computed with exactly the same order-statistic convention as historical_var / historical_cvar, so a simulated VaR and a historical VaR are directly comparable.

    Stress-Testing Framework

    Historical Scenario Stress Tests

    ScenarioPeriodChina A-share DrawdownUS Equity DrawdownBTC Drawdown10Y Government Bonds
    2008 financial crisis2008.01-2008.10-65%-50%N/Ayield ↓ 100bp
    2015 China equity crash2015.06-2015.08-45%-10%-20%yield ↓ 50bp
    2018 trade war2018.01-2018.12-25%-20%-80%yield ↓ 30bp
    2020 COVID shock2020.01-2020.03-15%-35%-50%yield ↓ 80bp
    2022 hiking cycle2022.01-2022.10-20%-25%-65%yield ↑ 200bp

    Hypothetical Scenario Design

    STRESS_SCENARIOS = {
        'rate_shock_up_100bp': {
            'equity': -0.10,    # equities down 10%
            'bond_10y': -0.08,  # 10-year bonds down 8%
            'bond_2y': -0.02,   # short bonds down 2%
            'gold': +0.05,      # gold up 5%
            'btc': -0.15,       # BTC down 15%
        },
        'credit_crisis': {
            'equity': -0.25,
            'bond_10y': +0.05,  # government bonds act as a safe haven
            'credit_bond': -0.15,
            'gold': +0.10,
            'btc': -0.30,
        },
        'liquidity_dry_up': {
            'equity': -0.20,
            'bond_10y': -0.05,  # when liquidity is poor, everything falls
            'gold': -0.05,
            'btc': -0.40,
            'cash': 0.0,
        },
        'geopolitical_conflict': {
            'equity': -0.15,
            'bond_10y': +0.03,
            'gold': +0.15,
            'oil': +0.30,
            'btc': -0.20,
        },
    }
    

    Stress-Test Implementation Steps

    1. Select a scenario: either historical or hypothetical
    2. Apply shocks: multiply scenario shocks by the current positions
    3. Compute portfolio loss: portfolio_loss = Σ(weight_i × shock_i × position_i)
    4. Assess adequacy: compare loss vs risk budget and whether stop-loss thresholds are triggered

    Tail-Risk Analysis (Extreme Value Theory, EVT)

    POT Method (Peaks Over Threshold)

    fit = fit_gpd_tail(returns, threshold_pct=5.0)   # keep the worst 5%
    fit["shape_xi"]      # ξ>0 fat tail, ξ=0 exponential tail, ξ<0 bounded tail
    fit["shape_stderr"]  # standard error of ξ -- quote ξ with it, never alone
    fit["scale_sigma"]   # in units of loss magnitude
    fit["tail_type"]     # "fat" | "exponential" | "bounded"
    fit["threshold"], fit["n_exceedances"], fit["exceedance_rate"]
    

    Exceedances are non-negative by construction (threshold - return, kept only where the return fell below the threshold), so the GPD location is pinned at zero. Letting loc float instead lets the optimiser absorb tail mass into a shifted origin and biases shape_xi.

    tail_type is decided against shape_stderr, not against exact zero. A fitted shape_xi is a float and is never exactly 0.0, so a bare ξ > 0 test would call a genuinely exponential tail "fat" purely on the sign of estimation noise. "fat" therefore means ξ > 2 × shape_stderr, "bounded" means ξ < -2 × shape_stderr, and anything in between is "exponential" — indistinguishable from zero at this sample size. Measured over 200 refits, that 2σ band labels a truly exponential tail "exponential" 96.5% of the time while still catching ξ = +0.40 and ξ = -0.35 100% of the time. A shape_xi of 0.03 with a shape_stderr of 0.02 is not evidence of a fat tail; get more exceedances before you call it one.

    Threshold choice is the real judgement call: too high and there is nothing left to fit (fewer than 2 exceedances raises), too low and the EVT limit theorem no longer applies, so the fitted shape stops meaning anything. Check that shape_xi is stable across a few nearby threshold_pct values before quoting it.

    Tail-Risk Metrics

    MetricCalculationMeaning
    Kurtosisreturns.kurtosis()>3 indicates fat tails; China A-shares are often in the 4-8 range
    Skewnessreturns.skew()<0 means left-skewed (large drops are more common than large rallies)
    Tail ratioworst 5% / best 5%>1 means larger downside risk
    Hill estimatorTail indexα<2 implies extremely fat tails

    Analysis Framework

    Input Requirements

    Required:
    - Return series (daily or higher frequency) or net-value series
    - Portfolio weights (if it is a portfolio)
    
    Optional:
    - Benchmark returns (for relative risk analysis)
    - Risk budget / constraint settings
    

    Analysis Steps

    1. Data preprocessing: compute returns, check missing values, and handle outliers
    2. Descriptive statistics: mean / volatility / skewness / kurtosis / maximum drawdown
    3. VaR/CVaR calculation: compare three methods at both 95% and 99% confidence levels
    4. Monte Carlo simulation: 10,000 paths, output distribution statistics and VaR
    5. Stress testing: at least 3 historical scenarios + 2 hypothetical scenarios
    6. Tail analysis: fit GPD and determine tail type
    7. Risk-control recommendations: provide concrete recommendations based on the results

    Output Format

    Note the sign flip: the module returns losses as positive numbers, while the report below prints them the way a reader expects to see them (max_drawdown 0.325-32.5%). Flip once, here at the presentation layer, and never inside a calculation.

    ## Risk Analysis Report
    
    ### Core Risk Metrics
    | Metric | Value |
    |------|-----|
    | Daily volatility | 1.85% |
    | Annualized volatility | 29.3% |
    | Maximum drawdown | -32.5% (2024.09.15 → 2024.11.20) |
    | VaR(95%, 1D) | -2.8% |
    | CVaR(95%, 1D) | -4.2% |
    | Skewness | -0.45 |
    | Kurtosis | 5.2 (fat tail) |
    
    ### Stress-Test Results
    | Scenario | Portfolio Loss | Stop Triggered |
    |------|---------|----------|
    | 2020 COVID replay | -18.5% | No |
    | Rates +100bp | -12.3% | No |
    | Liquidity dry-up | -28.7% | Yes |
    
    ### Monte Carlo Simulation (252 days, 10000 paths)
    | Statistic | Value |
    |------|-----|
    | Expected return | +8.2% |
    | Loss probability | 35% |
    | Worst 5% scenario | -22.4% |
    
    ### Risk-Control Recommendations
    1. Recommend setting a portfolio stop-loss at -15%
    2. Tail risk is elevated; consider allocating 5% to gold as a hedge
    3. Correlations rise in stressed markets, so diversification benefits will be discounted
    

    Notes

    1. VaR is not the maximum loss: VaR only says "with 95% probability, losses will not exceed X"; the remaining 5% can be far worse
    2. Normality assumption is dangerous: financial returns are almost always fat-tailed, so parametric VaR underestimates risk deep in the tail (99% and beyond). At 90–95% it usually reads higher than the historical figure, because the fat tail inflates the fitted sigma — see the table under "Parametric (normal)". Never cite a 95% parametric VaR as evidence that the normal fit is conservative
    3. History does not equal the future: historical simulation fails when structural breaks occur (for example, the first negative oil price)
    4. Correlation is unstable: correlation matrices observed in normal markets can collapse in crises (correlations trend toward 1)
    5. Monte Carlo seed: always pass seed= to monte_carlo_gbm and quote it in the report, so the numbers can be regenerated; use at least 10,000 paths for stability
    6. Holding-period scaling: the square-root-of-time rule only applies under i.i.d. returns; it becomes inaccurate under autocorrelation
    7. Risk in backtests: metrics.csv already includes max_drawdown and sharpe; this skill provides deeper analysis
    8. Sign discipline: every measure here returns a loss as a positive number. Do not re-derive a measure inline to "get the sign you want" — call the function and flip once when printing

    Frequently asked questions

    What to verify before installation and use

    What does the risk-analysis source document cover?

    Risk measurement and stress testing — VaR/CVaR/max drawdown calculation, Monte Carlo simulation, extreme-value tail-risk analysis, and historical scenario stress testing.

    How do I install risk-analysis?

    The source record exposes this install command: npx skills add https://github.com/HKUDS/Vibe-Trading --skill "agent/src/skills/risk-analysis". Inspect the command and pinned source before running it.

    Alternatives

    Compare before choosing

    Computed 10045,643

    coreyhaines31/marketingskills

    ab-testing

    When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

    Computed 1008

    narrative-io/narrative-skills-marketplace

    design-analysis

    Translate a fuzzy analytical question into a rigorous investigation plan. Interrogates the ask, grounds the plan in the available data dictionary, applies analytical best practices, and produces a structured brief of query specifications for a downstream query-writing skill. Plans, does not write SQL. Use when: "why did X drop", "is there a relationship between A and B", "who are our highest-value customers", "what's driving the change in Y", "investigate this trend", "design an analysis for", "

    Computed 97269

    Aperivue/medsci-skills

    calc-sample-size

    Interactive sample size calculator for medical research. Decision-tree guided test selection, reproducible R/Python code, effect size interpretation, and IRB-ready justification text. Supports diagnostic accuracy, agreement, proportions, continuous outcomes, survival, ANOVA, logistic regression, and non-inferiority/equivalence designs.

    Computed 97224

    yonatangross/orchestkit

    verify

    Grade work that already exists and decide whether it can merge. Runs the project's current unit, integration, and E2E suites plus security scanning and type checking, scores every dimension 0-10, and returns a merge verdict with a VERIFIED-vs-CLAIMED evidence manifest. Writes no test files and edits no source. Use when verifying changes are ready to merge. Use /ork:cover instead when the tests still have to be written.