99 Francs
sales@99francs.agency

HQ Paphos, Cyprus · worldwide

Case study · FinTech / Crypto

A custom Polymarket trading & market-making system — the latency-critical path rewritten in Rust.

99 Francs designed and built an automated trading and market-making system for an independent quantitative trading desk on Polymarket. We kept the quant logic in Python and moved only the latency-critical execution path into a Rust sidecar — cutting the reaction time on the most expensive event from roughly two seconds to the low tens of milliseconds, without rewriting a line of strategy code.

Polymarket trading system admin dashboard with a tab per strategy and live P&L
ClientIndependent quant trading desk (NDA)
ScopeAutomated trading & market-making system
Timeline~4 months (~1,770 commits)
Project value$25,000
StackPython · Rust · React · Node.js
VenuePolymarket · Polygon · CLOB
Measured outcome

Speed put exactly where it pays for itself.

The headline win is the reaction time on a partial fill — a measured before / after, with a sub-20 ms in-process decision budget verified against recorded market data.

~2s → ms

reaction after a partial fill

Measured before → after on the one event that actually costs money: reassembling a position after a partial fill.

~100×

faster on the expensive event

Round-number framing of roughly two seconds down to the low tens of milliseconds.

2,700+

automated tests

Across Python (1,731) and the Rust execution crate (~1,000) — unit, replay and certification runs.

~2 months

for the Rust execution plane

A bounded sub-project, flag-gated per market and validated live before being armed under a formal certification.

Direct answer

We build custom automated trading and market-making systems for prediction markets like Polymarket.

A Python quant engine, a low-latency Rust execution core, a React control dashboard, a full backtesting and replay system, and a safe virtual-to-real rollout. We build the infrastructure and the safeguards — strategy and returns stay with the client.

Challenge

On a fast market, a stale quote is money on the table.

The desk needed an execution path fast enough to avoid getting picked off, a way to test many strategies without risking capital, and a gated, reversible route to putting real money on-chain.

Execution latency decided profit and loss

On a fast market a resting quote that is not pulled in time gets picked off. The original Python control loop ran on a multi-second poll, so the follow-up quote after a partial fill appeared 0 to 2+ seconds late — long enough to turn a small, reliable profit into a several-times-larger loss.

Many strategies had to be tested without risking capital

The desk needed to compare dozens of strategies on live and recorded data — in a paper mode indistinguishable from real — before a single dollar moved on-chain.

Real capital needed a gated, reversible path to production

Going live had to be deliberate: fail-closed on any stale feed, reversible behind flags, and armed only after formal certification.

What we built

A two-plane system: a Python brain and a Rust execution core.

Four surfaces, each with one job — with the millisecond-sensitive work isolated in Rust so the rest could stay in the language it belonged in.

Python quant engine

The financial source of truth — strategy models (numpy / scipy), market discovery, EIP-712 order signing (web3), accounting, risk stops, alerts. Trusted and easy to change.

Rust execution core

