Repository navigation
autoconvert: route from Kraken's pair table; make the second leg fill - #4
Merged
Merged
Conversation
ZEC has no USDT market on Kraken (only ZEC/USD and ZEC/EUR), so every ZEC sale takes the intermediary route. Three things were wrong with it. The route was found by asking for ZECUSDT and catching the failure. kraken_request prints every failed call, so each pass (every 30-90s) logged "request to kraken ... failed" and "prepare_and_make_trade error", and the Zabbix item af.convert.errors (any error/failed line in 30m) paged on prod as soon as ZEC was in AUTOCONVERT_ASSETS. Routes now come from one /0/public/AssetPairs listing, indexed by (base, quote) altname and loaded with the asset names, so a missing market is a lookup miss. No route at all is still an error, raised once. The second leg could never fill. The limit was mid * (1 - slippage) for buys as well as sells, and an IOC buy limited below the book is cancelled unfilled, which would leave every ZEC sale sitting in USD. Buys are now limited above mid and sized at the ask with a fee margin (KRAKEN_FEE_MARGIN_PERCENT, 0.5), since Kraken's volume is the bought asset and a buy's fee is charged in the currency spent. A leg goes in whichever direction the market exists (sell on A/B, buy on B/A). The second leg spent the intermediary's whole balance, not this sale's proceeds: any USD the account held for another reason would have been converted too. It now spends the increase over the balance before the first leg, polled for up to 30s after the fill; proceeds that never show up are raised as an error naming what to convert by hand. In a dry run the second leg is validated with the first leg's expected proceeds, so both orders are now checked by Kraken (before, the second was skipped). Checked locally against Kraken's live pairs and books with private calls stubbed: 1366 pairs, routes XBT/LTC/XMR direct and ZEC via USD; selling 1.74715603 ZEC at limit 1191.39 (bid 1197.23), then buying 2053.05 USDT at limit 1.00379 (ask 0.99880). Tests: the Kraken fake is now a small market that fills a live IOC order only when its limit crosses the book and rejects unknown pairs the way Kraken does. A ZEC sale is a DryRunNeverMovesFunds scenario, and IndirectSale checks that the proceeds reach USDT while USD the account already held is untouched, and that routing around the missing market logs nothing Zabbix counts as an error. Mutation-checked: a buy limited below mid, spending the whole intermediary balance, probing the direct pair and catching the failure, and a dry run that places the second leg each fail a test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ZEC has no USDT market on Kraken (only ZEC/USD and ZEC/EUR), so every ZEC sale goes through USD. That path had three problems, all fixed here.
ZECUSDTand catching the failure. Each failed call printed two error lines every 30-90s, so prod'sAutoforwarder: errors in the autoconvert logtrigger opened at 19:35 UTC once ZEC was inAUTOCONVERT_ASSETS. Routes now come from a singleAssetPairslisting, so a missing market is just a lookup miss. If there is no route at all, that is still raised as an error.KRAKEN_FEE_MARGIN_PERCENT, default 0.5).In a dry run, the second leg is now validated using the first leg's expected proceeds. Before this, a dry run skipped the second leg entirely, which is why the staging run of T13 never caught problem 2.
Checked against live Kraken data (private calls stubbed, nothing sent):
Tests:
DryRunNeverMovesFunds.IndirectSalechecks two things: the proceeds reach USDT while USD the account already held is untouched, and routing around the missing market logs nothing Zabbix counts as an error.Follow-up in cake-tech/ansible: re-pin
autoforward_versionto this PR's merge commit.🤖 Generated with Claude Code