Valeon

Start typing to search posts by title.

Digital blocks connected with glowing lines, illustrating concepts of technology and data exchange in a graphic, futuristic style.

Three Adapters, One Wire

SFSayed Hamid Fatimi
20 min read
Listen to this post0:00 / --:--

In 160,000 Lines Later, the plan was a public release scoped to one exchangeBitMEX alonebecause that was the one exchange the UK KYC restriction had left me able to test with real capital. The other nine adapters were already built from spec, already audited, already sitting there doing nothing except waiting on a regulatory ceiling I don't control. It's the kind of constraint that looks, from the outside, like a technical limitation. It isn't. It's a bureaucratic one wearing a technical costume, and the distinction matters more than it sounds like it should, because a technical limitation eventually yields to enough engineering, and a bureaucratic one just sits there until someone with the right authority decides otherwise. What's changed in the week since that post isn't the ceiling. It's the count of exchanges sitting underneath it.

Let me state outright what the last post only gestured at, because it deserves its own sentence rather than an implication buried in a paragraph about Y Combinator: the KYC gate has never been a gate on who can use Plutarc. It is a gate on me, specifically, on how many of the ten already-built adapters I can personally validate with real money in the account before I'd trust any of them with someone else's. Every adapter passed the same spec-driven build and audit cycle back in April. KYC decides which of them I've actually watched execute a live order, under real market conditions, with capital that would hurt to lose. It says nothing about which of them work. A user reading the last post could reasonably have concluded that nine exchanges were unavailable to the platform. What was actually true, and what I failed to say clearly enough, is that nine exchanges were unavailable to my own verification processa much narrower and much more temporary problem than it read as.

It turned out I'd already cleared that bar on two exchanges I hadn't been counting. Phemex and WOO X were both sitting verifiedleftover account-opening admin from months earlier, done for reasons unrelated to Plutarc at the time, never revisited, never mentioned in a single planning conversation about launch. I found out by accident, checking something unrelated, and had one of those small vertiginous moments where a constraint you've been narrating as fixed turns out to have quietly moved without telling you. Alongside BitMEX, that's three exchanges I can put real capital behind rather than one. Three is a small number by most standards. It was large enough to stop treating what happened next as a fluke, and large enough to turn a single-exchange validation story into something closer to a methodology.

Debugging the Documentation

Live-testing an adapter with real funds is supposed to be the last stepthe part where a system that's already passed every backtest and every audit finally proves itself against the actual thing it was built to trade against. For about two weeks it was something closer to an argument with three exchanges' documentation, conducted at odd hours, and the argument had a shape I didn't expect going in.

Almost none of the failures were logic bugs. WOO X publishes three versions of its APIv1, v2, v3on the same domain, with no reliable signal for which page describes which version, so a field mapping built against what looked like current spec would turn out to describe an endpoint two generations dead, silently, with no error thrown anywhere to tell you so. Phemex's documentation is worse in a more interesting way: split across three separate properties, most of them stale, none of them cross-referencing the others, so the correct answer depended entirely on which of the three you happened to open first, and switching to a second source to double-check often introduced a contradiction rather than resolving one. Even where the docs agreed with each other, they didn't always agree with the exchange itself. Phemex's request endpoints are singularyou ask for a trade, not tradesbut the response comes back plural, trades or trades_p depending on contract type, an inversion that costs you nothing to know once you know it and an entire afternoon to discover the first time. Fields get renamed across endpoints with inconsistent prefixes and suffixes for what is, semantically, the identical value, so a script that correctly parses one endpoint's response will silently misparse the next one that happens to describe the same underlying quantity under a different name. A field typed as a string in the official spec arrives on the wire as a number, and depending on what you do with it downstream, that mismatch either throws immediately or, worse, doesn't throw at all and just quietly produces a wrong number three calculations later.

None of that is exotic. It's papercuts, dozens of them stacked on top of each other, and each one is indistinguishable from a real bug until you've spent the time proving it isn't. Fix a mismatch, hit the next one, fix that, hit a thirdthe same circular debugging loop across three exchanges, and the loop doesn't close on its own no matter how carefully you read the docs one more time, because rereading a source that was never accurate just returns you to the same wrong answer with more confidence. There's a version of the platform-level lesson from the last post's RSI Divergence section that applies here too, oddly: a failing test is ambiguous between two causes until you go looking for the mechanism yourself, and for two weeks the mechanism kept turning out to be the same one. Eventually the actual finding wasn't about any single field, or any single exchange. It was that we'd been treating documentation as ground truth this entire time, across every adapter we'd ever built, when it had never actually earned that role. It earned trust the way any secondary source doesprovisionally, and only until checked.

The Wire

So we stopped trusting it, and built something to trust instead.

