LIVE
connecting to the live quote stream…
--:--:--UTC
Learn/Bots/1D CNN (Sequence)
AI QuantsAI
▰

1D CNN (Sequence)

Reads the last 60 raw OHLCV candles like an image.

⟢In plain English

A small AI model that looks at the last 60 days of prices like a picture and learns to spot familiar shapes — breakouts, coils, head-and-shoulders. It doesn't know the names of these patterns, it just notices the ones that tend to come before big moves.

A 1D convolutional neural network that reads the last 60 days of OHLCV like an image and outputs an expected return. CNNs are translation-invariant by design — meaning the same pattern at the start, middle, or end of the window gets recognised. It learns recurring chart shapes (breakouts, coils, head-and-shoulders) without anyone telling it what they are.

⟢The math
formula
Conv1d → GAP → linear · trained on shape, not features
parameters
lookbackLookback (bars)range 30 → 120default · 60
⟢Live demo

Real 1D CNN (Sequence) bot, running on real Yahoo data when the symbol is available. Drag the params — the bot re-runs instantly.

symbolloading…
loading AMZN bars…
⟢Source code · public

This is the actual code the bot runs — not a re-explanation, not a simplified version. Whatever ships here is what executes when you press Run All in the workbench. Read it, copy it, fork it, build a better one.

●lib/quant/ai-bots.ts·lines 782–851
TypeScript · MIT-licensed
const sequenceCnn: BotDef = aiBot<DirReq, SeqRes>(
  {
    id: "ai-sequence",
    name: "1D CNN (Sequence)",
    category: "ai",
    glyph: "▰",
    tagline: "Reads the last 60 raw OHLCV candles like an image.",
    formula: "Conv1d → GAP → linear · trained on shape, not features",
    endpoint: "/api/sequence",
    module: "ai quants/models/sequence/train.py",
    params: [
      { key: "lookback", label: "Lookback (bars)", kind: "number", default: 60, min: 30, max: 120, step: 1 },
    ],
  },
  {
    request: dirRequest,
    // Free tier: run the real CNN on the user's machine (onnxruntime-web).
    deviceSource: "device-cnn",
    device: async (ctx) => {
      const res = await runSequenceCnn(ctx.symbol.toUpperCase());
      return res
        ? { expected_return: res.expectedReturn, direction: res.direction, horizon_days: 20 }
        : null;
    },
    build: (data) => {
      const pred = data.expected_return;
      return {
        signals: [],
        metrics: [
          { key: "pred", label: "20d return", value: `${(pred * 100).toFixed(2)}%`, tone: pred > 0 ? "bull" : "bear" },
          { key: "dir", label: "Direction", value: data.direction.toUpperCase(), tone: data.direction === "up" ? "bull" : "bear" },
          { key: "lookback", label: "Window", value: "60d OHLCV" },
          { key: "model", label: "Architecture", value: "Conv1d → GAP → Linear", tone: "info" },
        ],
        summary: `1D CNN reads the last 60 bars and outputs ${(pred * 100).toFixed(2)}% expected 20d return.`,
        beginner:
          "We treat the last 60 days of price data like an image and run a small convolutional network across it.",
        verdict: {
          side: pred > 0.015 ? "buy" : pred < -0.015 ? "sell" : "hold",
          text: `CNN sees a ${(pred * 100).toFixed(2)}% setup over the next 20 days.`,
          confidence: Math.min(1, Math.abs(pred) * 15),
        },
      };
    },
    mock: (ctx, p) => {
      const lookback = num(p, "lookback", 60);
      const px = closes(ctx.candles);
      const trend = trendStrength(px);
      const seed = hashStr(ctx.symbol + "cnn" + lookback);
      const rand = seedRand(seed);
      const pred = trend * 0.5 + (rand() - 0.5) * 0.04;
      return {
        signals: [],
        metrics: [
          { key: "pred", label: "20d return", value: `${(pred * 100).toFixed(2)}%`, tone: pred > 0 ? "bull" : "bear" },
          { key: "dir", label: "Direction", value: pred > 0 ? "UP" : "DOWN", tone: pred > 0 ? "bull" : "bear" },
          { key: "lookback", label: "Window", value: `${lookback}d OHLCV` },
          { key: "shape", label: "Detected pattern", value: trend > 0.05 ? "uptrend" : trend < -0.05 ? "downtrend" : "chop", tone: "info" },
        ],
        summary: `1D CNN (TS mock) suggests ${(pred * 100).toFixed(2)}% over 20d.`,
        beginner: "We treat the last 60 days of price data like an image and run a CNN.",
        verdict: {
          side: pred > 0.015 ? "buy" : pred < -0.015 ? "sell" : "hold",
          text: `CNN sees a ${(pred * 100).toFixed(2)}% setup over the next 20 days.`,
          confidence: Math.min(1, Math.abs(pred) * 15),
        },
      };
    },
  },
);
what each piece means
  • id — unique key the workbench uses to find the bot.
  • params — the sliders + inputs you see on the cell.
  • run(ctx, p) — the function that gets called with candles + your params and returns the verdict.
  • verdict — the BUY / SELL / HOLD pill at the top of the cell.
  • metrics — the small stat boxes shown in the cell body.
use this code yourself
  1. Copy the whole block above.
  2. On /quant, click + Import your bot in the bot library.
  3. Paste, hit save. It hot-loads into your workspace.
  4. Edit any param defaults or logic to your taste — it's now yours.
⟢Specialty · when it shines, when it fails
✓ Shines when
  • ·Pattern-driven traders. The CNN is essentially an automated chartist. It picks up on shapes that human eyes also notice but can't formalise.
  • ·Short-to-medium horizon (~20 days). The 60-bar window naturally caps how far back it can look.
  • ·Pairs nicely with classical indicators — the CNN catches what RSI/MACD don't.
✗ Fails when
  • ·Slow-moving fundamentals. The network can't see beyond 60 bars; it's blind to anything older.
  • ·Noisy intraday data. Designed for daily bars; minute data is too noisy for 60-step convolutions.
  • ·Names with little visual structure (treasuries, low-vol utilities). Not enough shape variation.
⟢How to read its verdict

BUY when expected return > +1.5%, SELL when < -1.5%, HOLD in between. The 'detected pattern' chip (uptrend / downtrend / chop) is a sanity-check label, not a formal classifier output — it's derived from recent trend strength.

⟢Python service

This bot tries to call the FastAPI service first. When it's up, you get real model output. When it's down, the bot transparently falls back to a deterministic TS surrogate.

srcai quants/models/sequence/train.pyapi/api/sequence
FastAPI··/api/sequenceCHECKING…
How the request flows+
01
BotCell.run()
User clicks Run on this bot in /quant
02
callApi()
POST to localhost:8000/api/sequence
03
load_surrogate()
ai quants/models/sequence/train.py
04
predict()
Forward pass on the inputs you provided
05
BotResult
JSON returned, card flips green Source: Python NN
spin it upcd "ai quants" && uvicorn serve:app --reload --port 8000
⟢FAQ
Why CNN instead of LSTM?+
CNNs are 5-10× faster to train and inference, translation-invariant, and on price data they perform comparably to LSTMs. We tried both; CNN won on pareto-front.
What does the model see, exactly?+
A 60×5 tensor: 60 bars of [open, high, low, close, volume], normalised by the last bar's price and average volume. Then three Conv1d layers, global average pooling, one linear head to a single scalar (the expected return).