Agent Memory for Autonomous Trading Agents

By Arc Labs Research8 min read

The Problem: Why Stateless Trading Fails

Autonomous trading agents without memory re-learn the market inefficiently:

  • Re-learning patterns: Agent observes "BTC typically sells at resistance, buys at support" after 500 trades. Next quarter, different agent re-learns the same pattern over 500 more trades.
  • Repeating losses: Agent loses 5Konastrategyinabearmarket.Twoweekslater,sameagenttriesidenticalstrategyinsimilarconditions,loses5K on a strategy in a bear market. Two weeks later, same agent tries identical strategy in similar conditions, loses 5K again.
  • Ignoring risk events: Agent was stopped out once by a flash crash. Without memory, agent doesn't remember: triggers the same trade in similar conditions, gets stopped out again.
  • No strategy persistence: Agent develops "bull market strategy A" and "bear market strategy B" that work, but has no memory linking strategy to market condition. Uses A in bear market (loses money).
  • Inefficient capital allocation: Agent treats every trade as independent. No memory of cumulative risk (already down 10%, should size down).

Result: Slower learning curve, repeated losses, inefficient risk management.

Agent memory solves this by storing market observations, trade outcomes, and learned risk rules. The agent remembers "what worked when" and avoids "what failed before."

Memory Types for Trading

A trading agent needs four types of memory:

TypeContentExampleRetrieval
Market FactsPatterns, indicators, conditions"BTC sells at 67K resistance", "VIX spike precedes 3% drop"Semantic + keyword
Trade HistoryTrades executed, entry/exit, P&L"Long BTC @ 62K, exit @ 64K, +2K","ShortETH@2500,stopped@2600,2K", "Short ETH @ 2500, stopped @ 2600, -500"Temporal + causal
Risk Rules LearnedRisk events, constraints, learnings"Flash crashes correlate with gap-up open; avoid market orders at open", "Size down when cumulative loss > 10%"Keyword + causal
Performance MetricsStrategy stats, win rate, drawdown"Bull market strategy A: 65% win rate, max drawdown 8%", "Bear market strategy B: 55% win rate, max drawdown 12%"Keyword

Retrieval Pattern: "Market Context + Strategy Selection"

When entering a new trading period, retrieve in sequence:

1. Current market condition (semantic: volatility, trend, regime)
   → Is this bull, bear, or sideways market?

2. Similar past market conditions (semantic: find 5 prior periods like today)
   → What strategies worked in this condition?

3. Trade history in those conditions (causal: filter trades by strategy + condition)
   → Which trades won, which lost, in this regime?

4. Risk rules learned (keyword: market regime, risk level)
   → What risks should we avoid? What position size?

5. Strategy performance (keyword: current regime)
   → Which strategy had highest win rate in this condition?

Example:

import { Brain } from "brain-ai";

const memory = new Brain({
  namespace: "trading",
});