Every adapter now holds what we're calling a wirean annotated, fully typed record of that exchange's entire API surface, constructed the obvious way first and then rebuilt the way it actually needs to be. Read the docs, encode the types as a first draft, and then throw a throwaway key and a small amount of real capital at the live endpoints and see what actually comes back, because a sandbox or testnet environment is its own kind of documentation problema simulated response shape is still somebody's claim about what the exchange does, not a direct observation of it. Every REST endpoint gets queried, public and private both. Every WebSocket path gets exercised, every frame captured across every scenario we can provokenormal fills, partial fills, rejections, disconnects, reconnects mid-position, the edge states a happy-path doc never mentions because nobody writing the doc had to live through one. The wire gets built from what the exchange actually sends, not from what the exchange, or a testnet standing in for it, claims to send. Once that wire exists, writing the adapter itself stops being an investigation and becomes what it should have been from the start: plain TDD against a contract that's already fully known, talking to the bot engine purely through the interface, with nothing left to discover mid-implementation and nothing left to argue about at 2am.

The effect was closer to a phase change than an improvement, the kind of shift where the nature of the remaining problem changes rather than just its quantity. Something like ninety to ninety-five percent of the issues we'd been fighting simply stopped existing, because they were never logic bugs to begin withthey were unverified assumptions about message shape, and the wire doesn't let an unverified assumption survive past the first live query. What's left after that is a smaller, more honest category of problem: not an adapter that's wrong, but an exchange that genuinely doesn't expose data the bot's contract expects, which is a reconciliation question rather than a debugging one, and a fundamentally different kind of work to do. You don't fix a reconciliation gap by reading harder. You fix it by deciding, deliberately, what the bot should assume in the absence of data the exchange simply isn't going to give you.

The part worth stating plainly is that none of this was a one-time cleanup exercise, useful once and then forgotten. It's a spec nowwritten down, argued over, verified in practice across three separate adapters with three separate sets of documentation problems, and ready to run against every exchange still ahead of us in the queue. The next seven don't each need their own two weeks of circular bug-hunting, conducted from scratch, rediscovering the same category of mistake under a new exchange's particular vocabulary for it. They need a wire, built once, the same disciplined way, and the discipline is the actual asset heremore than any individual bug fix, more even than the ninety-five percent figure. A process that survives contact with a third exchange without needing to be reinvented is a process, not a lucky first attempt.

Toward a Legible Platform

A good share of what shipped this week doesn't photograph well in a changelog, but the wire discipline pushed the rest of the platform toward the same underlying standard: don't guess, don't infer, show the actual state and let the interface get out of the way of it.

Positions got their own pageevery open position across the fleet in one place, with per-position and close-all actions, instead of living scattered only inside each bot's individual view where a busy fleet made the overview genuinely hard to scan. Equity got honest about multi-currency fleets: instead of one long undifferentiated list that got harder to read the more exchanges you traded across, it now groups by settle currency, largest first, the rest collapsed behind a clean "+N more," and the same currency-awareness reached the analytics equity curve and drawdown charts, so a BTC-denominated position and a USDT-denominated one stop being plotted on an axis that made neither of them readable. Bot setup collapsed from two screens into one, with a "setup required" badge that tells you exactly what's missing instead of making you guess which of the two steps you skipped, and a booting bot now shows what it's actually doingloading market data, establishing its first connectionsrather than just looking offline for a stretch that used to read, incorrectly, as a fault. The bot detail page now surfaces its deployment region directly as well, a small thing, but the kind of small thing you only notice you're missing once several bots across several regions start looking identical at a glance.

Security tightened in a way that's easy to describe and easy to underrate precisely because nothing about it is visible day to day: every account's exchange keys now get their own dedicated encryption key, wrapped by a hardware-backed master key, so a single compromised secret can no longer cascade into exposing anyone else's keys alongside it. Two documentation pieces landed that matter more than their size suggestsa page showing exactly what version of every app, adapter, and core library is currently live, generated automatically rather than maintained by hand and therefore actually trustworthy, and a capability matrix built directly from each adapter's live data, so "does this exchange support trailing stops, sub-minute candles, order entry over WebSocket" stops being a question you email support about and starts being a table you read yourself, confident it reflects what the adapter can currently do rather than what it could do at some earlier point someone forgot to update.

Underneath all of it, the wire kept paying rent on Phemex specifically, in ways that had nothing to do with any single flashy feature. Positions closed exchange-sidea native stop, a manual close on the Phemex website, a liquidationnow get detected and reconciled automatically instead of sitting stuck open on the dashboard, silently wrong, until someone happens to notice. Trade, unrealised PnL, and equity figures moved from periodic polling onto the live WebSocket stream, which is both faster in the ordinary sense and, per the wire, actually correct in the sense that matters morereading from the same channel the wire itself was built by verifying, rather than from a slower, separately-maintained code path that had its own chance to drift from what the exchange was really doing.

