binance: implement `Client.search_symbols()` using `rapidfuzz`

Change the deats inside the method and have the `brokerd` search task
just call it as needed since we already do internal mem caching on the
lookup table.

APIs changed so we need to make some tweaks as per:
- https://github.com/maxbachmann/RapidFuzz/blob/main/api_differences.md
- https://github.com/maxbachmann/RapidFuzz/blob/main/api_differences.md#differences-in-processor-functions

The main motivation is to get better wheel pkging support (for nixos),
better impl in C++, and a more simply licensed dep.
ib_py311_fixes
Tyler Goodlet 2023-09-13 11:59:51 -04:00
parent 4a180019f0
commit 2c88ebe697
2 changed files with 30 additions and 15 deletions

View File

@ -31,6 +31,8 @@ from pprint import pformat
from typing import (
Any,
Callable,
Hashable,
Sequence,
Type,
)
import hmac
@ -549,7 +551,7 @@ class Client:
if sym:
return pair_table[sym]
else:
self._pairs
return self._pairs
async def get_assets(
self,
@ -596,14 +598,26 @@ class Client:
fq_pairs: dict = await self.exch_info()
matches = fuzzy.extractBests(
pattern,
fq_pairs,
# TODO: cache this list like we were in
# `open_symbol_search()`?
keys: list[str] = list(fq_pairs)
matches: list[tuple[
Sequence[Hashable], # matching input key
Any, # scores
Any,
]] = fuzzy.extract(
query=pattern.upper(), # since all keys are uppercase
choices=keys,
score_cutoff=50,
)
# repack in dict form
return {item[0]['symbol']: item[0]
for item in matches}
matched_pairs: dict[str, Pair] = {}
for item in matches:
pair_key: str = item[0]
matched_pairs[pair_key] = self._pairs[pair_key]
return matched_pairs
async def bars(
self,

View File

@ -42,7 +42,7 @@ from trio_typing import TaskStatus
from pendulum import (
from_timestamp,
)
from fuzzywuzzy import process as fuzzy
from rapidfuzz import process as fuzzy
import numpy as np
import tractor
@ -533,14 +533,15 @@ async def open_symbol_search(
pattern: str
async for pattern in stream:
matches = fuzzy.extractBests(
# NOTE: pattern fuzzy-matching is done within
# the methd impl.
pairs: dict[str, Pair] = await client.search_symbols(
pattern,
client._pairs,
score_cutoff=50,
)
# repack in dict form
await stream.send({
item[0].bs_fqme: item[0]
for item in matches
})
# repack in fqme-keyed table
byfqme: dict[start, Pair] = {}
for pair in pairs.values():
byfqme[pair.bs_fqme] = pair
await stream.send(byfqme)