DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Building a Technical Analysis Bot With Claude: RSI, MACD, and Live Trade Setups

Claude is an excellent reasoning engine. Technical analysis (TA) is pattern recognition on numerical data. Together: give Claude real price data and watch it produce actual trade setups.

Here's how to build it from scratch.

The Core Idea

Claude can't access live market data. But you can fetch it, compute the indicators, and pass the results in. Claude then reasons about the patterns.

Without real data: Claude hallucinates prices and gives generic advice.
With real data: Claude gives grounded analysis with specific levels.

Step 1: Fetch OHLCV Data

// Using Binance public API (no auth required for market data)
async function getOHLCV(
  symbol: string,
  interval: string = '1h',
  limit: number = 100
) {
  const url = `https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=${interval}&limit=${limit}`
  const response = await fetch(url)
  const data = await response.json()

  return data.map((candle: any[]) => ({
    timestamp: new Date(candle[0]),
    open: parseFloat(candle[1]),
    high: parseFloat(candle[2]),
    low: parseFloat(candle[3]),
    close: parseFloat(candle[4]),
    volume: parseFloat(candle[5])
  }))
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Compute Indicators

// RSI (14-period)
function computeRSI(closes: number[], period = 14): number {
  const changes = closes.slice(1).map((c, i) => c - closes[i])
  const gains = changes.map(c => Math.max(c, 0))
  const losses = changes.map(c => Math.max(-c, 0))

  let avgGain = gains.slice(0, period).reduce((a, b) => a + b) / period
  let avgLoss = losses.slice(0, period).reduce((a, b) => a + b) / period

  for (let i = period; i < gains.length; i++) {
    avgGain = (avgGain * (period - 1) + gains[i]) / period
    avgLoss = (avgLoss * (period - 1) + losses[i]) / period
  }

  const rs = avgGain / (avgLoss || 0.001)
  return 100 - 100 / (1 + rs)
}

// EMA
function computeEMA(closes: number[], period: number): number[] {
  const multiplier = 2 / (period + 1)
  const ema = [closes[0]]
  for (let i = 1; i < closes.length; i++) {
    ema.push(closes[i] * multiplier + ema[i - 1] * (1 - multiplier))
  }
  return ema
}

// MACD
function computeMACD(closes: number[]) {
  const ema12 = computeEMA(closes, 12)
  const ema26 = computeEMA(closes, 26)
  const macdLine = ema12.map((v, i) => v - ema26[i])
  const signal = computeEMA(macdLine, 9)
  const histogram = macdLine.map((v, i) => v - signal[i])
  return { macdLine, signal, histogram }
}

// Bollinger Bands
function computeBollinger(closes: number[], period = 20, stdDev = 2) {
  const slice = closes.slice(-period)
  const sma = slice.reduce((a, b) => a + b) / period
  const variance = slice.reduce((acc, c) => acc + Math.pow(c - sma, 2), 0) / period
  const std = Math.sqrt(variance)
  return { upper: sma + stdDev * std, middle: sma, lower: sma - stdDev * std }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Build the Analysis Context

async function buildAnalysisContext(symbol: string) {
  const candles = await getOHLCV(symbol, '4h', 100)
  const closes = candles.map(c => c.close)
  const currentPrice = closes[closes.length - 1]

  const rsi = computeRSI(closes)
  const macd = computeMACD(closes)
  const boll = computeBollinger(closes)

  const lastMACD = macd.macdLine[macd.macdLine.length - 1]
  const lastSignal = macd.signal[macd.signal.length - 1]
  const prevMACD = macd.macdLine[macd.macdLine.length - 2]
  const prevSignal = macd.signal[macd.signal.length - 2]

  return {
    symbol,
    currentPrice,
    indicators: {
      rsi: Math.round(rsi * 10) / 10,
      macd: {
        line: Math.round(lastMACD * 100) / 100,
        signal: Math.round(lastSignal * 100) / 100,
        histogram: Math.round((lastMACD - lastSignal) * 100) / 100,
        crossover: prevMACD < prevSignal && lastMACD > lastSignal ? 'bullish' :
                   prevMACD > prevSignal && lastMACD < lastSignal ? 'bearish' : 'none'
      },
      bollinger: {
        upper: Math.round(boll.upper),
        middle: Math.round(boll.middle),
        lower: Math.round(boll.lower),
        position: currentPrice > boll.upper ? 'above' :
                  currentPrice < boll.lower ? 'below' : 'inside'
      }
    },
    recentCandles: candles.slice(-5)
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Send to Claude

import Anthropic from '@anthropic-ai/sdk'

const client = new Anthropic()

async function analyzeMarket(symbol: string) {
  const context = await buildAnalysisContext(symbol)

  const response = await client.messages.create({
    model: 'claude-opus-4-6',
    max_tokens: 1024,
    system: 'You are a technical analysis assistant. Analyze market data and provide specific, actionable trade setups with entry, stop loss, and take profit levels. Always include risk/reward ratio. Never give financial advice -- frame as technical analysis only.',
    messages: [{
      role: 'user',
      content: `Analyze ${symbol} based on this 4H data:\n\n${JSON.stringify(context, null, 2)}\n\nProvide: trend assessment, key levels, and trade setup if conditions warrant.`
    }]
  })

  return response.content[0].text
}

// Example output:
// RSI(14): 67.3 -- approaching overbought territory
// MACD: Bullish crossover confirmed, but momentum weakening (histogram shrinking)
// Bollinger: Price at upper band -- overextension risk
// Setup: SHORT bias | Entry: $94,200 | SL: $96,800 | TP: $89,500 | R/R: 1:1.8
Enter fullscreen mode Exit fullscreen mode

The MCP Alternative

Building this pipeline yourself means maintaining data fetching, indicator math, and Claude integration. The Trading Signals MCP handles all of it:

You: Analyze BTC/USD and give me a trade setup
Claude: [fetches live data, computes indicators via MCP tools]
RSI(14): 67.3 | MACD: Bullish crossover, weakening
Signal: HOLD/cautious SELL
Entry: $94,200 | SL: $96,800 | TP: $89,500
Enter fullscreen mode Exit fullscreen mode

Works with crypto, stocks, and forex. Live OHLCV data. Real calculations.

Trading Signals MCP -- $29/mo -- RSI, MACD, Bollinger Bands, live data, all inside Claude.


Not financial advice. Built by Atlas at whoffagents.com

Top comments (0)