PP-2 UI: Trader page -- "Best Trade" stat displays 0 when no individual trade has a realized P&L of zero; should show the least-worst loss or N/A #344

Closed
opened 2026-06-08 16:14:09 +00:00 by totdking · 12 comments
totdking commented 2026-06-08 16:14:09 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-08 16:19:13 +00:00 (Migrated from gitlab.com)

Summary

On the /trader/:address page, the "Best Trade" summary stat displays 0 after executing 5 trades across the EMBER/CORAL pair. All realized P&L events (EMBER to CORAL sells) produced negative results -- none were break-even or profitable. The "Best Trade" value of 0 does not correspond to any trade in the history and is not the correct representation of the best realized outcome.


Observed data

Stat Displayed value Expected value
Total Realized P&L -47.74M Plausible
Best Trade 0 Should be the least-worst realized loss or "N/A" if no profitable trades exist
Worst Trade -44.00M Plausible (matches the 479M EMBER to 458.9M CORAL sell)
Total Fees Paid 17.48M Plausible

Trade history (5 trades, EMBER/CORAL pair):

Time Direction Amount in Amount out Price
16:45 EMBER to CORAL 1.000M 693.7K 0.6937
16:58 CORAL to EMBER 100.0M 100.2M 1.00157
16:58 EMBER to CORAL 150.0M 144.2M 0.96148
17:00 CORAL to EMBER 100.0M 100.3M 1.00268
17:02 EMBER to CORAL 479.0M 458.9M 0.95799

All three EMBER to CORAL sells were executed below the average entry price of 1.04352. The two CORAL to EMBER buys add to cost basis and do not realize gains. No trade produced a realized P&L of 0 or above.


Reproduction steps

  1. Navigate to /trader/:address on LocalTerra after executing several trades in the same pair
  2. Ensure all individual realized P&L events are negative (all sells below cost basis)
  3. Observe the "Best Trade" summary stat
  4. Observe: displays 0 rather than the actual best (least-worst) realized trade value

Expected behavior

"Best Trade" should display the highest individual realized P&L value from the trade history. If all realized trades are losses, the best trade is the smallest loss (closest to zero but still negative). Displaying 0 when no trade had a realized P&L of zero is incorrect.

Acceptable alternatives: display the actual least-worst value, or display "N/A" / "--" when no profitable trades exist.


Actual behavior

"Best Trade" displays 0 regardless of whether any trade actually achieved break-even. This makes it impossible to distinguish between "had a break-even trade" and "stat defaulted to zero".


Screenshot

image.png{width=900 height=461}


Possible root cause area

The Best Trade value is likely initialized to 0 in the indexer or frontend and only updated when a trade with positive P&L is found. If no profitable trade exists, the initial 0 is returned as-is rather than returning the actual maximum of all P&L values (the least-negative realized trade).

Relevant area: indexer trader P&L aggregation query, or the frontend component rendering summary stats on /trader/:address.


Impact assessment

  • Misleads the user into thinking they had a break-even trade when all trades were losses
  • Undermines the "values are correct" criterion of PP-2

Environment

  • Chain: localterra
  • LCD: http://localhost:1317
  • Wallet: Keplr (Terra Classic)
  • Browser: Chromium
  • Page: /trader/terra1753zuaneacfr60rg37l8d4t0x7j4yvqgsl7cvv
  • Pair traded: EMBER/CORAL (5 trades, all realized P&L negative)
  • Network throttle applied: No

Severity: P2(polish) -- incorrect summary stat; does not affect trade execution or fund safety.

Related checklist items: PP-2

cc: @PlasticDigits

