Files
crypto_news/risk/position_sizing.py

60 lines
1.4 KiB
Python
Raw Normal View History

2026-03-20 07:49:42 +09:00
"""Position sizing utilities.
Provides various sizing methods beyond the basic risk-percentage approach.
"""
from __future__ import annotations
from enum import Enum
class SizingMethod(str, Enum):
FIXED_RISK = "fixed_risk"
FIXED_AMOUNT = "fixed_amount"
KELLY = "kelly"
def fixed_risk_size(
balance: float,
entry_price: float,
stop_loss: float,
risk_pct: float = 0.02,
) -> float:
"""Position size = (balance * risk%) / |entry - SL|."""
price_risk = abs(entry_price - stop_loss)
if price_risk == 0:
return 0.0
return round((balance * risk_pct) / price_risk, 8)
def fixed_amount_size(
amount_usd: float,
entry_price: float,
) -> float:
"""Fixed USD amount converted to asset quantity."""
if entry_price <= 0:
return 0.0
return round(amount_usd / entry_price, 8)
def kelly_size(
win_rate: float,
avg_win: float,
avg_loss: float,
balance: float,
entry_price: float,
fraction: float = 0.5,
) -> float:
"""Half-Kelly sizing for conservative edge exploitation.
Kelly% = W - (1-W)/R where R = avg_win/avg_loss
We use fraction (default 0.5) of full Kelly for safety.
"""
if avg_loss == 0 or entry_price <= 0:
return 0.0
r = avg_win / avg_loss
kelly_pct = win_rate - (1 - win_rate) / r
kelly_pct = max(0.0, min(kelly_pct * fraction, 0.1)) # cap at 10%
return round((balance * kelly_pct) / entry_price, 8)