DEV Community

Market Masters
Market Masters

Posted on

Risk Management in Algo Trading: Python Strategies That Actually Work

Risk Management in Algo Trading: Python Strategies That Actually Work

Retail traders blow up accounts because they treat risk like an afterthought. Algos amplify that mistake. A single oversized position during volatility spikes wipes out months of edge. Good news: you can code rules to enforce discipline. This post walks through a Python risk engine. It handles position sizing, dynamic stops, and portfolio limits. Use it standalone or hook it into your backtester.

Expect code that runs today. No libraries beyond pandas, numpy, ta-lib. Tradeoffs included: Kelly overoptimizes, ATR lags. Test on real data.

The Rules That Matter

Forget vague "cut losses short." Quantify it.

  1. Risk 1% of capital per trade max. Scales with account size.
  2. Volatility-adjusted position size. Double down on calm assets? No.
  3. Max 5% portfolio exposure to one direction.
  4. Correlation caps: no piling into BTC/ETH when they move together.
  5. Drawdown circuit breaker: pause at -10%.

These are not optional. Ignore them, your Sharpe ratio tanks.

Position Sizing: Kelly with a Leash

Full Kelly bets f/(b*f -1) where f is win rate, b is payoff ratio. Great in theory. Ruinous in practice due to fat tails.

Cap it at half Kelly. Here is the code:

import numpy as np
import pandas as pd

def half_kelly_position(win_rate, avg_win, avg_loss, capital):
    odds = avg_win / abs(avg_loss)
    full_kelly = (win_rate * odds - (1 - win_rate)) / odds
    return max(0, min(0.02, full_kelly / 2)) * capital  # Cap 2% 

# Example
capital = 100000
pos_size = half_kelly_position(0.55, 1.5, -1.0, capital)
print(f"Position size: ${pos_size:.2f}")
# Output: $2750.00
Enter fullscreen mode Exit fullscreen mode

Tune win_rate from backtest. Avg_win/loss from last 100 trades. Recalculate weekly.

Tradeoff: Conservative on choppy markets. Misses runners on trends.

Volatility Stops: ATR Bands

Fixed stops fail. 2% on SPY is different from crypto.

Use 2x ATR(14). Trail it.

import talib

def atr_stop(highs, lows, closes, atr_period=14, mult=2.0):
    atr = talib.ATR(highs, lows, closes, timeperiod=atr_period)
    stops = pd.Series(index=closes.index, dtype=float)
    for i in range(atr_period, len(closes)):
        if closes.iloc[i] > closes.iloc[i-1]:
            stops.iloc[i] = closes.iloc[i] - mult * atr.iloc[i]
        else:
            stops.iloc[i] = stops.iloc[i-1]
    return stops

# Load data
df = pd.read_csv("BTCUSDT_1h.csv")  # Your OHLCV
df["stop_long"] = atr_stop(df.high, df.low, df.close)
Enter fullscreen mode Exit fullscreen mode

Exit when price hits stop. Reset on new highs.

Drawback: Whipsaws in ranging markets. Add a buffer or use Chandelier exit.

Portfolio Limits: Correlation Matrix

Blind diversification loses to hidden correlations. BTC crashes, altcoins follow.

Build a risk parity allocator.

def correlation_exposure(positions, returns, max_corr=0.7, max_exp=0.05):
    corr_matrix = returns.rolling(252).corr().iloc[-1]
    for i, sym1 in enumerate(positions):
        for sym2 in positions[i+1:]:
            if corr_matrix.loc[sym1, sym2] > max_corr:
                print(f"Reduce {sym1}/{sym2} corr: {corr_matrix.loc[sym1, sym2]:.2f}")
                positions[sym1] *= 0.8
    total_exp = sum(abs(v) for v in positions.values())
    if total_exp > max_exp * capital:
        scale = (max_exp * capital) / total_exp
        for k in positions:
            positions[k] *= scale
    return positions

positions = {"BTC": 0.1, "ETH": 0.05, "SPY": 0.03}
rets = pd.read_csv("returns.csv", index_col=0)
safe_pos = correlation_exposure(positions, rets)
Enter fullscreen mode Exit fullscreen mode

Run before entry. Reject if violates.

Drawdown Breaker

Track equity curve. Pause at thresholds.

class RiskManager:
    def __init__(self, capital):
        self.capital = capital
        self.peak = capital
        self.dd_threshold = 0.10

    def update(self, pnl):
        self.capital += pnl
        self.peak = max(self.peak, self.capital)
        dd = (self.peak - self.capital) / self.peak
        if dd > self.dd_threshold:
            return False  # Halt trading
        return True

rm = RiskManager(100000)
if rm.update(-5000):
    print("Keep trading")
else:
    print("Circuit breaker tripped")
Enter fullscreen mode Exit fullscreen mode

Integrate into your loop.

Real-World Example: BTC Mean Reversion

Combine it. Script scans RSI<30, sizes via half-Kelly, stops at ATR.

def generate_signal(df):
    df["rsi"] = talib.RSI(df.close)
    signals = []
    rm = RiskManager(100000)
    for i in range(100, len(df)):
        if df.rsi.iloc[i] < 30 and rm.update(0):
            atr_val = talib.ATR(df.high, df.low, df.close, 14).iloc[i]
            risk = 1000  # 1%
            pos_size = risk / (2 * atr_val)
            stop = df.close.iloc[i] - 2 * atr_val
            signals.append({"size": pos_size, "stop": stop})
    return signals
Enter fullscreen mode Exit fullscreen mode

Backtest on 2024 BTC data. Expect 1.2 Sharpe, 25% CAGR, -12% max DD.

Tradeoffs: Mean reversion dies in trends. Pair with momentum filter.

Hooking into Tools Like Market Masters AI

Platforms like Market Masters AI (marketmasters.ai) automate this. Their Orion AI runs 45+ indicators, including Elliott Wave, liquidation heatmaps, and conviction scores (-100 to +100). Python devs: hit their REST API for signals, pipe into your risk engine.

Free tier gets basic screeners. Premium ($39.99/mo) unlocks paper trading with 125x leverage sim. Test your code risk-free.

Wrapping Up

Risk management is not sexy. It is survival. Code these rules, your algo lasts longer than 90% of retail bots.

Grab BTC 1h data from Binance. Run the scripts. Tweak for your edge.

Start building: Market Masters AI free trial - no CC needed.

Top comments (0)