The interface is localized. Skill descriptions and documents are machine-translated by AI into your language; code, commands, paths and technical terms stay in the original, and the author's document governs.
Explore skills
Productivity · SKILL.md

fundamentals-risk-management-basics

fundamentals-risk-management-basics

"Position sizing, stop-loss implementation, and system-level risk controls" to preserve capital

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill documentation

GitHub

name: fundamentals-risk-management-basics compatibility: opencode completeness: 95 content-types:

  • code
  • guidance
  • config
  • do-dont description: '"Position sizing, stop-loss implementation, and system-level risk controls" to preserve capital' license: MIT maturity: stable metadata: domain: trading output-format: code related-skills: backtest-drawdown-analysis, backtest-position-sizing, exchange-order-execution-api, risk-correlation-risk role: implementation scope: implementation triggers: fundamentals risk management basics, fundamentals-risk-management-basics, position, sizing, stop-loss archetypes:
    • tactical anti_triggers:
    • brainstorming
    • vague ideation
    • no risk management response_profile: verbosity: low directive_strength: high abstraction_level: operational version: "1.0.0"

Role: Guide an AI coding assistant to implement robust risk management that prevents catastrophic losses while allowing trading opportunities to breathe

Philosophy: Risk management is not about avoiding risk but about optimizing the risk-reward ratio to ensure survival. Capital preservation comes first; without it, no amount of profitable trading matters. Systems must have multiple layers of protection and clear kill-switch mechanisms.

Key Principles

  1. Position Sizing as Probability Management: Position size should be proportional to edge strength, volatility, and account drawdown to ensure survival across losing streaks.

  2. Stop-Loss as Risk Boundary: Stop-losses define maximum acceptable loss per trade; they should be based on technical levels, not arbitrary percentages.

  3. System-Level Kill Switches: Individual trade stops are necessary but insufficient. Systems need account-level, strategy-level, and market-level kill switches.

  4. Correlation-Aware Risk: Portfolio risk isn't the sum of individual risks. Systems must account for correlations between positions and market regimes.

  5. Risk in Context: Risk parameters must adapt to market regime, account size, and recent performance. Static risk rules fail in changing conditions.

Implementation Guidelines

Structure

  • Core logic: risk_management/sizing.py
  • Stops: risk_management/stops.py
  • Kill switches: risk_management/kill_switches.py
  • Portfolio exposure: risk_management/exposure.py

Patterns to Follow

  • Early Exit: Reject positions that violate risk constraints
  • Atomic Predictability: Each risk calculation should be pure and deterministic
  • Fail Fast: Halt operations when risk parameters are invalid
  • Intentional Naming: Clear function names that express risk intent
  • Parse Don't Validate: Risk data parsed at boundaries, trusted internally

Code Examples

# Example 1: Position Sizing Formulas
from dataclasses import dataclass
from decimal import Decimal
from typing import Optional
import math


@dataclass
class PositionSizing:
    """Position sizing calculations for different risk approaches"""
    
    account_balance: float
    max_risk_per_trade: float  # e.g., 0.01 for 1%
    stop_loss_pips: float
    pip_value: float
    volatility: float  # ATR or standard deviation
    edge_strength: float  # 0-1 scale based on signal conviction
    
    def fractional_kelly(
        self,
        win_rate: float,
        avg_win: float,
        avg_loss: float,
        kelly_fraction: float = 0.25
    ) -> float:
        """
        Fractional Kelly position sizing
        Kelly = W - [(1-W) / R]
        Where W = win rate, R = win/loss ratio
        """
        if win_rate <= 0 or win_rate >= 1:
            return 0
        
        win_loss_ratio = avg_win / abs(avg_loss) if avg_loss != 0 else 1
        
        kelly = win_rate - ((1 - win_rate) / win_loss_ratio)
        fractional_kelly = kelly * kelly_fraction
        
        # Bound Kelly to prevent overbetting
        return max(0, min(fractional_kelly, 0.5))
    
    def fixed_risk_sizing(self) -> float:
        """Size to risk fixed dollar amount per trade"""
        risk_amount = self.account_balance * self.max_risk_per_trade
        position_size = risk_amount / (self.stop_loss_pips * self.pip_value)
        return max(0, position_size)
    
    def volatility_adjusted_sizing(self) -> float:
        """Smaller positions in high volatility, larger in low volatility"""
        base_sizing = self.fixed_risk_sizing()
        volatility_multiplier = 0.2 / max(self.volatility, 0.001)  # Normalize to 20 bps
        return base_sizing * volatility_multiplier
    
    def edge_adjusted_sizing(self, edge_multiplier: float = 2.0) -> float:
        """Scale position by signal edge strength"""
        base_size = self.fixed_risk_sizing()
        edge_factor = 1 + (self.edge_strength * edge_multiplier)
        return base_size * edge_factor


