The first article in this series introduced our open-source market maker for cNGN. The second described the market it operates in: a Quidax order book that can show size but barely moves, and two Uniswap pools that move often but cannot absorb much size. This article is about the next problem. Once you decide to provide liquidity, where should you put it?
There is no good answer to this. We have a simple live policy, a larger research system around it, and several results that stopped us from making the live policy more complicated. We think this is useful progress. In a thin market, knowing what the data cannot support matters as much as finding a strategy that looks good in a backtest.
How We Provide Liquidity Today
On Base and BSC, we provide concentrated liquidity on Uniswap V4. This means we do not spread our capital across every possible price. We choose a lower and upper price, and earn fees only while the pool trades inside that range. A narrow range puts more of our capital close to the current price, which increases fee income per dollar while it remains active. A wide range earns less efficiently, but is less likely to be left behind when the market moves.
Our range begins with each pool's price history. The engine calculates an exponentially weighted moving average, or EWMA, which is an average that gives more weight to newer observations. It also estimates how much that pool has been moving. We place a range around the average and widen it when volatility is higher. We can also leave more room on one side when we expect the price to move in that direction (a parameter we call the "downside skew"). Base currently uses a range width of 2.75 standard deviations with a slight bias towards USD; BSC uses 3 standard deviations and is symmetric. Both use an EWMA lambda of 0.975, which makes the estimate slow to react to a single jump.
The range is then rounded to the ticks that Uniswap accepts. If price leaves it, we do not immediately chase the market. The engine waits until price has moved another 10% beyond the boundary, then closes the position, swaps the remaining tokens into the ratio needed for the new range, and mints again. This delay is deliberate: every move costs gas, may lock in a change in inventory value, and creates another swap. Base charges traders 15 basis points per swap and BSC charges 12. Those fees are our income when we are active, but they are also a cost to anyone arbitraging the pools back into line.
Quidax's order book is obviously very different. We create a ladder: limit orders to buy below a reference price and sell above it, with configurable spacing and size at each level. When the reference price moves far enough, the engine cancels the old ladder and replaces it, subject to a cooldown. This makes the trade-off easier to see. Quotes closer to the reference price are more likely to trade and make a tighter market, but leave less room for error; quotes further away trade less often but provide more protection against a stale or wrong reference. The DEX asks us to choose a continuous range. Quidax asks us to choose a set of discrete prices.
The operational plumbing tracks whether a position is in range, its token composition, its value, and its share of active liquidity. The production code is documented here.
The Questions We Have
The first question is range width. A tighter range can earn a larger share of fees, but only until price leaves it. A wider range stays useful for longer, but spreads the same capital more thinly. The right answer depends on fee volume, volatility, gas, the cost of changing the token mix, and how often a range needs to be rebuilt. A range that earns the most gross fees can still be the worse position after all those costs.
The second question is how quickly the EWMA should move. If it reacts quickly, the range follows recent prices but may chase noise. If it reacts slowly, it ignores short shocks but can remain centered on an old market. The same problem applies to every parameter. When should the volatility multiplier, skew, or rebalance threshold change? A backtest can always find a different winner in each period. That does not mean the engine should change settings every week. Data for such a new, thin market is just unstable.
The third question is whether we should move before price leaves the range. If flow is strongly one-sided, or one venue has already moved, an early shift could avoid an inactive position or a bad inventory conversion. It could also turn ordinary noise into needless trading costs. The useful test is not whether an early move would have looked smart once. It is whether the signal works on later data, at the decision time, and saves more than the move costs.
Thin markets make all three questions harder. There are fewer independent observations, long periods without a price update, and occasional trades large enough to dominate a window. The price itself may be a record of one participant's activity rather than a broad market view. We therefore need to know whether Base, BSC, or Quidax moves first; whether a move persists; and whether another venue adds information beyond a pool's own history. Without that, a “fair value” can easily become the same pool price fed back into its own strategy.
How We Do Research
We keep a small research canon here. The concentrated-liquidity papers give us the mechanics of ranges, liquidity math, position lifecycles, and early exits. The market-microstructure papers cover tick data, order-book imbalance, trade direction, flow and sizing. The backtesting papers provide the most important rule: model attainable size, capital use, fees, latency, churn and drawdown, then test later periods rather than choosing a policy on the whole history.
The repo's autoresearch work lives here. It is a set of explicit research briefs, datasets, scripts, result manifests and decision gates that let an automated research loop test a narrow hypothesis, record what happened, and pass the result into the next experiment. We point it at the raw Uniswap V4 histories, reconstructed marginal prices, Quidax snapshots and costed LP backtester. We're careful to specify that evidence is required before a result could change the live engine.
We gave this system four LP problems.
- Range selection: test EWMA and fixed-range policies across widths, smoothing speeds, skews and exit rules, including fees and position-management costs.
- Parameter change: use walk-forward windows and parameter-stability checks to distinguish a repeatable setting from a different in-sample winner every time.
The other two problems connect LP decisions to market structure.
- Thin-market signals: test whether past swap flow, fee intensity, volatility and liquidity conditions justify entering, skewing or leaving a range early.
- Cross-venue information: test whether Base, BSC or Quidax tends to move first, and whether the other venue's price improves a forecast or a costed LP decision. Each pool is evaluated separately because its fee tier, activity and token order differ.
There are strict limits. Historical V4 files contain two old price methodologies, so research uses sqrt_price_x96 as the canonical marginal pool price and separates periods around the known methodology boundaries. All features are built “as of” the decision timestamp, with the age of each source recorded. Random train/test splits are avoided in favor of walk-forward tests. Most importantly, the DEX cannot serve as both the input and an independent truth label. We do not yet have a clean external cNGN price series covering the relevant period, so several results remain diagnostic rather than deployable.
What We Have Learned So Far
Our first lead-lag study found a clear-looking pattern in 99 days of one-minute venue snapshots. Base led BSC at a peak lag of three minutes, with a correlation of 0.086 and a block-shuffle p-value below 0.01. The result was positive in all three sub-periods. Quidax did not lead either pool: its correlations were near zero, and its midpoint changed in only 161 of 142,568 minutes. When Quidax did re-quote, it moved in the direction of Base's prior move 69% of the time over 15 minutes, 66% over 30 minutes, and 63% over 60 minutes, although the event counts were small.
The trade-level follow-up made that pattern more concrete. After a Base swap moved its pool by at least 10 basis points, BSC recovered roughly 21–24% of the move within three minutes and 49–55% within 30 minutes, depending on the implementation. In the reverse direction, Base recovered only about 1% within three minutes and 4% within 30. Base moves also tended to continue, while BSC moves tended to reverse. Removing all 186 swaps linked to our own engine did not materially change the result. Quidax re-quotes were different again: matched responses came either after roughly 19–48 minutes or after 6–22 hours, and 78% of all quote changes occurred between 08:00 and 16:59 Lagos time. The book behaved like a manually maintained market, not a continuous source of price discovery.

