Contents

Building a Prediction Market From Scratch (0): Why, and Why Every Line Will Be Open

Building a Prediction Market From Scratch (0): Why, and Why Every Line Will Be Open |

Last weekend I didn’t make any other plans. I just wanted to settle a question that had been sitting in the back of my head for a long time: with one person, could you actually build a whole prediction-market backend — not a demo, but the kind you’d dare to put in front of real money?

Matching, clearing, risk, reconciliation — I’ve worked on these for years, and they’ve pulled me out of bed in the middle of the night more times than I’d like to count. I know where the soft spots are. So this wasn’t an idle “wouldn’t it be cool.” It was more like an itch I finally decided to scratch.

Two days later, it was running. That’s where this series comes from. Over the coming chapters I’ll build the whole thing again, out in the open, one module at a time — and I won’t skip the parts that are actually hard.

上个周末,我没安排别的事,就想把一个在脑子里搁了很久的问题给落地:凭一个人,到底能不能把一整套预测市场后端做出来——不是 demo,是敢放到真金白银面前的那种。

撮合、清算、风控、对账,这些我做了很多年,被它们半夜从床上拽起来的次数,我自己都不愿意数。哪儿是软肋,我心里有数。所以这不是那种"做出来一定很酷"的空想,更像一个憋了很久、终于决定挠一挠的痒。

两天后,它跑起来了。这个系列就是从这儿来的。接下来我会把整套东西当着所有人的面再做一遍,一块一块来,而且真正难的地方,我一处都不绕。

First, the thing I care about most

Before anything else, let me say the part that actually matters to me.

Every line of code in this series will be open. Every design decision — including the ones I got wrong and had to walk back — gets written down. All of it free, no strings: no “the core is open, the good parts cost money,” no license that quietly forbids you from shipping a product with it, no interesting 20% locked behind a wall. If you want to take the whole thing and build a business on it, take it. You don’t owe me anything.

I’m doing it this way because most of what goes into a trading system was never really a secret. How to model an account so money can’t appear out of thin air or quietly leak away; how to make matching reproducible; where the seams are that quietly kill a system in production — this knowledge mostly just sits scattered around, half-written-down, locked inside a few people’s heads and private repos. I’d rather put one complete, working, honest version somewhere anyone can read it. That feels more useful than keeping it.

先说我最在乎的一件事

别的都往后放,我先把真正在乎的那件事说了。

这个系列里的每一行代码都会公开。每一个设计决策——包括那些我做错了、后来推翻重来的——都写下来。全部免费,没有任何附加条件:不搞"核心开源、好东西收费",不用那种偷偷不让你拿去做产品的协议,不会把最有意思的那 20% 锁在墙后头。你想把整套东西拿去做成生意,拿走就是,你不欠我什么。

我之所以这么干,是因为做交易系统的这些东西,本来大多就不是什么秘密。怎么把账户建模到钱不会凭空冒出来、也不会悄悄漏掉;怎么让撮合可复现;那些会在生产环境里悄无声息要了系统命的接缝在哪——这些知识大多只是散落各处、半写不写地锁在少数人的脑子和私有仓库里。我宁愿把一个完整的、能跑的、诚实的版本,摆到任何人都能看见的地方。比攥在手里有用。

One person, and why that’s actually enough now

A few years back, a thing like this was a team and the better part of a year. A couple of people on the frontend, a couple on the backend, the most senior person pulled aside to wrestle with matching alone, someone permanently babysitting the database. I sat in plenty of those rooms. Half the calendar went to meetings whose only purpose was to keep everyone’s mental model of the same interface from drifting apart.

What changed isn’t that “AI can write code” — everyone knows that by now. What changed, for me, is quieter and a little counterintuitive. All the work that used to be spread across people and is tedious and error-prone by hand — scaffolding, boilerplate, migrations, half the tests, most of the docs — I hand to the AI now. It’s steadier than an intern and I never have to explain the same thing twice. So the attention I used to spend herding people, I now spend on the parts that decide whether the thing lives or dies.

And here’s the part that surprised me the first time I noticed it: when every core detail lives in one head, the system tends to break less, not more.

Trading systems rarely die because someone fat-fingered a function. They die at the seams. The matching person assumes clearing will mop up the remainder; the clearing person assumes matching already checked the balance; risk has its own private theory about the order money moves in. Each piece is correct on its own. You bolt them together, let real money flow through, and it cracks right at the joint. I’ve watched this happen more than once, and when you trace it all the way down, the root cause is almost always the same sentence: everyone assumed someone else had it.

One person, plus an AI that doesn’t get tired or forget, owns the whole thing end to end — and those seams just aren’t there to crack. The price is that this one person has to genuinely understand every block. Which, honestly, is the part I enjoy.

