feat: company names for tickers (Alpaca backfill + subtle display)
Deploy / lint (push) Successful in 6s
Deploy / test (push) Successful in 55s
Deploy / deploy (push) Successful in 32s

Store an optional company name on Ticker (migration 014) and backfill it from
Alpaca's asset list in a single Trading-API call for the whole universe — no
per-ticker fetch. Runs automatically at the end of universe bootstrap and via a
manual "Backfill Names" button (admin) / POST /admin/tickers/backfill-names.

The name ships on /tickers; a shared symbol→name map (useTickerNames) lets any view
show it without its own request. Displayed subtly next to the symbol — in the global
search, the ticker header, and as a small muted line under the symbol in Top Setups
and Open Trades (no extra column, truncated so it never widens the table).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 10:50:40 +02:00
co-authored by Claude Opus 4.8
parent a9f4686157
commit da0bb3367e
14 changed files with 169 additions and 2 deletions
+16
View File
@@ -283,6 +283,22 @@ export function useBootstrapTickers() {
});
}
export function useBackfillTickerNames() {
const qc = useQueryClient();
const { addToast } = useToast();
return useMutation({
mutationFn: () => adminApi.backfillTickerNames(),
onSuccess: (result) => {
qc.invalidateQueries({ queryKey: ['tickers'] });
addToast('success', `Company names: +${result.updated} filled (${result.unmatched} unmatched)`);
},
onError: (error: Error) => {
addToast('error', error.message || 'Failed to backfill company names');
},
});
}
// ── Jobs ──
export function useJobs() {
+14
View File
@@ -1,3 +1,4 @@
import { useMemo } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import * as tickersApi from '../api/tickers';
import { useToast } from '../components/ui/Toast';
@@ -9,6 +10,19 @@ export function useTickers() {
});
}
/** symbol (upper) → company name, from the tracked-ticker list. Shared lookup so
* any view can show the company behind a symbol without its own request. */
export function useTickerNames(): Map<string, string> {
const { data } = useTickers();
return useMemo(() => {
const map = new Map<string, string>();
for (const t of data ?? []) {
if (t.name) map.set(t.symbol.toUpperCase(), t.name);
}
return map;
}, [data]);
}
export function useAddTicker() {
const qc = useQueryClient();
const { addToast } = useToast();