
Risk
- 16 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
risk is a Claude skill that provides a trading risk engine with VaR, stress testing, volatility regimes, circuit breakers, and kill switches.
About
This skill is a risk management engine for trading, exposing circuit breakers, loss limits, Value-at-Risk, volatility regime detection, stress testing, and kill switches. Developers use /risk commands or a TypeScript API to validate trades through a 10-check pipeline, record P&L, view portfolio VaR and CVaR, run stress scenarios, and configure limits. It returns an adjusted position size based on Kelly and volatility regime. It is the pre-trade validation layer for a trading bot.
- Unified pre-trade risk engine running 10 checks including VaR and Kelly sizing
- Volatility regime detection with position-size multipliers and stress testing
- Circuit breakers, loss limits, and an emergency kill switch
Risk by the numbers
- 16 all-time installs (skills.sh)
- Ranked #739 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
risk capabilities & compatibility
- Capabilities
- risk management · value at risk · stress testing · position sizing
- Use cases
- trading
- Pricing
- Free
What risk says it does
Full risk management engine: circuit breakers, loss limits, Value-at-Risk, volatility regime detection, stress testing, and kill switches.
The risk engine is the single entry point for all pre-trade validation. It orchestrates 10 checks in order:
npx skills add https://github.com/alsk1992/cloddsbot --skill riskAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 16 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Validate trades through a risk engine with VaR, stress tests, limits, and kill switches.
Who is it for?
Adding pre-trade risk validation, loss limits, and VaR/stress analytics to a trading bot.
When should I use this skill?
A developer needs to validate a trade, set loss limits, or check portfolio risk before executing.
By the numbers
- 10 ordered pre-trade checks
- 5 stress scenarios
- 4 volatility regimes (low, normal, high, extreme)
Files
Risk - Complete API Reference
Full risk management engine: circuit breakers, loss limits, Value-at-Risk, volatility regime detection, stress testing, and kill switches.
---
Chat Commands
View Risk Status
/risk Current risk status
/risk status Detailed status with portfolio metrics
/risk limits View all limits
/risk dashboard Real-time risk metrics (VaR, regime, HHI, etc.)Risk Analytics
/risk var Value-at-Risk and CVaR numbers
/risk regime Current volatility regime and size multiplier
/risk stress [scenario] Run stress test (flash_crash, black_swan, etc.)Available stress scenarios: flash_crash, liquidity_crunch, platform_down, correlation_spike, black_swan
Configure Limits
/risk set max-loss 1000 Max daily loss ($)
/risk set max-loss-pct 10 Max daily loss (%)
/risk set max-drawdown 20 Max drawdown (%)
/risk set max-position 25 Max single position (%)
/risk set max-trades 50 Max trades per day
/risk set consecutive-losses 5 Stop after N lossesCircuit Breaker
/risk trip "manual stop" Manually trip breaker
/risk reset Reset after cooldown
/risk kill Emergency stop all trading
/risk check 500 Check if a $500 trade is allowed---
TypeScript API Reference
Unified Risk Engine
The risk engine is the single entry point for all pre-trade validation. It orchestrates 10 checks in order:
1. Kill switch (SafetyManager) 2. Circuit breaker (execution-level) 3. Max order size 4. Exposure limits 5. Daily loss limit 6. Max drawdown 7. Position concentration 8. VaR limit 9. Volatility regime 10. Kelly sizing recommendation
import { createRiskEngine } from 'clodds/risk';
const engine = createRiskEngine(
{
varLimit: 500, // Reject trades if portfolio VaR > $500
varConfidence: 0.95,
varWindowSize: 100,
volatilityConfig: {
lookbackWindow: 30,
haltOnExtreme: true, // Stop trading in extreme volatility
},
},
{
riskContext, // From trading/risk.ts
safetyManager, // From trading/safety.ts
circuitBreaker, // From execution/circuit-breaker.ts
kellyCalculator, // From trading/kelly.ts
getPositions: () => positions,
getPositionValues: () => positions.map(p => p.value),
}
);Validate a Trade
const decision = engine.validateTrade({
userId: 'user-123',
platform: 'polymarket',
marketId: 'market-456',
outcome: 'YES',
side: 'buy',
size: 500,
price: 0.65,
estimatedEdge: 0.05, // 5% edge
confidence: 0.8,
category: 'politics',
});
if (decision.approved) {
// Use adjustedSize — may be smaller than requested (Kelly + regime)
await executeTrade(decision.adjustedSize);
console.log(`Regime: ${decision.regime}`);
console.log(`Warnings: ${decision.warnings}`);
} else {
console.log(`Blocked: ${decision.reason}`);
// Check which step failed:
for (const check of decision.checks) {
console.log(` ${check.name}: ${check.passed ? 'PASS' : 'FAIL'} — ${check.message}`);
}
}Record Trade P&L (feeds VaR + volatility)
engine.recordPnL({
pnlUsd: -45.20,
pnlPct: -0.09,
positionId: 'polymarket:market-456:YES',
timestamp: new Date(),
});Portfolio Risk Snapshot
const risk = engine.getPortfolioRisk();
console.log(`Total value: $${risk.totalValue}`);
console.log(`VaR (95%): $${risk.var95}`);
console.log(`VaR (99%): $${risk.var99}`);
console.log(`CVaR (95%): $${risk.cvar95}`);
console.log(`Regime: ${risk.regime}`);
console.log(`Drawdown: ${risk.drawdownPct}%`);Value-at-Risk
import { createVaRCalculator, calculateVaR, calculateCVaR } from 'clodds/risk';
// Full calculator with rolling window
const calc = createVaRCalculator({ windowSize: 100, confidenceLevel: 0.95 });
calc.addObservation({ pnlUsd: -50, pnlPct: -0.05, timestamp: new Date() });
const result = calc.calculateAt(0.99);
console.log(`VaR (99%): $${result.historicalVaR}`);
console.log(`CVaR (99%): $${result.cvar}`);
// Quick one-liners
const var95 = calculateVaR(pnlArray, 0.95);
const cvar95 = calculateCVaR(pnlArray, 0.95);Volatility Regime Detection
import { createVolatilityDetector, detectRegime } from 'clodds/risk';
const detector = createVolatilityDetector({
lookbackWindow: 30,
haltOnExtreme: false,
regimeMultipliers: { low: 1.2, normal: 1.0, high: 0.5, extreme: 0.25 },
});
detector.addObservation(0.03); // 3% P&L
const snapshot = detector.detect();
console.log(`Regime: ${snapshot.regime}`); // 'low' | 'normal' | 'high' | 'extreme'
console.log(`Size multiplier: ${snapshot.sizeMultiplier}x`);
console.log(`Should halt: ${snapshot.shouldHalt}`);
// One-shot from array
const regime = detectRegime(recentPnLPcts);Stress Testing
import { runStressTest, runAllScenarios, getAvailableScenarios } from 'clodds/risk';
const result = runStressTest(positions, 'flash_crash');
console.log(`Estimated loss: $${result.estimatedLoss} (${result.estimatedLossPct}%)`);
console.log(`Severity: ${result.severity}`);
console.log(`Recommendations: ${result.recommendations.join(', ')}`);
// Run all scenarios at once
const all = runAllScenarios(positions); // sorted by severity
// Override scenario parameters
const custom = runStressTest(positions, 'flash_crash', {
scenarios: { flash_crash: { lossPct: 30, description: 'Severe crash' } },
});Risk Dashboard
import { getRiskDashboard } from 'clodds/risk';
const dashboard = engine.getDashboard();
console.log(`VaR (95%): $${dashboard.portfolioVaR95}`);
console.log(`Regime: ${dashboard.regime} (${dashboard.regimeSizeMultiplier}x)`);
console.log(`Daily P&L: $${dashboard.dailyPnL} / $${dashboard.dailyLossLimit}`);
console.log(`Drawdown: ${dashboard.currentDrawdown}% / ${dashboard.maxDrawdown}%`);
console.log(`Concentration HHI: ${dashboard.concentrationHHI}`);
console.log(`Kill switch: ${dashboard.killSwitchActive}`);
console.log(`Warnings: ${dashboard.warnings}`);Circuit Breaker (Standalone)
import { createCircuitBreaker, MODERATE_CONFIG } from 'clodds/risk';
// Feature-engineering circuit breaker (market-condition-aware)
const breaker = createCircuitBreaker(MODERATE_CONFIG);
breaker.startMonitoring();
if (!breaker.canTrade('polymarket', marketId)) {
return; // Trading halted
}
breaker.recordTrade({ success: true, pnl: 2.5 });Kill Switch
// Emergency stop via SafetyManager — no auto-resume
safetyManager.killSwitch('Market anomaly detected');
// Resume manually after review
safetyManager.resumeTrading();---
Risk Engine Checks
| # | Check | Module | Blocks Trade? |
|---|---|---|---|
| 1 | Kill switch | SafetyManager | Yes |
| 2 | Circuit breaker | CircuitBreaker | Yes |
| 3 | Max order size | trading/risk | Yes |
| 4 | Exposure limits | trading/risk | Yes |
| 5 | Daily loss limit | SafetyManager | Yes |
| 6 | Max drawdown | SafetyManager | Yes |
| 7 | Concentration | SafetyManager | Yes |
| 8 | VaR limit | VaRCalculator | Yes (if configured) |
| 9 | Volatility regime | VolatilityDetector | Yes (if extreme + halt) |
| 10 | Kelly sizing | DynamicKelly | No (adjusts size) |
Circuit Breaker Triggers
| Trigger | Default | Description |
|---|---|---|
| Daily loss (USD) | $1,000 | Absolute loss limit |
| Daily loss (%) | 10% | Percentage of capital |
| Drawdown | 20% | Peak-to-trough |
| Consecutive losses | 5 | Losses in a row |
| Error rate | 50% | Failed order rate |
| Max trades | 50 | Trades per day |
Volatility Regimes
| Regime | Size Multiplier | Description |
|---|---|---|
low | 1.2x | Calm markets, slightly larger positions |
normal | 1.0x | Baseline conditions |
high | 0.5x | Elevated volatility, half size |
extreme | 0.25x | Crisis — quarter size or halt trading |
Stress Test Scenarios
| Scenario | Loss | Description |
|---|---|---|
flash_crash | 20% | All positions lose value instantly |
liquidity_crunch | 10% | Slippage doubles, partial fills |
platform_down | 15% | Primary platform offline |
correlation_spike | 25% | All positions move together |
black_swan | 40% | 3-sigma tail event |
Status Levels
| Status | Description |
|---|---|
armed | Normal, trading allowed |
warning | Approaching limits (80%) |
tripped | Limit exceeded, trading stopped |
killed | Emergency stop, manual reset required |
---
Recovery Process
1. Auto-reset: Next day at midnight (daily counters) 2. Cooldown: Circuit breaker auto-resets after cooldown period 3. Manual reset: /risk reset to re-arm 4. Kill recovery: /risk reset after manual review (no auto-resume)
---
Best Practices
1. Start conservative — Lower limits while learning 2. Don't override — Respect the circuit breaker 3. Review trips — Understand why limits were hit 4. Monitor VaR — Use /risk var and /risk dashboard regularly 5. Run stress tests — Use /risk stress before large position changes 6. Watch regime — Use /risk regime to understand current volatility 7. Adjust limits — Based on strategy performance and regime
/**
* Risk CLI Skill
*
* Commands:
* /risk - Current risk status
* /risk status - Detailed status
* /risk limits - View all limits
* /risk set <param> <value> - Configure a limit
* /risk trip "reason" - Manually trip circuit breaker
* /risk reset - Reset after cooldown
* /risk kill - Emergency stop all trading
* /risk check <notional> - Check if a trade is allowed
* /risk dashboard - Real-time risk metrics
* /risk var - VaR / CVaR numbers
* /risk stress [scenario] - Run stress test
* /risk regime - Current volatility regime
*/
import { enforceMaxOrderSize } from '../../../trading/risk';
import type { RiskEngine } from '../../../risk/engine';
import { createVaRCalculator } from '../../../risk/var';
import { createVolatilityDetector } from '../../../risk/volatility';
import {
runStressTest,
getAvailableScenarios,
type StressPosition,
} from '../../../risk/stress';
import { getRiskDashboard } from '../../../risk/dashboard';
// =============================================================================
// STATE
// =============================================================================
// In-memory risk state — used when no real engine is wired in
let circuitBreakerState: 'armed' | 'tripped' | 'killed' = 'armed';
let tripReason: string | null = null;
let tripTime: number | null = null;
const limits: Record<string, number> = {
'max-loss': 1000,
'max-loss-pct': 10,
'max-drawdown': 20,
'max-position': 25,
'max-trades': 50,
'consecutive-losses': 5,
};
// Shared subsystem instances for dashboard/var/regime commands
const varCalculator = createVaRCalculator({ windowSize: 100 });
const volatilityDetector = createVolatilityDetector();
// Lazy-initialized engine (populated when a real context is available)
let _engine: RiskEngine | null = null;
/**
* Wire the skill to a real RiskEngine instance. Call this at startup
* if you have the necessary dependencies (DB, safety manager, etc.).
*/
export function setRiskEngine(engine: RiskEngine): void {
_engine = engine;
}
// =============================================================================
// HANDLERS
// =============================================================================
function handleStatus(): string {
let output = '**Risk Status**\n\n';
output += `Circuit Breaker: ${circuitBreakerState}\n`;
output += `Trading Allowed: ${circuitBreakerState === 'armed' ? 'Yes' : 'No'}\n`;
if (tripReason) {
output += `Trip Reason: ${tripReason}\n`;
}
if (tripTime) {
output += `Tripped At: ${new Date(tripTime).toLocaleString()}\n`;
}
// If engine is available, add real metrics
if (_engine) {
const risk = _engine.getPortfolioRisk();
output += `\n**Portfolio Risk**\n`;
output += ` Regime: ${risk.regime}\n`;
output += ` VaR (95%): $${risk.var95.toFixed(2)}\n`;
output += ` VaR (99%): $${risk.var99.toFixed(2)}\n`;
output += ` CVaR (95%): $${risk.cvar95.toFixed(2)}\n`;
output += ` Drawdown: ${risk.drawdownPct.toFixed(1)}%\n`;
output += ` Daily P&L: $${risk.dailyPnL.toFixed(2)}\n`;
output += ` Positions: ${risk.positionCount}\n`;
}
output += '\n**Limits:**\n';
for (const [key, value] of Object.entries(limits)) {
output += ` ${key}: ${value}\n`;
}
return output;
}
function handleLimits(): string {
let output = '**Risk Limits**\n\n';
output += `| Parameter | Value |\n`;
output += `|-----------|-------|\n`;
for (const [key, value] of Object.entries(limits)) {
output += `| ${key} | ${value} |\n`;
}
return output;
}
function handleSet(param: string, value: string): string {
const numValue = parseFloat(value);
if (isNaN(numValue)) {
return `Invalid value: ${value}. Must be a number.`;
}
const validParams = Object.keys(limits);
if (!validParams.includes(param)) {
return `Unknown parameter: ${param}\n\nValid parameters: ${validParams.join(', ')}`;
}
limits[param] = numValue;
return `Set **${param}** to **${numValue}**`;
}
function handleTrip(reason: string): string {
if (circuitBreakerState === 'killed') {
return 'System is in KILLED state. Use `/risk reset` first.';
}
circuitBreakerState = 'tripped';
tripReason = reason || 'Manual trip';
tripTime = Date.now();
return `Circuit breaker **TRIPPED**: ${tripReason}`;
}
function handleReset(): string {
if (circuitBreakerState === 'armed') {
return 'Circuit breaker is already armed. No reset needed.';
}
circuitBreakerState = 'armed';
tripReason = null;
tripTime = null;
return 'Circuit breaker **RESET**. Trading is now allowed.';
}
function handleKill(): string {
circuitBreakerState = 'killed';
tripReason = 'Emergency kill switch activated';
tripTime = Date.now();
return '**EMERGENCY STOP** - All trading disabled. Manual reset required via `/risk reset`.';
}
function handleCheck(notionalStr: string): string {
const notional = parseFloat(notionalStr);
if (isNaN(notional) || notional <= 0) {
return 'Usage: /risk check <notional>\n\nExample: /risk check 500';
}
if (circuitBreakerState !== 'armed') {
return `Trade **BLOCKED** - Circuit breaker is ${circuitBreakerState}.\nReason: ${tripReason || 'N/A'}`;
}
const maxOrderSize = limits['max-loss'] ?? 1000;
const result = enforceMaxOrderSize(
{ tradingContext: { maxOrderSize }, db: { getUser: () => undefined, getPositions: () => [] } },
notional,
`Risk check for $${notional}`
);
if (result) {
return `Trade **BLOCKED**:\n\`\`\`json\n${result}\n\`\`\``;
}
return `Trade **ALLOWED** - $${notional} is within risk limits.`;
}
function handleDashboard(): string {
if (_engine) {
const db = _engine.getDashboard();
let output = '**Risk Dashboard**\n\n';
output += `| Metric | Value |\n`;
output += `|--------|-------|\n`;
output += `| VaR (95%) | $${db.portfolioVaR95.toFixed(2)} |\n`;
output += `| VaR (99%) | $${db.portfolioVaR99.toFixed(2)} |\n`;
output += `| CVaR (95%) | $${db.cvar95.toFixed(2)} |\n`;
output += `| Regime | ${db.regime} (${db.regimeSizeMultiplier}x) |\n`;
output += `| Circuit Breaker | ${db.circuitBreakerTripped ? 'TRIPPED' : 'OK'} |\n`;
output += `| Daily P&L | $${db.dailyPnL.toFixed(2)} |\n`;
output += `| Daily Loss Limit | $${db.dailyLossLimit} |\n`;
output += `| Loss Utilization | ${(db.dailyLossUtilization * 100).toFixed(0)}% |\n`;
output += `| Drawdown | ${db.currentDrawdown.toFixed(1)}% / ${db.maxDrawdown}% |\n`;
output += `| Open Positions | ${db.openPositions} |\n`;
output += `| Concentration (HHI) | ${db.concentrationHHI} |\n`;
output += `| Kill Switch | ${db.killSwitchActive ? 'ACTIVE' : 'Off'} |\n`;
output += `| Kelly Fraction | ${db.kellyFraction} |\n`;
if (db.warnings.length > 0) {
output += `\n**Warnings:**\n`;
for (const w of db.warnings) {
output += `- ${w}\n`;
}
}
return output;
}
// Fallback: use standalone subsystems
const dashboard = getRiskDashboard({
varCalculator,
volatilityDetector,
});
let output = '**Risk Dashboard** (standalone mode)\n\n';
output += `| Metric | Value |\n`;
output += `|--------|-------|\n`;
output += `| VaR (95%) | $${dashboard.portfolioVaR95.toFixed(2)} |\n`;
output += `| VaR (99%) | $${dashboard.portfolioVaR99.toFixed(2)} |\n`;
output += `| Regime | ${dashboard.regime} |\n`;
output += `| Circuit Breaker | ${circuitBreakerState} |\n`;
output += `\n*Connect a RiskEngine for full metrics.*`;
return output;
}
function handleVaR(): string {
if (_engine) {
const calc = _engine.getVaRCalculator();
const var95 = calc.calculateAt(0.95);
const var99 = calc.calculateAt(0.99);
let output = '**Value-at-Risk**\n\n';
output += `| Metric | Value |\n`;
output += `|--------|-------|\n`;
output += `| Historical VaR (95%) | $${var95.historicalVaR.toFixed(2)} |\n`;
output += `| Parametric VaR (95%) | $${var95.parametricVaR.toFixed(2)} |\n`;
output += `| CVaR / ES (95%) | $${var95.cvar.toFixed(2)} |\n`;
output += `| Historical VaR (99%) | $${var99.historicalVaR.toFixed(2)} |\n`;
output += `| Parametric VaR (99%) | $${var99.parametricVaR.toFixed(2)} |\n`;
output += `| CVaR / ES (99%) | $${var99.cvar.toFixed(2)} |\n`;
output += `| Sample Size | ${var95.sampleSize} |\n`;
output += `| Mean P&L | $${var95.meanPnL.toFixed(2)} |\n`;
output += `| Std Dev | $${var95.stdDev.toFixed(2)} |\n`;
const positions = calc.positionVaR();
if (positions.length > 0) {
output += '\n**Per-Position VaR (95%)**\n\n';
output += `| Position | VaR | Contribution |\n`;
output += `|----------|-----|--------------|\n`;
for (const p of positions.slice(0, 10)) {
output += `| ${p.positionId} | $${p.var95.toFixed(2)} | ${(p.varContribution * 100).toFixed(0)}% |\n`;
}
}
return output;
}
// Fallback
const var95 = varCalculator.calculateAt(0.95);
let output = '**Value-at-Risk** (standalone mode)\n\n';
output += `VaR (95%): $${var95.historicalVaR.toFixed(2)}\n`;
output += `CVaR (95%): $${var95.cvar.toFixed(2)}\n`;
output += `Sample Size: ${var95.sampleSize}\n`;
output += `\n*Connect a RiskEngine and record trades for meaningful VaR.*`;
return output;
}
function handleStress(scenarioArg?: string): string {
const positions: StressPosition[] = [];
// Try to get real positions from engine
if (_engine) {
const risk = _engine.getPortfolioRisk();
// Use portfolio snapshot as a single position if we don't have detail
if (risk.totalValue > 0) {
positions.push({
id: 'portfolio',
platform: 'mixed',
value: risk.totalValue,
pnlPct: 0,
side: 'long',
});
}
}
if (positions.length === 0) {
// Show available scenarios even without positions
const scenarios = getAvailableScenarios();
let output = '**Stress Test** — No positions to test against\n\n';
output += 'Available scenarios:\n';
for (const s of scenarios) {
output += `- \`${s.name}\` — ${s.description}\n`;
}
output += '\nUsage: `/risk stress flash_crash`';
return output;
}
const result = runStressTest(positions, scenarioArg || 'flash_crash');
let output = `**Stress Test: ${result.scenario}**\n\n`;
output += `${result.description}\n\n`;
output += `| Metric | Value |\n`;
output += `|--------|-------|\n`;
output += `| Estimated Loss | $${result.estimatedLoss.toFixed(2)} (${result.estimatedLossPct.toFixed(1)}%) |\n`;
output += `| Portfolio Before | $${result.portfolioValueBefore.toFixed(2)} |\n`;
output += `| Portfolio After | $${result.portfolioValueAfter.toFixed(2)} |\n`;
output += `| Positions at Risk | ${result.positionsAtRisk} |\n`;
output += `| Severity | ${result.severity.toUpperCase()} |\n`;
if (result.mostAffected.length > 0) {
output += `\n**Most Affected:**\n`;
for (const p of result.mostAffected) {
output += `- ${p.id}: -$${p.estimatedLoss.toFixed(2)}\n`;
}
}
output += `\n**Recommendations:**\n`;
for (const r of result.recommendations) {
output += `- ${r}\n`;
}
return output;
}
function handleRegime(): string {
if (_engine) {
const detector = _engine.getVolatilityDetector();
const snapshot = detector.detect();
let output = '**Volatility Regime**\n\n';
output += `| Metric | Value |\n`;
output += `|--------|-------|\n`;
output += `| Regime | ${snapshot.regime.toUpperCase()} |\n`;
output += `| Size Multiplier | ${snapshot.sizeMultiplier}x |\n`;
output += `| Rolling Std Dev | ${(snapshot.rollingStdDev * 100).toFixed(2)}% |\n`;
output += `| ATR | ${(snapshot.atr * 100).toFixed(2)}% |\n`;
output += `| Mean P&L | ${(snapshot.meanPnL * 100).toFixed(2)}% |\n`;
output += `| Sample Size | ${snapshot.sampleSize} |\n`;
output += `| Should Halt | ${snapshot.shouldHalt ? 'YES' : 'No'} |\n`;
output += '\n**Regime Thresholds:**\n';
output += '- low: 1.2x (calm)\n';
output += '- normal: 1.0x (baseline)\n';
output += '- high: 0.5x (reduced)\n';
output += '- extreme: 0.25x (minimal/halt)\n';
return output;
}
// Fallback
const snapshot = volatilityDetector.detect();
let output = '**Volatility Regime** (standalone mode)\n\n';
output += `Regime: ${snapshot.regime.toUpperCase()}\n`;
output += `Size Multiplier: ${snapshot.sizeMultiplier}x\n`;
output += `Sample Size: ${snapshot.sampleSize}\n`;
output += `\n*Connect a RiskEngine and record trades for live regime detection.*`;
return output;
}
// =============================================================================
// MAIN HANDLER
// =============================================================================
export async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const command = parts[0]?.toLowerCase() || 'status';
const rest = parts.slice(1);
switch (command) {
case 'status':
return handleStatus();
case 'limits':
return handleLimits();
case 'set':
if (rest.length < 2) return 'Usage: /risk set <param> <value>\n\nExample: /risk set max-loss 2000';
return handleSet(rest[0], rest[1]);
case 'trip':
return handleTrip(rest.join(' '));
case 'reset':
return handleReset();
case 'kill':
return handleKill();
case 'check':
if (!rest[0]) return 'Usage: /risk check <notional>\n\nExample: /risk check 500';
return handleCheck(rest[0]);
case 'dashboard':
case 'dash':
return handleDashboard();
case 'var':
return handleVaR();
case 'stress':
return handleStress(rest[0]);
case 'regime':
case 'vol':
return handleRegime();
case 'help':
default:
return `**Risk Management Commands**
**Status:**
/risk Current risk status
/risk status Detailed status
/risk limits View all limits
/risk dashboard Real-time risk metrics
/risk var VaR / CVaR numbers
/risk stress [scenario] Run stress test
/risk regime Volatility regime
**Configure:**
/risk set max-loss 1000 Max daily loss ($)
/risk set max-loss-pct 10 Max daily loss (%)
/risk set max-drawdown 20 Max drawdown (%)
/risk set max-position 25 Max single position (%)
/risk set max-trades 50 Max trades per day
/risk set consecutive-losses 5 Stop after N losses
**Circuit Breaker:**
/risk trip "reason" Manually trip breaker
/risk reset Reset after cooldown
/risk kill Emergency stop all trading
**Checks:**
/risk check 500 Check if trade is allowed
**Stress Scenarios:**
flash_crash, liquidity_crunch, platform_down,
correlation_spike, black_swan`;
}
}
export default {
name: 'risk',
description: 'Circuit breaker, loss limits, VaR, stress tests, and automated risk controls',
commands: ['/risk'],
handle: execute,
};
Related skills
FAQ
How many checks run before a trade is approved?
The unified engine runs 10 checks in order, from kill switch through Kelly sizing.
What stress scenarios are available?
flash_crash, liquidity_crunch, platform_down, correlation_spike, and black_swan.