Commit Graph
36 Commits
Author SHA1 Message Date
matitos 5a8c7ecc58 Show a loading state in the strategy dropdown
While the strategy list is being fetched the dropdown now shows a disabled
"Loading strategies…" option instead of an empty select, and "No strategies
available" once loading finishes with no results. Applies to the strategy,
backtest and sweep panels via a loading prop. Adds tests.
2026-09-21 18:26:01 +00:00
matitos def86d7f56 Retry the strategy list and make collapse obvious
CI/CD / backend (push) Successful in 5m14s
CI/CD / frontend (push) Successful in 5m16s
CI/CD / build (push) Successful in 17s
CI/CD / cleanup (push) Successful in 4s
CI/CD / deploy (push) Successful in 50s
2026-09-21 17:11:18 +00:00
matitos b9c69c546c Retry the strategy list and make collapse obvious
- The strategy/preset lists were loaded once with failures swallowed, so a
  single failed first request left the strategy dropdown empty forever. They
  are now retried every 3s until populated.
- Clearer collapse affordance: hover highlight, a hide/show hint, and a
  tooltip; Backtest and Parameter sweep start collapsed so the strategy
  selector and status are immediately visible.
- Adds an integration test that the strategy dropdown is populated and the
  panel actually collapses.
2026-09-21 17:11:18 +00:00
matitos 9eddd66a82 Collapse the strategy, backtest and sweep panels
CI/CD / backend (push) Successful in 5m14s
CI/CD / frontend (push) Successful in 5m9s
CI/CD / build (push) Successful in 17s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 50s
2026-09-21 16:40:54 +00:00
matitos 1b44e456c6 Collapse the strategy, backtest and sweep panels
Adds a reusable CollapsiblePanel (chevron header, optional summary shown when
collapsed, state persisted in localStorage) and wraps the Strategy, Backtest
and Parameter sweep panels with it, so any single part of the dashboard can be
focused on quickly. Panels stay mounted (v-show) so their form/results state is
preserved across collapse. Includes component tests.
2026-09-21 16:40:48 +00:00
matitos fedcd07ffd Don't let a failing initial fetch block the socket/polling fallback
CI/CD / backend (push) Successful in 5m32s
CI/CD / frontend (push) Successful in 5m7s
CI/CD / build (push) Successful in 20s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 40s
2026-09-21 15:57:51 +00:00
matitos cf54ff8b45 Don't let a failing initial fetch block the socket/polling fallback
onMounted awaited the initial REST calls before setting up the socket and the
6s polling fallback, so any rejected request aborted the handler and left the
badge stuck on "connecting". Set up the socket and fallback first, make the
initial loads best-effort, and log [ws] connect/open/close for debugging.
2026-09-21 15:57:50 +00:00
matitos 7057a5999e Show client and server build versions in the footer
CI/CD / backend (push) Successful in 5m20s
CI/CD / frontend (push) Successful in 5m6s
CI/CD / build (push) Successful in 19s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 40s
2026-09-21 14:47:04 +00:00
matitos cc602423b9 Show client and server build versions in the footer
Adds a footer with the client build SHA and the server /api/version value, a
mismatch warning, and the socket error text, so it is unambiguous whether the
browser is running a stale bundle and why the live feed fell back to polling.
2026-09-21 14:47:03 +00:00
matitos 2b8f6bf385 Force-recreate containers on deploy and verify the served build
CI/CD / backend (push) Successful in 6m8s
CI/CD / frontend (push) Successful in 4m59s
CI/CD / build (push) Successful in 19s
CI/CD / cleanup (push) Successful in 7s
CI/CD / deploy (push) Successful in 1m31s
2026-09-21 12:12:29 +00:00
matitos c121a4190a Force-recreate containers on deploy and verify the served build
The frontend container was serving the very first build (498-byte index.html)
through every later deploy: `docker compose up -d` did not replace a
config-identical service. Deploy now uses `build --pull` and
`up --force-recreate`, the frontend image writes a .build-version marker, and
the workflow fails the deploy if the served marker != the commit SHA.
2026-09-21 12:12:28 +00:00
matitos 1428220210 Self-heal a stale cached bundle via a build version
CI/CD / frontend (push) Successful in 5m15s
CI/CD / backend (push) Successful in 5m26s
CI/CD / build (push) Successful in 39s
CI/CD / cleanup (push) Successful in 7s
CI/CD / deploy (push) Successful in 1m22s
2026-09-21 00:16:49 +00:00
matitos 7b97f010c9 Self-heal a stale cached bundle via a build version
Phones kept running old JS because their cached index.html pointed at an old
hashed asset. Both images now bake the commit SHA as BUILD_VERSION; the backend
exposes it at GET /api/version and the client reloads once with a cache-busting
query when its own baked version differs. Guarded by sessionStorage so it cannot
loop. /api/version is unauthenticated like /api/health.
2026-09-21 00:16:43 +00:00
matitos 7ad14449ce Never hang on connecting: time out the socket and fall back
CI/CD / backend (push) Successful in 5m53s
CI/CD / frontend (push) Successful in 5m11s
CI/CD / build (push) Successful in 21s
CI/CD / cleanup (push) Successful in 6s
CI/CD / deploy (push) Successful in 20s
2026-09-20 23:43:13 +00:00
matitos ed14019052 Never hang on "connecting": time out the socket and fall back
iOS Safari can leave a blocked wss:// upgrade hanging without firing
onclose/onerror, so the badge sat on "connecting". The socket now times out a
slow handshake after 5s, reports at most one failure per attempt, and the app
commits to polling after a 6s grace period if the socket never opens.
2026-09-20 23:43:12 +00:00
matitos 5af879bc2f Present REST polling as a normal live state
CI/CD / backend (push) Successful in 5m23s
CI/CD / frontend (push) Successful in 4m55s
CI/CD / build (push) Successful in 13s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 24s
2026-09-20 14:01:38 +00:00
matitos 8bb2836d7e Present REST polling as a normal live state
Some browsers (notably iOS Safari on an auth-gated page) abort the wss://
upgrade even though the server accepts it. Rather than showing a perpetual
"reconnecting", stop retrying after three failures, poll every 3s, and label
the badge "live (polling)" in green. The socket error is kept as a tooltip.
2026-09-20 13:47:42 +00:00
matitos 43831d31f6 Merge pull request: Fall back to REST polling when the WebSocket cannot connect
CI/CD / backend (push) Successful in 6m1s
CI/CD / frontend (push) Successful in 5m18s
CI/CD / build (push) Successful in 16s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 17s
2026-09-20 13:00:52 +00:00
matitos bf7eda3f6a Fall back to REST polling when the WebSocket cannot connect
CI/CD / backend (pull_request) Successful in 6m6s
CI/CD / frontend (pull_request) Successful in 5m15s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
On some mobile networks/browsers the wss:// upgrade is blocked even though the
page loads (the server side is verified working: a browser-style handshake gets
101). After three socket failures the header now shows "polling (5s)" instead
of a misleading perpetual "reconnecting", since the 5s REST poll keeps all data
correct. The socket error handler also surfaces the browser's message.
2026-09-20 12:48:10 +00:00
matitos 07c17fbd2c Merge pull request #7: Stop caching index.html and speed up socket reconnect
CI/CD / backend (push) Successful in 5m42s
CI/CD / frontend (push) Successful in 5m15s
CI/CD / build (push) Successful in 17s
CI/CD / cleanup (push) Successful in 4s
CI/CD / deploy (push) Successful in 16s
2026-09-20 00:10:52 +00:00
matitos c63753e592 Stop caching index.html and speed up socket reconnect
CI/CD / backend (pull_request) Successful in 5m41s
CI/CD / frontend (pull_request) Successful in 5m18s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
Phones offer no easy hard-refresh, so a cached index.html kept serving an old
bundle after a deploy (the live feed showed "reconnecting"). index.html and the
SPA catch-all now send Cache-Control: no-store, while hashed /assets stay
immutable. Also retry the first socket reconnect after 1s (was 2s) and surface
the close code in the header so a failure is actionable on a phone.
2026-09-19 23:52:54 +00:00
matitos 6df44520fa Merge pull request 'Add trailing stops and parameter sweeps' (#6) from feat/trailing-stops-sweep into main
CI/CD / backend (push) Successful in 5m51s
CI/CD / frontend (push) Successful in 5m4s
CI/CD / build (push) Successful in 18s
CI/CD / cleanup (push) Successful in 4s
CI/CD / deploy (push) Successful in 31s
2026-09-20 01:18:51 +02:00
matitos 9dc00eba95 Add trailing stops and parameter sweeps
CI/CD / backend (pull_request) Successful in 6m6s
CI/CD / frontend (pull_request) Successful in 5m17s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
Trailing stops: strategies can pass trailing_stop_pct to enter_long/enter_short.
advance_trailing_stop in app/engine/portfolio.py ratchets the stop with the price
(up for longs, down for shorts) and never loosens; the engine persists the
ratcheted level and the backtester applies the same logic. Position gains a
trailing_stop_pct column (additive migration). momentum exposes it as a param.

Parameter sweeps: app/backtest/sweep.py runs a cartesian grid through the same
backtester and ranks by return minus max drawdown. POST /api/sweep plus a
dashboard Parameter sweep panel.
2026-09-19 23:04:20 +00:00
matitos d80e7b155e Merge pull request 'Make the API token fully optional' (#5) from fix/optional-api-token into main
CI/CD / backend (push) Successful in 5m30s
CI/CD / frontend (push) Successful in 5m5s
CI/CD / build (push) Successful in 25s
CI/CD / cleanup (push) Successful in 5s
CI/CD / deploy (push) Successful in 34s
2026-09-19 16:35:35 +02:00
matitos 2a88f55689 Make the API token fully optional
CI/CD / backend (pull_request) Successful in 5m36s
CI/CD / frontend (pull_request) Successful in 5m12s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
The deploy job hard-failed without CRYPTO_API_TOKEN, and /api/ws (which skips
Basic auth) relied on that token. Drop the requirement: the app now works with
no token at all, matching the backend guard that was always a no-op when unset.
When a token is configured it still protects /api and /api/ws; when it is not,
/api/ws is as open as the rest of the API, which the Traefik Basic auth still
guards for everything else. Adds tests for the tokenless API and WebSocket.
2026-09-19 14:31:42 +00:00
matitos ba7a69c1ce Merge pull request 'Add a friendly GET /api/ws response' (#4) from chore/retrigger-deploy into main
CI/CD / backend (push) Successful in 5m24s
CI/CD / frontend (push) Successful in 5m14s
CI/CD / build (push) Successful in 54s
CI/CD / cleanup (push) Successful in 7s
CI/CD / deploy (push) Failing after 12s
2026-09-19 15:58:16 +02:00
matitos 386137c90e Add a friendly GET /api/ws response
CI/CD / backend (pull_request) Canceled after 0s
CI/CD / frontend (pull_request) Canceled after 0s
CI/CD / build (pull_request) Canceled after 0s
CI/CD / deploy (pull_request) Canceled after 0s
CI/CD / cleanup (pull_request) Canceled after 0s
A plain browser hit on the socket URL now returns a JSON hint instead of a
confusing 404/426. Companion to the Basic-auth bypass on /api/ws.
2026-09-19 13:41:55 +00:00
matitos d0b941e305 chore: trigger deploy after WS auth fix 2026-09-19 13:14:11 +00:00
matitos c9ee3e3aef Merge pull request 'Serve /api/ws without Basic auth so the live feed connects' (#3) from fix/websocket-basic-auth into main
CI/CD / backend (push) Canceled after 0s
CI/CD / frontend (push) Canceled after 0s
CI/CD / build (push) Canceled after 0s
CI/CD / deploy (push) Canceled after 0s
CI/CD / cleanup (push) Canceled after 0s
2026-09-19 15:11:16 +02:00
matitos 3e19612cc0 Serve /api/ws without Basic auth so the live feed connects
CI/CD / backend (pull_request) Successful in 5m58s
CI/CD / frontend (pull_request) Successful in 5m3s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
Browsers don't reliably replay Basic-auth credentials on a WebSocket upgrade,
so the dashboard's live feed was stuck on "reconnecting" (only the 5s REST
poll worked). Give /api/ws a higher-priority Traefik router that skips Basic
auth; the backend still requires API_TOKEN, which nginx injects on the
handshake. The deploy now fails closed unless CRYPTO_API_TOKEN is set.

Also: split the nginx /api/ws block so upgrade headers are only set there, and
add reconnect backoff (2s -> 30s) so a failing socket stops hammering.
2026-09-19 12:52:06 +00:00
matitos 97fbd5901e Merge pull request 'Bitcoin favicon, more strategies, default timeframe 5m' (#2) from feat/strategies-favicon-5m into main
CI/CD / backend (push) Successful in 5m23s
CI/CD / frontend (push) Successful in 5m3s
CI/CD / build (push) Successful in 16s
CI/CD / cleanup (push) Successful in 4s
CI/CD / deploy (push) Successful in 23s
2026-09-18 22:14:39 +02:00
matitos c500fb7572 Bitcoin favicon, more strategies, default timeframe 5m
CI/CD / backend (pull_request) Successful in 5m21s
CI/CD / frontend (pull_request) Successful in 5m4s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
- Add an SVG Bitcoin favicon and link it in index.html.
- New indicators: macd() and roc().
- Five new strategies: macd_trend, bollinger_reversion, donchian_breakout,
  ema_cross, momentum (plus the existing sma_cross, rsi_reversion).
- Default TIMEFRAME is now 5m (config, .env.example, compose, workflow, UI).
2026-09-18 20:03:30 +00:00
matitos 186a6949ee Merge pull request 'Risk controls, alerts, API token, more exchanges, presets' (#1) from feat/risk-notify-exchanges-presets into main
CI/CD / backend (push) Successful in 5m16s
CI/CD / frontend (push) Successful in 4m58s
CI/CD / build (push) Successful in 23s
CI/CD / cleanup (push) Successful in 4s
CI/CD / deploy (push) Successful in 23s
2026-09-18 21:39:05 +02:00
matitos 03dfa369e5 Risk controls, alerts, API token, more exchanges, presets
CI/CD / backend (pull_request) Successful in 6m18s
CI/CD / frontend (pull_request) Successful in 4m55s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped
- RiskManager halts + flattens on max daily loss / drawdown, caps position
  size and trades per day; adds a manual kill switch (POST /api/bot/kill).
- Telegram and webhook notifications on trades, errors and halts.
- Optional API bearer token on /api, injected server-side by the frontend
  nginx so the browser never sees it.
- Kraken and Coinbase market data (public); Coinbase live broker. Live on an
  unsupported exchange now errors instead of silently falling back to paper.
- Strategy presets backed by the StrategyConfig table (CRUD API + UI).
- Idempotent additive-column migration so existing SQLite databases upgrade in
  place (fixes the new strategy_configs.name column).
2026-09-18 19:26:29 +00:00
matitos 9c3bee87ac Crypto trading bot: engine, brokers, backtester, dashboard, deploy
CI/CD / backend (push) Successful in 5m18s
CI/CD / frontend (push) Successful in 5m2s
CI/CD / build (push) Successful in 34s
CI/CD / cleanup (push) Successful in 6s
CI/CD / deploy (push) Successful in 22s
FastAPI backend with a single-strategy async engine, paper and Binance
brokers, pure-python indicators, a backtester that shares the engine's
portfolio math, and a Vue dashboard with a live WebSocket feed. Adds the
Gitea Actions CI/CD workflow that deploys to Traefik via docker_default.
2026-09-18 17:02:33 +00:00
matitos 98028248c2 Initial commit 2026-09-18 19:01:49 +02:00