That sounds like Base is the leader. It is a useful working description of this sample, but not sufficient to label as a stable rule. An expanding walk-forward model tested whether adding one pool's price improved forecasts of the other. It did not. At the one-hour horizon, adding BSC made the Base forecast worse by 0.242 basis points of mean absolute error, while adding Base made the BSC forecast worse by 0.587 basis points. Alternative linear, autoregressive, nonlinear and outlier-resistant models did not rescue the result. Timing estimates also changed sign across weeks and alignment choices. Our current perspective is therefore narrower: the pools co-move, but directional leadership remains largely unresolved.
The short-horizon extension reinforces that caution. At 15 minutes, only 31.7% of BSC-to-Base shocks and 32.0% of Base-to-BSC shocks had a new target-pool observation. Roughly two-thirds had no recorded update at all. Mean responses were small and every simultaneous confidence band included zero. This is the basic thin-market problem in numbers: a visible lag may reflect information moving slowly, or simply one venue not trading.
The LP backtests gave us another reason not to overfit. We tested 2,640 EWMA combinations and 2,240 fixed-range strategies with explicit take-profit, stop-loss, and out-of-range exit rules. The setting selected as best in training changed almost every walk-forward window: Base chose 26 distinct EWMA tuples in 26 windows, while BSC chose 25 in 37. After costs, all four streams built from each window's top-ranked setting lost money, ranging from -0.460% for the Base fixed-range strategy to -2.086% for its BSC counterpart. We then tested a much smaller directional policy. Its summed net return was +1.039% across four active Base windows, but -1.272% across seven BSC windows. Thus, it did not transfer.
For the cross-pool test, we froze a related but broader route-aware Base policy. Using only Base-local information, it could choose an upside-biased range, a tight fee-capture range, a downside-biased range, or cash. The preceding +1.039% result retained only four especially strong upside windows. The frozen policy covered the complete decision rule, so the cross-pool forecast could only veto an existing decision while the routes, ranges, and costs remained unchanged.
This cross-pool informed forecast did not improve net return. We evaluated the ungated and forecast-gated policies over the same 23 validation windows, restarting each window with the same virtual bankroll rather than carrying gains or losses forward. Summed across those independent windows, the ungated policy returned +0.515%, compared with +0.310% for the forecast-gated version. The gated version also had a worse worst window: -0.096% versus -0.009%. We also tried to evaluate multiple LP candidates under shared capital and inventory accounting rather than as isolated positions. The allocation histories needed to calculate a valid portfolio return were incomplete, so we report no portfolio result.
Conclusion
The practical finding is simple. Base, BSC and Quidax are not interchangeable copies of one market. Base often looked like the first mover, BSC often looked like the follower, and Quidax updated on a human schedule. But that pattern has not yet produced a stable forecasting rule or a better LP policy after costs. We have therefore kept the live engine simple: venue-local ranges, slow-moving estimates, explicit costs, and conservative reranging.
The more complicated ideas remain in research until they work on later data, across the relevant venues, and against an independent measure of value. In a thin market, restraint is part of the strategy.
One thing to note is that Uniswap has switched on pool fees since we gathered a lot of the data this article is grounded in. This makes LP’ing into such exotic, thin markets even less profitable and likely shifts a lot of how our research is set up, given that the fees we stand to earn are now reduced. This, in itself, is a complex topic with lots of differing opinions. What we can say in this context is that AMMs appear to be really good at helping long tail, exotic pairs discover real prices in transparent ways which are otherwise not possible. Taking fees out of what LPs earn for market making those pairs makes this more unlikely to happen at the scale we need it to. It will be interesting to see if and where such markets will move in the coming months.
We're publishing our thinking in full here so that you can challenge it, and use it to inform whatever you do to improve the current code. Our goal is to build an efficient market maker for cNGN and provide an open reference for anyone building markets around other emerging-market stablecoins. We also want to show regulators how market makers operate and how transparent market-making can support fairer, more efficient markets.
Publishing the system and the research behind it is one way we hope to support greater geographic decentralization. Global networks can distribute value more widely when people in more places are able to understand, shape and operate them.