Position Sizing Position sizing is the single most important risk management decision in trading. Your entry signal determines direction; your position size determines survival. A mediocre strategy with proper sizing will outperform a great strategy with reckless sizing over any meaningful time horizon. Core principle : Size determines survival, not entries. Two traders with the same signals but different sizing will have wildly different outcomes. The one who sizes conservatively survives drawdowns and compounds capital; the one who oversizes blows up. Methods Covered | Method | Best For | K…

:>10} {'Risk%':>8} {'Sector':\u003c10}\"\n print(header)\n print(f\" {'-' * 74}\")\n\n for p in sorted(positions, key=lambda x: x.position_value, reverse=True):\n pct_acct = (p.position_value / account_size) * 100\n risk_pct_acct = (p.total_risk / account_size) * 100\n print(\n f\" {p.symbol:\u003c8} \"\n f\"${fmt(p.position_value):>9} \"\n f\"{pct_acct:>7.1f}% \"\n f\"${fmt(p.unrealized_pnl):>9} \"\n f\"{p.unrealized_pnl_pct:>+7.1f}% \"\n f\"${fmt(p.total_risk):>9} \"\n f\"{risk_pct_acct:>7.1f}% \"\n f\"{p.sector:\u003c10}\"\n )\n\n print(f\" {'-' * 74}\")\n total_risk_pct = (metrics['total_risk'] / account_size) * 100\n print(\n f\" {'TOTAL':\u003c8} \"\n f\"${fmt(metrics['total_value']):>9} \"\n f\"{metrics['exposure_pct']:>7.1f}% \"\n f\"${fmt(metrics['total_pnl']):>9} \"\n f\"{'':>8} \"\n f\"${fmt(metrics['total_risk']):>9} \"\n f\"{total_risk_pct:>7.1f}% \"\n )\n\n # ── Risk Analysis ───────────────────────────────────────────\n print_header(\"RISK ANALYSIS\")\n print(f\" Simple Total Risk: ${fmt(metrics['total_risk'])} ({total_risk_pct:.1f}% of account)\")\n print(f\" Correlation-Adjusted Risk: ${fmt(corr_risk)} ({corr_risk / account_size * 100:.1f}% of account)\")\n print(f\" Diversification Benefit: ${fmt(metrics['total_risk'] - corr_risk)} saved by diversification\")\n\n if metrics[\"total_risk\"] > 0:\n div_ratio = corr_risk / metrics[\"total_risk\"]\n print(f\" Diversification Ratio: {div_ratio:.2f} (1.0 = no benefit, lower = better)\")\n\n # ── Sector Exposure ─────────────────────────────────────────\n print_header(\"SECTOR EXPOSURE\")\n print(f\" {'Sector':\u003c12} {'Positions':\u003c20} {'Value':>10} {'% Acct':>8} {'Risk

Position Sizing Position sizing is the single most important risk management decision in trading. Your entry signal determines direction; your position size determines survival. A mediocre strategy with proper sizing will outperform a great strategy with reckless sizing over any meaningful time horizon. Core principle : Size determines survival, not entries. Two traders with the same signals but different sizing will have wildly different outcomes. The one who sizes conservatively survives drawdowns and compounds capital; the one who oversizes blows up. Methods Covered | Method | Best For | K…

