From db2e02c316dc705cead6e979145d4ee44c8267bd Mon Sep 17 00:00:00 2001 From: zwitschi Date: Sun, 7 Jun 2026 17:44:26 +0200 Subject: [PATCH] feat: add pairings management page and integrate with Kraken API for syncing feat: create configuration templates for alerts, Kraken settings, risk limits, and runtime settings refactor: streamline config form by including separate template files for better organization --- src/arbitrade/api/routes.py | 48 +- src/arbitrade/market_data/order_book.py | 3 +- src/arbitrade/web/templates/_header.html | 7 +- .../web/templates/config/alerts.html | 192 +++++ .../web/templates/config/kraken.html | 93 +++ src/arbitrade/web/templates/config/risk.html | 57 ++ .../web/templates/config/runtime.html | 140 ++++ src/arbitrade/web/templates/pairings.html | 52 ++ .../web/templates/partials/config.html | 657 +----------------- 9 files changed, 581 insertions(+), 668 deletions(-) create mode 100644 src/arbitrade/web/templates/config/alerts.html create mode 100644 src/arbitrade/web/templates/config/kraken.html create mode 100644 src/arbitrade/web/templates/config/risk.html create mode 100644 src/arbitrade/web/templates/config/runtime.html create mode 100644 src/arbitrade/web/templates/pairings.html diff --git a/src/arbitrade/api/routes.py b/src/arbitrade/api/routes.py index 69b7618..a7fcaae 100644 --- a/src/arbitrade/api/routes.py +++ b/src/arbitrade/api/routes.py @@ -899,6 +899,25 @@ async def dashboard_audit(request: Request) -> HTMLResponse: ) +@router.get("/dashboard/config/pairings", response_class=HTMLResponse) +async def dashboard_config_pairings_page( + request: Request, + search: str | None = None, + enabled: str | None = None, +) -> HTMLResponse: + """Standalone pairings management page.""" + return templates.TemplateResponse( + request=request, + name="pairings.html", + context={ + "title": "Currency Pairings", + "request": request, + "search": search or "", + "enabled": enabled or "all", + }, + ) + + @router.get("/dashboard/config", response_class=HTMLResponse) async def dashboard_config_page(request: Request) -> HTMLResponse: d_context = await _dashboard_config_context(request) @@ -1447,19 +1466,20 @@ async def dashboard_api_pairings_toggle(request: Request) -> HTMLResponse: ) -@router.post("/dashboard/api/pairings/sync") -async def dashboard_api_pairings_sync(request: Request) -> JSONResponse: - """Trigger a re-sync of pairings from Kraken.""" - kraken_client = request.app.state.kraken_client +@router.post("/dashboard/api/pairings/sync", response_class=HTMLResponse) +async def dashboard_api_pairings_sync(request: Request) -> HTMLResponse: + """Sync pairings from Kraken and return refreshed table.""" + from arbitrade.config.pairing_sync import sync_pairings_from_kraken + store = request.app.state.store - summary = await sync_pairings_from_kraken(kraken_client, store) - - await _record_audit( - request, - actor="dashboard_user", - event_type="dashboard.pairings.sync", - decision="approved", - payload=summary, # type: ignore + kraken = getattr(request.app.state, "kraken_client", None) + if kraken is not None: + await sync_pairings_from_kraken(kraken, store) + repo = _pairing_repo(request) + pairings = await repo.list_pairings() + pairings.sort(key=lambda p: (p.base_asset, p.quote_asset)) + return templates.TemplateResponse( + request=request, + name="partials/pairings_table.html", + context={"request": request, "pairings": pairings}, ) - - return JSONResponse(summary) diff --git a/src/arbitrade/market_data/order_book.py b/src/arbitrade/market_data/order_book.py index a4ba86a..a95803b 100644 --- a/src/arbitrade/market_data/order_book.py +++ b/src/arbitrade/market_data/order_book.py @@ -86,7 +86,8 @@ class OrderBook: BookLevel(price=price, volume=self._bids[price]) for price in reversed(bid_keys[-depth:]) ] - asks = [BookLevel(price=price, volume=self._asks[price]) for price in ask_keys[:depth]] + asks = [BookLevel(price=price, volume=self._asks[price]) + for price in ask_keys[:depth]] return bids, asks def compute_checksum(self, depth: int = 10) -> int: diff --git a/src/arbitrade/web/templates/_header.html b/src/arbitrade/web/templates/_header.html index b7a5d85..7e42202 100644 --- a/src/arbitrade/web/templates/_header.html +++ b/src/arbitrade/web/templates/_header.html @@ -5,9 +5,10 @@ {% set nav_links = [ {"url": "/dashboard", "label": "Dashboard", "class": "secondary"}, {"url": "/dashboard/config", "label": "Config", "class": - "secondary"}, {"url": "/dashboard/backtesting", "label": "Backtesting", - "class": "secondary"}, {"url": "/dashboard/health", "label": "Health", - "class": "secondary"}, ] %} + "secondary"}, {"url": "/dashboard/config/pairings", "label": "Pairings", + "class": "secondary"}, {"url": "/dashboard/backtesting", "label": + "Backtesting", "class": "secondary"}, {"url": "/dashboard/health", "label": + "Health", "class": "secondary"}, ] %}
{% for link in nav_links %} +
Alerting
+ + + + + + + +
+ + + +
+ + +
+ + + + + + + + +
diff --git a/src/arbitrade/web/templates/config/kraken.html b/src/arbitrade/web/templates/config/kraken.html new file mode 100644 index 0000000..73226e9 --- /dev/null +++ b/src/arbitrade/web/templates/config/kraken.html @@ -0,0 +1,93 @@ +
+
Kraken Exchange
+ + + + + + + + + + + +
diff --git a/src/arbitrade/web/templates/config/risk.html b/src/arbitrade/web/templates/config/risk.html new file mode 100644 index 0000000..75cd550 --- /dev/null +++ b/src/arbitrade/web/templates/config/risk.html @@ -0,0 +1,57 @@ +
+
Risk & Guardrails
+ + + + + + +
diff --git a/src/arbitrade/web/templates/config/runtime.html b/src/arbitrade/web/templates/config/runtime.html new file mode 100644 index 0000000..42429b0 --- /dev/null +++ b/src/arbitrade/web/templates/config/runtime.html @@ -0,0 +1,140 @@ +
+
Runtime
+ + + + + + + + + + + + + + + + +
diff --git a/src/arbitrade/web/templates/pairings.html b/src/arbitrade/web/templates/pairings.html new file mode 100644 index 0000000..337b4f8 --- /dev/null +++ b/src/arbitrade/web/templates/pairings.html @@ -0,0 +1,52 @@ +{% extends "_base.html" %} {% block title %}{{ title }}{% endblock %} {% block +main_class %}shell{% endblock %} {% block header %} {% with +page_title="Currency Pairings", +page_subtitle="Enable/disable pairings, search, and sync from Kraken." %} +{% include "_header.html" %} {% endwith %} {% endblock %} {% block content %} + +
+ + + + + +
+ +
+ {% include "partials/pairings_table.html" %} +
+ +{% endblock %} \ No newline at end of file diff --git a/src/arbitrade/web/templates/partials/config.html b/src/arbitrade/web/templates/partials/config.html index b7ea8b7..7793350 100644 --- a/src/arbitrade/web/templates/partials/config.html +++ b/src/arbitrade/web/templates/partials/config.html @@ -4,657 +4,14 @@ hx-post="{{ config_endpoint }}" hx-target="#config-panel" hx-swap="outerHTML" - style=" - grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); - gap: 20px; - " + style="grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 20px" > - -
-
Runtime
- - - - - - - - - - - - - - - - -
- - -
-
Alerting
- - - - - - - -
- - - -
- - -
- - - - - - - - -
- - -
-
Kraken Exchange
- - - - - - - - - - - -
- - -
-
Currency Pairings
-
- - -
-
-
- Loading pairings... -
-
-
- - -
-
Risk Limits
- - - - - - -
- - -
-
Stat-Arb Strategy
- - {% if strategy_stat_arb_enabled %} - - - - - {% endif %} -
- - -
- + {% include "config/runtime.html" %} + {% include "config/alerts.html" %} + {% include "config/kraken.html" %} + {% include "config/risk.html" %} +
+