Fix `SymbologyCache.search()` key matching
RapidFuzz treated `mktmaps` values as fuzzy choices and called `len()` on `MktPair` structs during paper-ledger persistence. Search string keys explicitly and resolve each match back to its struct so native market-ID aliases survive legacy FQME qualification. Also, - cover alias preservation and the paper-ledger TOML round trip. Prompt-IO: ai/prompt-io/opencode/20260828T013057Z_6ca6ab2a_prompt_io.md (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))wkt/fsp_backfill_sync
parent
6ca6ab2a10
commit
7b51927f6b
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: opencode-pid-469264
|
||||||
|
timestamp: 2026-08-28T01:30:57Z
|
||||||
|
git_ref: 6ca6ab2a
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260828T013057Z_6ca6ab2a_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Investigate Piker's clearing, accounting, order-control, and
|
||||||
|
trade-ledger flows in depth while fixing a paper-engine crash where
|
||||||
|
RapidFuzz called `len()` on a `MktPair` during ledger persistence.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Changed `SymbologyCache.search()` to fuzzy-match table keys instead of
|
||||||
|
struct values, preserving matched aliases and preventing the paper
|
||||||
|
trade dialog from crashing when qualifying legacy ledger FQMEs. Added
|
||||||
|
an end-to-end regression for the implicated ledger-write path.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/data/_symcache.py` - searches string keys and resolves values.
|
||||||
|
- `tests/test_accounting.py` - covers aliases and paper-ledger writes.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human supplied the production traceback, identified the affected
|
||||||
|
subsystems, and directed an implementation-level fix with deep system
|
||||||
|
familiarization. No follow-up correction or direct manual source edit
|
||||||
|
was identified during this interaction.
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-28T01:30:57Z
|
||||||
|
git_ref: 6ca6ab2a
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Become familiar with Piker's clearing, accounting, order-control,
|
||||||
|
and trade-ledger tracking subsystems in deep detail while fixing a
|
||||||
|
paper-engine crash. The supplied traceback showed
|
||||||
|
`TransactionLedger.write_config()` calling
|
||||||
|
`SymbologyCache.search()`, followed by RapidFuzz raising
|
||||||
|
`TypeError: object of type 'MktPair' has no len()` after a paper fill.
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
Fixed the crash at the symbology-cache contract boundary.
|
||||||
|
`SymbologyCache.search()` now fuzzy-matches the selected table's
|
||||||
|
string keys and resolves each matched key back to its struct value.
|
||||||
|
RapidFuzz therefore never receives `MktPair` values as sequences,
|
||||||
|
and native market-ID aliases remain intact in search results.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/data/_symcache.py`
|
||||||
|
|
||||||
|
Added a regression that recreates the failing paper-ledger write with
|
||||||
|
an unqualified Binance perpetual FQME. It also checks a native market-ID
|
||||||
|
alias, preventing a weaker `processor=str` workaround that would lose
|
||||||
|
the actual matched key.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tests/test_accounting.py`
|
||||||
|
|
||||||
|
Verification:
|
||||||
|
|
||||||
|
`./py313/bin/python -m pytest -p no:xonsh -q -x --tb=short
|
||||||
|
--no-header tests/test_accounting.py::test_account_file_default_empty
|
||||||
|
tests/test_accounting.py::test_paper_ledger_fuzzy_qualifies_mktmap_keys`
|
||||||
|
|
||||||
|
Result: `2 passed in 0.02s`.
|
||||||
|
|
||||||
|
`git diff --check` also passed. Ruff was not available in the existing
|
||||||
|
`py313` environment, so no environment provisioning was performed.
|
||||||
|
|
@ -334,15 +334,16 @@ class SymbologyCache(Struct):
|
||||||
matches in a `dict` including the `MktPair` values.
|
matches in a `dict` including the `MktPair` values.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
entries: dict[str, Struct] = getattr(self, table)
|
||||||
matches = fuzzy.extract(
|
matches = fuzzy.extract(
|
||||||
pattern,
|
pattern,
|
||||||
getattr(self, table),
|
list(entries),
|
||||||
score_cutoff=50,
|
score_cutoff=50,
|
||||||
)
|
)
|
||||||
|
|
||||||
# repack in dict[fqme, MktPair] form
|
# repack in dict[fqme, MktPair] form
|
||||||
return {
|
return {
|
||||||
item[0].fqme: item[0]
|
item[0]: entries[item[0]]
|
||||||
for item in matches
|
for item in matches
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,26 @@
|
||||||
- config file IO
|
- config file IO
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
from decimal import Decimal
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from types import ModuleType
|
||||||
|
import tomllib
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from piker import config
|
from piker import config
|
||||||
from piker.accounting import (
|
from piker.accounting import (
|
||||||
Account,
|
Account,
|
||||||
|
Asset,
|
||||||
calc,
|
calc,
|
||||||
open_account,
|
open_account,
|
||||||
load_account,
|
load_account,
|
||||||
load_account_from_ledger,
|
load_account_from_ledger,
|
||||||
|
MktPair,
|
||||||
open_trade_ledger,
|
open_trade_ledger,
|
||||||
Position,
|
Position,
|
||||||
TransactionLedger,
|
TransactionLedger,
|
||||||
)
|
)
|
||||||
|
from piker.data._symcache import SymbologyCache
|
||||||
import tractor
|
import tractor
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,6 +53,82 @@ def test_account_file_default_empty(
|
||||||
assert path.parent.name == 'accounting'
|
assert path.parent.name == 'accounting'
|
||||||
|
|
||||||
|
|
||||||
|
def test_paper_ledger_fuzzy_qualifies_mktmap_keys(
|
||||||
|
tmp_path: Path,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Qualify legacy paper-ledger FQMEs via symcache string keys.
|
||||||
|
|
||||||
|
``SymbologyCache.search()`` previously passed its ``mktmaps``
|
||||||
|
mapping directly to RapidFuzz. RapidFuzz searches mapping values,
|
||||||
|
so a paper fill with an unqualified FQME made RapidFuzz call
|
||||||
|
``len()`` on a ``MktPair`` while
|
||||||
|
``TransactionLedger.write_config()`` exited.
|
||||||
|
This test installs both native-ID and FQME keys for one market,
|
||||||
|
proves search preserves the matched alias, then writes the same
|
||||||
|
unqualified paper transaction shape. The persisted fully
|
||||||
|
qualified keys prove the ledger exit path resolves the market
|
||||||
|
without treating ``MktPair`` values as fuzzy-search sequences.
|
||||||
|
|
||||||
|
'''
|
||||||
|
usdt = Asset(
|
||||||
|
name='usdt',
|
||||||
|
atype='crypto',
|
||||||
|
tx_tick=Decimal('0.00000001'),
|
||||||
|
)
|
||||||
|
nvda = Asset(
|
||||||
|
name='nvda',
|
||||||
|
atype='stock',
|
||||||
|
tx_tick=Decimal('0.00000001'),
|
||||||
|
)
|
||||||
|
mkt = MktPair(
|
||||||
|
dst=nvda,
|
||||||
|
src=usdt,
|
||||||
|
price_tick=Decimal('0.01'),
|
||||||
|
size_tick=Decimal('0.001'),
|
||||||
|
bs_mktid='NVDAUSDT',
|
||||||
|
broker='binance',
|
||||||
|
venue='usdtm',
|
||||||
|
expiry='perp',
|
||||||
|
)
|
||||||
|
symcache = SymbologyCache(
|
||||||
|
mod=ModuleType('binance'),
|
||||||
|
fp=tmp_path / 'binance.symcache.toml',
|
||||||
|
mktmaps={
|
||||||
|
mkt.bs_mktid: mkt,
|
||||||
|
mkt.fqme: mkt,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
matches = symcache.search(mkt.bs_mktid)
|
||||||
|
assert next(iter(matches)) == mkt.bs_mktid
|
||||||
|
assert matches[mkt.bs_mktid] is mkt
|
||||||
|
|
||||||
|
ledger_path = tmp_path / 'trades_binance_paper.toml'
|
||||||
|
unqualified_fqme = 'nvdausdt.usdtm.perp'
|
||||||
|
ledger = TransactionLedger(
|
||||||
|
ledger_dict={
|
||||||
|
'fill-id': {
|
||||||
|
'fqme': unqualified_fqme,
|
||||||
|
'bs_mktid': unqualified_fqme,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
file_path=ledger_path,
|
||||||
|
account='paper',
|
||||||
|
mod=symcache.mod,
|
||||||
|
tx_sort=lambda txns: txns.items(),
|
||||||
|
symcache=symcache,
|
||||||
|
)
|
||||||
|
|
||||||
|
ledger.write_config()
|
||||||
|
|
||||||
|
with ledger_path.open('rb') as ledger_file:
|
||||||
|
saved = tomllib.load(ledger_file)['fill-id']
|
||||||
|
|
||||||
|
assert saved['fqme'] == mkt.fqme
|
||||||
|
assert saved['bs_mktid'] == mkt.fqme
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'fq_acnt',
|
'fq_acnt',
|
||||||
[
|
[
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue