Build a bot.
Read the news.
Beat the room.

A simulated stock market runs for one hour. Everyone trades it at the same time. Prices move because of news, and the news is written to fool you. Whoever's bot ends the hour with the most money wins.
3per team
100,000starting cash
7companies
1index fund
60 minthat count
1winner
What this is

A hackathon where the scoreboard settles it.

We are spending the day building trading bots with Claude Code and running them against the same simulated market, live, at the same time. Most hackathons end with a room arguing about which idea was best. This one ends with a leaderboard that has been on the wall since lunchtime.

You will work in teams of about three. In the morning you build and test against a practice market where nothing counts. At half past twelve the real market opens for one hour, and whatever your bot does in that hour is your score. In the afternoon every team gets five minutes to say what they tried, where Claude Code genuinely helped, and where it produced confident nonsense.

The point is not to produce a trading system anybody keeps. It is to spend a day using Claude Code hard, under time pressure, on a problem where being sloppy is immediately visible to everyone in the room.

01

You get an account

Your team starts with 100,000 in cash and access to a market of seven companies, plus an index fund that holds all of them. Everyone starts with exactly the same thing.

02

News arrives all hour

A headline lands roughly every minute. Some genuinely move a company's share price. Many are noise. A few say the opposite of what they mean.

03

Your bot decides

You build it with Claude Code during the day. Whether it works out what the news means, or just trades the price action, is entirely up to you.

The interesting problem is not "can you call an API". It is that a headline reading like a disaster is sometimes the best news of the hour, and knowing the difference is worth real money.
Your task

Build a trading bot.

That is the whole brief. There are no restrictions on how, no marks for elegance, and no judging panel. Your final balance is the result.

You are given

An account and an API

A team API key, 100,000 in cash, and an HTTP API that tells you prices, publishes news, and accepts orders. Plus a machine that can already talk to Claude.

You build

Something that trades on its own

A program that runs unattended for an hour: watching the market, deciding what is worth acting on, and placing orders. In any language you like, using whatever approach you think will win.

You are scored on

One number

Cash plus the value of what you hold, at the moment the market closes. Nothing else counts, and nothing from the practice round carries over.

Two ways to get an edge. Pick either, or both.

Worth separating two things that sound the same and are not. Everybody builds their bot with Claude Code - that is the point of the day. Whether the bot itself calls a model while it is running is a completely separate decision, and it is yours.

Route A

Have your bot read the news

Your machine can already call Claude over the LiteLLM proxy. Your bot sends each headline as it arrives and gets back a judgement: which company this actually affects, in which direction, and how confident the model is. You then decide what to do with that in your own code.

Why bother: the news is where the largest moves come from, and the feed is written so that reading it properly is genuinely hard. This is the only route that gets at that directly.

Route B

Trade the market mechanically

Never call a model at all. Watch prices, spot moves as they begin, follow trends, fade overreactions, spread risk across names, size by volatility, use the index fund as a base position. Ordinary quantitative rules, written and tuned by you.

Why bother: it is testable, it is fast, it never hallucinates, and it keeps working when an API call times out. A well-tuned mechanical bot will beat a badly wired clever one every time.

Most teams will end up somewhere in between, and that is probably the right answer: mechanical rules for risk, sizing and exits, where you want predictability, and a model call for the one question that actually needs judgement. Whichever way you go, the logic you care about should stay in code you wrote and can test.

Watch poll /snapshot A new headline one you have not seen Price movement and your history of it Ask the model what does this imply, and how sure are you OPTIONAL Your own signals trend, reversion, spread, volatility, relationships Decide and size your rules, your code, inside the 30% cap Trade or not every few seconds, all hour
Only the dashed purple box needs a language model, and it is optional. A bot that never draws it is still a perfectly good bot. Everything else is ordinary code, and that is the part you can actually debug.

You already have everything you need

Your machine can already talk to Claude, through the same configuration Claude Code itself uses. There is nothing to install, no key to request, and no reason to try running a model locally: the sandbox has two cores and no graphics card. The exact code is in Building it below.