# Example 2: Stop-Loss Implementation
class StopLossManager:
    """Manages dynamic stop-loss levels based on technical analysis"""
    
    def __init__(self, config: dict):
        self.config = config
        self.stops: dict[str, dict] = {}
    
    def calculate_atr_stop(
        self,
        entry_price: float,
        atr: float,
        multiplier: float = 2.0,
        trend_direction: str = 'long'
    ) -> float:
        """ATR-based stop-loss that adapts to volatility"""
        if trend_direction == 'long':
            return entry_price - (atr * multiplier)
        else:
            return entry_price + (atr * multiplier)
    
    def calculate_support_resistance_stop(
        self,
        entry_price: float,
        key_level: float,
        buffer_percent: float = 0.5,
        trend_direction: str = 'long'
    ) -> float:
        """Stop placed beyond key support/resistance with buffer"""
        if trend_direction == 'long':
            return min(entry_price, key_level) * (1 - buffer_percent / 100)
        else:
            return max(entry_price, key_level) * (1 + buffer_percent / 100)
    
    def calculate_trailing_stop(
        self,
        current_price: float,
        highest_price: float,
        trail_percent: float = 3.0,
        trend_direction: str = 'long'
    ) -> float:
        """Dynamic trailing stop that moves with price"""
        if trend_direction == 'long':
            return highest_price * (1 - trail_percent / 100)
        else:
            return current_price  # For shorts, trailing works differently
    
    def update_stop(
        self,
        symbol: str,
        entry_price: float,
        current_price: float,
        atr: float,
        support_level: Optional[float] = None,
        trend_direction: str = 'long'
    ) -> float:
        """Update stop-loss to most restrictive level"""
        
        atr_stop = self.calculate_atr_stop(entry_price, atr, trend_direction=trend_direction)
        
        # If support/resistance is closer, use it
        if support_level:
            sr_stop = self.calculate_support_resistance_stop(
                entry_price, support_level, trend_direction=trend_direction
            )
            # Use the more protective stop
            return max(sr_stop, atr_stop) if trend_direction == 'long' else min(sr_stop, atr_stop)
        
        return atr_stop


