feat: system logs page + dynamic IV watchlist with auto-add from cycle
Backend:
- DB: add system_logs table (level/source/cycle_id/ticker/message) and
iv_watchlist table (ticker/added_by/is_active); seed builtin 18 tickers
- DBLogHandler attached at startup — all WARNING+ logs auto-persist to DB
- log_system_event() helper for structured manual events
- New router /api/logs: GET with filters (level, source, cycle_id, ticker,
date range), GET /sources, GET /cycles for dropdowns, DELETE /clear
- iv_watchlist now read from DB instead of hardcoded constant; options_vol
watchlist/refresh/bootstrap endpoints all use get_watchlist_tickers()
- New endpoints: POST/DELETE /options-vol/watchlist-tickers/{ticker} to
add/remove tickers; adding triggers background 1-year bootstrap
- auto_cycle: after log_trade_entries(), auto-detect new underlying proxies
not yet in watchlist, add them and bootstrap their IV history
Frontend:
- New page SystemLogs (/logs): log table with level/source/cycle/ticker/date
filters, color-coded rows, expandable JSON details, auto-refresh 30s
- Options Lab: WatchlistManager section — add ticker input, chip list with
builtin/auto/manual color coding, remove button for non-builtins
- Sidebar: Logs Système nav link (ScrollText icon)
- useApi: useSystemLogs, useLogSources, useLogCycles, useClearLogs,
useWatchlistTickers, useAddWatchlistTicker, useRemoveWatchlistTicker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -705,3 +705,61 @@ export const useRiskDashboard = () =>
|
||||
staleTime: 2 * 60_000,
|
||||
refetchInterval: 5 * 60_000,
|
||||
})
|
||||
|
||||
// ── System Logs ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface LogFilters {
|
||||
level?: string
|
||||
source?: string
|
||||
cycle_id?: string
|
||||
ticker?: string
|
||||
date_from?: string
|
||||
date_to?: string
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export const useSystemLogs = (filters: LogFilters = {}) =>
|
||||
useQuery({
|
||||
queryKey: ['system-logs', filters],
|
||||
queryFn: () => api.get('/logs', { params: filters }).then(r => r.data),
|
||||
staleTime: 30_000,
|
||||
refetchInterval: 30_000,
|
||||
})
|
||||
|
||||
export const useLogSources = () =>
|
||||
useQuery({
|
||||
queryKey: ['log-sources'],
|
||||
queryFn: () => api.get('/logs/sources').then(r => r.data),
|
||||
staleTime: 60_000,
|
||||
})
|
||||
|
||||
export const useLogCycles = () =>
|
||||
useQuery({
|
||||
queryKey: ['log-cycles'],
|
||||
queryFn: () => api.get('/logs/cycles').then(r => r.data),
|
||||
staleTime: 60_000,
|
||||
})
|
||||
|
||||
export const useClearLogs = () =>
|
||||
useMutation({
|
||||
mutationFn: (days: number) => api.delete('/logs/clear', { params: { older_than_days: days } }).then(r => r.data),
|
||||
})
|
||||
|
||||
// ── IV Watchlist Management ───────────────────────────────────────────────────
|
||||
|
||||
export const useWatchlistTickers = () =>
|
||||
useQuery({
|
||||
queryKey: ['watchlist-tickers'],
|
||||
queryFn: () => api.get('/options-vol/watchlist-tickers').then(r => r.data),
|
||||
staleTime: 60_000,
|
||||
})
|
||||
|
||||
export const useAddWatchlistTicker = () =>
|
||||
useMutation({
|
||||
mutationFn: (ticker: string) => api.post(`/options-vol/watchlist-tickers/${encodeURIComponent(ticker)}`).then(r => r.data),
|
||||
})
|
||||
|
||||
export const useRemoveWatchlistTicker = () =>
|
||||
useMutation({
|
||||
mutationFn: (ticker: string) => api.delete(`/options-vol/watchlist-tickers/${encodeURIComponent(ticker)}`).then(r => r.data),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user