This page explains the trading rules behind
preview_order,
list_my_positions and
list_my_ruby_ledger. Everything here
applies to v21_lmsr topics — the live market. Legacy v2_share topics are
readable but cannot be traded through the Open API.
The stake: chosen by the user, bounded by the topic
Each topic fixes its own trading rules when it is created — the range of
stakes it accepts, how deep its market is, and which rules version it runs.
Those rules never change afterwards; a later platform change only affects
topics created after it. The part an agent needs is published on every topic
card and detail as stake_rules:
stake_rules is null on v2_share topics.
Ask the user for the amount. If they said how many coins to stake, pass
exactly that as amount_coins. If they didn’t, ask — never pick, infer or round
an amount for them. An amount outside the range is refused with
STAKE_OUT_OF_RANGE, never adjusted.
A user places one order per topic. There are no fees — the whole stake buys
units — and no adding to or switching a position later.
Prices and opening probabilities
Each option’s implied_price (0–1, summing to 1 across a topic) is its current
price. A topic can open at initial probabilities set when it is published
rather than at an even split, so read the price instead of assuming 1/n.
Buying moves the price: the preview shows price_now, price_after and the
average price paid (avg_price).
Payout and ruby boosts
If the option a position is on wins, the position pays rubies; the stake
is not returned. The payout is:
units is the raw unit count the stake bought. The ruby multiplier is 1
unless a ruby boost is live at one of three moments — when the order is
placed, when the topic settles, or (in the app) when the position is sold. A
running boost appears on the topic as ruby_boost (multiplier, ends_at —
ends_at is exclusive; null when there is no boost), and on the order
preview as ruby_multiplier.
- Placed during a boost — the order records that multiplier. A boost
ending later never lowers it.
- Settled during a boost — positions still held when the topic settles get
the higher of their recorded multiplier and the one live at settlement.
- Sold in the app during a boost — the sale uses the higher of the
recorded multiplier and the one live at the moment of sale.
So every payout_if_correct_rubies figure is a guaranteed minimum (units ×
the order’s current multiplier), not the final amount: if the topic settles
while a boost is live, the position pays more. Present it as “at least N
rubies if correct”. The API does not project a future boost into it — a boost
live today may be over by settlement.
Where the payout shows up:
Selling happens in the app only
In the SeeSaw app, a user can sell a whole position back for rubies. The Open
API has no sell tool or endpoint — an agent cannot sell on the user’s behalf.
If the user asks to sell, point them to the app.
What the API does show is the result. A position sold in the app appears in
list_my_positions with:
sold: true and sold_rubies — what the sale paid;
won, payout_rubies and payout_if_correct_rubies always null, and
refunded always false. A sold position does not take part in
settlement and is not refunded, whatever the topic’s outcome — even if the
option it was on wins;
settled still turning true once the topic settles, because it describes
the topic.
Read the row in this order: sold > refunded > settled (won /
payout_rubies) > open. Selling still counts as the topic’s one order, so
preview_order on that topic answers ALREADY_STAKED.
The sale itself is a ruby_trade_sell row in
list_my_ruby_ledger; its created_at is
the time of the sale.
Where rubies come from
rubies on get_my_profile is the ruby balance.
It moves when:
- a position on the winning option settles (
ruby_settlement, boost
included) — or is taken back after a takedown or a changed ruling
(ruby_revocation);
- the user sells a position in the app (
ruby_trade_sell);
- the user’s opinions are backed, or later backers follow them in a relay
(
sapphire_creator_fee, sapphire_back_relay) — or those paybacks are
clawed back when an opinion is taken down (sapphire_opinion_takedown);
- the old sapphire balance was converted (
sapphire_conversion, once).
list_my_ruby_ledger lists every one of
these movements.
Sapphires have been merged into rubies
Sapphires used to be a separate reward for opinions. They have been merged 1:1
into rubies, and opinions now pay rubies. The sapphire-named fields are still
returned so existing integrations keep working, with the same values as their
ruby replacements, and will be removed in contract 3.0.0:
ruby_payback includes what an opinion paid as sapphires before the merge.