Do not hand the model the whole loop

Ask it what a story means and how confident it is. Keep how much to risk, when to stay out and when to sell in code you wrote. Those are the rules you will want to change at 12:15, and you cannot change a rule that lives inside a paragraph of prose.

How it moves

Prices react on a delay. That delay is your edge.

When a story that matters is published, the price does not jump instantly. There is a window where the market has not moved yet and you still can.

YOUR WINDOW · 90 SECONDS Headline published price has not moved Price starts to move +90s Settled +210s drifts over 120s read it, judge it, size it, trade it
You have about a minute and a half between a story appearing and the price responding to it. That is the whole game.

Being fast is not enough

A bot that buys the instant any headline appears will be inside the window every time, and will still lose, because roughly half the stories it reacts to either mean nothing or mean the opposite of what they look like.

Being right is not enough either

Some stories move a price 1%. Some move it 8%. Getting the direction right on the small ones and putting your whole account behind them, while nibbling at the big ones, is how you finish mid-table with a great hit rate.

Why it's hard

The feed is written to punish skim-reading.

If "good words mean buy" worked, this would be a typing race. Here are the four traps, with invented examples. None of these companies exist in your market.

Trap 1 · It says the opposite
Consolidated Wire
Fenwick Shipping halts its flagship expansion programme
The programme was suspended after the board concluded the capacity it would have added is already covered by the fleet acquired last quarter. Fenwick expects to release the reserved capital to shareholders.
Buy "Halts flagship programme" is about as bad as a headline can sound. Read the body: they no longer need to spend the money. Every negative word in that story is attached to a positive fact.
Trap 2 · It reads positive, it isn't
Consolidated Wire
Aldermoor Foods reports record annual sales
Sales reached an all-time high. The growth was bought with aggressive price cuts: gross margin fell 400 basis points, unsold stock rose by a third, and the company withdrew its profit guidance for the year.
Sell Count the positive words and this is the best story of the day. Read what actually happened and the company just told you it does not know what it will earn.
Trap 3 · It moves someone else
Consolidated Wire
Regulator approves a large tariff rise for Castlebridge Energy
Industrial electricity tariffs will increase from next quarter. Castlebridge said the decision supports its investment programme.
Look elsewhere Mildly good for the energy company named in the story. Considerably worse for whoever buys that electricity, and that company is not mentioned anywhere in the text. You are given the map of who supplies whom. Use it.
Trap 4 · It means nothing at all
Consolidated Wire
Eurozone composite PMI unchanged at 51.2
The reading matched both the flash estimate and the consensus forecast.
Do nothing Close to half the feed is filler like this: macro data in line, routine maintenance, a new marketing director. Trading it is not free. Every round trip costs you, and a bot that reacts to everything pays that toll dozens of times.

And one thing nobody will tell you

Every story arrives with a source attached. There is more than one source. They are not equally reliable, and nobody is going to say which is which. Working that out is worth a surprising amount, and the only way to find it is to keep track of what happened after each one.

Try it

Four headlines. Buy, sell, or ignore?

Same style as the real feed, none of the real content. See how you do before you teach a machine to do it.

The market

Seven companies, and they depend on each other.

This map is the difference between guessing and reasoning. When a story lands on one company, the interesting question is often which other company it just moved.

