Skip to content

Add lofty account rebates — recover the undocumented maker-rebate rate - #17

Merged
piekstra merged 2 commits into
mainfrom
feat/account-rebates
Aug 3, 2026
Merged

Add lofty account rebates — recover the undocumented maker-rebate rate#17
piekstra merged 2 commits into
mainfrom
feat/account-rebates

Conversation

@piekstra

@piekstra piekstra commented Aug 3, 2026

Copy link
Copy Markdown
Owner

The gap

Lofty advertises "maker rebates — paid at fill" but publishes the rate nowhere — not on the marketing page, not in llms-full.txt, not in the SDK docs. The amounts appear only on the signed-in account page, so they're invisible to any API consumer.

That's not academic. A cached scrape of that page can report $0 for weeks while rebates are actually being paid — which is precisely what happened, and it led to the confident conclusion "we earn no rebates."

The rate, recovered

account trades has carried buyerFeeAmount and sellerFeeAmount the whole time. Comparing them against rebates actually paid:

A maker rebate is 50% of the platform fee on YOUR side of the trade, paid only when your order was the resting one.

Verified to the cent on both a buy (rebate = ½ the buyer fee) and a sell (rebate = ½ the seller fee), then reproduced live — the command's total matched the account page's all-time figure.

The corroboration is the nice part: a fill that crossed the book earned nothing. That's what "paid at fill" means in practice — paid to the maker, not the taker.

Usage

$ lofty account rebates
PRICE  | PROPERTY | QTY | REBATE  | SIDE | YOUR FEE
$45.00 | 01SAMPLE…| 1.0 | $0.5625 | buy  | $1.1250
total $0.5625 across 1 maker fill(s) at 50% of your side's fee; 0 taker fill(s)
earned nothing (crossing the book pays no rebate)

--property-id and --since filter; --json emits account-rebates/v1. Figures above are illustrative.

Inference, stated honestly

A trade record carries no maker/taker flag, so it's inferred: a fill counts as maker when one of your orders rested at that exact price and side. Unmatched trades are reported as takers (no rebate) rather than optimistically credited — the conservative direction.

Testing

5 unit tests, including reproducing the real paid rebates, a taker fill earning nothing, the correct side's fee being used (mixing them up silently misprices every rebate), an opposite-side order not counting as maker, and --since filtering. 87 tests, fmt, clippy -D warnings clean.

Resolves the project's long-open note that the maker-rebate rate was undocumented.

Lofty advertises "maker rebates - paid at fill" but publishes no rate, and the
amounts appear only on the signed-in account page. That makes rebates invisible to
any API consumer, and a stale scrape of that page can report zero for weeks while
rebates are actually being paid.

The rate is recoverable from your own fills: `account trades` carries
buyerFeeAmount and sellerFeeAmount, and a maker rebate is 50% of the fee on YOUR
side of the trade. Verified to the cent against real paid rebates on both a buy
and a sell, and reproduced live against the account page's all-time total.

Rebates are paid only to the RESTING side. A fill that crossed the book earned
nothing, which is the corroboration that "paid at fill" means paid to the maker.
Trade records carry no maker/taker flag, so it is inferred from whether one of our
orders rested at that exact price and side; unmatched trades are reported as
takers rather than optimistically credited.

Figures in the README example are illustrative.
@piekstra
piekstra requested a review from piekstra-dev August 3, 2026 12:57

@piekstra-dev piekstra-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: d10bc3bc8e16
Profile: reviewer - Posting as: piekstra-dev

Summary

Reviewer Findings
policies:conventions 0
documentation:docs 1
documentation:docs (1 finding)

Minor - README.md:276

The account rebates summary line is printed by a single eprintln! in render_rebates (src/commands/account.rs), so real output is one unbroken line: total $0.5625 across 1 maker fill(s) at 50% of your side's fee; 0 taker fill(s) earned nothing (crossing the book pays no rebate). The README example splits this into two lines (... 0 taker fill(s) / earned nothing (crossing the book pays no rebate)), which misrepresents the actual console output and could mislead someone diffing or scripting against it. Join it back into one line to match the real output (contrast with the rewards reconcile example a few sections up, which genuinely emits two separate eprintln! calls and is correctly shown as two lines).

Reviewer Coverage

Reviewer Status Inspected Skipped Constraints
policies:conventions complete_broad src/commands/account.rs unavailable unavailable
documentation:docs complete_broad README.md unavailable unavailable

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 2m 23s | $1.68 | claude-sonnet-5 | cr 0.10.268
Field Value
Model claude-sonnet-5
Reviewers policies:conventions, documentation:docs
Engine claude_cli · claude-sonnet-5
Reviewed by cr · piekstra-dev
Duration 2m 23s wall · 3m 23s compute
Cost $1.68
Tokens 82 in / 14.3k out

Per-workstream usage

Workstream Model In Out Cache read Cache create Cost Duration
orchestrator-selection claude-sonnet-5 6 1.7k 36.3k 22.1k $0.17 21s
policies:conventions claude-sonnet-5 30 4.6k 656.2k 66.3k $0.66 1m 02s
documentation:docs claude-sonnet-5 40 7.6k 718.1k 68.1k $0.74 1m 49s
orchestrator-rollup claude-sonnet-5 6 408 56.8k 14.7k $0.11 10s

Comment thread README.md Outdated
$ lofty account rebates
PRICE | PROPERTY | QTY | REBATE | SIDE | YOUR FEE
$45.00 | 01SAMPLE…| 1.0 | $0.5625 | buy | $1.1250
total $0.5625 across 1 maker fill(s) at 50% of your side's fee; 0 taker fill(s)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The account rebates summary line is printed by a single eprintln! in render_rebates (src/commands/account.rs), so real output is one unbroken line: total $0.5625 across 1 maker fill(s) at 50% of your side's fee; 0 taker fill(s) earned nothing (crossing the book pays no rebate). The README example splits this into two lines (... 0 taker fill(s) / earned nothing (crossing the book pays no rebate)), which misrepresents the actual console output and could mislead someone diffing or scripting against it. Join it back into one line to match the real output (contrast with the rewards reconcile example a few sections up, which genuinely emits two separate eprintln! calls and is correctly shown as two lines).

Reply inline to this comment.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — fixed in f1ab165. It is one eprintln!, so the example now shows one line. Good catch on the contrast with rewards reconcile, which genuinely emits two.

Review: the README split one eprintln! across two lines, so anyone diffing or
scripting against the example would mismatch real output. The reconcile example
above it genuinely emits two calls and is correctly shown as two lines.
@piekstra
piekstra merged commit cf0a5bf into main Aug 3, 2026
2 checks passed
@piekstra
piekstra deleted the feat/account-rebates branch August 3, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants