Risk management is the single most important factor separating profitable futures traders from those who blow their accounts. In this tutorial, we'll build a complete risk calculator in Python that handles position sizing, margin requirements, and max drawdown tracking.
Why Risk Calculation Matters
Most aspiring futures traders focus on entries and exits. But the math is clear: even a strategy with 60% win rate will fail if position sizes are too large. Let's build a tool that enforces discipline.
The Core Calculator
from dataclasses import dataclass
from typing import Optional
@dataclass
class FuturesContract:
symbol: str
tick_size: float
tick_value: float
margin: float
# Common futures contracts
CONTRACTS = {
"ES": FuturesContract("ES", 0.25, 12.50, 15_400),
"NQ": FuturesContract("NQ", 0.25, 5.00, 18_700),
"MES": FuturesContract("MES", 0.25, 1.25, 1_540),
"MNQ": FuturesContract("MNQ", 0.25, 0.50, 1_870),
"CL": FuturesContract("CL", 0.01, 10.00, 6_600),
}
class RiskCalculator:
def __init__(self, account_balance: float, max_risk_pct: float = 1.0):
self.account_balance = account_balance
self.max_risk_pct = max_risk_pct
def max_risk_dollars(self) -> float:
return self.account_balance * (self.max_risk_pct / 100)
def position_size(self, symbol: str, stop_ticks: int) -> dict:
contract = CONTRACTS[symbol]
risk_per_contract = stop_ticks * contract.tick_value
max_contracts = int(self.max_risk_dollars() / risk_per_contract)
return {
"symbol": symbol,
"max_contracts": max_contracts,
"risk_per_contract": risk_per_contract,
"total_risk": max_contracts * risk_per_contract,
"margin_required": max_contracts * contract.margin,
"risk_pct": (max_contracts * risk_per_contract / self.account_balance) * 100,
}
def drawdown_tracker(self, trades: list[float]) -> dict:
peak = self.account_balance
balance = self.account_balance
max_dd = 0
for pnl in trades:
balance += pnl
peak = max(peak, balance)
dd = (peak - balance) / peak * 100
max_dd = max(max_dd, dd)
return {
"final_balance": balance,
"peak": peak,
"max_drawdown_pct": round(max_dd, 2),
"total_pnl": sum(trades),
}
# Example usage
calc = RiskCalculator(account_balance=50_000, max_risk_pct=1.5)
result = calc.position_size("ES", stop_ticks=8)
print(f"Max ES contracts with 8-tick stop: {result['max_contracts']}")
print(f"Total risk: ${result['total_risk']:.2f} ({result['risk_pct']:.1f}%)")
Adding Drawdown Rules
Different prop firms have different drawdown rules. Some use End-of-Day (EOD) trailing drawdown, others use real-time. Let's model both:
def eod_trailing_drawdown(daily_closes: list[float], max_dd: float) -> dict:
peak = daily_closes[0]
for i, close in enumerate(daily_closes):
peak = max(peak, close)
dd = peak - close
if dd >= max_dd:
return {"blown": True, "day": i, "drawdown": dd}
return {"blown": False, "max_observed_dd": max(peak - min(daily_closes[daily_closes.index(peak):]), 0)}
def realtime_trailing_drawdown(equity_curve: list[float], max_dd: float) -> dict:
peak = equity_curve[0]
for i, val in enumerate(equity_curve):
peak = max(peak, val)
dd = peak - val
if dd >= max_dd:
return {"blown": True, "tick": i, "drawdown": dd}
return {"blown": False, "peak": peak}
Putting It All Together
if __name__ == "__main__":
calc = RiskCalculator(50_000, max_risk_pct=1.0)
for symbol in ["ES", "MES", "NQ", "MNQ"]:
pos = calc.position_size(symbol, stop_ticks=10)
print(f"{symbol}: {pos['max_contracts']} contracts, "
f"risk ${pos['total_risk']:.0f}, margin ${pos['margin_required']:,.0f}")
# Simulate drawdown tracking
sample_trades = [200, -150, 300, -400, 250, -100, 350, -200, 150, -50]
dd_result = calc.drawdown_tracker(sample_trades)
print(f"\nMax drawdown: {dd_result['max_drawdown_pct']}%")
print(f"Final P&L: ${dd_result['total_pnl']:+,.0f}")
Key Takeaways
- Never risk more than 1-2% per trade β the math protects you from ruin
- Know your contract specs β tick values vary dramatically between instruments
- Track drawdown continuously β not just at end of day
If you're evaluating prop trading firms for futures, PropFirmKey maintains a detailed comparison of major futures prop firms including Alpha Futures with current pricing, drawdown rules, and payout structures.
The full calculator code is on my GitHub. Questions or improvements? Drop them in the comments!
Top comments (0)