Skip to content
Back to blog
Engineering June 12, 2026 · By MEXAR Engineering

Inventory and pricing for a money changer: stock, cost and rates

A currency-exchange business is really an inventory business. Here is how MEXAR models accounts and balances, tracks cost with a moving average, and separates the six rate types that drive a transaction.

Run a money changer for a week and you realise it is an inventory business wearing a finance costume. You buy currency at one cost, hold it, and sell it at a price — and your real profit depends on what that stock actually cost you, not on the headline spread. MEXAR models this explicitly, so operators can see true margin instead of guessing at it.

Accounts, balances, and flows

Money lives in a three-layer structure. An Account is a container with a type; each account holds one AccountCurrencyBalance per currency; and every movement is recorded as an AccountFlow.

Accounts come in fourteen types, because “cash in the drawer” and “money owed to an agent” behave nothing alike: CASH, BANK, CRYPTO, APP, EWALLET, PAYABLE, BALANCE, VIRTUAL, TEMPORARY, CONTRA, DEBT, DEBIT, CREDIT, and EXPENSE. A balance is not a single number either — it splits into balance_available (usable now) and balance_hold (committed but not yet settled):

balance            = balance_available + balance_hold
balance_available  = free to use for new transactions
balance_hold       = frozen, occupied by transactions in progress

That split powers anticipated flow: when a transaction is created but not yet completed, MEXAR pre-occupies the balance it will need. The stock is reserved, so two transactions cannot both sell the same notes — over-selling is prevented before it can happen, and the hold converts into a formal flow once the transaction settles.

Cost that follows the stock: Moving Average Cost

To know profit, you need cost — and cost changes every time you restock. MEXAR uses Moving Average Cost (MAC): each inflow recomputes the blended cost basis of what you hold.

New Average Cost = (Q_old × C_old + Q_new × C_new) / (Q_old + Q_new)

When you later sell, profit is measured against that basis, not against a market quote:

profit = Outflow Amount × (Outflow Rate − Average Cost)

Costs and profit are expressed in the account’s base currency (base_cost / cost_to_base), so a multi-currency operation can roll everything up into one denomination for P&L. When there is no inventory to cost against, a spot rate stands in as the reference instead.

Six rates, one transaction

“The rate” is never just one number. MEXAR distinguishes six rate types, each with a job:

Rate typeWhat it is
Base currencythe internal denomination all cost and profit roll up into
Average costper-unit cost of held inventory, from MAC
Spot rateexternal market reference when there is no inventory
Public buywhat you pay a customer selling currency to you
Public sellwhat you charge a customer buying currency from you
Sell rate (internal)public rate adjusted by your margin, for profit control

The internal sell rate is derived, not hand-set, so margin stays deliberate:

SellRate(X) = PublicSell(X) × (1 + Markup)
BuyRate(X)  = PublicBuy(X)  × (1 − Markdown)

One flag that prevents a whole class of bugs

Currency pairs are quoted in two directions — and mixing up the direct and indirect format is how rounding errors and mispriced deals creep in. Is a USD rate “rupiah per dollar” or “dollars per rupiah”? Get it backwards and every amount is wrong. MEXAR makes the direction explicit with a use_reverse_rate flag at the department-currency level:

  • direct (use_reverse_rate = false): converted = amount × rate
  • indirect (use_reverse_rate = true): converted = amount ÷ rate

Set it once per currency and every calculation downstream applies the conversion the same way — there is no per-transaction guesswork about which side of the pair you are on, and the same money math helper enforces it everywhere.

Rates as an operating surface

All of this is exposed to operators, not buried in code. Staff manage public buy, sell, and spot rates per currency from one screen — editing inline or pushing a CSV bulk update across many currencies at once — and customer groups can carry their own rates, so a walk-in price and a partner price coexist without a second system. Crucially, a rate change applies only to new transactions: anything already in flight keeps the rate it was created with. That is the append-only ledger doing its job — pricing can move without rewriting the deals you have already struck.

Why model it this way

An operator could track stock in a spreadsheet and price by feel. The reason to build it into the platform is that cost, holds, and rate direction are where a money changer quietly loses money — to over-selling, to mispriced inventory, to a reversed conversion. By making average cost, anticipated holds, and rate direction first-class, MEXAR turns “roughly profitable” into a number you can actually see per transaction, per currency, per department — on the same append-only ledger that keeps the history honest.