distribution cold chain freight materials copper power credit lines working capital card payments ARNArnhold Retail HLXHelix Biosciences NWLNorthwind Logistics KMTKestrel Materials MRDMeridian Power VTCVantage Compute WRBWire Bank
An arrow means "supplies, sends business to, or lends to". Wire Bank sits underneath three of the others, which matters more than it looks. Your bot can fetch this same map from the API at any time.
NWL
Northwind Logistics
Freight & Logistics
Road and rail freight. Carries goods for the retailer, bulk output for the miner, and runs the refrigerated network the pharma company needs. When any of those three has a bad day, so does Northwind.
KMT
Kestrel Materials
Industrial Materials
Mines and processes specialty metals. Sells into datacentre construction and into power grid buildout, so it rises and falls with what those two are spending.
ARN
Arnhold Retail
Consumer Retail
Around 400 stores plus a growing online arm. Thin margins, so small changes in discounting move the share price more than you would expect.
HLX
Helix Biosciences
Pharmaceuticals
Two approved products and a late-stage pipeline. Its news is binary and regulator-driven, which makes it the most violent name in the market in both directions.
VTC
Vantage Compute
Technology & Datacentres
Runs colocation and AI training datacentres. Its two biggest costs are electricity and building materials, both bought from other companies on this list.
WRB
Wire Bank
Banking & Payments
Payments processor and business bank, and by a distance the fastest growing company here. It runs card acquiring for the retailer and lends working capital to the freight operator and the miner. Also the most volatile name in the market, in both directions.
MRD
Meridian Power
Utilities & Energy
Regulated generation and grid. Normally the calmest name here, which is not the same thing as being safe on any particular day.

And one thing that is not a company

The eighth instrument is ORB, the Orbis Market Index Fund. It is an ETF: it holds all seven companies above, weighted by size, and it has no news of its own. Its price is only ever the weighted performance of what it holds.

What ORB holds
VTC 23%
HLX 19%
MRD 17%
KMT 14%
NWL 12%
ARN 8%
WRB 7%
Weighted by size, like a real index. A company that has a catastrophic day costs the fund its weight, not your whole position.

It is the one thing with no position cap

Every company is capped at 30% of your portfolio. ORB is not capped at all, because it is diversified by construction. You can put the entire account into it. Buying the index and doing nothing else is a legitimate strategy, and it is roughly the benchmark everyone else is trying to beat.

It is not a safe harbour

An index fund owns everything, and everything includes whichever company is quietly having the worst day of its life. ORB will not fall as far as a single name can, but it does not get to opt out either.

The rules

Six things that constrain you.

All of them are enforced by the server, so there is no arguing with any of them at 12:40.

Starting cash
100,000

Identical for every team. Your score at the end is cash plus whatever your holdings are worth.

Position cap
30%

No single company may be worth more than 30% of your portfolio when you buy. An order that would breach it is rejected, not trimmed. The index fund is the exception and has no cap at all.

Buying only
No shorting

You can only sell what you already hold. So bad news is only useful to you if you own the thing, which makes knowing when to get out as important as when to get in.

Cost per round trip
0.30%

Every buy and every sell pays a small spread. Trade forty times on noise and you have handed back more than most teams make all hour.

Requests per minute
60

Per team, not per person. Three people each running the bot share one budget. Polling harder is not a strategy.

At some point
A shock

One company will fall hard and fast during the live hour. You will not be told when or which. Decide now what your bot does when something it owns collapses.

The cap is checked when you buy, not continuously

This catches people out, so it is worth saying plainly. The 30% limit is applied at the moment an order is placed. If you buy right up to the cap and the price then rises, that position keeps growing as a share of your portfolio and nothing stops it. The server will never sell anything on your behalf. If you want to stay at 30%, you have to trim it yourself. In testing, a bot that repeatedly topped a winner up to the cap ended the hour with far more than 30% of its money in it, which was fine right up until it was not.

Building it

How to actually get this done in a morning.

None of this is required and none of it is strategy advice. It is the set of things that, in testing, made the difference between a bot that traded all hour and a bot that was still being debugged at 12:50.

1. Get to a trade in ten minutes

Before any strategy, any model call, any structure. Prove the key works, the order format is right, and you can see the result. Everything else is easier once something round-trips.

import httpx

API = httpx.Client(base_url="http://SERVER:3015",
                   headers={"X-API-Key": "tk_yourteamkey"}, timeout=10)

s = API.get("/snapshot").json()
print(s["state"], s["portfolio"]["cash"])
print(API.post("/order", json={"symbol": "NWL", "side": "buy", "quantity": 1}).json())

If that prints a fill, you are further along than you think. Open the inspector page in a browser next to it and watch the position appear.

2. Give Claude Code the rules, once, in writing