一个人,以及为什么现在真的够了

几年前,这种事是一个团队加上大半年。前端两三个人,后端两三个人,最资深的那个被单独拎出去啃撮合,再有个人长期守着数据库。这种屋子我没少待过。日历有一半花在开会上,而那些会唯一的作用,就是别让每个人脑子里对同一个接口的理解越跑越远。

变的不是"AI 会写代码"——这事现在谁都知道。对我来说,变化更安静,也有点反直觉。那些过去摊给好几个人、手写起来又烦又容易错的活儿——脚手架、样板、迁移、一半的测试、大部分文档——我现在都交给 AI。它比实习生稳,我也不用把同一件事讲第二遍。于是我从前花在"招呼人"上的精力,现在全花在决定这东西生死的地方。

而真正让我第一次留意到时有点意外的,是下面这件事:当所有核心细节都待在一个脑子里的时候,系统反而更不容易坏。

交易系统很少死于谁手抖写错了一个函数。它死在接缝上。撮合的人以为清算会把零头收干净,清算的人以为撮合早就校验过余额,风控那边对资金按什么顺序流转又有自己一套理解。每一块单独看都对。拼到一起,真金白银一淌过去,正好在接缝处裂开。这种事我见过不止一次,顺着往下刨到底,根因几乎永远是同一句话:当时大家都以为对方会管。

一个人,加上一个不会累、不会忘的 AI,端到端把整件事扛下来——那些接缝压根就不存在,也就无从裂起。代价是这个人得真懂每一块。说实话,这恰恰是我觉得有意思的地方。

The places I won’t let myself wave a hand

There’s a wide river between a trading system that demos and one you’d dare to take live. To demo, you wire the pieces together, run the happy path, done. To go live, you have to answer a string of questions that keep you up at night. I’ve fallen into each of these myself, and I’ve been the one pulling other people out of them. Let me lay them on the table, because the whole series is really just walking down this list:

The account model. How is money kept? How do you separate available balance from frozen? You freeze on order, unfreeze on cancel, settle on fill — and across all that motion, can you swear that not one cent ever appears from nowhere or quietly goes missing? This is the foundation. Tilt it a millimeter and every floor above cracks.

Matching and clearing. Who trades with whom, at what price, and afterward how does each side’s balance and position move? Where does the unfilled half of a limit order go; what happens to the part of a market order nobody fills? Simple on paper, pure devil-in-the-details in code.

Risk control. Do you lock funds before you accept an order, and how much? How do you stop someone trading with themselves? An order that’s obviously wrong — does the system reject it on the spot, or let it in and wait for the blowup?

Fund safety. Deposits and withdrawals sit closest to the money, which means they’re the part everyone with bad intentions is watching. One sloppy signing authorization, one withdrawal whose upper bound you forgot to pin down, and you’ve handed money to someone who should never have touched it. I’ll give this a whole chapter, and use it to show how Polymarket pulls the same thing off non-custodially, on-chain.

The edge cases. A service dies, a message goes missing, the database lags half a beat — does the system get the books wrong because of it? This is the hardest line between a toy and a product. Anyone can write the happy path. The craft is all in the error branches.

The prediction market we’re building is, honestly, simpler than something like a leveraged perpetuals exchange — no liquidations, no funding rates, balances and positions all stay non-negative. But not one item on that list gets to be skipped. Simple doesn’t buy you the right to be sloppy.

哪些地方我不让自己挥手带过

能演示的交易系统,和敢上线的交易系统,中间隔着一条很宽的河。能演示,你把零件拼起来,把 happy path 跑通,就完事了。敢上线,你得回答一连串让人睡不着的问题。这几处我自己栽进去过,也当过把别人从里头捞出来的那个人。我索性都摆到台面上,因为这个系列说到底,就是顺着这张单子往下走:

账户模型。 钱怎么记?可用余额和冻结怎么分?挂单冻结、撤单解冻、成交结算——这一通来回里,你敢不敢拍胸脯说,一分钱都不会凭空出现,也不会悄悄少掉?这是地基。歪一毫米,上面每一层都裂。

撮合与清算。 谁和谁成交,什么价,成交完两边的余额和持仓各自怎么动?限价单没吃完的那一半挂哪儿,市价单没人接的部分怎么办?纸上简单,落到代码里全是魔鬼细节。

风控。 接单之前要不要先锁钱,锁多少?怎么拦住一个人自己跟自己成交?一笔明显有问题的单,系统是当场拒掉,还是放进去等着出事?