// At market open, agent selects strategy and position sizing
async function selectStrategyForToday(
  symbol: string,
  marketCondition: {
    trend: "bull" | "bear" | "sideways";
    volatility: "low" | "medium" | "high";
    vixLevel: number;
  }
) {
  // 1. Store today's market condition
  await memory.store({
    agentId: "trader-1",
    content: `Market open: ${JSON.stringify(marketCondition)}`,
    type: "market_fact",
    metadata: {
      symbol,
      trend: marketCondition.trend,
      volatility: marketCondition.volatility,
      vixLevel: marketCondition.vixLevel,
      timestamp: new Date().toISOString(),
    },
  });

  // 2. Find similar past market conditions
  const similarConditions = await memory.retrieve({
    agentId: "trader-1",
    query: `${marketCondition.trend} market, ${marketCondition.volatility} volatility`,
    topK: 5,
    filters: { type: "market_fact" },
  });

  // 3. For each similar condition, retrieve trade history
  const strategiesByOutcome: Record<string, number[]> = {}; // strategy -> [P&Ls]

  for (const condition of similarConditions) {
    const trades = await memory.retrieve({
      agentId: "trader-1",
      query: condition.content,
      topK: 10,
      filters: {
        type: "trade_history",
        metadata: { symbol },
      },
    });

    // Tally wins by strategy
    for (const trade of trades) {
      const strategy = trade.metadata?.strategy;
      const pnl = trade.metadata?.pnl;
      if (strategy && pnl) {
        if (!strategiesByOutcome[strategy]) strategiesByOutcome[strategy] = [];
        strategiesByOutcome[strategy].push(pnl);
      }
    }
  }

  // 4. Calculate win rate by strategy
  const winRateByStrategy: Record<string, number> = {};
  for (const [strategy, pnls] of Object.entries(strategiesByOutcome)) {
    const wins = pnls.filter((p) => p > 0).length;
    winRateByStrategy[strategy] = wins / pnls.length;
  }

  // 5. Select best strategy for this condition
  const selectedStrategy = Object.entries(winRateByStrategy).sort(
    (a, b) => b[1] - a[1]
  )[0]?.[0];

  // 6. Retrieve risk rules for this condition
  const riskRules = await memory.retrieve({
    agentId: "trader-1",
    query: `Risk rules: ${marketCondition.trend} market`,
    topK: 3,
    filters: { type: "risk_rule" },
  });

  // 7. Determine position size based on rules + prior drawdown
  let positionSize = 0.02; // 2% of capital (default)
  for (const rule of riskRules) {
    if (rule.content.includes("Size down")) {
      positionSize = 0.01; // 1% of capital in high-risk conditions
    }
  }

  return {
    strategy: selectedStrategy,
    positionSize,
    riskRules: riskRules.map((r) => r.content),
  };
}

// After each trade closes, store outcome
async function recordTrade(
  symbol: string,
  entry: number,
  exit: number,
  strategy: string
) {
  const pnl = (exit - entry) / entry;

  await memory.store({
    agentId: "trader-1",
    content: `Trade: ${strategy} on ${symbol}. Entry: $${entry}, Exit: $${exit}, P&L: ${pnl > 0 ? "+" : ""}${(pnl * 100).toFixed(2)}%`,
    type: "trade_history",
    metadata: {
      symbol,
      strategy,
      entry,
      exit,
      pnl,
      outcome: pnl > 0 ? "win" : "loss",
      timestamp: new Date().toISOString(),
    },
  });

  // If loss, check if this trade had high-risk characteristics
  if (pnl < -0.02) {
    // Loss > 2%
    const riskAnalysis = await analyzeTrade(entry, exit, symbol);

    // Store risk rule learned from this loss
    await memory.store({
      agentId: "trader-1",
      content: `Risk rule: Avoid ${riskAnalysis.riskType} in ${riskAnalysis.marketCondition} markets. Learned from loss of ${(pnl * 100).toFixed(2)}%.`,
      type: "risk_rule",
      metadata: {
        riskType: riskAnalysis.riskType,
        marketCondition: riskAnalysis.marketCondition,
        outcome: "REJECTED",
        timestamp: new Date().toISOString(),
      },
    });
  }
}

Example: Trading Agent Learns Over 1000 Trades

Initial phase (trades 1–500): Agent learns market patterns

Trade 1: Buy BTC @ 61K, sell @ 60.8K → Loss -0.3%
Trade 50: Buy BTC @ 61K, sell @ 61.5K → Win +0.8%
Trade 100: Observe: "BTC typically bounces 1-2% off round numbers (61K, 62K)"
Trade 250: Observe: "Bull market trades (long) have 65% win rate, bear market (short) have 45%"
Trade 350: Develop rule: "Bias long in bull markets, short in bear markets"

Middle phase (trades 500–800): Agent applies learned rules

Trade 500: Bull market detected → Use "long bias strategy"
  BTC stays bullish, wins increase to 70% win rate
  