# Example 3: System-Level Kill Switches
class RiskKillSwitch:
    """Multiple layers of risk control"""
    
    def __init__(self, config: dict):
        self.config = config
        self.active = True
        self.violations: list[dict] = []
    
    def check_account_level(
        self,
        account_balance: float,
        daily_pnl: float,
        daily_drawdown: float,
        session: str = 'all'
    ) -> tuple[bool, list[str]]:
        """Check account-level risk limits"""
        issues = []
        
        # Daily drawdown limit
        max_daily_drawdown = self.config.get('max_daily_drawdown', 0.05)
        if abs(daily_drawdown) > max_daily_drawdown:
            issues.append(f"Daily drawdown {abs(daily_drawdown):.1%} exceeds limit {max_daily_drawdown:.1%}")
        
        # Daily loss limit
        max_daily_loss = self.config.get('max_daily_loss', 0.03)
        if daily_pnl < -max_daily_loss * account_balance:
            issues.append(f"Daily loss {daily_pnl/account_balance:.1%} exceeds limit {max_daily_loss:.1%}")
        
        # Minimum equity requirement
        min_equity = self.config.get('min_equity_requirement', 1000)
        if account_balance < min_equity:
            issues.append(f"Account balance ${account_balance:.2f} below minimum ${min_equity}")
        
        return len(issues) == 0, issues
    
    def check_strategy_level(
        self,
        strategy_id: str,
        unrealized_pnl: float,
        max_strategy_drawdown: float,
        correlated_exposure: float
    ) -> tuple[bool, list[str]]:
        """Check strategy-level risk"""
        issues = []
        
        max_strategy_drawdown_limit = self.config.get('max_strategy_drawdown', 0.10)
        if abs(max_strategy_drawdown) > max_strategy_drawdown_limit:
            issues.append(f"Strategy {strategy_id} drawdown {abs(max_strategy_drawdown):.1%} exceeds limit")
        
        max_correlated_exposure = self.config.get('max_correlated_exposure', 0.30)
        if correlated_exposure > max_correlated_exposure:
            issues.append(f"Correlated exposure {correlated_exposure:.1%} exceeds limit {max_correlated_exposure:.1%}")
        
        return len(issues) == 0, issues
    
    def check_market_level(
        self,
        market_volatility: float,
        spread_width: float,
        liquidity_score: float,
        regime: str
    ) -> tuple[bool, list[str]]:
        """Check market conditions for trading suitability"""
        issues = []
        
        # High volatility filter
        max_volatility = self.config.get('max_volatility', 0.03)  # 3% daily
        if market_volatility > max_volatility:
            issues.append(f"Market volatility {market_volatility:.1%} exceeds limit")
        
        # Spread widen filter
        max_spread = self.config.get('max_spread_bps', 5.0)
        if spread_width > max_spread:
            issues.append(f"Spread {spread_width:.1f} bps exceeds limit {max_spread:.1f} bps")
        
        # Low liquidity filter
        min_liquidity = self.config.get('min_liquidity_score', 0.5)
        if liquidity_score < min_liquidity:
            issues.append(f"Liquidity score {liquidity_score:.2f} below minimum {min_liquidity}")
        
        # Regime filter
        allowed_regimes = self.config.get('allowed_regimes', ['trending', 'range_bound'])
        if regime not in allowed_regimes:
            issues.append(f"Market regime '{regime}' not in allowed list")
        
        return len(issues) == 0, issues
    
    def should_halt_trading(
        self,
        account_balance: float,
        daily_pnl: float,
        daily_drawdown: float,
        strategy_id: str,
        strategy_pnl: float,
        strategy_drawdown: float,
        market_volatility: float,
        spread_width: float,
        liquidity_score: float
    ) -> tuple[bool, list[str]]:
        """Determine if trading should be halted"""
        all_issues = []
        
        account_ok, account_issues = self.check_account_level(
            account_balance, daily_pnl, daily_drawdown
        )
        all_issues.extend(account_issues)
        
        strategy_ok, strategy_issues = self.check_strategy_level(
            strategy_id, strategy_pnl, strategy_drawdown, 0  # correlated exposure to be calculated
        )
        all_issues.extend(strategy_issues)
        
        market_ok, market_issues = self.check_market_level(
            market_volatility, spread_width, liquidity_score, 'trending'
        )
        all_issues.extend(market_issues)
        
        return len(all_issues) == 0, all_issues