Below the Minute

The single most technically interesting thing to ship this week is also the clearest proof that the adapter work isn't purely defensivethat hardening a foundation doesn't just prevent bad things, it makes new things possible that weren't before. Sub-minute candles now exist1, 3, 5, 15, and 30 secondsbuilt not from anything the exchange hands you as a kline, since no exchange in the lineup serves anything below a one-minute bar natively, but reconstructed entirely from its raw trade stream, aggregated client-side down to whatever window a strategy actually needs. This is the same fast-clock architecture that's underpinned scalping-oriented components since the last posttrade prints driving execution directly rather than waiting on a candle to closeextended one layer further, so that fast-clock output can also be bucketed into a fixed interval for strategies that want the discipline of a candle without giving up the resolution a one-minute bar throws away.

It shipped on BitMEX first, then WOO X a day later once WOO X's own wire was solid enough to trust the same aggregation logic running against itand that one-day gap is itself a small demonstration of what the wire is actually for. The aggregation module didn't need to be rewritten for a second exchange. It needed a second exchange whose trade stream could be trusted the same way BitMEX's already was, and once that trust existed, the feature followed almost immediately behind it. It comes with an honest warning in the template editor, because sub-minute data can be sparse depending on the instrument and the moment, and this is not a beginner's toolbut it's real, it's live, and it exists specifically because the wire made the underlying trade stream trustworthy enough to build on top of without a second layer of doubt underneath the first.

Capability Is Not a Recommendation

None of the above is a claim that BitMEX, Phemex, and WOO X are good venues for sub-minute strategies. It's a claim that the trade stream feeding those candles on all three exchanges is now accurate, which is a floor requirement, not a sufficient one, and the gap between those two things is exactly where the discipline warning in the template editor is trying to do its job. The docs and the UI are both deliberately blunt about it rather than leaving it as a footnote: sparse data and thin liquidity aren't edge cases at this timescale, they're the default condition most of the time, on most instruments, on most exchanges most traders have access to.

Order-flow and fast-clock strategies live or die on liquidity in a way that hourly and four-hour strategies mostly don't have to think about. A trend-following signal on a four-hour candle is averaging over enough real trading activity that a thin book barely registers in the result. A one-second candle built from the same instrument's trade tape has nowhere to hide that thinnessif the order book is shallow, the "signal" in the tape is mostly noise wearing the shape of a pattern, and no amount of accuracy in how faithfully the wire reports that noise changes what it actually is. The wire guarantees the platform isn't lying to you about what happened on the exchange. It says nothing about whether what happened on the exchange, at that size and that timescale, was ever meaningful to begin with. That second judgment is a venue-suitability question, and it's one the platform is built to inform rather than to make on a user's behalf.

This is why feature support across all three exchanges without a corresponding recommendation to actually trade this strategy class on them isn't an inconsistency that needs explaining away. It's the platform being honest that capability and suitability are different claims, and collapsing them into one would be doing users a disservice in the direction that costs them money. The capability matrix tells you what an adapter can technically do. It was never designed to tell you where a given strategy is well-advised, because that answer depends on the instrument, the size being traded, and the depth of that specific venue at that specific momentnone of which the platform can responsibly decide for you in the abstract.

Region matters here in a way it simply doesn't for slower strategies, and it's worth being concrete rather than gesturing at "latency matters" as a vague caveat. A pure trade-based fast-clock strategy is, by construction, reacting to individual prints arriving on the order of tens of milliseconds aparttwenty-five milliseconds between trades is not an unusual cadence on an active instrument. Deploy that strategy from a European region against an exchange whose matching engine sits in Asia-Pacific, and you're not shaving a few milliseconds off an already-workable setupyou're adding a network round-trip on the order of 250 milliseconds or more on top of a signal that updates roughly ten times faster than that round-trip itself takes to complete. At that point the bot isn't reacting to the tape. It's reacting to a stale, resampled memory of the tape, several update-cycles removed from what's actually happening on the exchange, and the irregular jitter that comes with cross-continental latency doesn't apply evenlyit can itself introduce gaps in the reconstructed trade stream that no client-side aggregation logic can paper over after the fact, because the aggregation can only work with the prints that actually arrived. This isn't a hypothetical, and it isn't specific to any one exchangeit's a general property of the timescale: below roughly a second, deployment region stops being a cost-and-convenience decision and becomes a structural precondition for the strategy meaning anything at all.

