mirror of
https://github.com/caty21/forex-dashboard.git
synced 2026-07-27 20:37:45 +00:00
fix: yearEndImplied now uses last meeting of current year (not 380d window)
Two bugs fixed in fetchAllCBPaths / fetchCBPath: - yearEndImplied was taking the last meeting within 380 days (~mid-2027) instead of the last meeting of the current calendar year (Dec 2026) — caused bps to be significantly overstated (e.g. USD showed +40 instead of +29.6) - IL article bpsYearEnd was overriding rateprobability.com yearEndImplied for all currencies; now IL only overrides CHF (no RP coverage); other 7 CBs use live OIS Dashboard yearEndBps now matches rateprobability.com raw API exactly for all CBs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+16
-8
@@ -127,9 +127,13 @@ async function fetchCBPath(ccy: Currency, slug: string): Promise<CBRatePath | nu
|
||||
? meetings.reduce((best, m) => m.probMovePct > best.probMovePct ? m : best, meetings[0])
|
||||
: null;
|
||||
|
||||
const yearEndImplied = meetings.length > 0
|
||||
? meetings[meetings.length - 1].impliedRate
|
||||
: null;
|
||||
// yearEndImplied = taux implicite à la dernière réunion de l'année en cours (pas mid-2027)
|
||||
const currentYear = new Date().getFullYear();
|
||||
const yearEndIso = `${currentYear}-12-31`;
|
||||
const meetsThisYear = meetings.filter(m => m.dateIso <= yearEndIso);
|
||||
const yearEndImplied = meetsThisYear.length > 0
|
||||
? meetsThisYear[meetsThisYear.length - 1].impliedRate
|
||||
: meetings.length > 0 ? meetings[0].impliedRate : null;
|
||||
|
||||
return { currency: ccy, asOf, currentRate, meetings, peakMeeting, yearEndImplied };
|
||||
} catch { return null; }
|
||||
@@ -225,8 +229,9 @@ export async function fetchAllCBPaths(): Promise<RateProbData> {
|
||||
if (snbPath) data["CHF"] = snbPath;
|
||||
}
|
||||
|
||||
// Enrichir yearEndImplied avec bpsYearEnd de IL (Giuseppe Dellamotta — source humaine)
|
||||
// + calculer ilDelta (Δ vs article semaine précédente) pour les flèches de tendance.
|
||||
// IL enrichment : yearEndImplied uniquement pour CHF (RP ne couvre pas la SNB).
|
||||
// Pour les 7 autres devises, on garde yearEndImplied de rateprobability.com (données OIS live).
|
||||
// ilDelta (flèches hebdo) reste calculé pour toutes les devises via l'article IL.
|
||||
for (const [ccyStr, ilEntry] of Object.entries(ilData)) {
|
||||
const ccy = ccyStr as keyof RateProbData;
|
||||
const path = data[ccy];
|
||||
@@ -234,10 +239,13 @@ export async function fetchAllCBPaths(): Promise<RateProbData> {
|
||||
if (typeof ilEntry.bpsYearEnd !== "number") continue;
|
||||
if (ilEntry.nextMeetingIsNoChange && Math.abs(ilEntry.bpsYearEnd) < 10) continue;
|
||||
|
||||
const ilYearEnd = parseFloat((path.currentRate + ilEntry.bpsYearEnd / 100).toFixed(4));
|
||||
// CHF only : pas de données RP → IL est la seule source pour yearEndImplied
|
||||
const yearEndImplied = ccy === "CHF"
|
||||
? parseFloat((path.currentRate + ilEntry.bpsYearEnd / 100).toFixed(4))
|
||||
: path.yearEndImplied;
|
||||
|
||||
// Delta semaine/semaine depuis l'article précédent de Giuseppe
|
||||
let ilDelta: import("./rateprobability").ILWeeklyDelta | undefined;
|
||||
let ilDelta: ILWeeklyDelta | undefined;
|
||||
const prevEntry = ilPrev[ccy];
|
||||
if (prevEntry && prevDate) {
|
||||
ilDelta = {
|
||||
@@ -248,7 +256,7 @@ export async function fetchAllCBPaths(): Promise<RateProbData> {
|
||||
};
|
||||
}
|
||||
|
||||
data[ccy] = { ...path, yearEndImplied: ilYearEnd, ...(ilDelta ? { ilDelta } : {}) };
|
||||
data[ccy] = { ...path, yearEndImplied, ...(ilDelta ? { ilDelta } : {}) };
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
Reference in New Issue
Block a user