A low-latency sidecar (tokio + the venue's official Rust CLOB SDK) owning only the millisecond-sensitive work: a lock-free order-book cache, a ~5 ms decision tick, place / cancel, and folding fills into inventory in real time.

React control dashboard

A single-page app (lightweight-charts + recharts) with a tab per strategy, live equity curves, a signal-log browser, real-wallet equity and one-switch mirror settings.

Node / SQLite admin API

An Express API over a single SQLite book-of-record — strategy configs as rows, live heartbeats and circuit-breaker state, and safe start / stop of the engine.

Architecture

How one trade flows, end to end.

Live price feeds and the venue order book continuously update in-memory state. The Python engine runs each enabled strategy in its own loop; when conditions are met it sizes the position against real book depth, signs the order, and either sends it directly or — for the market-making path — hands the quote context to the Rust sidecar over a local Unix socket. The sidecar owns the millisecond place / cancel loop; fills stream back over a user-WebSocket, reconcile into inventory and write to SQLite, which instantly powers the dashboard and Telegram alerts. The sidecar is best-effort: if it drops, Python falls back to native handling — it can never take the system down.

React dashboardlightweight-charts · per-strategy tabs
HTTP
Node / Express APISQLite book-of-record
child process
Python quant enginenumpy · scipy · web3 signing · strategy loops
Unix socket
Rust fastquote sidecartokio · CLOB SDK · lock-free book · user-WS
↕ market-data · user-fill WebSockets · REST
Polymarket CLOB · Exchange price feed + on-chain oracle
Python → Rust

A slow control loop, not a slow language.

The obvious answer — “rewrite it all in Rust” — was the wrong one. The quant models, signing, accounting and risk were correct and valuable. We moved only order-book ingestion, the decision loop and place / cancel into a Rust sidecar; the core migration landed in about two weeks, and the full execution plane followed over the next weeks.

What we measuredBefore (Python)After (Rust plane)
Reaction after a partial fill0–2+ secondslow tens of ms (sub-20 ms in-process decision, verified on recorded market data)
Decision tickmulti-second poll~5 ms
Cancel pathPython HTTP round-tripremoved from the hot path
Strategy code rewrittennone
Capabilities

Everything a quant desk needs to test, watch and go live safely.

Strategy thresholds and formulas stay the client's — what we built is the system around them.

Multi-strategy A/B framework

Every strategy is a config row, enabled or disabled independently, each with its own dashboard tab. Roughly 25+ variants — arbitrage, market-making, momentum, latency — have run side-by-side on live data.

Virtual and mirror-to-real modes

Every strategy runs simulated by default; any one can be mirrored to a real-wallet configuration, with a flag on every trade distinguishing virtual from real.

Backtesting & replay

Fills are modelled against real order-book depth, not the midpoint — replaying six years of minute data, real recorded venue prices, and full captured order-book sessions on a monotonic clock with a latency sweep.

Order-book imbalance detection

Depth-weighted imbalance across the top levels flags when the market has abandoned a side, with hysteresis and staleness guards — so the maker stops buying the losing leg instead of chasing it.

Anti-pickoff execution

Orders are formed and signed before they are needed, and a WebSocket-reactive requote loop cancels a stale leg in milliseconds — shrinking the window in which a resting quote can be picked off.

Telegram alerts & admin control

~20 typed alerts (placements, resolutions, daily stops, guard pauses) plus a React admin for per-strategy config, mirror settings and strategy creation.

Real-money mirror config: enable a strategy per asset and timeframe cell
Per-cell mirror-to-real controls (asset × timeframe)
Per-bet signal log with direction and virtual vs real P&L per trade
Per-bet signal log · direction and P&L per trade
Proof the tooling works

We build the tools. The desk keeps the edge.

On the platform's A/B framework the client backtested around 65 strategies. One automated arbitrage strategy reached +955% ROI at a 77.1% win rate across 481 fully automated trades over ~4 months. That is the client's own result on our infrastructure — we make no performance promises and never sell returns; we build the system that lets a quant team find and validate strategies safely.

Strategy dashboard: 955.7% ROI, 77.1% win rate, 481 trades, with the equity curve
Client's strategy dashboard · 955.7% ROI · 77.1% win rate · 481 trades
Process

Correctness first, speed second, real money last.

Spec-driven and test-heavy: a detailed design doc — reviewed independently before a line was written — preceded every milestone, each shipped in small, feature-flagged, reversible steps.

01

Platform + first strategies

We stood up the three-tier stack, migrated to the venue's V2 API, and shipped the first arbitrage family — establishing functional correctness before any optimisation.

02

Strategy library + adverse selection

The center of gravity: proliferating and hardening strategies, diagnosing where the market-maker was getting picked off, and building the first fast-cancel Rust sidecar.

03

Per-lot accounting + Rust decision loop

We refactored the engine into a registry-driven layout, made inventory accounting exact, and moved the book and decision loop into Rust — the core migration landed in about two weeks.

04

Multi-market execution plane + measurement

We extended the sidecar to serve several markets at once, then ran an explicit measurement phase — verifying latency and parity against recorded data before scaling by diversification, not size.

How we shipped it safely

Real money, so speed never compromised correctness.

Every major milestone passed multiple rounds of independent AI code review before merge, and the live controller stays flag-gated per market — a control surface for safe rollout, not a sign the path is unfinished.

Deterministic order identity

Each order's ID is derived from its signature before it is sent, so a lost network response never means a lost order.

Exact-integer accounting

Fills are counted in integer micro-units, never floating point — no rounding drift at any size, and idempotent writes survive restarts and WebSocket replays.

Fail-closed by design

A stale feed, a dropped socket or a watchdog timeout all resolve to “stop quoting,” never “quote on stale prices.”

Production-proven, flag-gated

The autonomous Rust controller runs the full decision → place → cancel → fill loop on its own, with its latency wins validated live. Because it trades real money, every part sits behind feature flags — armed, paused or rolled back instantly per market — and was cleared by a formal certification: zero accounting drift, 100% canonical-path fills, zero secrets. The flags are a safety feature, not a sign the path is unfinished.

AI agents, bots & custom systems

Have a system that's fast enough to be dangerous but slow enough to leak money?

Trading systems · Automation · Python · Rust · Real-time dashboards
Case study FAQ

Questions about building a Polymarket trading system.

Yes. 99 Francs builds custom automated trading and market-making systems for prediction markets like Polymarket: a Python quant engine, a low-latency Rust execution core, a React control dashboard and a safe virtual-to-real rollout. We build the infrastructure and safeguards; strategy and returns stay with the client.
This system was built over roughly four months and ~1,770 commits, with the Rust execution plane as a bounded ~2-month sub-project inside that. The core Python-to-Rust migration of the hot path landed in about two weeks on top of a detailed, independently reviewed design.

Only for the latency-critical path. Here the problem was a slow control loop, not a slow language: a multi-second poll left the follow-up quote seconds late. We kept the quant logic in Python and moved only order-book ingestion, the decision loop and place/cancel into a Rust sidecar. More on the approach in our Python-to-Rust migration write-up, and the Python development service.

Pickoff (adverse selection) is when the underlying moves and a resting bid on the now-stale leg gets hit before the maker can pull it, leaving a losing one-sided position. Defences here include pre-signed orders, a WebSocket-reactive requote loop that cancels a stale leg in milliseconds, order-book imbalance detection that pauses buys on the abandoned leg, and enforced post-only quoting.
No. 99 Francs builds the trading infrastructure, testing framework and safeguards — not the strategy edge and not a return. Any performance figures shown are the client's own results on the platform, and past results never guarantee future ones.