None of this is automated away, and it's a deliberate choice that it isn't. The dashboard surfaces the tools that let a user make this judgment correctlythe capability matrix, the per-region latency tables, the inline warning the moment a sub-minute interval is selected in the template editorbut matching a strategy class to a venue with adequate depth, and to a region with adequate proximity to that venue's matching engine, stays a decision the user makes deliberately rather than one the platform makes silently on their behalf. Automating that choice away would mean guessing at intent the platform doesn't actually have access to. Leaving it explicit means the person building the strategy is the one who has to know what they're building it for, which is exactly the right place for that responsibility to sit at this end of the interval ladder.

The Rest of the Ledger

Around the adapter work, the less dramatic infrastructure kept moving on its own schedule, mostly untouched by any of the above and worth recording anyway. A cheaper compute tier now exists for strategies that don't need to shave milliseconds off executionswing and low-frequency approaches where the marginal latency of a budget instance simply doesn't show up in the outcomesitting alongside the existing latency-sensitive tier for everything that does care. Five new deployment regions landed across Europe, the Americas, and Asia-Pacific, with meaningfully lower pricing in the APAC ones specifically, closing a gap where proximity to APAC exchanges had previously meant paying a premium simply for being close to them. Long-range backtests now fail loudly and immediately instead of silently hanging past a year of range, which sounds like a small fix until you've been the person staring at a spinner that will never resolve, and three new timeframesthirty minutes, daily, weeklysit at the opposite end of the same spectrum the fast-clock work occupies at the other. Same trigger-interval architecture, same components, running from a second to a week depending on what a strategy is actually trying to do, which is really the same underlying idea as the sub-minute work wearing a different scale: the catalog doesn't care what clock it's evaluated against, as long as the clock is one it can trust.

There's a piece still sitting on the other side of an approval that isn't mine to grant, and it's worth naming precisely because it's the one thing in this post that isn't a story about persistence paying off. Order placement over BitMEX's binary WebSocket channel is built and tested, a meaningfully faster execution path than the REST order flow the exchange currently requires for everything else, and it's blocked on a network-level authorisation from BitMEX's own technical teamrequested, pending, and entirely out of my hands. Some bottlenecks get solved by building a wire, by being more rigorous, by refusing to trust a source until you've checked it yourself. Some are just somebody else's inbox, and no amount of discipline on my end changes whose queue the request sits in.

A Second Live Footnote

The wire methodology reads clean in a blog post, all process and percentages and a tidy narrative arc from documentation problem to documentation-shaped solution. It didn't feel clean at two in the morning, watching a Phemex position's unrealised PnL jump by an amount that made no sense for the size of the move that had actually happened, on an account with real if modest money sitting behind it. My first instinct was the same one from the last post's footnoteassume the bot is wrong, assume the worst, stop first and ask questions later, let the private undocumented panic get there before the diagnostic process does. I paused the position instead of the bot this time, which felt like a small piece of progress even in the moment, though it's hard to take too much credit for choosing the less destructive of two overreactions.

It wasn't the bot. It was a field the documentation described as the position's realised PnL that was, on that particular response shape, actually returning something closer to cumulative funding paidcorrect data, arriving reliably, simply labeled wrong, and a downstream calculation that had trusted the label instead of checking what the number actually represented. The wire caught it within the hour, because that's precisely the kind of mismatch a verified type surface exists to catch, and the fix itself was smaller than the panic that preceded it by a wide margin. Three adapters in, I'm still consistently the slowest part of the validation loop. The system built specifically to be more disciplined than I am keeps turning out to be right slightly faster than I'm willing to trust it, and I'm not sure that gap closes just because I know, intellectually, that it should have by now.

Related posts

Illustration of interconnected database icons with glowing lines and data symbols, depicting a digital network or data management system in a dark, futuristic style.

160,000 Lines Later

Plutarc's journey from 82,000 lines of code to nearly 160,000 reveals hard-won lessons about trading platform development, as it transitions toward a public release focused on real-world usability with a single exchange while navigating regulatory constraints and enhancing its features.

SFSayed Hamid Fatimi
14 min read
Isometric illustration of the Plutarc orchestration layer chip at centre, with glowing circuit pathways connecting to nine exchange logos — OKX, KuCoin, Deribit, Gemini, Phemex, Bybit, BitMEX, Binance, and Kraken — against a dark trading dashboard backdrop with candlestick charts and the number 82,000 rising in a column of binary code

82,000 Lines of Code Later

Nine exchanges, a full adapter suite, equity protection, compute downsizing, and an honest account of what multi-exchange support actually requires to get right.

SFSayed Hamid Fatimi
16 min read
A person sits at a desk in a dimly lit room, working on dual computer screens with a colorful design, surrounded by art supplies and photography equipment.

Illness is an Audit

Recent challenges led to crucial behind-the-scenes upgrades at Valeon, resulting in improved resilience and transparency across our products, with powerful new features in gramatic, and a seamless integration with Canva to enhance content production workflows.

SFSayed Hamid Fatimi
5 min read