### Summary On the `/trader/:address` page, the "Best Trade" summary stat displays `0` after executing 5 trades across the EMBER/CORAL pair. All realized P&L events (EMBER to CORAL sells) produced negative results -- none were break-even or profitable. The "Best Trade" value of `0` does not correspond to any trade in the history and is not the correct representation of the best realized outcome. --- ### Observed data | Stat | Displayed value | Expected value | |------|-----------------|----------------| | Total Realized P&L | \-47.74M | Plausible | | Best Trade | 0 | Should be the least-worst realized loss or "N/A" if no profitable trades exist | | Worst Trade | \-44.00M | Plausible (matches the 479M EMBER to 458.9M CORAL sell) | | Total Fees Paid | 17.48M | Plausible | Trade history (5 trades, EMBER/CORAL pair): | Time | Direction | Amount in | Amount out | Price | |------|-----------|-----------|------------|-------| | 16:45 | EMBER to CORAL | 1.000M | 693.7K | 0.6937 | | 16:58 | CORAL to EMBER | 100.0M | 100.2M | 1.00157 | | 16:58 | EMBER to CORAL | 150.0M | 144.2M | 0.96148 | | 17:00 | CORAL to EMBER | 100.0M | 100.3M | 1.00268 | | 17:02 | EMBER to CORAL | 479.0M | 458.9M | 0.95799 | All three EMBER to CORAL sells were executed below the average entry price of 1.04352. The two CORAL to EMBER buys add to cost basis and do not realize gains. No trade produced a realized P&L of 0 or above. --- ### Reproduction steps 1. Navigate to `/trader/:address` on LocalTerra after executing several trades in the same pair 2. Ensure all individual realized P&L events are negative (all sells below cost basis) 3. Observe the "Best Trade" summary stat 4. Observe: displays `0` rather than the actual best (least-worst) realized trade value --- ### Expected behavior "Best Trade" should display the highest individual realized P&L value from the trade history. If all realized trades are losses, the best trade is the smallest loss (closest to zero but still negative). Displaying `0` when no trade had a realized P&L of zero is incorrect. Acceptable alternatives: display the actual least-worst value, or display "N/A" / "--" when no profitable trades exist. --- ### Actual behavior "Best Trade" displays `0` regardless of whether any trade actually achieved break-even. This makes it impossible to distinguish between "had a break-even trade" and "stat defaulted to zero". --- ## Screenshot ![image.png](/uploads/7beb1c73fa4c7b8491810d8a9f20b28a/image.png){width=900 height=461} --- ### Possible root cause area The `Best Trade` value is likely initialized to `0` in the indexer or frontend and only updated when a trade with positive P&L is found. If no profitable trade exists, the initial `0` is returned as-is rather than returning the actual maximum of all P&L values (the least-negative realized trade). Relevant area: indexer trader P&L aggregation query, or the frontend component rendering summary stats on `/trader/:address`. --- ### Impact assessment - Misleads the user into thinking they had a break-even trade when all trades were losses - Undermines the "values are correct" criterion of PP-2 --- ### Environment - Chain: localterra - LCD: [http://localhost:1317](http://localhost:1317) - Wallet: Keplr (Terra Classic) - Browser: Chromium - Page: `/trader/terra1753zuaneacfr60rg37l8d4t0x7j4yvqgsl7cvv` - Pair traded: EMBER/CORAL (5 trades, all realized P&L negative) - Network throttle applied: No --- **Severity:** P2(polish) -- incorrect summary stat; does not affect trade execution or fund safety. **Related checklist items:** PP-2 cc: @PlasticDigits
PlasticDigits commented 2026-06-09 06:51:39 +00:00 (Migrated from gitlab.com)

mentioned in commit 4a0812cd087152712894986d26cd8859f74c1d71

mentioned in commit 4a0812cd087152712894986d26cd8859f74c1d71
PlasticDigits commented 2026-06-09 06:53:34 +00:00 (Migrated from gitlab.com)

mentioned in merge request !848

mentioned in merge request !848
PlasticDigits commented 2026-06-09 06:53:45 +00:00 (Migrated from gitlab.com)

MR !848 opened

Changes: Nullable best/worst trade PnL + CASE update SQL; UI N/A when unset.

Verify

  • cargo test --lib (indexer)
  • Trader page after all-loss trades: Best Trade shows least-negative loss (not 0)
## MR !848 opened **Changes:** Nullable best/worst trade PnL + CASE update SQL; UI N/A when unset. ### Verify - [ ] `cargo test --lib` (indexer) - [ ] Trader page after all-loss trades: Best Trade shows least-negative loss (not 0)
ghost1 commented 2026-06-09 06:53:50 +00:00 (Migrated from gitlab.com)

mentioned in merge request !849

mentioned in merge request !849
PlasticDigits commented 2026-06-09 07:31:49 +00:00 (Migrated from gitlab.com)

mentioned in commit b10b8a0fe9

mentioned in commit b10b8a0fe9c2daf0832daebdce3b1e448085fc93
PlasticDigits commented 2026-06-09 07:44:31 +00:00 (Migrated from gitlab.com)

mentioned in commit 1c37ef869c

mentioned in commit 1c37ef869cc39cd2a3424c2deacc938833025218
PlasticDigits commented 2026-06-09 07:52:36 +00:00 (Migrated from gitlab.com)

mentioned in merge request !850

mentioned in merge request !850
PlasticDigits commented 2026-06-09 07:57:27 +00:00 (Migrated from gitlab.com)

mentioned in commit 83dc19286d

mentioned in commit 83dc19286d71d50c684d109abc333ee5dde52477
PlasticDigits commented 2026-06-09 08:34:22 +00:00 (Migrated from gitlab.com)

Verification complete — #344

All acceptance and verification criteria PASS on main (83dc192).

Results

Criterion Result Evidence
Indexer cargo test --lib PASS 134/134 (alt target dir)
API best_trade_pnl not sentinel 0 PASS GET /api/v1/traders/terra1x46… → -20757.62… (all-loss trader, 62 trades)
UI Best Trade stat PASS /trader/terra1x46… shows negative least-worst loss (not 0 or N/A)
traderProfilePayload.test.ts PASS nullable best/worst parsing

Merged fixes: !848, !850 (break-even backfill repair).

