mirror of
https://github.com/caty21/forex-dashboard.git
synced 2026-07-27 20:37:45 +00:00
auto: sync 2026-06-02 16:41
This commit is contained in:
@@ -508,6 +508,7 @@ type IndicatorResult = {
|
|||||||
surprise: number | null;
|
surprise: number | null;
|
||||||
trend: "up" | "down" | "flat" | null;
|
trend: "up" | "down" | "flat" | null;
|
||||||
lastUpdated: string | null;
|
lastUpdated: string | null;
|
||||||
|
consensus?: number | null;
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
function toIndicator(obs: Obs[]): IndicatorResult {
|
function toIndicator(obs: Obs[]): IndicatorResult {
|
||||||
@@ -1087,7 +1088,6 @@ export async function GET(req: NextRequest) {
|
|||||||
// Core CPI MoM (pages individuelles, décimales précises)
|
// Core CPI MoM (pages individuelles, décimales précises)
|
||||||
const teCoreMoM = teCoreMoMMap[currency];
|
const teCoreMoM = teCoreMoMMap[currency];
|
||||||
if (teCoreMoM) {
|
if (teCoreMoM) {
|
||||||
// prev=null pour les devises index-only (JPY/CHF/AUD/NZD)
|
|
||||||
const surprise = teCoreMoM.prev !== null
|
const surprise = teCoreMoM.prev !== null
|
||||||
? parseFloat((teCoreMoM.value - teCoreMoM.prev).toFixed(3))
|
? parseFloat((teCoreMoM.value - teCoreMoM.prev).toFixed(3))
|
||||||
: null;
|
: null;
|
||||||
@@ -1097,6 +1097,7 @@ export async function GET(req: NextRequest) {
|
|||||||
surprise,
|
surprise,
|
||||||
trend: teCoreMoM.value > 0 ? "up" : teCoreMoM.value < 0 ? "down" : "flat",
|
trend: teCoreMoM.value > 0 ? "up" : teCoreMoM.value < 0 ? "down" : "flat",
|
||||||
lastUpdated: teCoreMoM.refMonth,
|
lastUpdated: teCoreMoM.refMonth,
|
||||||
|
consensus: parseTeF(teCpiForecast?.cpiCoreMoM) ?? null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,6 +1113,7 @@ export async function GET(req: NextRequest) {
|
|||||||
surprise,
|
surprise,
|
||||||
trend: tePPI.value > 0 ? "up" : tePPI.value < 0 ? "down" : "flat",
|
trend: tePPI.value > 0 ? "up" : tePPI.value < 0 ? "down" : "flat",
|
||||||
lastUpdated: tePPI.refMonth,
|
lastUpdated: tePPI.refMonth,
|
||||||
|
consensus: parseTeF(teCpiForecast?.ppiMoM) ?? null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,9 +1134,11 @@ export async function GET(req: NextRequest) {
|
|||||||
forecasts: {
|
forecasts: {
|
||||||
// CPI — TE calendar forecast (priorité) puis ForexFactory
|
// CPI — TE calendar forecast (priorité) puis ForexFactory
|
||||||
// Les forecasts TE sont des strings "2.8%" → parseFloat les convertit en number
|
// Les forecasts TE sont des strings "2.8%" → parseFloat les convertit en number
|
||||||
cpi: parseTeF(teCpiForecast?.cpiYoY) ?? ffForecasts.cpi ?? null,
|
cpi: parseTeF(teCpiForecast?.cpiYoY) ?? ffForecasts.cpi ?? null,
|
||||||
cpiCore: parseTeF(teCpiForecast?.cpiCore) ?? null,
|
cpiCore: parseTeF(teCpiForecast?.cpiCore) ?? null,
|
||||||
cpiMoM: parseTeF(teCpiForecast?.cpiMoM) ?? null,
|
cpiMoM: parseTeF(teCpiForecast?.cpiMoM) ?? null,
|
||||||
|
cpiCoreMoM: parseTeF(teCpiForecast?.cpiCoreMoM) ?? null,
|
||||||
|
ppiMoM: parseTeF(teCpiForecast?.ppiMoM) ?? null,
|
||||||
cpiSurprise: ffForecasts.cpiSurprise,
|
cpiSurprise: ffForecasts.cpiSurprise,
|
||||||
unemployment: ffForecasts.unemployment,
|
unemployment: ffForecasts.unemployment,
|
||||||
unemploymentSurprise: ffForecasts.unemploymentSurprise,
|
unemploymentSurprise: ffForecasts.unemploymentSurprise,
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ import NarrativeButton from "./NarrativeButton";
|
|||||||
interface Ind { value: number | null; prev: number | null; surprise: number | null; trend: "up"|"down"|"flat"|null; lastUpdated: string | null }
|
interface Ind { value: number | null; prev: number | null; surprise: number | null; trend: "up"|"down"|"flat"|null; lastUpdated: string | null }
|
||||||
interface MacroForecasts {
|
interface MacroForecasts {
|
||||||
cpi: number | null; cpiSurprise: number | null;
|
cpi: number | null; cpiSurprise: number | null;
|
||||||
cpiCore: number | null;
|
cpiCore: number | null;
|
||||||
cpiMoM: number | null;
|
cpiMoM: number | null;
|
||||||
|
cpiCoreMoM: number | null;
|
||||||
|
ppiMoM: number | null;
|
||||||
unemployment: number | null; unemploymentSurprise: number | null;
|
unemployment: number | null; unemploymentSurprise: number | null;
|
||||||
pmiMfg: number | null; pmiMfgSurprise: number | null;
|
pmiMfg: number | null; pmiMfgSurprise: number | null;
|
||||||
pmiSvc: number | null; pmiSvcSurprise: number | null;
|
pmiSvc: number | null; pmiSvcSurprise: number | null;
|
||||||
@@ -382,7 +384,7 @@ export default function CurrencyCard({ currency, expectations, yields, sentiment
|
|||||||
</div>
|
</div>
|
||||||
{(inflFilter === "all" || inflFilter === "mom") && (
|
{(inflFilter === "all" || inflFilter === "mom") && (
|
||||||
<>
|
<>
|
||||||
<Row label="PPI MoM" ind={inds?.ppiMoM ?? null} unit="%" />
|
<Row label="PPI MoM" ind={inds?.ppiMoM ?? null} unit="%" consensus={fc?.ppiMoM ?? null} />
|
||||||
<Row label="CPI MoM" ind={inds?.cpiMoM ?? null} unit="%" consensus={fc?.cpiMoM ?? null} info="Source : Inflation Rate MoM (TradingEconomics)" />
|
<Row label="CPI MoM" ind={inds?.cpiMoM ?? null} unit="%" consensus={fc?.cpiMoM ?? null} info="Source : Inflation Rate MoM (TradingEconomics)" />
|
||||||
<Row
|
<Row
|
||||||
label={(() => {
|
label={(() => {
|
||||||
@@ -391,6 +393,7 @@ export default function CurrencyCard({ currency, expectations, yields, sentiment
|
|||||||
})()}
|
})()}
|
||||||
ind={inds?.cpiCoreMoM ?? null}
|
ind={inds?.cpiCoreMoM ?? null}
|
||||||
unit="%"
|
unit="%"
|
||||||
|
consensus={fc?.cpiCoreMoM ?? null}
|
||||||
tooltip={(() => {
|
tooltip={(() => {
|
||||||
const raw = (inds?.cpiCoreMoM as (Ind & { _raw?: { last: number; prev: number; refMonth: string } }) | null)?._raw;
|
const raw = (inds?.cpiCoreMoM as (Ind & { _raw?: { last: number; prev: number; refMonth: string } }) | null)?._raw;
|
||||||
const base = "=Core Inflation Rate MoM";
|
const base = "=Core Inflation Rate MoM";
|
||||||
|
|||||||
+14
-7
@@ -221,9 +221,11 @@ function parseCalendarHTML(html: string): TECalendarEvent[] {
|
|||||||
// Utilisé par la macro route pour remplir forecasts.cpiCore / forecasts.cpiMoM.
|
// Utilisé par la macro route pour remplir forecasts.cpiCore / forecasts.cpiMoM.
|
||||||
|
|
||||||
export interface TEInflationForecasts {
|
export interface TEInflationForecasts {
|
||||||
cpiYoY: string | null;
|
cpiYoY: string | null;
|
||||||
cpiCore: string | null;
|
cpiCore: string | null;
|
||||||
cpiMoM: string | null;
|
cpiMoM: string | null;
|
||||||
|
cpiCoreMoM: string | null;
|
||||||
|
ppiMoM: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchTEInflationForecasts(
|
export async function fetchTEInflationForecasts(
|
||||||
@@ -241,14 +243,19 @@ export async function fetchTEInflationForecasts(
|
|||||||
|
|
||||||
const ccy = ev.currency;
|
const ccy = ev.currency;
|
||||||
const title = ev.title.toLowerCase();
|
const title = ev.title.toLowerCase();
|
||||||
if (!result[ccy]) result[ccy] = { cpiYoY: null, cpiCore: null, cpiMoM: null };
|
if (!result[ccy]) result[ccy] = { cpiYoY: null, cpiCore: null, cpiMoM: null, cpiCoreMoM: null, ppiMoM: null };
|
||||||
|
|
||||||
const r = result[ccy]!;
|
const r = result[ccy]!;
|
||||||
if (!r.cpiCore && /core.*inflation.*yoy|core.*cpi.*yoy|core.*rate.*yoy/i.test(title)) {
|
// Order matters: Core MoM before generic MoM, Core YoY before generic YoY, PPI before CPI
|
||||||
|
if (!r.ppiMoM && /ppi.*mom|producer.*price.*mom/i.test(title)) {
|
||||||
|
r.ppiMoM = ev.forecast;
|
||||||
|
} else if (!r.cpiCoreMoM && /core.*mom|core.*inflation.*mom|core.*rate.*mom/i.test(title)) {
|
||||||
|
r.cpiCoreMoM = ev.forecast;
|
||||||
|
} else if (!r.cpiCore && /core.*inflation.*yoy|core.*cpi.*yoy|core.*rate.*yoy/i.test(title)) {
|
||||||
r.cpiCore = ev.forecast;
|
r.cpiCore = ev.forecast;
|
||||||
} else if (!r.cpiMoM && /inflation.*mom|cpi.*mom|rate.*mom/i.test(title)) {
|
} else if (!r.cpiMoM && /^(?!.*core).*(?:inflation.*mom|cpi.*mom|rate.*mom)/i.test(title)) {
|
||||||
r.cpiMoM = ev.forecast;
|
r.cpiMoM = ev.forecast;
|
||||||
} else if (!r.cpiYoY && /inflation.*yoy|cpi.*yoy|inflation\s+rate.*yoy/i.test(title)) {
|
} else if (!r.cpiYoY && /^(?!.*core).*(?:inflation.*yoy|cpi.*yoy|inflation\s+rate.*yoy)/i.test(title)) {
|
||||||
r.cpiYoY = ev.forecast;
|
r.cpiYoY = ev.forecast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user