Back to Blog
Building Self-Improving Strategies with LLM Reactions
LLM Reaction7 min read

Building Self-Improving Strategies with LLM Reactions

Here's a thing that happens to basically every strategy eventually: it works great for a while, and then it just... doesn't. Maybe the market shifted. Maybe you hardcoded a threshold that made sense in March and stopped making sense in June. Maybe there's a small bug that's been quietly eating trades for two weeks and you only find out when you happen to open the logs.

The usual fix is you, checking in, noticing something's off, and going to patch it. Which works, but it doesn't scale past however many strategies you're personally willing to babysit.

So we built a way around that. You can now have one strategy watch another — pull its trade history, check its errors, and rewrite the logic itself if something needs fixing. No app-opening required.

This post walks through actually setting that up. Two live examples if you want to poke at something running before you build your own:

What we're building

Two pieces:

  1. A Code strategy — the thing actually trading. We'll use a small BTCUSDT momentum strategy for this walkthrough.
  2. An LLM reaction — the supervisor. It gets triggered periodically, looks at how the strategy's been doing, and decides whether to leave it alone or fix something.

The connection between them is a Data Webhook. The strategy pings it on a schedule, the webhook wakes up the reaction, the reaction does its review. That's the whole loop.

Step 1: Create the Data Webhook

Start here, before you write any strategy code. Go create a Data Webhook in Sigrex — there's nothing to configure really, it just needs to exist so it has somewhere for the strategy to post to.

Grab its hash from the settings page once it's created. You'll drop that into the strategy code in the next step — it's the part of the URL after https://hook.sigrex.io/data/.

Step 2: Write the strategy

Any working code strategy will do here, but let's use something concrete. A simple momentum play on BTCUSDT: buy when price jumps 1% from wherever we last checked in, take profit at +2%, stop out at -1%. Not a strategy we're claiming is good, just one with enough real logic to generate actual signals — and eventually actual mistakes for the supervisor to catch.

This runs inside Sigrex's code strategy sandbox, so all you get is the injected $ object — no fetch, no console, none of the usual JS globals. Here's the whole thing, webhook hash from Step 1 already dropped in:

// Momentum strategy for BTCUSDT
// Entry: price up 1% from the last checkpoint
// Exit: +2% take profit or -1% stop loss
// Also triggers a review every 3 days via a Data Webhook

const REVIEW_INTERVAL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days
const REVIEW_WEBHOOK = "https://hook.sigrex.io/data/xxxx--your-hook-hash-xxxx";

const state = await $.Storage.get() || { checkpoint: null, lastReviewAt: 0 };

if (state.checkpoint === null) {
  // First run — just set the initial checkpoint, no trade yet
  state.checkpoint = $.Price.price;
  await $.Storage.set(state);
} else if ($.Strategy.lastTrigger.action === $.Action.LONG) {
  // We're in a position — check exit conditions
  const roi = $.Strategy.roi(true);

  if (roi !== null && roi <= -1) {
    await $.Strategy.action($.Action.EXIT);
    state.checkpoint = $.Price.price;
    await $.Storage.set(state);
  } else if (roi !== null && roi >= 2) {
    await $.Strategy.action($.Action.EXIT);
    state.checkpoint = $.Price.price;
    await $.Storage.set(state);
  }
} else {
  // No position open — check entry condition
  const changePercent = (($.Price.price - state.checkpoint) / state.checkpoint) * 100;

  if (changePercent >= 1) {
    await $.Strategy.action($.Action.LONG);
    state.checkpoint = $.Price.price;
    await $.Storage.set(state);
  }
}

// Self-trigger a review: every 3 days, ping the Data Webhook that wakes
// up the supervising LLM reaction. This runs independently of the trade
// logic above, so it fires on schedule even on runs with no trade at all.
const now = Date.now();
if (now - state.lastReviewAt >= REVIEW_INTERVAL_MS) {
  await $.Http.post(REVIEW_WEBHOOK, {
    request: "self_check",
    strategyId: $.Strategy.id,
    strategyType: $.Strategy.type,
    lastAction: $.Strategy.lastTrigger.action,
    lastActionAt: $.Strategy.lastTrigger.at,
    checkedAt: now
  });

  state.lastReviewAt = now;
  await $.Storage.set(state);
}

Most of that is just the trading logic — check if we're in a position, check ROI against our thresholds, enter or exit. Standard stuff, nothing you haven't seen before if you've written a code strategy already.

The part that actually matters for this guide is at the bottom. Every 3 days, the strategy posts a small payload to its own Data Webhook and remembers when it last did that, so it doesn't spam the thing on every single run. That POST is the whole trigger mechanism — no external cron job, no separate scheduler sitting somewhere. The strategy is the one deciding when it's time for a check-in.

A few things worth knowing about that payload:

  • It fires on every execution regardless of whether a trade happened, so it stays on schedule even through long stretches of nothing happening.
  • $.Strategy.id and $.Strategy.type tell the reaction exactly which strategy is checking in — useful the moment you have more than one strategy pointing at the same webhook.
  • Everything else stays light on purpose. The reaction can go pull the full signal and error history itself once it's awake — this is just the wake-up call, not the whole report.

And walking through the trading logic itself, quickly: $.Storage.get() pulls a small object that survives between runs (a checkpoint price, plus when we last reviewed). First run ever, there's nothing to compare against, so we just record the price and move on. After that, $.Strategy.lastTrigger.action tells us if we're holding a position — if so we check ROI against our exit thresholds, if not we check whether price has moved enough to enter. Every trade resets the checkpoint so the next entry gets measured fresh.

Step 3: Build the LLM reaction

Now for the actual supervisor. Create an LLM reaction hooked up to the same Data Webhook from Step 1. Unlike the strategy, this one is written in plain language — a prompt, not code.

The {{data}} template variable contains the full payload sent by the code strategy, so you can include whatever information the strategy needs to pass to the supervisor — such as its ID, type, last action, timestamps, or any other custom data.

A good prompt should explain what “doing well” means for that strategy, what to check before taking action, and what to do depending on what it finds.

Something like this is a reasonable starting point:

You are supervising code strategy {{data}}

First, fetch its signal logs and error logs from the last review period.

Evaluate:
- Is it trading at a reasonable frequency, or has it gone silent?
- Are there repeated errors (sandbox violations, failed actions)?
- Does its recent win/loss pattern suggest the entry logic is too loose or too tight?

If everything looks healthy, take no action.

If there are repeated errors, fix the underlying bug in the code and explain what you changed.

If the strategy has been idle for more than 5 consecutive checks with no trades,
loosen the entry threshold slightly and note the adjustment.

If it's been stopped out significantly more than it's profited over the last 20 trades,
tighten the entry logic and note the adjustment.

Always explain your reasoning before taking any action.

Notice there's no code in here, no template syntax beyond what's needed. The reasoning happens inside the model when it runs, not in some rules engine you have to maintain separately.

Step 4: Give it the tools it needs

For the reaction to actually do something with all that, it needs a handful of capabilities during its run — reading the target strategy's current code, pulling its signal logs (the real trade history), pulling its error logs, rewriting the code if a fix is warranted, and starting or stopping the strategy outright if that's the better call.

You don't have to orchestrate any of this by hand. These map to tools already available, and the model reaches for whichever one fits based on what your prompt asked it to do. Write the intent clearly and it figures out the mechanics.

Step 5: Don't fully trust it on day one

Before you let this run unsupervised — especially against anything trading real money — do a handful of dry runs where the reaction tells you what it would do without actually touching the code. Read the reasoning. See if its idea of "too many errors" or "underperforming" lines up with yours.

Once a few of those checks feel right, let it act on its own.

The loop, start to finish

Code strategy trades live
        ↓
Fires a trigger every N days → Data Webhook
        ↓
Webhook wakes up the LLM reaction
        ↓
LLM reaction pulls signal + error logs, reviews the code
        ↓
No issue found → does nothing
Bug found → rewrites the code, logs what changed
Underperforming → adjusts thresholds
Broken beyond repair → stops the strategy
        ↓
Loops back automatically on the next trigger

A few things we've learned setting this up

Give it a narrow job, not a vague one. "Make this strategy better" gives the model nothing concrete to check against. "If it's been idle for 5 checks, loosen the entry" gives it an actual decision to make.

Have it explain itself every time, even when it decides to do nothing. That trail of reasoning is basically the only way you'll be able to audit whether it's making good calls six months from now.

The review interval matters more than it seems like it should. Too tight and it's reacting to noise — a couple of losing trades in a row doesn't mean the logic is broken. Too loose and a real bug sits there unfixed for a while. A few days is a fine starting point; adjust once you've watched it work for a bit.

And — this one's worth saying plainly — this doesn't mean you stop paying attention. Even a supervisor you trust should get an occasional look-in from an actual person, especially early on. Think of it as cutting down your workload, not removing yourself from the loop entirely.

Where this goes next

Once it works for one strategy, it scales sideways pretty naturally. One LLM session can review several strategies in a single scheduled run. You can even chain supervisors — a reaction watching a handful of other reactions. Same core idea every time: pull the history, reason about it, act if there's actually something to act on.

Full reference on LLM reactions, template variables, and the tools underneath all this is in the docs.

Related posts

Building a News-To-Trade Workflow for Polymarket
LLM Reaction·7 min read

Building a News-To-Trade Workflow for Polymarket

Prediction markets move on information. A market resolves on a specific, checkable question — did the rate cut happen, did the bill pass, did the company hit the number — and every time new information about that question becomes public, there's a brief window before the market price catches up with it. Most of that window closes in minutes. Nobody is checking Polymarket by hand fast enough to consistently catch it. This post walks through a pipeline that does the watching for you: Perigon deli

2026-08-26
How to Forward Test a Strategy
Testing·5 min read

How to Forward Test a Strategy

Sigrex has no backtester, and that is a design consequence, not a missing feature. A strategy here can read any API and ask any LLM, and you can't replay that from history. What you can do is run the strategy on the live market with nothing attached to it, and watch. Why a backtester doesn't fit Sigrex A backtest replays the past. It feeds old data into your rules and counts what would have happened. That works when two things are true: every input the strategy uses has a recorded history, an

2026-10-02
Talk to Your Trading Bots: Introducing the Sigrex MCP Server
MCP·4 min read

Talk to Your Trading Bots: Introducing the Sigrex MCP Server

Building trading automation usually means a lot of clicking. Open a strategy, edit a value, save, check the logs, switch to another bot, repeat. It works, but it's slow, and it pulls your attention away from the part that actually matters: the trading ideas themselves. Today that changes. With the Sigrex MCP server, you can connect AI assistants like Claude and ChatGPT directly to your Sigrex account and manage your whole trading setup in plain language. Ask a question, get an answer from your

2026-09-25