Skip to content

Pricing Model

joogiebear edited this page Jul 15, 2026 · 1 revision

Pricing Model

RoyalBazaar is not a fixed-price shop. Every item sits on an AMM-style (automated-market-maker) price curve, and the server is always the counterparty with infinite depth — so there's no order book and no waiting for a matching offer. Prices move purely from supply and demand.

Every parameter below is set per item (with category-wide defaults) — see Categories.

The mid price

Each item has a mid price: its current fair value, held in memory and persisted between restarts. Everything else derives from it.

  • Buying pushes the mid up.
  • Selling pushes the mid down.
  • Over time, mean reversion pulls the mid back toward the item's configured base price.

Buy and sell quotes (the spread)

The price a player pays or receives straddles the mid by half the spread:

buy price  = mid × (1 + spread/2)
sell price = mid × (1 − spread/2)

So spread is the gap between what players pay to buy and receive to sell. It's your margin and a passive inflation sink — money spent crossing the spread leaves the economy. A spread: 0.05 is a 5% gap.

Order cost is progressive

Large orders are not priced at a flat quantity × price. Cost and proceeds are the integral along the curve, so each additional unit is priced a little worse than the last:

buy cost   = elasticity × mid × (e^( q/elasticity) − 1) × (1 + spread/2)
sell yield  = elasticity × mid × (1 − e^(−q/elasticity)) × (1 − spread/2)

elasticity is how many units it takes to move the price by a factor of ehigher = more stable, lower = more reactive. Because the curve steepens as you walk it:

Buying a stack and immediately selling it back is a guaranteed loss. Round-tripping and "whale-draining" the market aren't profitable by construction — you can't extract money the market didn't already contain.

Market impact

After a trade of q units, the mid moves exponentially and is then clamped to the item's floor/ceiling:

mid after buy  = clamp( mid × e^( q/elasticity), floor, ceiling )
mid after sell = clamp( mid × e^(−q/elasticity), floor, ceiling )

Mean reversion

On each engine tick (engine.tick-interval-seconds, default 60s) every mid is pulled a fraction of the way back toward its base price, in log-space:

new mid = clamp( exp( ln(mid) + (ln(base) − ln(mid)) × reversion_rate ), floor, ceiling )

A reversion_rate: 0.02 closes 2% of the gap to base each tick. This heals one-off spikes and crashes on their own without ever snapping the price back instantly.

Floors and ceilings

floor_pct and ceiling_pct are fractions of the item's base price, and hard-cap how far it can ever move:

floor   = base × floor_pct     # e.g. 0.4 → never below 40% of base
ceiling = base × ceiling_pct   # e.g. 3.0 → never above 300% of base

Every quote, trade, and reversion result is clamped into [floor, ceiling].

Tuning cheat-sheet

Want… Change
Prices to move less per trade Raise elasticity
Prices to move more per trade Lower elasticity
A bigger buy/sell margin (inflation sink) Raise spread
Prices to recover faster after a dump Raise reversion_rate
A tighter or wider allowed price band Adjust floor_pct / ceiling_pct

See Categories for where these are configured, and Configuration for the engine tick rate.

Clone this wiki locally