计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
risk-kelly-criterion【效率与协作】Calculates optimal position sizing using Kelly Criterion and Fractional Kelly formulas to maximize geometric growth while controlling drawdown risk in algorithmic trading systems.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: risk-kelly-criterion description: Calculates optimal position sizing using Kelly Criterion and Fractional Kelly formulas to maximize geometric growth while controlling drawdown risk in algorithmic trading systems. license: MIT compatibility: opencode metadata: version: "1.0.0" domain: trading triggers: kelly criterion, fractional kelly, position sizing, optimal f, bet sizing, geometric growth, edge calculation, bankroll management role: implementation scope: implementation output-format: code content-types: [code, guidance, config, do-dont] archetypes: [tactical] anti_triggers: [vague ideation, long-form architecture, brainstorming] response_profile: verbosity: low directive_strength: high abstraction_level: operational related-skills: risk-stop-loss, risk-position-sizing, risk-kill-switches
Implements Kelly Criterion calculations to determine mathematically optimal position sizes based on win rate, reward-to-risk ratio, and account equity. Converts theoretical edge into practical trading execution using Fractional Kelly to mitigate volatility drag and estimation error risk.
Use this skill when:
Avoid this skill for:
risk-stop-loss and risk-kill-switchesCollect Performance Statistics — Extract historical win rate (W) and average reward-to-risk ratio (R). Use trade logs spanning at least 100 trades across multiple market regimes. Exclude outliers caused by infrastructure failures or data feed errors. Checkpoint: Verify sample size ≥ 100 and calculate standard error for W. If confidence interval width exceeds ±15%, defer Kelly sizing until more data is collected.
Calculate Full Kelly Percentage — Apply the classic formula: K = W - ((1 - W) / R). Convert result to decimal (e.g., 0.12 = 12% of bankroll). If K ≤ 0, the strategy has no mathematical edge under current conditions.
Checkpoint: Reject sizing if K < 0 or if input parameters rely on fewer than 50 confirmed closed trades.
Apply Fractional Scaling — Multiply full K by a fractional coefficient f (typically 0.25 to 0.5). Fractional Kelly reduces volatility drag, lowers maximum drawdown, and cushions against parameter estimation error.
Checkpoint: Use f = 0.25 for high-variance strategies or limited live-track history. Use f = 0.5 only after 6+ months of stable execution with verified edge persistence.
Compute Actual Position Size — Convert the fractional Kelly percentage into contracts, lots, or shares based on current account equity and per-unit risk exposure (e.g., stop distance in price terms). Checkpoint: Ensure calculated size respects exchange tick sizes, minimum lot requirements, margin thresholds, and portfolio-wide allocation caps.
Monitor and Adjust Dynamically — Track rolling win rate and R:R using exponentially weighted moving average (EWMA) or fixed rolling windows. Recalculate Kelly only when metrics drift beyond a configured tolerance band (default ±10%). Checkpoint: Never recalculate Kelly after a single trade outcome. Strategy edge is a statistical property, not a per-trade variable. Log every recalculation with inputs, fraction applied, and resulting allocation.
Structured data model for collecting and validating performance statistics before computation. Ensures type safety and automatic range checking.
from pydantic import BaseModel, Field, field_validator
from typing import Optional
class TradeStatistics(BaseModel):
"""Validated trade performance statistics for Kelly calculation."""
win_rate: float = Field(ge=0.0, le=1.0, description="Historical win rate (0.0 to 1.0)")
avg_reward_to_risk: float = Field(gt=0.0, description="Average profit factor / R:R ratio")
total_trades: int = Field(ge=30, description="Minimum sample size for statistical validity")
max_drawdown_pct: float = Field(ge=0.0, description="Peak-to-trough drawdown percentage")
@field_validator("avg_reward_to_risk")
@classmethod
def validate_rr_ratio(cls, v: float) -> float:
if v < 0.5:
raise ValueError("R:R below 0.5 indicates negative or negligible edge — Kelly sizing inappropriate")
return v
@field_validator("total_trades")
@classmethod
def validate_sample_size(cls, v: int) -> int:
if v < 30:
raise ValueError(f"Sample size {v} is below minimum threshold for reliable Kelly estimation")
return v
Core computation module following the APEX platform risk_engine/ path structure. Includes production-grade safety caps and logging hooks.
import logging
from dataclasses import dataclass, field
logger = logging.getLogger(__name__)
@dataclass(frozen=True)
class KellyParameters:
"""Immutable configuration for Kelly-based position sizing."""
base_kelly_pct: float
fractional_multiplier: float = 0.5
max_position_cap_pct: float = 10.0
min_position_size: int = 1
@property
def effective_kelly_pct(self) -> float:
"""Apply fractional scaling and hard caps."""
raw_size = self.base_kelly_pct * self.fractional_multiplier
return min(raw_size, self.max_position_cap_pct)
def calculate_kelly_size(
win_rate: float,
reward_to_risk: float,
account_equity: float,
stop_distance: float,
asset_price: float,
params: Optional[KellyParameters] = None
) -> dict:
"""Compute optimal position size using Fractional Kelly Criterion.
Args:
win_rate: Historical probability of winning trades (0.0-1.0)
reward_to_risk: Average profit per winning trade / average loss per losing trade
account_equity: Current available trading capital
stop_distance: Price distance to stop loss level
asset_price: Current market price of the asset
params: Optional Kelly configuration overrides
Returns:
Dictionary with calculated position size, risk allocation, and metadata.
"""
if params is None:
params = KellyParameters(fractional_multiplier=0.25) # Conservative default
# Full Kelly calculation
full_kelly = win_rate - ((1 - win_rate) / reward_to_risk)
if full_kelly <= 0:
logger.warning("Kelly output ≤ 0 — strategy edge not statistically validated")
return {"position_size": params.min_position_size, "allocation_pct": 0.0, "kelly_raw": 0.0}
safe_params = KellyParameters(
base_kelly_pct=full_kelly,
fractional_multiplier=params.fractional_multiplier,
max_position_cap_pct=params.max_position_cap_pct
)
effective_pct = safe_params.effective_kelly_pct
risk_amount = account_equity * (effective_pct / 100)
shares_or_contracts = int(risk_amount / stop_distance) if stop_distance > 0 else params.min_position_size
actual_allocation = (shares_or_contracts * asset_price) / account_equity * 100
logger.info(
"Kelly sizing computed: W=%.2f R:R=%.2f K_full=%.3f K_frac=%.3f Size=%d",
win_rate, reward_to_risk, full_kelly, effective_pct, shares_or_contracts
)
return {
"position_size": max(shares_or_contracts, params.min_position_size),
"allocation_pct": round(effective_pct, 3),
"kelly_raw": round(full_kelly, 4),
"risk_amount": round(risk_amount, 2)
}
# ❌ BAD: Full Kelly with no fractional scaling, no validation, no caps
def naive_kelly(win_rate, rr):
k = win_rate - ((1 - win_rate) / rr)
return int(account * k / stop_dist) # Will overallocate during drawdowns, ignores sample size
# ✅ GOOD: Validated fractional Kelly with parameter bounds and logging
def production_kelly(stats: TradeStatistics, equity: float, price: float, distance: float):
raw = stats.win_rate - ((1 - stats.win_rate) / stats.avg_reward_to_risk)
if raw <= 0:
return {"position_size": 0} # No edge detected
frac = 0.25 if stats.total_trades < 200 else 0.5
effective = min(raw * frac, 0.10) # Hard cap at 10% of bankroll
size = max(1, int(equity * effective / distance))
return {"position_size": size, "allocation_pct": round(effective * 100, 2)}
| Skill | Purpose |
|---|---|
risk-stop-loss | Layer adaptive stop losses on top of Kelly-sized positions to cap downside risk |
risk-position-sizing | Alternative sizing methods (fixed fractional, volatility-adjusted) for comparison |
risk-kill-switches | Emergency circuit breakers that override Kelly sizing during extreme market stress |
Authoritative documentation and mathematical foundations for Kelly Criterion in algorithmic trading.