From b4076f89b68687c82ef49bd9d341641a485f1b10 Mon Sep 17 00:00:00 2001 From: Henry Winkel Date: Thu, 14 May 2026 11:19:22 +0200 Subject: [PATCH] fix: add bars data for TradingView chart from Alpaca - Modify quote.ts to fetch historical bars for chart data - Update analyze.ticker.tsx to pass bars data to TradingViewChart - Chart now displays candlestick data from Alpaca API --- app/routes/analyze.ticker.tsx | 19 +++++++++++++++++-- app/routes/api/alpaca/quote.ts | 29 ++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/app/routes/analyze.ticker.tsx b/app/routes/analyze.ticker.tsx index 960594e..1b87874 100644 --- a/app/routes/analyze.ticker.tsx +++ b/app/routes/analyze.ticker.tsx @@ -8,6 +8,7 @@ interface LoaderData { ticker: string; position: number | null; orders: any[]; + bars: any[]; } export async function loader({ params, request }: { params: { ticker: string }; request: Request }) { @@ -27,11 +28,25 @@ export async function loader({ params, request }: { params: { ticker: string }; const ordersData = ordRes.ok ? await ordRes.json() : { orders: [] }; const orders = ordersData.orders?.filter((o: any) => o.symbol === ticker) || []; + // Fetch bars for chart + const barsRes = await fetch(`${baseUrl}/api/alpaca/quote/${ticker}`); + const barsData = barsRes.ok ? await barsRes.json() : null; + const bars = barsData?.bars || []; + return Response.json({ ticker, position, orders }); } export default function StockDetail() { - const { ticker, position, orders } = useLoaderData() as LoaderData; + const { ticker, position, orders, bars } = useLoaderData() as LoaderData; + + // Convert Alpaca bars to TradingView format + const chartData = bars?.map((bar: any) => ({ + time: bar.t, + open: bar.o, + high: bar.h, + low: bar.l, + close: bar.c, + })) || []; return (
@@ -39,7 +54,7 @@ export default function StockDetail() {

{ticker} Detail

- +

Position

diff --git a/app/routes/api/alpaca/quote.ts b/app/routes/api/alpaca/quote.ts index 9cb0939..529e217 100644 --- a/app/routes/api/alpaca/quote.ts +++ b/app/routes/api/alpaca/quote.ts @@ -14,17 +14,36 @@ export async function loader({ params }: { params: { ticker: string } }) { } try { - // Use latest trade instead of quote for real transaction price + // Get latest trade for current price const trade = await alpaca.getLatestTrade(ticker); - // trade has: Price, Size, Exchange, Timestamp, etc. const price = (trade as { Price?: number }).Price || 0; + + // Get historical bars for chart (last 30 days, daily) + const bars = await alpaca.getBarsV2(ticker, { + timeframe: "1Day", + limit: 30, + }); + + // Convert async generator to array + const barsArray = []; + for await (const bar of bars) { + barsArray.push({ + t: (bar as any).Timestamp || (bar as any).t, + o: (bar as any).Open || (bar as any).o, + h: (bar as any).High || (bar as any).h, + l: (bar as any).Low || (bar as any).l, + c: (bar as any).Close || (bar as any).c, + v: (bar as any).Volume || (bar as any).v, + }); + } + return Response.json({ ticker, price, - timestamp: (trade as { Timestamp?: string }).Timestamp, + bars: barsArray, }); } catch (error) { - console.error("Alpaca trade error:", error); - return Response.json({ error: "Failed to fetch trade" }, { status: 500 }); + console.error("Alpaca data error:", error); + return Response.json({ error: "Failed to fetch data" }, { status: 500 }); } } \ No newline at end of file