Trade 600: Flash crash event → Short strategy triggers
  Loses $2K on stop loss at open
  
Trade 650: Market recovers (bull resumes)
  Agent memory: "Avoid market orders at gap-up open"
  (learned from trade 600)

Mature phase (trades 800–1000): Agent refines and avoids losses

Trade 800: Similar market to trade 600 (gap-up open)
  Agent retrieves memory: "Avoid market orders at gap-up open"
  Uses limit order instead → Avoids stop loss
  
Trade 900: Similar condition to trade 250 (bull market)
  Agent knows: Bull strategies win 70% of time
  Applies bull strategy, wins
  
Trade 1000: Agent has 65% win rate
  (vs. 50% random strategy, 52% without memory)

Metrics:

  • Win rate improved from 50% → 65% (by learning patterns)
  • Avoided 5 repeated losses (by remembering "what failed in this condition")
  • Reduced maximum drawdown by 30% (by learning risk rules, resizing down)
  • Capital efficiency improved 20% (by selecting best strategy per regime)

Memory Schema for Trading

interface TradingMemory {
  agentId: string; // "trader-1"
  namespace: "trading";

  // Content
  content: string;

  // What is this?
  type: "market_fact" | "trade_history" | "risk_rule" | "performance_metric";

  metadata: {
    symbol: string;

    // For market facts: conditions
    trend?: "bull" | "bear" | "sideways";
    volatility?: "low" | "medium" | "high";
    vixLevel?: number;

    // For trade history: entry, exit, outcome
    strategy?: string;
    entry?: number;
    exit?: number;
    pnl?: number; // As decimal: 0.05 = +5%
    outcome?: "win" | "loss";

    // For risk rules: learned constraints
    riskType?: string; // "gap-up-open", "flash-crash", "high-volatility"
    marketCondition?: string;

    // For performance metrics: strategy stats
    winRate?: number;
    maxDrawdown?: number;
    avgReturn?: number;

    timestamp: string;
  };
}

Use-Case Decision Table

When should you use structured vs. unstructured memory for trading?

DecisionStructuredUnstructuredExample
Market observationsPartially (trend, volatility)Mostly free text{ trend: "bull", volatility: "high", content: "Observation: BTC resistance at 67K" }
Trade historyYes, include entry/exit/P&L/strategyOptionally explain{ strategy: "bull-bias", entry: 62000, exit: 63000, pnl: 0.016, outcome: "win" }
Risk rules learnedYes, include risk type + market conditionNo{ riskType: "gap-up-open", marketCondition: "bull", outcome: "REJECTED" }
Performance metricsYes, strategy + metricsNo{ strategy: "bull-bias", winRate: 0.70, maxDrawdown: 0.08 }

Rule of thumb: Structured fields for filters (strategy = "bull-bias"), comparisons (outcome = "loss"), and decisions (select best strategy).

Metrics: Impact of Agent Memory

Trading agents with memory see:

  • Win rate +15%: Agent selects best strategy for regime, avoids failed strategies
  • Drawdown -30%: Agent learns risk rules, applies them, avoids repeated losses
  • Capital efficiency +20%: Agent sizes positions based on prior performance + cumulative risk
  • Learning speed 3x faster: Agent learns from 1000 prior trades instead of restarting

Implementation Checklist

  • Design schema: market facts, trade history, risk rules, performance metrics
  • Implement regime detection: identify bull/bear/sideways from market data
  • Implement strategy selection: retrieve similar conditions, calculate win rate by strategy
  • Implement risk rule learning: after loss, store rule (avoid X in Y condition)
  • Add memory store after market observation and trade close
  • Monitor: win rate, drawdown, strategy selection, rule effectiveness
  • Iterate: refine regime detection, risk rule triggers, position sizing

Next Steps

Related reading

Updates from the lab.

Engineering notes, research drops, occasional product updates. Roughly monthly.