# Example 4: Portfolio Heat Calculator
def calculate_portfolio_heat(
    positions: list[dict],
    correlations: dict[str, dict[str, float]]
) -> dict:
    """
    Calculate portfolio-wide risk metrics
    
    positions: List of {symbol, size, pnl, volatility}
    correlations: {symbol1: {symbol2: correlation, ...}, ...}
    """
    if not positions:
        return {
            'total_exposure': 0,
            'net_exposure': 0,
            'gross_exposure': 0,
            'concentration': 0,
            'systemic_risk': 0
        }
    
    # Calculate exposures
    sizes = [p['size'] for p in positions]
    gross_exposure = sum(abs(s) for s in sizes)
    net_exposure = sum(sizes)
    
    # Concentration (Herfindahl-Hirschman Index)
    total_size = gross_exposure or 1
    concentration = sum((s / total_size) ** 2 for s in sizes)
    
    # Systemic risk (portfolio variance approximation)
    portfolio_variance = 0
    for i, p1 in enumerate(positions):
        for j, p2 in enumerate(positions):
            if i <= j:
                corr = correlations.get(p1['symbol'], {}).get(p2['symbol'], 0)
                portfolio_variance += (
                    p1['size'] * p2['size'] * 
                    p1['volatility'] * p2['volatility'] * 
                    corr
                )
    
    portfolio_volatility = math.sqrt(abs(portfolio_variance))
    
    return {
        'total_exposure': gross_exposure,
        'net_exposure': net_exposure,
        'gross_exposure': gross_exposure,
        'concentration': concentration,
        'systemic_risk': portfolio_volatility
    }

Adherence Checklist

Before completing your task, verify:

  • Position sizing accounts for volatility, edge, and account drawdown
  • Stop-losses are based on technical levels, not arbitrary percentages
  • Kill switches operate at account, strategy, and market levels
  • Portfolio heat calculation includes correlations
  • Risk calculations use intention-revealing names
  • Early exit guards prevent trading when risk limits are breached

Common Mistakes to Avoid

  1. Fixed Dollar Position Sizing: Ignoring volatility differences between assets
  2. Stop-Loss Hunting: Placing stops at obvious technical levels where they get hunted
  3. Lack of Kill Switch Testing: Not testing kill switch thresholds in simulation
  4. Correlation Blindness: Treating positions as independent when they're correlated
  5. Static Risk Parameters: Using the same risk settings across all market regimes

References

  • Brown, S. (2013). The Art of Risk Management. Wiley.
  • Tharp, T. (2014). Thoughts on Risk Trading. Van Tharp Institute.
  • Papoulis, A. & Pillai, S. (2002). Probability, Random Variables and Stochastic Processes. McGraw-Hill.
  • Risk Management Standards - CFA Institute
  • Portfolio Risk Metrics - Markowitz (1952)

Base Directory

file:///home/paulpas/git/ideas/trading_bot/skills/trading-fundamentals```python

Risk Management Example: Calculating VaR

def calculate_var(returns: np.ndarray, confidence: float = 0.95) -> float: """Calculate Value at Risk using historical simulation.""" sorted_returns = np.sort(returns) index = int((1 - confidence) * len(sorted_returns)) return abs(sorted_returns[index])

Risk Management Example: Expected Shortfall

def calculate_expected_shortfall(returns: np.ndarray, confidence: float = 0.95) -> float: """Calculate Expected Shortfall (Conditional VaR).""" sorted_returns = np.sort(returns) index = int((1 - confidence) * len(sorted_returns)) return abs(sorted_returns[:index].mean())


---

---

## Constraints

### MUST DO
- Define explicit, measurable criteria for each trading concept rather than using subjective or vague definitions
- Include concrete examples of how each principle applies to real market scenarios with specific conditions and outcomes
- Link each fundamental concept to its practical impact on position sizing, risk management, or execution timing
- Maintain version control on framework documents — note when principles are added, modified, or deprecated

### MUST NOT DO
- Do not present trading psychology concepts as universally applicable without acknowledging individual trader differences
- Avoid conflating correlation with causation when discussing market behavior patterns and their drivers
- Never include subjective profit targets or return expectations as part of a fundamental framework
- Do not present risk management principles in isolation — always connect them to specific position and portfolio mechanics


## Live References

> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.

- [Risk Management Tutorial](https://docs.quantconnect.com/tutorials/risk-management)
- [Position Sizing and Risk Control](https://www.investopedia.com/terms/p/position-sizing.asp)
- [Portfolio Risk Metrics](https://en.wikipedia.org/wiki/Value_at_risk)
- [Risk Management Best Practices for Traders](https://www.investopedia.com/articles/trading/05/riskmanagement.asp)
- [Drawdown Control Strategies](https://www.investopedia.com/terms/d/drawdown.asp)
Saved skills