mirror of
https://github.com/caty21/forex-dashboard.git
synced 2026-08-22 17:08:05 +00:00
auto: sync 2026-06-01 23:46
This commit is contained in:
@@ -5,6 +5,7 @@ import cpiOverridesRaw from "@/data/cpi_overrides.json";
|
||||
import rateDecisionsRaw from "@/data/rate_decisions.json";
|
||||
import { fetchFFThisWeek, fetchFFEvents } from "@/lib/forexfactory";
|
||||
import type { FFEvent } from "@/lib/forexfactory";
|
||||
import { fetchTECoreInflation } from "@/lib/tecpi";
|
||||
|
||||
const FRED_BASE = "https://api.stlouisfed.org/fred/series/observations";
|
||||
const REVALIDATE = 86400; // cache 24h
|
||||
@@ -1002,6 +1003,27 @@ export async function GET(req: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── TE Core CPI (priorité maximale — données du jour, toutes devises) ────────
|
||||
// Remplace les séries FRED erronées :
|
||||
// GBP GBRCPIALLMINMEI = All Items (headline), pas core → écart ~1%
|
||||
// JPY PCPI total (3.6%) ≠ core (1.4%) → erreur massive
|
||||
// USD CPILFESL retard 1 mois → écart 0.2%
|
||||
// AUD/NZD trimestriels → retard jusqu'à 3 mois
|
||||
{
|
||||
const teCpi = await fetchTECoreInflation();
|
||||
const te = teCpi[currency];
|
||||
if (te) {
|
||||
const surprise = parseFloat((te.value - te.prev).toFixed(3));
|
||||
indicators.cpiCore = {
|
||||
value: te.value,
|
||||
prev: te.prev,
|
||||
surprise,
|
||||
trend: surprise > 0 ? "up" : surprise < 0 ? "down" : "flat",
|
||||
lastUpdated: te.refMonth,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Stale-if-error
|
||||
const hasAnyValue = Object.values(indicators).some((v) => v !== null);
|
||||
if (!hasAnyValue && staleCache) {
|
||||
|
||||
+12
-4
@@ -10,6 +10,7 @@ import CurrencyCard from "@/components/CurrencyCard";
|
||||
import DriversBar from "@/components/DriversBar";
|
||||
import CalendarTab from "@/components/CalendarTab";
|
||||
import SentimentPairsTab from "@/components/SentimentPairsTab";
|
||||
import YieldsTab from "@/components/YieldsTab";
|
||||
import type { CalendarEvent } from "@/app/api/calendar/route";
|
||||
|
||||
const REFRESH_MS = parseInt(process.env.NEXT_PUBLIC_REFRESH_INTERVAL_MS ?? "3600000");
|
||||
@@ -17,12 +18,12 @@ const REFRESH_MS = parseInt(process.env.NEXT_PUBLIC_REFRESH_INTERVAL_MS ?? "3600
|
||||
export default function Dashboard() {
|
||||
const [drivers, setDrivers] = useState<DriverData | null>(null);
|
||||
const [expectations, setExpectations] = useState<Record<string, unknown> | null>(null);
|
||||
const [yields, setYields] = useState<{ yields: Record<string, number | null>; spreads: Record<string, number | null> } | null>(null);
|
||||
const [yields, setYields] = useState<{ yields: Record<string, number | null>; spreads: Record<string, number | null>; dayDeltas?: Record<string, number | null> } | null>(null);
|
||||
const [sentiment, setSentiment] = useState<Record<string, SentimentEntry> | null>(null);
|
||||
const [cot, setCot] = useState<Record<string, CotEntry> | null>(null);
|
||||
const [calEvents, setCalEvents] = useState<CalendarEvent[]>([]);
|
||||
const [nextWeekAvail, setNextWeekAvail] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState<"dashboard" | "calendar" | "pairs">("dashboard");
|
||||
const [activeTab, setActiveTab] = useState<"dashboard" | "calendar" | "pairs" | "yields">("dashboard");
|
||||
const [rawSymbols, setRawSymbols] = useState<Array<{ name: string; longPercentage: number; shortPercentage: number; totalPositions: number }> | null>(null);
|
||||
const [rateProbabilities, setRateProbabilities] = useState<RateProbData | null>(null);
|
||||
const [lastRefresh, setLastRefresh] = useState<Date>(new Date());
|
||||
@@ -264,7 +265,7 @@ export default function Dashboard() {
|
||||
|
||||
{/* Tab navigation */}
|
||||
<div className="flex gap-0 border-b border-gray-200 mb-4">
|
||||
{(["dashboard", "calendar", "pairs"] as const).map((tab) => (
|
||||
{(["dashboard", "calendar", "pairs", "yields"] as const).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
@@ -274,7 +275,10 @@ export default function Dashboard() {
|
||||
: "border-transparent text-gray-500 hover:text-gray-700"
|
||||
}`}
|
||||
>
|
||||
{tab === "dashboard" ? "Dashboard" : tab === "calendar" ? "📅 Calendrier" : "↕ Paires"}
|
||||
{tab === "dashboard" ? "Dashboard"
|
||||
: tab === "calendar" ? "📅 Calendrier"
|
||||
: tab === "pairs" ? "↕ Paires"
|
||||
: "📈 Yields 10Y"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -331,6 +335,10 @@ export default function Dashboard() {
|
||||
<SentimentPairsTab symbols={rawSymbols} />
|
||||
)}
|
||||
|
||||
{activeTab === "yields" && (
|
||||
<YieldsTab yieldsData={yields} />
|
||||
)}
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="mt-6 text-center text-xs text-gray-400 space-y-1">
|
||||
<p>
|
||||
|
||||
Reference in New Issue
Block a user