资金安全。 充值提现离钱最近,也就意味着,它是所有不怀好意的人都盯着的地方。一次马虎的签名授权,一个忘了卡死上限的提现,就足以把钱递到一个本不该碰到它的人手里。这一块我会单开一章,顺手讲讲 Polymarket 是怎么在链上把同样的事做成非托管的。

异常场景。 服务挂了、消息丢了、数据库慢了半拍——系统会不会因此把账算错?这是玩具和产品之间最硬的一道分界线。Happy path 谁都会写,真功夫全在异常分支里。

我们要做的这个预测市场,说实话比带杠杆的永续合约简单——没有爆仓,没有资金费率,余额和持仓全是非负的。但上面这张单子,一项都省不掉。简单,不等于你就有资格马虎。

Three things I’ll keep next to me the whole way

Talk only about your own code for long enough and it turns into a hall of mirrors. So I’ll keep three things next to me throughout, to mark where “it runs” and “it’s production-grade” actually part ways.

The first is the project itself — three Rust services you can run, change, and ship. That’s the spine of the series.

The second is an article I think highly of. The author is also one person plus an AI, chewing through a perpetuals DEX, and at one point he takes the deposit/withdrawal module completely apart. His way of thinking and what I’m trying to get across are nearly the same thing, so I’ll borrow his reasoning when it fits.

The third is Polymarket — the largest prediction market in the world, real money, running on-chain.

Here’s what I find genuinely nice: under the hood, all three are the same shape — match off-chain, settle in one central place. Polymarket matches off-chain on an order book and settles on-chain through contracts; that perpetuals DEX does off-chain matching, on-chain settlement; ours does off-chain matching, database settlement. Understand one and the other two click into place. I’ll lean on this again and again, especially once we get to the money.

全程我会放在手边的三样东西

只盯着自己的代码讲,讲久了就成了照镜子。所以全程我会把三样东西放在手边,用它们标出"能跑"和"生产级"到底在哪儿分的岔。

第一样是这套项目本身——三个 Rust 服务,你能跑、能改、能上线,是整个系列的脊梁。

第二样是一篇我挺服气的文章。作者也是一个人加一个 AI,在啃一套永续合约 DEX,其中有一段,他把充提模块整个拆开摆给你看。他的思路跟我想传达的几乎是一回事,合适的时候我会把他的想法借过来用。

第三样是 Polymarket——全世界最大的预测市场,真金白银,跑在链上。

我觉得真正妙的地方在这儿:剥到底下,这三样是同一个形状——链下撮合,集中到一处结算。 Polymarket 是链下用订单簿撮合、链上靠合约结算;那套永续 DEX 是链下撮合、链上结算;我们这套是链下撮合、数据库结算。把一个想透,另外两个一点就通。这条线我后面会反复用,尤其是讲到钱的时候。

A word about working with the AI

This series is itself the product of one person and an AI. If you want to work this way too, there are three habits I keep — not rules, just things I’ve learned the hard way.

I write the spec before the code. I get clear on what I’m building, where the edges are, and what counts as done — on paper — and only then let the AI implement it. Every minute I skip here comes back later as debugging, with interest. There’s a folder of these specs in the repo; you’ll see them.

I make myself explain the principle out loud. The AI will hand me working code all day, but whether I can say why it’s correct is on me. The spots I can’t explain are exactly the spots I don’t really understand yet — and those are the spots that come back to bite.

And I verify in small steps. Finish a block, run it, look at the real output, then move on. In a trading system, “I assumed it worked” is the single most expensive sentence there is.

That’s enough preamble. Next chapter, we get the system running on your machine and place a first order by hand. And the code — every line of it — will be sitting in the open repo, free, no strings, exactly like I said.

顺便说说跟 AI 一起干这件事

这个系列本身就是一个人加一个 AI 攒出来的。你要是也想这么干,有三个习惯我一直守着——不是什么铁律,就是吃过亏才学会的几件事。

我先写规格,再写代码。先在纸面上想清楚要做什么、边界在哪、怎么才算做完,然后才让 AI 去实现。在这一步省下的每一分钟,后面都会变成调试,连本带利还回来。仓库里有一个专门放这些规格的文件夹,你会看到。

我逼自己把原理讲出声。AI 可以一整天给我递能跑的代码,但能不能说清它为什么对,是我的事。我讲不清的地方,恰恰就是我还没真懂的地方——而这些地方,迟早会回头咬你一口。

还有,我小步验证。写完一块就跑一跑,看一眼真实输出,再往下走。在交易系统里,“我以为它对了”,是最贵的一句话。

开场白到这儿就够了。下一章,我们把系统在你机器上跑起来,亲手下出第一单。而代码——每一行——都会摆在公开仓库里,免费,没有附加条件,就像我说的那样。