Skip to content

feat(scrypt): tighten price deviation cap to 0.3% + notify on overshoot#3736

Draft
TaprootFreak wants to merge 1 commit into
developfrom
feat/scrypt-tighten-price-deviation-check
Draft

feat(scrypt): tighten price deviation cap to 0.3% + notify on overshoot#3736
TaprootFreak wants to merge 1 commit into
developfrom
feat/scrypt-tighten-price-deviation-check

Conversation

@TaprootFreak
Copy link
Copy Markdown
Collaborator

Why

On 2026-05-21 a 570'000 EUR BTC/EUR buy on Scrypt cleared at a 0.65 % spread vs. our pricing reference, costing ~2'870 EUR more than the equivalent Kraken trade would have (Kraken BTC/EUR fee is a constant 0.14 % over 5'685 historical trades). The trade went through silently because the existing pre-trade check ScryptAdapter.getAndCheckTradePrice has a default maxPriceDeviation of 5 %, far above any reasonable threshold.

Scrypt embeds its commission into the quoted price ("price you see is what you get", per their FAQ), so it does not return a separate fee via its WebSocket API. The spread between Scrypt's executable price and our internal pricing reference is therefore the only pre-trade signal that the implicit cost is too high.

What

  • New constant Config.scrypt.maxPriceDeviation = 0.003 (0.3 %)
  • ScryptAdapter.getAndCheckTradePrice defaults to that cap (was hardcoded 0.05)
  • Existing per-action maxPriceDeviation override in paramMap still wins, so emergency loosening stays possible without code change
  • On overshoot the adapter now sends an ErrorMonitoring mail (with isLiqMail: true, so monitoring + liq team both get it) before throwing OrderFailedException
  • Mail is debounced 1 h per asset pair via correlationId + suppressRecurring to avoid alert spam

Effect on the 2026-05-21 incident

With this change, the BTC/EUR buy at 0.65 % spread would have:

  1. Failed the pre-trade check (0.645 % > 0.300 %)
  2. Triggered an immediate alert to monitoring + liq team
  3. Routed to the failover (or surfaced the routing gap) instead of silently overpaying ~2'870 EUR

Test plan

  • CI green (lint + build + 941 unit tests pass locally)
  • Verify on DEV: provoke a price gap and confirm the trade is rejected with OrderFailedException and a mail lands in monitoring inbox
  • Verify debounce: trigger twice within 1 h on the same pair, confirm only the first mail is sent
  • Re-check after deploy: any legitimate Scrypt trades blocked? If 0.3 % turns out to be too tight, increase via PR or per-action override

Scrypt embeds its commission into the quoted price ("price you see is
what you get"), so the spread between Scrypt's executable price and our
pricing reference is the only pre-trade signal that the implicit cost
is too high.

The default maxPriceDeviation of 5% in ScryptAdapter.getAndCheckTradePrice
was too loose: on 2026-05-21 a 570'000 EUR BTC/EUR buy on Scrypt cleared
at a 0.65% spread vs. our pricing reference, costing ~2'870 EUR more
than Kraken would have. The check passed silently because 0.65% << 5%.

Changes:
- Add Config.scrypt.maxPriceDeviation = 0.003 (0.3%)
- ScryptAdapter.getAndCheckTradePrice defaults to that cap
- On overshoot: send ErrorMonitoring mail (isLiqMail) before throwing
  OrderFailedException, debounced 1h per asset pair to avoid spam
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.

1 participant