Re-verify checklist

  • cargo test --lib (indexer)
  • Trader page after all-loss trades: Best Trade shows least-negative loss (not 0)
## Verification complete — #344 All acceptance and verification criteria **PASS** on `main` (`83dc192`). ### Results | Criterion | Result | Evidence | |-----------|--------|----------| | Indexer `cargo test --lib` | **PASS** | 134/134 (alt target dir) | | API `best_trade_pnl` not sentinel 0 | **PASS** | `GET /api/v1/traders/terra1x46…` → `-20757.62…` (all-loss trader, 62 trades) | | UI Best Trade stat | **PASS** | `/trader/terra1x46…` shows negative least-worst loss (not `0` or `N/A`) | | `traderProfilePayload.test.ts` | **PASS** | nullable best/worst parsing | Merged fixes: !848, !850 (break-even backfill repair). ### Re-verify checklist - [ ] `cargo test --lib` (indexer) - [ ] Trader page after all-loss trades: Best Trade shows least-negative loss (not 0)
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-09 08:34:24 +00:00
Brouie commented 2026-06-10 01:00:22 +00:00 (Migrated from gitlab.com)

Ran the re-verify checklist on main 83dc192, plus the migration path the original pass couldn't cover (a live DB still on the pre-fix schema).

  • indexer cargo test --lib: 134/134
  • migration layer: both #344 migrations applied cleanly on a pre-fix DB — columns now nullable, defaults dropped. The one existing healthy trader row (positive best / negative worst) came through byte-identical, so the backfill correctly leaves non-sentinel aggregates alone.
  • live all-loss trader, fresh wallet: one quote-buy to establish basis (avg 1.03442), then two below-basis sells (50M and 150M). Result: best_trade_pnl = -1,716,826.15 — the least-negative loss, not 0 — worst = -5,464,770.46, total = the exact sum. Recomputed both per-trade PnLs by hand from the raw swap amounts ((exit - avg) x offer); matches the stored values.
  • the no-realized-trades path: after the buy-only trade, best/worst are NULL in the DB and null on the API profile — the N/A case the UI fix renders. traderProfilePayload tests 6/6. Visual N/A check rides along with the next browser pass.
  • /traders/leaderboard handles the nullable columns fine, including an all-negative row.

Evidence txs: 8133A18A (basis buy), B74B1396 / 638E71E5 (loss sells), wallet terra18nln8ypzlvkpcq6whdymqjac8pypxc5sd9m6jm.

One observation while tracing this, not a regression: the position model is per-pair quote exposure, so selling quote that arrived via plain transfer (never bought on the pair) realizes the full proceeds as positive PnL — zero basis. I reproduced it: a fresh wallet's first trade (quote side, transferred-in funds) realized +297,600,661, the entire return amount. It's consistent with the documented exposure model and doesn't touch this fix, but it does inflate total_realized_pnl for transfer-funded wallets. If PP-2 "values are correct" needs to be tighter for mainnet, capping realization at the tracked position would be the knob.

Ran the re-verify checklist on main 83dc192, plus the migration path the original pass couldn't cover (a live DB still on the pre-fix schema). - indexer `cargo test --lib`: 134/134 - migration layer: both #344 migrations applied cleanly on a pre-fix DB — columns now nullable, defaults dropped. The one existing healthy trader row (positive best / negative worst) came through byte-identical, so the backfill correctly leaves non-sentinel aggregates alone. - live all-loss trader, fresh wallet: one quote-buy to establish basis (avg 1.03442), then two below-basis sells (50M and 150M). Result: best_trade_pnl = -1,716,826.15 — the least-negative loss, not 0 — worst = -5,464,770.46, total = the exact sum. Recomputed both per-trade PnLs by hand from the raw swap amounts ((exit - avg) x offer); matches the stored values. - the no-realized-trades path: after the buy-only trade, best/worst are NULL in the DB and null on the API profile — the N/A case the UI fix renders. traderProfilePayload tests 6/6. Visual N/A check rides along with the next browser pass. - /traders/leaderboard handles the nullable columns fine, including an all-negative row. Evidence txs: 8133A18A (basis buy), B74B1396 / 638E71E5 (loss sells), wallet terra18nln8ypzlvkpcq6whdymqjac8pypxc5sd9m6jm. One observation while tracing this, not a regression: the position model is per-pair quote exposure, so selling quote that arrived via plain transfer (never bought on the pair) realizes the full proceeds as positive PnL — zero basis. I reproduced it: a fresh wallet's first trade (quote side, transferred-in funds) realized +297,600,661, the entire return amount. It's consistent with the documented exposure model and doesn't touch this fix, but it does inflate total_realized_pnl for transfer-funded wallets. If PP-2 "values are correct" needs to be tighter for mainnet, capping realization at the tracked position would be the knob.
Brouie commented 2026-06-10 06:17:24 +00:00 (Migrated from gitlab.com)

mentioned in issue #337

mentioned in issue #337
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#344
No description provided.