The single highest-leverage thing you can do. Put a CLAUDE.md in your project directory containing the constraints. Every Claude Code session in that folder picks it up, so you stop re-explaining the market and it stops writing code that breaks rules it was never told about.

# Trading bot for the Trading Floor Challenge

## Rules this code must never violate
- Long only. Never sell more than we currently hold.
- Max 30% of portfolio value in any one company, checked at order time.
  ORB is an index fund and is NOT capped.
- 60 requests per minute per key, shared by the whole team.
  Poll GET /snapshot (one call), never four separate endpoints.
- Quantities are positive whole numbers.
- Use the server clock from the response, never local time.

## API
Base URL: http://SERVER:3015 - full reference at /docs
Do not invent endpoints. If unsure, check /docs first.

That last line matters more than it looks. The most common failure mode we saw was a confidently written client calling endpoints that do not exist.

3. Ask for small pieces, not "a trading bot"

Works well

"Write a function that takes a news item and returns the parsed JSON verdict from the model." Then: "Write a function that turns a verdict plus my portfolio into an order size, respecting the 30% cap." Then wire them together yourself. Each piece is small enough to read, and you can test it without the market open.

Works badly

"Build me a trading bot for this API." You will get 300 plausible lines, it will be wrong in two places you cannot see, and you will spend the morning bisecting something you did not write. Under time pressure that is the expensive path.

Two more that pay off immediately: ask it to write you a replay harness that feeds saved news items through your logic with no server, so you can test decisions in a second instead of waiting for the market. And ask it to write the tests for your sizing function. Position sizing is where teams lose, and it is trivially unit-testable.

4. Route A: calling the model from your bot

Skip this part if your bot is not going to read the news. Section 5 is the mechanical route.

Your machine already has credentials. Claude Code authenticates through a LiteLLM proxy using two environment variables that are already set, and your bot can reuse them exactly as they are. Nothing to install, nothing to request, no key to manage. This is an ordinary outbound HTTPS call, the same as everything else your bot does.

import os, json, anthropic

llm = anthropic.Anthropic(
    base_url=os.environ["ANTHROPIC_BASE_URL"],
    auth_token=os.environ["ANTHROPIC_AUTH_TOKEN"],
)

def assess(item, relationships):
    r = llm.messages.create(
        model="claude-haiku-4-5",          # fast and cheap; you are in a loop
        max_tokens=350,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content":
            f"Company relationships:\n{relationships}\n\n"
            f"Source: {item['source']}\n"
            f"Headline: {item['headline']}\n"
            f"Body: {item['body']}"}],
    )
    return json.loads(r.content[0].text)
Use haiku
In the hot path. claude-sonnet-5 and claude-opus-5 are also available and are worth trying offline on headlines you got wrong, but latency costs you window.
One call per story
Not per tick. Keep a set of news ids you have already seen and never pay for the same headline twice.
Ask for JSON
Direction, conviction, expected size, affected symbol. Parse it. Prose is unusable in a loop and you will end up regexing it at 12:30.
Validate the symbol
Against the instrument list before you act on it. Models do occasionally return a company that is not in the market.
Handle failure
Wrap the call. On a timeout, a parse error or a refusal, the correct default is do nothing, not guess.

4b. What to put in the prompt

Ask the model what a story implies, not what you should do. The buy or sell decision belongs in your code, where you can change it without re-reading a paragraph of English.

Worth telling it

That surface wording is frequently the opposite of the real implication. That a story may move a company it never names, and here is the relationship map. That many stories move nothing and saying so is a valid answer. That being unsure is information you want back, not something to hide behind a confident number.

Worth asking for

The affected symbol or symbols. Direction. A conviction from 0 to 1. An expected magnitude. And one short sentence of reasoning, which costs almost nothing and is the only thing that will make your debrief interesting.

Treat low conviction as a reason not to trade, rather than a reason to trade small. Those are different rules and they produce very different afternoons.

5. Route B: trading without a model at all

Entirely legitimate, and for a team that would rather write and tune rules than engineer prompts, probably the faster path to something that works. These are the angles this particular market actually offers. None of them require a single API call to a model.

Ride the drift

