March 4, 2026 ยท 6 min read

Portfolio Rebalancing for AI Agents: A Complete Guide

Left alone, a portfolio naturally drifts toward its biggest winners. If BTC doubles while ETH stays flat, your original 50/50 allocation becomes 66/34 โ€” meaning you now have twice the concentration in a single asset that has already had its big run. This is how unrebalanced portfolios silently accumulate concentration risk over time, even without any active decision-making by the agent.

Portfolio rebalancing is the systematic correction of this drift. By periodically selling overweight positions and buying underweight ones, your agent maintains the risk profile it was designed for. This guide covers threshold-based and time-based rebalancing, the math behind drift calculation, and a complete Python implementation using the Purple Flea wallet and trading APIs.

The Math of Rebalancing

Define your target weights as the desired percentage of total portfolio value held in each asset. At any point in time, the current weight of an asset is simply its current value divided by total portfolio value.

Drift for an asset is the absolute difference between its current weight and its target weight. A portfolio with targets [BTC 50%, ETH 30%, USDC 20%] and current values worth [BTC 65%, ETH 25%, USDC 10%] has drifts of [15%, 5%, 10%]. The maximum drift is 15% โ€” meaning BTC is significantly overweight.

The rebalance trade for each asset is: trade value = (target weight โˆ’ current weight) ร— total portfolio value. Negative values mean sell; positive values mean buy. Execute sells first to generate USDC, then use that USDC for the buy side.

Threshold-Based Rebalancing

Rebalancing on a fixed schedule (e.g., every month) has a flaw: if a market moves 30% on day 2 of the month, you won't correct until day 30. Threshold-based rebalancing triggers whenever any asset drifts beyond a defined tolerance โ€” commonly 5% absolute or 25% relative.

This approach minimizes unnecessary transaction costs (you don't rebalance when drift is within tolerance) while correcting meaningful imbalances promptly. The 5% threshold is a practical sweet spot: tight enough to maintain your intended allocation, wide enough to avoid constant small trades eating into returns through fees.

import purpleflea
import os

client = purpleflea.TradingClient(api_key=os.environ["PURPLEFLEA_API_KEY"])
wallet = purpleflea.WalletClient(api_key=os.environ["PURPLEFLEA_API_KEY"])

TARGET_WEIGHTS = {
    "BTC": 0.50,
    "ETH": 0.30,
    "SOL": 0.20,
}
DRIFT_THRESHOLD = 0.05  # 5% absolute drift triggers rebalance

def get_portfolio_state():
    # Fetch current balances and prices
    balances = wallet.get_balances()
    prices = client.get_prices(symbols=["BTC-USDT", "ETH-USDT", "SOL-USDT"])

    holdings = {}
    total_value = 0.0

    for asset, target in TARGET_WEIGHTS.items():
        qty = balances.get(asset, {}).get("available", 0.0)
        price = prices[f"{asset}-USDT"]["last"]
        value = qty * price
        holdings[asset] = {"qty": qty, "price": price, "value": value}
        total_value += value

    for asset in holdings:
        holdings[asset]["weight"] = holdings[asset]["value"] / total_value if total_value > 0 else 0
        holdings[asset]["drift"] = abs(holdings[asset]["weight"] - TARGET_WEIGHTS[asset])

    return holdings, total_value

def needs_rebalance(holdings):
    return any(h["drift"] > DRIFT_THRESHOLD for h in holdings.values())

holdings, total_value = get_portfolio_state()
print(f"Portfolio value: ${total_value:,.2f}")
for asset, h in holdings.items():
    print(f"  {asset}: {h['weight']:.1%} (target {TARGET_WEIGHTS[asset]:.1%}, drift {h['drift']:.1%})")

if needs_rebalance(holdings):
    print("Rebalance triggered.")
else:
    print("Portfolio within tolerance. No action needed.")

Executing the Rebalance

When drift exceeds the threshold, calculate trade sizes and execute. Always process sells before buys to ensure USDC is available for the buy-side orders.

def execute_rebalance(holdings, total_value):
    trades = []
    for asset, h in holdings.items():
        target_value = TARGET_WEIGHTS[asset] * total_value
        delta_usdt = target_value - h["value"]
        if abs(delta_usdt) < 10:  # skip trades smaller than $10
            continue
        trades.append({
            "asset": asset,
            "symbol": f"{asset}-USDT",
            "side": "sell" if delta_usdt < 0 else "buy",
            "usdt_amount": abs(delta_usdt)
        })

    # Execute sells first
    for trade in sorted(trades, key=lambda t: t["side"], reverse=True):
        order = client.place_order(
            symbol=trade["symbol"],
            side=trade["side"],
            quote_amount=trade["usdt_amount"],
            order_type="market"
        )
        print(
            f"  {trade['side'].upper()} {trade['asset']}: "
            f"${trade['usdt_amount']:.2f} | "
            f"Fill: ${order['fill_price']:,.2f}"
        )

Time-Based Rebalancing

Some agents prefer the simplicity of a fixed schedule: rebalance on the first of each month, period. This approach requires less monitoring logic and is easier to reason about in audit logs. The tradeoff is that large interim drifts may persist for weeks before correction.

The best production configuration combines both approaches: check drift every hour, trigger an emergency rebalance if any asset drifts beyond 15%, and always rebalance on the monthly schedule regardless of drift. This provides a safety net for large moves while avoiding over-trading during calm periods.

Multi-Chain Rebalancing

Advanced agents hold positions across multiple chains simultaneously โ€” ETH on Ethereum mainnet, SOL on Solana, BTC perpetuals on Hyperliquid. Purple Flea's multi-chain wallet API consolidates balances from all supported chains into a single view, enabling cross-chain drift calculation with the same approach as single-chain rebalancing.

When rebalancing requires moving assets across chains (e.g., selling overweight ETH mainnet to buy underweight SOL), the agent must account for bridge latency (typically 2-15 minutes) and bridge fees. Build this latency into your rebalancing logic by placing the sell order, waiting for confirmation, bridging, then placing the buy order once the bridged funds arrive.

Monitoring: Tracking Drift Over Time

Log every rebalance event and the drift state that triggered it. Over weeks of data, you can visualize drift patterns to optimize your threshold. If you rebalanced 40 times in a month, your threshold is too tight โ€” raise it. If a position drifted to 30% before triggering, lower it.

Rebalance Trigger Avg Monthly Trades Max Drift Observed Best For
2% threshold 25-40 3% Very tight allocation control
5% threshold 6-12 8% Most agents (recommended)
10% threshold 2-4 15% Low-fee environments
Monthly schedule 1 20%+ Minimal complexity agents
5% + Monthly 6-12 8% Production best practice

Fee consideration: Each rebalance incurs trading fees. At 0.1% per trade and 3 assets, a full rebalance costs ~0.3% of portfolio value. A monthly rebalance costs 3.6%/year in fees. Threshold-based rebalancing only when drift exceeds 5% typically costs 0.6-1.2%/year โ€” a significant saving at scale.

Rebalancing is the difference between a portfolio that compounds risk and one that maintains its intended characteristics over market cycles. For agents running long-term accumulation strategies โ€” DCA, index-style holds, or yield farming โ€” automated rebalancing is a mandatory component of sound portfolio design.

Explore the complete reference at /agent-portfolio-rebalancing, and see all balance and price endpoints at /crypto-wallet-api and /trading-api.