fix: fetch trend history per-window and run aggregation 24/7
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize Pipeline was successful
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize Pipeline was successful
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
Two fixes for missing intraday data: 1. Frontend: lifted selectedWindow state to page level so useTrendHistory passes window param to the API. Previously fetched all windows with limit=500 which exhausted the limit before reaching recent intraday data. Now fetches only the selected window's data. 2. Scheduler: removed market-hours-only restriction from periodic aggregation. Runs every 15 minutes 24/7 so intraday data is always populated for backtesting regardless of market state.
This commit is contained in:
@@ -44,7 +44,8 @@ export function CompanyDetailPage() {
|
|||||||
const { data: signals } = useCompetitiveSignals(company?.ticker);
|
const { data: signals } = useCompetitiveSignals(company?.ticker);
|
||||||
const { data: decisions } = useCorporateDecisions(company?.ticker);
|
const { data: decisions } = useCorporateDecisions(company?.ticker);
|
||||||
const { data: trends } = useTrends({ ticker: company?.ticker, limit: 200 });
|
const { data: trends } = useTrends({ ticker: company?.ticker, limit: 200 });
|
||||||
const { data: trendHistory } = useTrendHistory({ ticker: company?.ticker, limit: 500 });
|
const [selectedWindow, setSelectedWindow] = useState('7d');
|
||||||
|
const { data: trendHistory } = useTrendHistory({ ticker: company?.ticker, window: selectedWindow, limit: 500 });
|
||||||
const { data: marketPrices } = useMarketPrices(company?.ticker, 200);
|
const { data: marketPrices } = useMarketPrices(company?.ticker, 200);
|
||||||
const { data: positions } = usePositions(company?.ticker);
|
const { data: positions } = usePositions(company?.ticker);
|
||||||
const [tab, setTab] = useState<'trends' | 'sources' | 'aliases' | 'macro' | 'competitors' | 'patterns' | 'signals' | 'decisions'>('trends');
|
const [tab, setTab] = useState<'trends' | 'sources' | 'aliases' | 'macro' | 'competitors' | 'patterns' | 'signals' | 'decisions'>('trends');
|
||||||
@@ -87,7 +88,7 @@ export function CompanyDetailPage() {
|
|||||||
{tab === 'trends' && (
|
{tab === 'trends' && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<PositionCard positions={positions ?? []} ticker={company.ticker} />
|
<PositionCard positions={positions ?? []} ticker={company.ticker} />
|
||||||
<TrendHistoryChart trends={trendHistory ?? []} latestTrends={trends ?? []} ticker={company.ticker} marketPrices={marketPrices ?? []} />
|
<TrendHistoryChart trends={trendHistory ?? []} latestTrends={trends ?? []} ticker={company.ticker} marketPrices={marketPrices ?? []} selectedWindow={selectedWindow} onWindowChange={setSelectedWindow} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -662,8 +663,7 @@ function PositionCard({ positions, ticker }: { positions: import('../api/hooks')
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TrendHistoryChart({ trends, latestTrends, ticker, marketPrices }: { trends: TrendSummary[]; latestTrends: TrendSummary[]; ticker: string; marketPrices: MarketPrice[] }) {
|
function TrendHistoryChart({ trends, latestTrends, ticker, marketPrices, selectedWindow, onWindowChange }: { trends: TrendSummary[]; latestTrends: TrendSummary[]; ticker: string; marketPrices: MarketPrice[]; selectedWindow: string; onWindowChange: (w: string) => void }) {
|
||||||
const [selectedWindow, setSelectedWindow] = useState('7d');
|
|
||||||
|
|
||||||
// Determine the time range for the selected window to filter data
|
// Determine the time range for the selected window to filter data
|
||||||
const windowHours: Record<string, number> = {
|
const windowHours: Record<string, number> = {
|
||||||
@@ -742,7 +742,7 @@ function TrendHistoryChart({ trends, latestTrends, ticker, marketPrices }: { tre
|
|||||||
{(availableWindows.length > 0 ? availableWindows : WINDOW_ORDER).map((w) => (
|
{(availableWindows.length > 0 ? availableWindows : WINDOW_ORDER).map((w) => (
|
||||||
<button
|
<button
|
||||||
key={w}
|
key={w}
|
||||||
onClick={() => setSelectedWindow(w)}
|
onClick={() => onWindowChange(w)}
|
||||||
className={`rounded-md px-3 py-1 text-xs font-medium transition-colors ${
|
className={`rounded-md px-3 py-1 text-xs font-medium transition-colors ${
|
||||||
selectedWindow === w
|
selectedWindow === w
|
||||||
? 'bg-brand-600 text-white'
|
? 'bg-brand-600 text-white'
|
||||||
|
|||||||
@@ -501,22 +501,11 @@ async def schedule_cycle(pool: asyncpg.Pool, rds: aioredis.Redis) -> int:
|
|||||||
async def enqueue_periodic_aggregation(pool: asyncpg.Pool, rds: aioredis.Redis) -> int:
|
async def enqueue_periodic_aggregation(pool: asyncpg.Pool, rds: aioredis.Redis) -> int:
|
||||||
"""Enqueue aggregation jobs for all active tickers.
|
"""Enqueue aggregation jobs for all active tickers.
|
||||||
|
|
||||||
Runs periodically during market hours to ensure trend data stays fresh
|
Runs periodically to ensure trend data stays fresh even when no new
|
||||||
even when no new documents are being ingested. This gives the intraday
|
documents are being ingested. During market hours this runs every ~15
|
||||||
and 1d windows continuous updates based on existing signals and market
|
minutes; outside market hours it runs every ~60 minutes (for backtesting
|
||||||
price changes.
|
data continuity).
|
||||||
"""
|
"""
|
||||||
# Only run during US market hours (Mon-Fri, 6:30 AM - 1:30 PM PT / 13:30-20:30 UTC)
|
|
||||||
from datetime import datetime, timezone
|
|
||||||
now = datetime.now(timezone.utc)
|
|
||||||
weekday = now.weekday() # 0=Mon, 6=Sun
|
|
||||||
hour_utc = now.hour + now.minute / 60.0
|
|
||||||
|
|
||||||
if weekday >= 5: # Weekend
|
|
||||||
return 0
|
|
||||||
if hour_utc < 13.5 or hour_utc > 20.5: # Outside market hours (with 30min buffer)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Fetch all active tickers
|
# Fetch all active tickers
|
||||||
rows = await pool.fetch(
|
rows = await pool.fetch(
|
||||||
"SELECT ticker FROM companies WHERE active = TRUE ORDER BY ticker"
|
"SELECT ticker FROM companies WHERE active = TRUE ORDER BY ticker"
|
||||||
|
|||||||
Reference in New Issue
Block a user