This is the big one, and it is a direct consequence of how the market is built. A story does not move the price instantly: the move begins about 90 seconds later and then plays out over roughly two minutes. So a price that has just started moving decisively is very often a price that will keep moving in that direction for another minute or so. You do not need to know why. You only need to notice early and be confident it is a real move rather than noise.

Separate signal from noise

The baseline wobble is small and constant; a news-driven move is larger and sustained. Those are statistically distinguishable, which means the whole problem can be posed as "is this move bigger than this instrument normally wobbles". Compute each name's normal variation over the session and treat anything well outside it as an event. Note the instruments genuinely differ: one of them is roughly twice as jumpy as the calmest.

Trade the relationships

The company map is published and machine readable. If one company starts moving hard on news, the companies connected to it very often move shortly afterwards. You can exploit that mechanically, without understanding a single word of the story: detect a decisive move in one name, then look at what depends on it.

Fade the overreaction, carefully

Moves settle at a new level rather than continuing forever, so a price that has run a long way in two minutes is usually done running. Mean reversion works on the tail of a completed move. It works very badly on a move that has only just started, and catastrophically on a company that is genuinely in trouble. Know which you are looking at.

Size by volatility, not by conviction

If you have no view on how big a move will be, let the instrument tell you. Smaller positions in the jumpy names, larger in the calm ones, so no single holding dominates your outcome. This alone puts you ahead of most teams, and it is about fifteen lines of code.

Use the index as a base

The index fund has no position cap, so you can park most of the account in it and trade actively around the edges with the rest. That way you are in the market earning whatever the market does, instead of sitting in cash while your bot decides what it thinks, and your active bets are what you are actually judged on.

The one mechanical approach that does not work

Counting positive and negative words in the headline. It is the first thing everyone thinks of, it takes ten minutes to write, and the feed is specifically constructed to defeat it. In testing, a keyword bot finished below a bot that never traded at all. If you want to read the news, read it properly. If you do not want to read the news, trade the prices. Do not do the thing in between.

To be straight about the trade-off, with real numbers. We built the drift-follower described above and ran it against eight strategies through a full session. It finished fifth of eight at +1.5%. It beat sitting in cash, and it beat keyword matching by a wide margin. It also lost heavily to the bots that actually understood what the stories meant, which finished north of +20%, and it paid one of the largest spread bills on the board getting there, because following moves means trading often.

Take that as calibration rather than discouragement. Ours was a first attempt with guessed thresholds and no tuning, which is exactly what you would have by mid-morning, and a tuned one would do better. But the honest summary is that the news is where the large moves are, and a bot that never looks at it is leaving the biggest edge in the market on the table. The counterweight is equally real: a working mechanical bot beats a clever one that is still throwing exceptions at 12:45, and that is not a hypothetical either.

6. Mind the latency budget

Route A only.

You have about 90 seconds from a story appearing to the price starting to move. A model call is a few seconds, which is comfortable for one headline and not comfortable for five. Stories do arrive in bursts.

If your loop analyses headlines one after another while blocking, a busy minute can push your last decision outside the window it was for. Options, in increasing order of effort: analyse in a background thread while the main loop keeps polling; do them concurrently; or triage first, cheaply, and only spend a model call on stories that mention something you hold or something you might buy.

7. Things that will bite you

Silent order rejections

A rejected order returns an error code with a 4xx, not an exception. If you are not checking the status, your bot will happily believe it owns something it never bought. Log every rejection loudly.

Restarts

Your bot will crash at least once. The server remembers your positions, your bot does not. On startup, read /portfolio and /orders and believe those rather than anything you kept in memory, and do not re-analyse news you already traded.

The rate limit is per team

Three people each running the bot while debugging shares one budget of 60. You will hit it, blame the server, and lose twenty minutes. Agree who is running the live one.

Cap drift

The 30% limit is checked when you buy and never again. A winner that keeps winning quietly becomes half your account. If you care about staying at 30%, you have to trim it yourself.

8. Split the work three ways

Three people cannot productively edit one file, and the morning is short. A split that works, because the interfaces between these are small and obvious:

Plumbing
The API client, polling, rate-limit handling, order placement, logging. Owns the fact that the bot stays alive for an hour.
Judgement
The prompt and the analysis function. Iterates offline against saved headlines, and is the only person who should be changing the prompt.
Policy
Sizing, entries, exits, risk. Owns the numbers. Also the person with the inspector page open, watching what the bot is actually doing.

9. A ladder, if you want one

Build these in order and stop wherever the clock runs out. Every rung is a working bot, which is the point: at no stage are you holding a half-finished one.

It connects and it trades

Polls the market, places one hardcoded order, prints the portfolio. Ten minutes. You now have something that cannot fail at 12:30 for a boring reason.

It has an opinion

Polls /snapshot and acts on something. Route A: send each new headline to the model, buy a fixed amount on a positive verdict, sell on a negative one. Route B: detect a decisive move against that instrument's normal wobble and follow it. Either one, at fixed size, will already beat several teams.

It sizes and it exits

Position size scaled by conviction and expected magnitude. A stop loss and a take profit. Stops opening new positions near the close. This is where the leaderboard starts to separate, and it is mostly arithmetic rather than cleverness.

It remembers

Keeps state per company rather than treating every signal as fresh, so new information about something you already hold makes you re-evaluate rather than just stacking another position on top. Route A adds source weighting and story arcs. Route B adds the relationship map and reacting to what a move implies for connected names. This is the bot that wins.

Keep a log you can read afterwards

Every decision, with the headline, the model's verdict, its one-sentence reasoning, what you did, and what the price did next. It costs one line of code. It is how you will find the trade where the model was fluent, specific and completely wrong, and that trade is the most interesting thing you will have to say in the debrief.

The day

One practice run, one hour that counts.

09:00

Kickoff

What the game is, how the API works, and your team's key.

09:30 · morning

Practice market opens

Real API, fake money, nothing scored. This is where you find out that your order format is wrong and that you hit the rate limit in ninety seconds. Much cheaper to learn now. The practice news is completely different from the afternoon's, so there is nothing to memorise.

12:00

Lunch

Balances reset. Nothing from the morning carries over.

12:30 · one hour

Live session

The real run, leaderboard on the big screen the whole time. Somewhere in the middle, the shock hits.

13:30

Market closes

Orders stop being accepted. Your balance at that instant is your score.

13:45

Debrief

Five minutes per team: what your strategy was, where Claude Code genuinely helped, and where it produced confident nonsense. This is usually the best part of the day.

How you actually win

Three skills, and only one of them is reading.

Skill 01

Judgement

Is this signal real, is it noise, and which company does it actually touch? Whether you answer that by reading the story or by measuring the price, everything downstream depends on getting it right.

Skill 02

Sizing

A story worth 1% and a story worth 8% should not get the same amount of your money. Teams that read the market best and still lose almost always lost here.

Skill 03

Discipline

Knowing when to sell, when to sit out entirely, and what to do when something you own falls off a cliff. Staying in cash is a decision, not an absence of one.

The most likely story of the day: some team will read the news better than anyone else in the room and still not win, because they sized it wrong. That contrast is the whole reason we are running it this way.

Ways teams reliably lose

Trading every headline. Roughly half of them mean nothing. The spread quietly eats you while your hit rate looks respectable.

Going all in on one conviction. The cap stops the worst of it, but a maxed position in the wrong name when the shock lands is a very bad afternoon.

Buying and then not reading. Stories come in sequences. The thing that made you buy at 12:40 can be undone at 12:55, and only if you are still watching will you notice.

Trusting the headline. The body text is where the actual information is. Every trap in this game is sprung on someone who only read the first line.

Treating a denial as an answer. A company rejecting an allegation is not the same as the allegation being false, and a company that has reassured you three times has still only ever reassured you. Ask what would have to be true, and whether anything published so far actually establishes it.

Letting a winner become the whole account. The best performer in the market is the best performer right up until the moment it is the story instead. Size is a decision you have to keep making, not one you make once.

Getting started

Before the live session, do these.