:>10} {'Limit':>10}\")\n print(f\" {'-' * 70}\")\n\n max_sector = account_size * MAX_CORRELATED_PCT\n for sector, data in sorted(sectors.items(), key=lambda x: x[1][\"total_value\"], reverse=True):\n pos_str = \", \".join(data[\"positions\"])\n over = \" OVER\" if data[\"total_value\"] > max_sector else \"\"\n print(\n f\" {sector:\u003c12} \"\n f\"{pos_str:\u003c20} \"\n f\"${fmt(data['total_value']):>9} \"\n f\"{data['exposure_pct']:>7.1f}% \"\n f\"${fmt(data['total_risk']):>9} \"\n f\"${fmt(max_sector):>9}{over}\"\n )\n\n # ── Portfolio Limit Checks ──────────────────────────────────\n print_header(\"LIMIT CHECKS\")\n\n checks = [\n (\n \"Total exposure \u003c 70%\",\n metrics[\"exposure_pct\"] \u003c= MAX_TOTAL_EXPOSURE_PCT * 100,\n f\"{metrics['exposure_pct']:.1f}%\",\n ),\n (\n \"Each position \u003c 10%\",\n all((p.position_value / account_size) * 100 \u003c= MAX_SINGLE_POSITION_PCT * 100 for p in positions),\n f\"max {max((p.position_value / account_size) * 100 for p in positions):.1f}%\" if positions else \"N/A\",\n ),\n ]\n\n # Check each sector\n for sector, data in sectors.items():\n ok = data[\"exposure_pct\"] \u003c= MAX_CORRELATED_PCT * 100\n checks.append((\n f\"{sector} sector \u003c 25%\",\n ok,\n f\"{data['exposure_pct']:.1f}%\",\n ))\n\n for label, passed, detail in checks:\n status = \"PASS\" if passed else \"FAIL\"\n print(f\" [{status}] {label:\u003c35} ({detail})\")\n\n # ── Available Budget ────────────────────────────────────────\n print_header(\"AVAILABLE BUDGET FOR NEXT TRADE\")\n print(f\" Remaining exposure capacity: ${fmt(budget['remaining_exposure'])}\")\n print(f\" Max single position: ${fmt(budget['max_single_position'])}\")\n print(f\" Max new position value: ${fmt(budget['max_new_position'])}\")\n print(f\" Risk budget (2% of account): ${fmt(budget['risk_budget'])}\")\n\n if budget[\"can_add_position\"]:\n print(f\"\\n You can open a new position up to ${fmt(budget['max_new_position'])} in value.\")\n print(f\" With 2% risk ({fmt(budget['risk_budget'])} USD), and a 10% stop,\")\n print(f\" that allows ~${fmt(budget['risk_budget'] / 0.10)} notional position.\")\n else:\n print(\"\\n Portfolio is at maximum exposure. Close or reduce a position before adding new ones.\")\n\n if budget[\"sector_room\"]:\n print(\"\\n Room by sector before hitting 25% limit:\")\n for sector, room in sorted(budget[\"sector_room\"].items(), key=lambda x: x[1]):\n print(f\" {sector:\u003c12} ${fmt(room)} remaining\")\n\n\n# ── Main ────────────────────────────────────────────────────────────\n\ndef main() -> None:\n \"\"\"Run the portfolio sizer with demo or configured data.\"\"\"\n positions = get_demo_positions()\n\n if ACCOUNT_SIZE \u003c= 0:\n print(\"Error: ACCOUNT_SIZE must be positive\")\n sys.exit(1)\n\n print(\"Using demo portfolio (5 positions)\")\n print(f\"Account size: ${fmt(ACCOUNT_SIZE)} (set ACCOUNT_SIZE env var to change)\")\n\n print_portfolio_report(positions, ACCOUNT_SIZE)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":17126,"content_sha256":"286614c9255774253ff9f9ee3e3d004e33328de5d5bb0696db767af95e7279c0"},{"filename":"scripts/size_calculator.py","content":"#!/usr/bin/env python3\n\"\"\"Position size calculator using multiple sizing methods.\n\nCalculates position size using fixed fractional, volatility-adjusted,\nKelly criterion, and liquidity-constrained methods. Shows the binding\nconstraint and provides a formatted report.\n\nUsage:\n python scripts/size_calculator.py\n\n Or with environment variables:\n ACCOUNT_SIZE=10000 ENTRY_PRICE=1.50 STOP_LOSS=1.30 python scripts/size_calculator.py\n\nDependencies:\n None (pure math, no external packages required)\n\nEnvironment Variables:\n ACCOUNT_SIZE: Account value in USD (default: 10000)\n ENTRY_PRICE: Entry price per unit (default: 1.50)\n STOP_LOSS: Stop loss price per unit (default: 1.30)\n WIN_RATE: Historical win rate 0-1 (default: 0.55)\n AVG_WIN_RATIO: Average win / average loss ratio (default: 1.8)\n POOL_LIQUIDITY: Total pool liquidity in USD (default: 50000)\n ATR_VALUE: 14-period ATR in price units (default: 0.12)\n TARGET_VOL_PCT: Target daily portfolio vol as decimal (default: 0.02)\n FEE_RATE: One-way trading fee as decimal (default: 0.003)\n SLIPPAGE_EST: Estimated slippage as decimal (default: 0.005)\n\"\"\"\n\nimport os\nimport sys\nfrom typing import Optional\n\n\n# ── Configuration ───────────────────────────────────────────────────\n\ndef get_float_env(name: str, default: float) -> float:\n \"\"\"Read a float from an environment variable with a default.\"\"\"\n val = os.getenv(name, \"\")\n if not val:\n return default\n try:\n return float(val)\n except ValueError:\n print(f\"Warning: {name}='{val}' is not a valid number, using default {default}\")\n return default\n\n\nACCOUNT_SIZE = get_float_env(\"ACCOUNT_SIZE\", 10_000.0)\nENTRY_PRICE = get_float_env(\"ENTRY_PRICE\", 1.50)\nSTOP_LOSS = get_float_env(\"STOP_LOSS\", 1.30)\nWIN_RATE = get_float_env(\"WIN_RATE\", 0.55)\nAVG_WIN_RATIO = get_float_env(\"AVG_WIN_RATIO\", 1.8)\nPOOL_LIQUIDITY = get_float_env(\"POOL_LIQUIDITY\", 50_000.0)\nATR_VALUE = get_float_env(\"ATR_VALUE\", 0.12)\nTARGET_VOL_PCT = get_float_env(\"TARGET_VOL_PCT\", 0.02)\nFEE_RATE = get_float_env(\"FEE_RATE\", 0.003)\nSLIPPAGE_EST = get_float_env(\"SLIPPAGE_EST\", 0.005)\n\n\n# ── Fixed Fractional Sizing ────────────────────────────────────────\n\ndef fixed_fractional(\n account: float,\n risk_pct: float,\n entry: float,\n stop: float,\n fee_rate: float = 0.0,\n slippage: float = 0.0,\n) -> dict:\n \"\"\"Calculate position size using fixed fractional method.\n\n Args:\n account: Total account value.\n risk_pct: Fraction of account to risk (e.g., 0.02 for 2%).\n entry: Entry price per unit.\n stop: Stop loss price per unit.\n fee_rate: One-way fee rate (applied to entry and exit).\n slippage: Estimated slippage as fraction of entry price.\n\n Returns:\n Dictionary with units, value, risk_amount, and effective_risk.\n \"\"\"\n risk_amount = account * risk_pct\n price_risk = abs(entry - stop)\n fee_cost = entry * fee_rate * 2 # round-trip fees\n slippage_cost = entry * slippage\n effective_risk = price_risk + fee_cost + slippage_cost\n\n if effective_risk \u003c= 0:\n return {\"units\": 0.0, \"value\": 0.0, \"risk_amount\": risk_amount, \"effective_risk\": 0.0}\n\n units = risk_amount / effective_risk\n value = units * entry\n\n return {\n \"units\": units,\n \"value\": value,\n \"risk_amount\": risk_amount,\n \"effective_risk\": effective_risk,\n \"price_risk\": price_risk,\n \"fee_cost\": fee_cost,\n \"slippage_cost\": slippage_cost,\n }\n\n\n# ── Volatility-Adjusted Sizing ─────────────────────────────────────\n\ndef volatility_adjusted(\n account: float,\n target_vol_pct: float,\n atr: float,\n entry: float,\n) -> dict:\n \"\"\"Calculate position size scaled by volatility.\n\n Args:\n account: Total account value.\n target_vol_pct: Target daily portfolio volatility as decimal.\n atr: Average True Range (14-period) in price units.\n entry: Current price per unit.\n\n Returns:\n Dictionary with units, value, and volatility metrics.\n \"\"\"\n if atr \u003c= 0:\n return {\"units\": 0.0, \"value\": 0.0, \"daily_vol_pct\": 0.0, \"expected_daily_pnl\": 0.0}\n\n target_daily_pnl = account * target_vol_pct\n daily_vol_pct = atr / entry\n units = target_daily_pnl / atr\n value = units * entry\n expected_daily_pnl = units * atr\n\n return {\n \"units\": units,\n \"value\": value,\n \"daily_vol_pct\": daily_vol_pct,\n \"expected_daily_pnl\": expected_daily_pnl,\n \"target_daily_pnl\": target_daily_pnl,\n }\n\n\n# ── Kelly Criterion Sizing ─────────────────────────────────────────\n\ndef kelly_criterion(\n account: float,\n win_rate: float,\n payoff_ratio: float,\n entry: float,\n stop: float,\n fraction: float = 0.25,\n) -> dict:\n \"\"\"Calculate position size using Kelly criterion.\n\n Args:\n account: Total account value.\n win_rate: Probability of winning trade (0-1).\n payoff_ratio: Average win / average loss.\n entry: Entry price per unit.\n stop: Stop loss price per unit.\n fraction: Kelly fraction to use (0.25 recommended).\n\n Returns:\n Dictionary with full Kelly, fractional Kelly, units, and value.\n \"\"\"\n q = 1.0 - win_rate\n if payoff_ratio \u003c= 0:\n return {\n \"full_kelly\": 0.0, \"fractional_kelly\": 0.0, \"fraction_used\": fraction,\n \"units\": 0.0, \"value\": 0.0, \"has_edge\": False,\n }\n\n full_kelly = (win_rate * payoff_ratio - q) / payoff_ratio\n has_edge = full_kelly > 0\n fractional_kelly = max(0.0, full_kelly * fraction)\n\n price_risk = abs(entry - stop)\n if price_risk \u003c= 0 or not has_edge:\n units = 0.0\n else:\n risk_amount = account * fractional_kelly\n units = risk_amount / price_risk\n\n value = units * entry\n\n return {\n \"full_kelly\": full_kelly,\n \"fractional_kelly\": fractional_kelly,\n \"fraction_used\": fraction,\n \"units\": units,\n \"value\": value,\n \"has_edge\": has_edge,\n \"expected_growth_fraction\": fractional_kelly * (2 - fractional_kelly / max(full_kelly, 1e-9)),\n }\n\n\n# ── Liquidity-Constrained Sizing ───────────────────────────────────\n\ndef liquidity_constrained(\n pool_liquidity: float,\n max_slippage_pct: float,\n entry: float,\n) -> dict:\n \"\"\"Calculate maximum position size based on pool liquidity.\n\n Args:\n pool_liquidity: Total pool liquidity in USD.\n max_slippage_pct: Maximum acceptable slippage as decimal.\n entry: Token price per unit.\n\n Returns:\n Dictionary with max_value, max_units, and expected slippage.\n \"\"\"\n if pool_liquidity \u003c= 0 or entry \u003c= 0:\n return {\"max_value\": 0.0, \"max_units\": 0.0, \"expected_slippage_pct\": 0.0}\n\n max_value = pool_liquidity * max_slippage_pct\n max_units = max_value / entry\n expected_slippage_pct = max_slippage_pct\n\n return {\n \"max_value\": max_value,\n \"max_units\": max_units,\n \"expected_slippage_pct\": expected_slippage_pct,\n \"pool_liquidity\": pool_liquidity,\n \"position_as_pct_of_pool\": (max_value / pool_liquidity) * 100,\n }\n\n\n# ── R:R Targets ────────────────────────────────────────────────────\n\ndef calculate_rr_targets(\n entry: float,\n stop: float,\n units: float,\n) -> list:\n \"\"\"Calculate reward-to-risk targets for a given position.\n\n Args:\n entry: Entry price.\n stop: Stop loss price.\n units: Number of units in position.\n\n Returns:\n List of dicts with R multiple, target price, and P&L.\n \"\"\"\n risk_per_unit = abs(entry - stop)\n direction = 1 if entry > stop else -1 # long if stop below entry\n targets = []\n\n for r_multiple in [1.0, 1.5, 2.0, 3.0, 5.0]:\n target_price = entry + direction * risk_per_unit * r_multiple\n pnl = units * direction * (target_price - entry)\n targets.append({\n \"r_multiple\": r_multiple,\n \"target_price\": round(target_price, 6),\n \"pnl\": round(pnl, 2),\n })\n\n return targets\n\n\n# ── Report Formatting ──────────────────────────────────────────────\n\ndef format_number(val: float, decimals: int = 2) -> str:\n \"\"\"Format a number with commas and specified decimals.\"\"\"\n return f\"{val:,.{decimals}f}\"\n\n\ndef print_header(title: str) -> None:\n \"\"\"Print a section header.\"\"\"\n width = 60\n print(f\"\\n{'=' * width}\")\n print(f\" {title}\")\n print(f\"{'=' * width}\")\n\n\ndef print_row(label: str, value: str, width: int = 40) -> None:\n \"\"\"Print a label-value row.\"\"\"\n print(f\" {label:\u003c{width}} {value}\")\n\n\ndef print_report(\n account: float,\n entry: float,\n stop: float,\n win_rate: float,\n payoff_ratio: float,\n pool_liquidity: float,\n atr: float,\n target_vol_pct: float,\n fee_rate: float,\n slippage_est: float,\n) -> None:\n \"\"\"Print the complete position sizing report.\n\n Args:\n account: Account value in USD.\n entry: Entry price per unit.\n stop: Stop loss price per unit.\n win_rate: Historical win rate (0-1).\n payoff_ratio: Avg win / avg loss.\n pool_liquidity: Pool liquidity in USD.\n atr: 14-period ATR in price units.\n target_vol_pct: Target daily vol as decimal.\n fee_rate: One-way fee rate.\n slippage_est: Estimated slippage fraction.\n \"\"\"\n # ── Input Summary ───────────────────────────────────────────\n print_header(\"POSITION SIZE CALCULATOR\")\n print_row(\"Account Size\", f\"${format_number(account)}\")\n print_row(\"Entry Price\", f\"${format_number(entry, 6)}\")\n print_row(\"Stop Loss\", f\"${format_number(stop, 6)}\")\n print_row(\"Price Risk\", f\"${format_number(abs(entry - stop), 6)} ({abs(entry - stop) / entry * 100:.1f}%)\")\n print_row(\"Win Rate\", f\"{win_rate * 100:.1f}%\")\n print_row(\"Payoff Ratio\", f\"{payoff_ratio:.2f}x\")\n print_row(\"Pool Liquidity\", f\"${format_number(pool_liquidity)}\")\n print_row(\"ATR(14)\", f\"${format_number(atr, 6)}\")\n print_row(\"Fee Rate (one-way)\", f\"{fee_rate * 100:.2f}%\")\n print_row(\"Slippage Estimate\", f\"{slippage_est * 100:.2f}%\")\n\n # ── Fixed Fractional ────────────────────────────────────────\n print_header(\"METHOD 1: FIXED FRACTIONAL\")\n results_ff = {}\n for risk_pct in [0.01, 0.02, 0.03]:\n ff = fixed_fractional(account, risk_pct, entry, stop, fee_rate, slippage_est)\n results_ff[risk_pct] = ff\n label = f\"{risk_pct * 100:.0f}% risk\"\n print_row(\n label,\n f\"{format_number(ff['units'])} units | ${format_number(ff['value'])} value | ${format_number(ff['risk_amount'])} at risk\",\n )\n ff_default = results_ff[0.02]\n print(f\"\\n Fee-adjusted risk per unit: ${format_number(ff_default['effective_risk'], 4)}\")\n print(f\" (Price risk ${format_number(ff_default['price_risk'], 4)} + fees ${format_number(ff_default['fee_cost'], 4)} + slippage ${format_number(ff_default['slippage_cost'], 4)})\")\n\n # ── Volatility-Adjusted ─────────────────────────────────────\n print_header(\"METHOD 2: VOLATILITY-ADJUSTED\")\n va = volatility_adjusted(account, target_vol_pct, atr, entry)\n print_row(\"Daily Vol (ATR/Price)\", f\"{va['daily_vol_pct'] * 100:.1f}%\")\n print_row(\"Target Daily PnL\", f\"${format_number(va['target_daily_pnl'])}\")\n print_row(\"Position Size\", f\"{format_number(va['units'])} units\")\n print_row(\"Position Value\", f\"${format_number(va['value'])}\")\n print_row(\"Expected Daily PnL Range\", f\"+/- ${format_number(va['expected_daily_pnl'])}\")\n\n # ── Kelly Criterion ─────────────────────────────────────────\n print_header(\"METHOD 3: KELLY CRITERION\")\n kelly_results = {}\n for frac, label in [(1.0, \"Full Kelly\"), (0.5, \"Half Kelly\"), (0.25, \"Quarter Kelly\")]:\n kc = kelly_criterion(account, win_rate, payoff_ratio, entry, stop, frac)\n kelly_results[frac] = kc\n edge_str = \"\" if kc[\"has_edge\"] else \" [NO EDGE]\"\n print_row(\n f\"{label} ({frac:.0%})\",\n f\"{kc['fractional_kelly'] * 100:.1f}% risk | {format_number(kc['units'])} units | ${format_number(kc['value'])}{edge_str}\",\n )\n full_kc = kelly_results[1.0]\n print(f\"\\n Full Kelly fraction: {full_kc['full_kelly'] * 100:.2f}%\")\n if not full_kc[\"has_edge\"]:\n print(\" *** NEGATIVE KELLY: No statistical edge detected. Do not trade. ***\")\n else:\n print(\" Recommendation: Use Quarter Kelly (0.25x) as default\")\n\n # ── Liquidity-Constrained ───────────────────────────────────\n print_header(\"METHOD 4: LIQUIDITY-CONSTRAINED\")\n liq_results = {}\n for slip_pct in [0.01, 0.02, 0.05]:\n lc = liquidity_constrained(pool_liquidity, slip_pct, entry)\n liq_results[slip_pct] = lc\n print_row(\n f\"{slip_pct * 100:.0f}% max slippage\",\n f\"{format_number(lc['max_units'])} units | ${format_number(lc['max_value'])} max value | {lc['position_as_pct_of_pool']:.1f}% of pool\",\n )\n\n # ── Combined Recommendation ─────────────────────────────────\n print_header(\"RECOMMENDATION (BINDING CONSTRAINT)\")\n\n candidates = {\n \"Fixed Fractional (2%)\": ff_default[\"units\"],\n \"Volatility-Adjusted\": va[\"units\"],\n \"Quarter Kelly\": kelly_results[0.25][\"units\"],\n \"Liquidity (2% slip)\": liq_results[0.02][\"max_units\"],\n }\n\n # Filter out zero/negative\n valid = {k: v for k, v in candidates.items() if v > 0}\n if not valid:\n print(\" No valid position size found. Check inputs.\")\n return\n\n binding_method = min(valid, key=valid.get)\n recommended_units = valid[binding_method]\n recommended_value = recommended_units * entry\n pct_of_account = (recommended_value / account) * 100\n\n print_row(\"Binding Constraint\", binding_method)\n print_row(\"Recommended Size\", f\"{format_number(recommended_units)} units\")\n print_row(\"Position Value\", f\"${format_number(recommended_value)}\")\n print_row(\"% of Account\", f\"{pct_of_account:.1f}%\")\n\n # Check portfolio limits\n print(\"\\n Portfolio limit checks:\")\n single_ok = pct_of_account \u003c= 10\n print(f\" Single position \u003c 10%: {'PASS' if single_ok else 'FAIL'} ({pct_of_account:.1f}%)\")\n\n print(\"\\n All methods compared:\")\n for method, units in sorted(candidates.items(), key=lambda x: x[1]):\n marker = \" \u003c-- BINDING\" if method == binding_method else \"\"\n val = units * entry\n print(f\" {method:\u003c30} {format_number(units):>12} units ${format_number(val):>12}{marker}\")\n\n # ── R:R Targets ─────────────────────────────────────────────\n print_header(\"R:R TARGETS (at recommended size)\")\n risk_per_unit = abs(entry - stop)\n risk_total = recommended_units * risk_per_unit\n targets = calculate_rr_targets(entry, stop, recommended_units)\n\n print_row(\"Risk per trade\", f\"${format_number(risk_total)}\")\n print()\n print(f\" {'R:R':\u003c8} {'Target Price':\u003c16} {'P&L':\u003c16} {'% of Account'}\")\n print(f\" {'-' * 56}\")\n for t in targets:\n pct = (t[\"pnl\"] / account) * 100\n print(f\" {t['r_multiple']:\u003c8.1f} ${format_number(t['target_price'], 6):\u003c14} ${format_number(t['pnl']):\u003c14} {pct:+.2f}%\")\n\n\n# ── Validation ──────────────────────────────────────────────────────\n\ndef validate_inputs(\n account: float,\n entry: float,\n stop: float,\n win_rate: float,\n payoff_ratio: float,\n pool_liquidity: float,\n) -> list:\n \"\"\"Validate inputs and return list of warning messages.\n\n Args:\n account: Account size.\n entry: Entry price.\n stop: Stop loss price.\n win_rate: Win rate (0-1).\n payoff_ratio: Avg win / avg loss.\n pool_liquidity: Pool liquidity.\n\n Returns:\n List of warning/error strings. Empty list means all OK.\n \"\"\"\n errors: list = []\n if account \u003c= 0:\n errors.append(\"Account size must be positive\")\n if entry \u003c= 0:\n errors.append(\"Entry price must be positive\")\n if stop \u003c= 0:\n errors.append(\"Stop loss must be positive\")\n if entry == stop:\n errors.append(\"Entry and stop loss cannot be the same price\")\n if not 0 \u003c win_rate \u003c 1:\n errors.append(f\"Win rate must be between 0 and 1, got {win_rate}\")\n if payoff_ratio \u003c= 0:\n errors.append(\"Payoff ratio must be positive\")\n if pool_liquidity \u003c= 0:\n errors.append(\"Pool liquidity must be positive\")\n\n # Warnings (non-fatal)\n risk_pct = abs(entry - stop) / entry * 100\n if risk_pct > 30:\n errors.append(f\"Warning: Stop distance is {risk_pct:.1f}% from entry (very wide)\")\n if pool_liquidity \u003c account * 0.1:\n errors.append(\"Warning: Pool liquidity is less than 10% of account size\")\n\n return errors\n\n\n# ── Main ────────────────────────────────────────────────────────────\n\ndef main() -> None:\n \"\"\"Run the position size calculator with configured parameters.\"\"\"\n issues = validate_inputs(\n ACCOUNT_SIZE, ENTRY_PRICE, STOP_LOSS,\n WIN_RATE, AVG_WIN_RATIO, POOL_LIQUIDITY,\n )\n\n fatal = [i for i in issues if not i.startswith(\"Warning\")]\n warnings = [i for i in issues if i.startswith(\"Warning\")]\n\n if fatal:\n print(\"Input errors:\")\n for e in fatal:\n print(f\" - {e}\")\n sys.exit(1)\n\n if warnings:\n print(\"Warnings:\")\n for w in warnings:\n print(f\" - {w}\")\n\n print_report(\n account=ACCOUNT_SIZE,\n entry=ENTRY_PRICE,\n stop=STOP_LOSS,\n win_rate=WIN_RATE,\n payoff_ratio=AVG_WIN_RATIO,\n pool_liquidity=POOL_LIQUIDITY,\n atr=ATR_VALUE,\n target_vol_pct=TARGET_VOL_PCT,\n fee_rate=FEE_RATE,\n slippage_est=SLIPPAGE_EST,\n )\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":19136,"content_sha256":"267693e742aa613f089b7e02392e0321a6c3bed907e23a56666c9a981e9235f4"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Position Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"Position sizing is the single most important risk management decision in trading. Your entry signal determines direction; your position size determines survival. A mediocre strategy with proper sizing will outperform a great strategy with reckless sizing over any meaningful time horizon.","type":"text"}]},{"type":"paragraph","content":[{"text":"Core principle","type":"text","marks":[{"type":"strong"}]},{"text":": Size determines survival, not entries. Two traders with the same signals but different sizing will have wildly different outcomes. The one who sizes conservatively survives drawdowns and compounds capital; the one who oversizes blows up.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Methods Covered","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Best For","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Key Input","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fixed Fractional","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"General trading, most recommended","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Account risk %","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Volatility-Adjusted","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Volatile markets, multi-asset","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ATR or realized vol","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Kelly Criterion","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Quantified edge with track record","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Win rate + payoff ratio","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Liquidity-Constrained","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low-liquidity Solana tokens","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pool depth","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Anti-Martingale","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trend-following strategies","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Recent P&L streak","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"1. Fixed Fractional Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"The most recommended method for most traders. Risk a fixed percentage of your account on each trade.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Formula","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"risk_amount = account_value * risk_percentage\nprice_risk_per_unit = entry_price - stop_loss_price\nposition_size_units = risk_amount / price_risk_per_unit\nposition_value = position_size_units * entry_price","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Risk Tiers","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tier","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Risk Per Trade","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use Case","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Conservative","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.5–1%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"New strategies, drawdown recovery","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Standard","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1–2%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Most traders, proven strategies","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Aggressive","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"3–5%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High-conviction setups with strong, measured edge","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"account = 10_000 # $10,000 or 100 SOL\nrisk_pct = 0.02 # 2%\nentry = 1.50\nstop_loss = 1.30\n\nrisk_amount = account * risk_pct # $200\nprice_risk = entry - stop_loss # $0.20\nposition_units = risk_amount / price_risk # 1,000 tokens\nposition_value = position_units * entry # $1,500","type":"text"}]},{"type":"paragraph","content":[{"text":"With this sizing, if the stop loss is hit, you lose exactly 2% of your account regardless of the token's price or volatility.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"2. Volatility-Adjusted Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"Scale position size inversely with volatility. When volatility is high, take smaller positions; when low, take larger positions. This normalizes the dollar risk across different market conditions.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Formula","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"adjusted_size = base_size * (target_vol / current_vol)","type":"text"}]},{"type":"paragraph","content":[{"text":"Where:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"target_vol","type":"text","marks":[{"type":"code_inline"}]},{"text":": your desired daily portfolio volatility (e.g., 2%)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"current_vol","type":"text","marks":[{"type":"code_inline"}]},{"text":": the token's current daily volatility (from ATR or realized vol)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Using ATR","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"atr_14 = 0.12 # 14-period ATR\nclose_price = 1.50\ndaily_vol_pct = atr_14 / close_price # 8%\n\ntarget_daily_vol = account * 0.02 # $200 target daily move\nposition_size = target_daily_vol / atr_14 # 1,667 units","type":"text"}]},{"type":"paragraph","content":[{"text":"This automatically reduces exposure in volatile markets and increases it in calm ones.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"3. Kelly Criterion","type":"text"}]},{"type":"paragraph","content":[{"text":"The mathematically optimal fraction of capital to risk, maximizing long-term growth rate. Derived from maximizing expected logarithmic utility.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Formula","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"f* = (p * b - q) / b","type":"text"}]},{"type":"paragraph","content":[{"text":"Where:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"p","type":"text","marks":[{"type":"code_inline"}]},{"text":" = win rate (probability of winning trade)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"q","type":"text","marks":[{"type":"code_inline"}]},{"text":" = 1 - p (probability of losing trade)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"b","type":"text","marks":[{"type":"code_inline"}]},{"text":" = average win / average loss (payoff ratio)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"f*","type":"text","marks":[{"type":"code_inline"}]},{"text":" = optimal fraction of capital to risk","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Equivalent form: ","type":"text"},{"text":"f* = (p * (b + 1) - 1) / b","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Critical Rule: NEVER Use Full Kelly","type":"text"}]},{"type":"paragraph","content":[{"text":"Full Kelly assumes perfect knowledge of your edge. In practice, edge estimates are noisy. Always use fractional Kelly:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fraction","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use Case","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Notes","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.25x Kelly","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Conservative, recommended default","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Robust to edge estimation error","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0.50x Kelly","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Moderate, for well-measured edges","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Still significant drawdown risk","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1.0x Kelly","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Never in practice","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Theoretical maximum, catastrophic if edge is overestimated","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"win_rate = 0.55 # 55% win rate\navg_win = 2.0 # Average win is 2x the average loss\navg_loss = 1.0\npayoff_ratio = avg_win / avg_loss # b = 2.0\n\nkelly = (win_rate * payoff_ratio - (1 - win_rate)) / payoff_ratio\n# kelly = (0.55 * 2.0 - 0.45) / 2.0 = 0.325 = 32.5%\n\nquarter_kelly = kelly * 0.25 # 8.1% — use this\nhalf_kelly = kelly * 0.50 # 16.25%","type":"text"}]},{"type":"paragraph","content":[{"text":"If Kelly is negative, you have no edge. Do not trade.","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/sizing_formulas.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full mathematical derivation.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"4. Liquidity-Constrained Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"Critical for Solana tokens. Even if your risk model says you can take a large position, the pool may not support it without unacceptable slippage.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Formula (Constant-Product AMM)","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"slippage ≈ trade_size / pool_liquidity\nmax_trade = pool_liquidity * max_slippage_pct","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Rules of Thumb","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Constraint","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Guideline","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max single trade","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"2% of pool liquidity","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max position","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"5% of pool liquidity","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Minimum pool depth","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"10x your desired position size","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"pool_sol = 500 # 500 SOL in pool\nmax_slippage = 0.02 # 2% max slippage\n\nmax_trade_sol = pool_sol * max_slippage # 10 SOL\n# For a $150 SOL price, that's $1,500 max per trade","type":"text"}]},{"type":"paragraph","content":[{"text":"Always check all pools","type":"text","marks":[{"type":"strong"}]},{"text":", not just the largest. Aggregate liquidity across Raydium, Orca, and Meteora for the full picture. See the ","type":"text"},{"text":"liquidity-analysis","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill for pool depth assessment.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"5. Anti-Martingale Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"Increase size after wins, decrease after losses. This is the opposite of the gambler's fallacy (Martingale). The logic: winning streaks may indicate your strategy is in sync with the market; losing streaks may indicate regime change.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Implementation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"def anti_martingale_size(\n base_size: float,\n consecutive_wins: int,\n consecutive_losses: int,\n scale_factor: float = 0.25,\n max_multiplier: float = 2.0,\n min_multiplier: float = 0.5,\n) -> float:\n if consecutive_losses > 0:\n multiplier = max(min_multiplier, 1.0 - consecutive_losses * scale_factor)\n elif consecutive_wins > 0:\n multiplier = min(max_multiplier, 1.0 + consecutive_wins * scale_factor)\n else:\n multiplier = 1.0\n return base_size * multiplier","type":"text"}]},{"type":"paragraph","content":[{"text":"Use conservatively. After 3+ consecutive losses, reducing size by 50% protects capital during drawdowns.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Position Sizing Ladder","type":"text"}]},{"type":"paragraph","content":[{"text":"Combine all methods and take the most conservative result:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"1. Calculate Kelly size → theoretical max based on edge\n2. Calculate fixed fractional → risk-based size\n3. Calculate volatility-adjusted → vol-normalized size\n4. Calculate liquidity-constrained max → market-based ceiling\n5. Final size = min(all four) → binding constraint wins","type":"text"}]},{"type":"paragraph","content":[{"text":"The binding constraint tells you what is limiting your size:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Kelly-bound","type":"text","marks":[{"type":"strong"}]},{"text":": your edge is small, size accordingly","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Risk-bound","type":"text","marks":[{"type":"strong"}]},{"text":": standard risk management is the limit","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Volatility-bound","type":"text","marks":[{"type":"strong"}]},{"text":": market is too volatile for larger size","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Liquidity-bound","type":"text","marks":[{"type":"strong"}]},{"text":": pool cannot absorb more without slippage","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Account-Level Limits","type":"text"}]},{"type":"paragraph","content":[{"text":"Individual position sizing is necessary but not sufficient. You also need portfolio-level constraints:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Limit","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Guideline","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rationale","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max single position","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"10% of portfolio","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Diversification floor","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max correlated exposure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"25% of portfolio","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Correlated assets move together","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max total exposure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"50–80% of portfolio","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cash reserve for opportunities/margin","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max positions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"5–10 concurrent","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Attention and management bandwidth","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"PumpFun / Meme Token Sizing","type":"text"}]},{"type":"paragraph","content":[{"text":"PumpFun and early-stage meme tokens require special sizing discipline:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Very small positions","type":"text","marks":[{"type":"strong"}]},{"text":": 0.1–1 SOL per trade due to extreme risk","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scale with bonding curve fill %","type":"text","marks":[{"type":"strong"}]},{"text":": smaller when early (high rug risk), slightly larger when proven (graduated to Raydium)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never size based on expected return","type":"text","marks":[{"type":"strong"}]},{"text":" — size based on acceptable total loss","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Treat as lottery tickets","type":"text","marks":[{"type":"strong"}]},{"text":": expect most to go to zero","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Position limit","type":"text","marks":[{"type":"strong"}]},{"text":": no more than 5–10% of portfolio across all meme positions combined","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# PumpFun sizing example\naccount_sol = 100\nmeme_budget = account_sol * 0.05 # 5 SOL total for memes\nper_trade = meme_budget / 10 # 0.5 SOL each, 10 shots","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Integration with Other Skills","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skill","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Integration","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"risk-management","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Portfolio-level limits, drawdown rules","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"liquidity-analysis","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pool depth data for liquidity constraints","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"kelly-criterion","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Deeper Kelly math, edge estimation","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"exit-strategies","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Stop loss placement affects fixed fractional sizing","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"volatility-modeling","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Better vol estimates for volatility-adjusted sizing","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"slippage-modeling","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Precise slippage estimates for liquidity constraints","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Files","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/sizing_formulas.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Mathematical derivations for all sizing methods with worked examples","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/practical_guide.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Sizing by account size, token type, and common mistakes","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Scripts","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/size_calculator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Calculates position size using all methods, shows binding constraint","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/portfolio_sizer.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Portfolio risk dashboard with per-position risk and available budget","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Reference","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Minimal fixed fractional sizing — copy-paste starter\ndef calc_position_size(\n account: float, risk_pct: float, entry: float, stop: float\n) -> float:\n \"\"\"Return number of units to buy.\"\"\"\n risk_amount = account * risk_pct\n price_risk = abs(entry - stop)\n if price_risk == 0:\n return 0.0\n return risk_amount / price_risk","type":"text"}]}]},"metadata":{"date":"2026-11-02","name":"position-sizing","author":"@skillopedia","source":{"stars":508,"repo_name":"claude-trading-skills","origin_url":"https://github.com/agiprolabs/claude-trading-skills/blob/HEAD/skills/position-sizing/SKILL.md","repo_owner":"agiprolabs","body_sha256":"522a7c3de61d7b7edcf36c2ea36f58cb77fc827ee41420abd1e5bc96885d1e5a","cluster_key":"93fa103e826ff5aef1d800b5927e36fb3f3c13d0e35ffe49f1a7601343846ea2","clean_bundle":{"format":"clean-skill-bundle-v1","source":"agiprolabs/claude-trading-skills/skills/position-sizing/SKILL.md","text_bytes":50633,"source_commit":"981e1d736cdc02bdc1c55c74ec9224e956414706","skills_sh_rank":17590,"attachment_count":4,"text_attachments":4,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/position-sizing/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"finance-legal-compliance","category_label":"Finance"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"finance-legal-compliance","import_tag":"skills-sh-top20k-2026-11","description":"Trade sizing methods including fixed fractional, volatility-adjusted, Kelly criterion, and liquidity-constrained sizing"}},"renderedAt":1793661322370}

Position Sizing Position sizing is the single most important risk management decision in trading. Your entry signal determines direction; your position size determines survival. A mediocre strategy with proper sizing will outperform a great strategy with reckless sizing over any meaningful time horizon. Core principle : Size determines survival, not entries. Two traders with the same signals but different sizing will have wildly different outcomes. The one who sizes conservatively survives drawdowns and compounds capital; the one who oversizes blows up. Methods Covered | Method | Best For | K…