4c59a0e4cb
- Added `sync_pairings_from_kraken` function to fetch and upsert asset pairs into the config_pairings table. - Introduced `run_pairing_sync_loop` for periodic synchronization of pairings. - Enhanced `KrakenWsClient` to manage subscribed symbols for market data feeds. - Created `build_detector_from_enabled_pairings` to initialize cycle detection based on enabled pairings. - Updated FastAPI app to start market data feed and pairing synchronization tasks. - Added new API routes for managing pairings, including listing, toggling, and syncing from Kraken. - Improved dashboard templates to display pairing options and allow user interaction for backtesting. - Refactored database queries to streamline fetching and updating of pairing data.
80 lines
2.4 KiB
Python
80 lines
2.4 KiB
Python
"""Sync available Kraken asset pairs into the config_pairings table."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
import structlog
|
|
|
|
from arbitrade.config.service import ConfigPairing
|
|
from arbitrade.detection.graph import CurrencyGraph
|
|
from arbitrade.exchange.kraken_rest import KrakenRestClient
|
|
from arbitrade.storage.db import DuckDBStore
|
|
from arbitrade.storage.repositories import ConfigPairingRepository
|
|
|
|
_LOG = structlog.get_logger(__name__)
|
|
|
|
|
|
async def sync_pairings_from_kraken(
|
|
kraken_client: KrakenRestClient,
|
|
store: DuckDBStore,
|
|
) -> dict[str, int]:
|
|
"""Fetch all asset pairs from Kraken and upsert into config_pairings.
|
|
|
|
Returns a summary dict with 'added', 'updated', 'total' counts.
|
|
"""
|
|
asset_pairs = await kraken_client.asset_pairs()
|
|
graph = CurrencyGraph.from_kraken_asset_pairs(asset_pairs)
|
|
repo = ConfigPairingRepository(store)
|
|
|
|
added = 0
|
|
updated = 0
|
|
total = 0
|
|
|
|
# Dedupe: pair_by_direction has entries for both (base,quote) and (quote,base).
|
|
seen_symbols: set[str] = set()
|
|
for (base, quote), symbol in graph.pair_by_direction.items():
|
|
if symbol in seen_symbols:
|
|
continue
|
|
seen_symbols.add(symbol)
|
|
existing = repo.get_pairing(base, quote)
|
|
pairing = ConfigPairing(
|
|
base_asset=base,
|
|
quote_asset=quote,
|
|
enabled=existing.enabled if existing else False,
|
|
source="kraken",
|
|
)
|
|
try:
|
|
repo.upsert_pairing(pairing)
|
|
total += 1
|
|
if existing:
|
|
updated += 1
|
|
else:
|
|
added += 1
|
|
except Exception:
|
|
_LOG.warning("sync_pairing_failed", base=base, quote=quote)
|
|
|
|
_LOG.info(
|
|
"pairing_sync_complete",
|
|
added=added,
|
|
updated=updated,
|
|
total=total,
|
|
)
|
|
return {"added": added, "updated": updated, "total": total}
|
|
|
|
|
|
async def run_pairing_sync_loop(
|
|
kraken_client: KrakenRestClient,
|
|
store: DuckDBStore,
|
|
stop_event: asyncio.Event,
|
|
interval_seconds: int = 86400,
|
|
) -> None:
|
|
"""Periodically sync pairings from Kraken (default daily)."""
|
|
await sync_pairings_from_kraken(kraken_client, store)
|
|
try:
|
|
while not stop_event.is_set():
|
|
await asyncio.wait_for(stop_event.wait(), timeout=interval_seconds)
|
|
await sync_pairings_from_kraken(kraken_client, store)
|
|
except (TimeoutError, asyncio.CancelledError):
|
|
pass
|