From 978d1c35eb390924ef856017fcf6efc0cdf6b77f Mon Sep 17 00:00:00 2001 From: Tvishi Agarwal Date: Mon, 6 Apr 2026 23:46:40 +0000 Subject: [PATCH] v5final --- index.html | 38 ++++++-------------------- netlify/functions/deep-dive-summary.js | 1 + 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/index.html b/index.html index 5e49bef..3a61517 100644 --- a/index.html +++ b/index.html @@ -26,36 +26,16 @@ const G10=[{p:"EURUSD",q:"EUR",i:1},{p:"GBPUSD",q:"GBP",i:1},{p:"USDJPY",q:"JPY" const EMP=[{p:"USDCNY",q:"CNY"},{p:"USDMXN",q:"MXN"},{p:"USDBRL",q:"BRL"},{p:"USDZAR",q:"ZAR"},{p:"USDINR",q:"INR"},{p:"USDKRW",q:"KRW"},{p:"USDTRY",q:"TRY"},{p:"USDPLN",q:"PLN"},{p:"USDHUF",q:"HUF"},{p:"USDCZK",q:"CZK"},{p:"USDSGD",q:"SGD"},{p:"USDIDR",q:"IDR"},{p:"USDTHB",q:"THB"}].map(x=>({...x,i:0})); const SYM=[...new Set([...G10,...EMP].map(x=>x.q))].join(","); -const RT=[{c:"US",f:"๐Ÿ‡บ๐Ÿ‡ธ",cb:5.50,ccy:"USD"},{c:"Eurozone",f:"๐Ÿ‡ช๐Ÿ‡บ",cb:4.50,ccy:"EUR"},{c:"UK",f:"๐Ÿ‡ฌ๐Ÿ‡ง",cb:5.25,ccy:"GBP"},{c:"Japan",f:"๐Ÿ‡ฏ๐Ÿ‡ต",cb:0.10,ccy:"JPY"},{c:"Switzerland",f:"๐Ÿ‡จ๐Ÿ‡ญ",cb:1.75,ccy:"CHF"},{c:"Australia",f:"๐Ÿ‡ฆ๐Ÿ‡บ",cb:4.35,ccy:"AUD"},{c:"New Zealand",f:"๐Ÿ‡ณ๐Ÿ‡ฟ",cb:5.50,ccy:"NZD"},{c:"Canada",f:"๐Ÿ‡จ๐Ÿ‡ฆ",cb:5.00,ccy:"CAD"},{c:"Sweden",f:"๐Ÿ‡ธ๐Ÿ‡ช",cb:4.00,ccy:"SEK"},{c:"Norway",f:"๐Ÿ‡ณ๐Ÿ‡ด",cb:4.50,ccy:"NOK"},{c:"Brazil",f:"๐Ÿ‡ง๐Ÿ‡ท",cb:10.75,ccy:"BRL"},{c:"Mexico",f:"๐Ÿ‡ฒ๐Ÿ‡ฝ",cb:11.00,ccy:"MXN"},{c:"South Africa",f:"๐Ÿ‡ฟ๐Ÿ‡ฆ",cb:8.25,ccy:"ZAR"},{c:"India",f:"๐Ÿ‡ฎ๐Ÿ‡ณ",cb:6.50,ccy:"INR"},{c:"South Korea",f:"๐Ÿ‡ฐ๐Ÿ‡ท",cb:3.50,ccy:"KRW"},{c:"Turkey",f:"๐Ÿ‡น๐Ÿ‡ท",cb:50.00,ccy:"TRY"},{c:"Poland",f:"๐Ÿ‡ต๐Ÿ‡ฑ",cb:5.75,ccy:"PLN"}]; +const RT=[{c:"US",f:"๐Ÿ‡บ๐Ÿ‡ธ",cb:null,ccy:"USD"},{c:"Eurozone",f:"๐Ÿ‡ช๐Ÿ‡บ",cb:null,ccy:"EUR"},{c:"UK",f:"๐Ÿ‡ฌ๐Ÿ‡ง",cb:null,ccy:"GBP"},{c:"Japan",f:"๐Ÿ‡ฏ๐Ÿ‡ต",cb:null,ccy:"JPY"},{c:"Switzerland",f:"๐Ÿ‡จ๐Ÿ‡ญ",cb:null,ccy:"CHF"},{c:"Australia",f:"๐Ÿ‡ฆ๐Ÿ‡บ",cb:null,ccy:"AUD"},{c:"New Zealand",f:"๐Ÿ‡ณ๐Ÿ‡ฟ",cb:null,ccy:"NZD"},{c:"Canada",f:"๐Ÿ‡จ๐Ÿ‡ฆ",cb:null,ccy:"CAD"},{c:"Sweden",f:"๐Ÿ‡ธ๐Ÿ‡ช",cb:null,ccy:"SEK"},{c:"Norway",f:"๐Ÿ‡ณ๐Ÿ‡ด",cb:null,ccy:"NOK"},{c:"Brazil",f:"๐Ÿ‡ง๐Ÿ‡ท",cb:null,ccy:"BRL"},{c:"Mexico",f:"๐Ÿ‡ฒ๐Ÿ‡ฝ",cb:null,ccy:"MXN"},{c:"South Africa",f:"๐Ÿ‡ฟ๐Ÿ‡ฆ",cb:null,ccy:"ZAR"},{c:"India",f:"๐Ÿ‡ฎ๐Ÿ‡ณ",cb:null,ccy:"INR"},{c:"South Korea",f:"๐Ÿ‡ฐ๐Ÿ‡ท",cb:null,ccy:"KRW"},{c:"Turkey",f:"๐Ÿ‡น๐Ÿ‡ท",cb:null,ccy:"TRY"},{c:"Poland",f:"๐Ÿ‡ต๐Ÿ‡ฑ",cb:null,ccy:"PLN"}]; const cOf={};RT.forEach(r=>cOf[r.c]=r.ccy); const tvF={US:"TVC:DXY",Eurozone:"FX:EURUSD",UK:"FX:GBPUSD",Japan:"FX:USDJPY",Switzerland:"FX:USDCHF",Australia:"FX:AUDUSD","New Zealand":"FX:NZDUSD",Canada:"FX:USDCAD",Sweden:"FX:USDSEK",Norway:"FX:USDNOK",Brazil:"FX:USDBRL",Mexico:"FX:USDMXN","South Africa":"FX:USDZAR",India:"FX:USDINR","South Korea":"FX:USDKRW",Turkey:"FX:USDTRY",Poland:"FX:USDPLN"}; const tvY={US:"TVC:US10Y",Eurozone:"TVC:DE10Y",UK:"TVC:GB10Y",Japan:"TVC:JP10Y",Canada:"TVC:CA10Y",Australia:"TVC:AU10Y"}; const pOf={US:"DXY",Eurozone:"EURUSD",UK:"GBPUSD",Japan:"USDJPY",Switzerland:"USDCHF",Australia:"AUDUSD","New Zealand":"NZDUSD",Canada:"USDCAD",Sweden:"USDSEK",Norway:"USDNOK",Brazil:"USDBRL",Mexico:"USDMXN","South Africa":"USDZAR",India:"USDINR","South Korea":"USDKRW",Turkey:"USDTRY",Poland:"USDPLN"}; const nKw={US:["fed","fomc","treasury","dollar","powell","nonfarm"],Eurozone:["ecb","lagarde","eurozone","bund"],UK:["boe","bailey","gilt","sterling","uk gdp","uk cpi"],Japan:["boj","ueda","yen","jgb","japan"],Switzerland:["snb","swiss","franc"],Australia:["rba","aussie","australia"],Canada:["boc","canada","loonie"],"New Zealand":["rbnz","kiwi","new zealand"],Sweden:["riksbank","sweden"],Norway:["norges","norway"],Brazil:["bcb","brazil","real"],Mexico:["banxico","mexico","peso"],"South Africa":["sarb","south africa","rand"],India:["rbi","india","rupee"],"South Korea":["bok","korea","won"],Turkey:["cbrt","turkey","lira"],Poland:["nbp","poland","zloty"]}; -// โ•โ•โ• FULL MACRO DATABASE โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• -const MD={ -US:{cpi:"3.2%",cpiP:"3.1%",cpiT:"re-accelerating",core:"3.8%",gdp:"2.5%",gdpT:"resilient",unemp:"3.7%",unempT:"near cycle lows",wages:"4.1% YoY",pmi:"52.6",tb:"-$68.5B",stance:"Hawkish hold",next:"2026-05-01",last:"Hold 5.50%",pricing:"2 cuts in 12m"}, -Eurozone:{cpi:"2.6%",cpiP:"2.8%",cpiT:"falling toward target",core:"3.1%",gdp:"0.3%",gdpT:"anaemic",unemp:"6.4%",unempT:"stable",wages:"3.5% YoY",pmi:"49.2",tb:"+โ‚ฌ28B",stance:"Easing bias",next:"2026-04-10",last:"Hold 4.50%",pricing:"3 cuts in 12m"}, -UK:{cpi:"3.4%",cpiP:"4.0%",cpiT:"falling but sticky services",core:"4.5%",gdp:"0.2%",gdpT:"tepid",unemp:"4.2%",unempT:"rising",wages:"5.6% YoY",pmi:"53.8",tb:"-ยฃ4.8B",stance:"Cautious hold",next:"2026-05-09",last:"Hold 5.25%",pricing:"2 cuts in 12m"}, -Japan:{cpi:"2.8%",cpiP:"2.5%",cpiT:"rising and broadening",core:"2.5%",gdp:"1.2%",gdpT:"recovering",unemp:"2.5%",unempT:"tight",wages:"2.1% (Shunto: 5.3%)",pmi:"51.4",tb:"-ยฅ580B",stance:"Cautious normalisation",next:"2026-04-26",last:"Hold 0.10%",pricing:"1 hike in 12m"}, -Switzerland:{cpi:"1.4%",cpiP:"1.2%",cpiT:"low",core:"1.2%",gdp:"0.6%",gdpT:"modest",unemp:"2.3%",unempT:"stable",wages:"1.8% YoY",pmi:"48.5",tb:"+CHF5.2B",stance:"Easing",next:"2026-06-19",last:"Cut to 1.75%",pricing:"1-2 more cuts"}, -Australia:{cpi:"3.6%",cpiP:"3.4%",cpiT:"sticky",core:"3.9%",gdp:"1.5%",gdpT:"slowing",unemp:"3.9%",unempT:"stable",wages:"4.2% YoY",pmi:"50.1",tb:"+A$8.5B",stance:"On hold",next:"2026-05-20",last:"Hold 4.35%",pricing:"2 cuts in 12m"}, -"New Zealand":{cpi:"4.7%",cpiP:"4.7%",cpiT:"sticky",core:"4.3%",gdp:"-0.3%",gdpT:"recession",unemp:"4.3%",unempT:"rising",wages:"3.8% YoY",pmi:"47.1",tb:"-NZ$1.2B",stance:"Easing",next:"2026-05-28",last:"Cut to 5.50%",pricing:"3-4 cuts"}, -Canada:{cpi:"2.9%",cpiP:"2.8%",cpiT:"near target",core:"3.2%",gdp:"1.0%",gdpT:"slowing",unemp:"5.8%",unempT:"rising",wages:"3.9% YoY",pmi:"49.8",tb:"-C$1.5B",stance:"Easing",next:"2026-04-16",last:"Cut to 5.00%",pricing:"2-3 more cuts"}, -Sweden:{cpi:"2.2%",cpiP:"2.5%",cpiT:"at target",core:"2.5%",gdp:"0.1%",gdpT:"stagnant",unemp:"8.2%",unempT:"high",wages:"3.5% YoY",pmi:"48.2",tb:"+SEK12B",stance:"Easing",next:"2026-05-07",last:"Cut to 4.00%",pricing:"2-3 more cuts"}, -Norway:{cpi:"3.6%",cpiP:"3.9%",cpiT:"sticky",core:"4.1%",gdp:"0.8%",gdpT:"stable",unemp:"3.7%",unempT:"low",wages:"5.2% YoY",pmi:"51.8",tb:"+NOK80B",stance:"Hawkish hold",next:"2026-05-08",last:"Hold 4.50%",pricing:"1-2 cuts"}, -Brazil:{cpi:"4.5%",cpiP:"4.2%",cpiT:"rising",core:"4.0%",gdp:"2.1%",gdpT:"strong",unemp:"7.8%",unempT:"falling",wages:"N/A",pmi:"52.1",tb:"+$7.2B",stance:"Tightening",next:"2026-05-07",last:"Hike to 10.75%",pricing:"Terminal ~12%"}, -Mexico:{cpi:"4.2%",cpiP:"4.4%",cpiT:"slowly falling",core:"4.6%",gdp:"2.5%",gdpT:"resilient",unemp:"2.8%",unempT:"tight",wages:"N/A",pmi:"51.5",tb:"-$5.8B",stance:"Cautious hold",next:"2026-05-15",last:"Hold 11.00%",pricing:"2-3 cuts"}, -"South Africa":{cpi:"5.3%",cpiP:"5.1%",cpiT:"elevated",core:"4.6%",gdp:"0.7%",gdpT:"weak",unemp:"32.1%",unempT:"structural",wages:"N/A",pmi:"49.5",tb:"-ZAR15B",stance:"Hold",next:"2026-05-29",last:"Hold 8.25%",pricing:"1-2 cuts"}, -India:{cpi:"5.1%",cpiP:"5.3%",cpiT:"moderating",core:"4.2%",gdp:"6.5%",gdpT:"strong",unemp:"7.1%",unempT:"stable",wages:"N/A",pmi:"58.3",tb:"-$20B",stance:"Easing bias",next:"2026-04-09",last:"Cut to 6.50%",pricing:"2 more cuts"}, -"South Korea":{cpi:"2.1%",cpiP:"2.3%",cpiT:"at target",core:"2.0%",gdp:"2.0%",gdpT:"recovering",unemp:"2.7%",unempT:"stable",wages:"N/A",pmi:"50.8",tb:"+$4.5B",stance:"Easing",next:"2026-05-29",last:"Cut to 3.50%",pricing:"1-2 cuts"}, -Turkey:{cpi:"65%",cpiP:"67%",cpiT:"falling from peak",core:"70%",gdp:"3.2%",gdpT:"slowing",unemp:"9.4%",unempT:"stable",wages:"N/A",pmi:"49.1",tb:"-$7.5B",stance:"Hawkish hold",next:"2026-04-17",last:"Hold 50.00%",pricing:"Cuts H2 2026"}, -Poland:{cpi:"3.9%",cpiP:"3.7%",cpiT:"rising",core:"4.1%",gdp:"2.8%",gdpT:"solid",unemp:"5.1%",unempT:"stable",wages:"12% YoY",pmi:"50.2",tb:"-PLN5B",stance:"On hold",next:"2026-05-07",last:"Hold 5.75%",pricing:"Cuts unlikely H1"}, -}; +const MD={}; + -const DCAL=[{date:"2026-04-08",time:"12:30",ctry:"๐Ÿ‡บ๐Ÿ‡ธ",ev:"FOMC Minutes",prev:"โ€”",fcast:"โ€”",act:"โ€”",imp:"red"},{date:"2026-04-09",time:"12:30",ctry:"๐Ÿ‡บ๐Ÿ‡ธ",ev:"US CPI YoY",prev:"3.2%",fcast:"3.1%",act:"โ€”",imp:"red"},{date:"2026-04-10",time:"11:00",ctry:"๐Ÿ‡ช๐Ÿ‡บ",ev:"ECB Rate Decision",prev:"4.50%",fcast:"4.25%",act:"โ€”",imp:"red"},{date:"2026-04-10",time:"07:00",ctry:"๐Ÿ‡ฌ๐Ÿ‡ง",ev:"UK GDP MoM",prev:"-0.1%",fcast:"0.2%",act:"โ€”",imp:"red"}]; -const CP=["EURUSD","GBPUSD","USDJPY","AUDUSD","USDCAD","NZDUSD","Gold","US10Y"];const CM=[[1,.82,-.31,.65,-.72,.58,.42,-.35],[.82,1,-.22,.55,-.61,.48,.35,-.28],[-.31,-.22,1,-.45,.38,-.42,-.18,.72],[.65,.55,-.45,1,-.58,.85,.52,-.42],[-.72,-.61,.38,-.58,1,-.52,-.38,.32],[.58,.48,-.42,.85,-.52,1,.45,-.38],[.42,.35,-.18,.52,-.38,.45,1,-.55],[-.35,-.28,.72,-.42,.32,-.38,-.55,1]]; /* โ•โ•โ• UI ATOMS โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */ const Dot=({on})=>; @@ -66,13 +46,13 @@ function RiskBar({d,live}){const vd=(d.VIX?.chg||0)<0,dd=(d.DXY?.chg||0)<0,on=vd /* โ•โ•โ• PAGES โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */ function FxTbl({data,live}){return
{live?"Live via Frankfurter":"Loading..."}
C.b},{k:"spot",l:"Spot",rn:r=>r.spot!=null?Number(r.spot).toFixed(r.spot>100?2:4):"โ€”"},{k:"d1",l:"1D %",rn:r=>fc(r.d1),cl:r=>cc(r.d1)},{k:"w1",l:"1W %",rn:r=>fc(r.w1),cl:r=>cc(r.w1)},{k:"m1",l:"1M %",rn:r=>fc(r.m1),cl:r=>cc(r.m1)},{k:"ytd",l:"YTD %",rn:r=>fc(r.ytd),cl:r=>cc(r.ytd)}]} rows={data}/>
} -function YldTbl({yld,live}){return
{live?"US via FRED ยท Others: CB rate only":"No yield data"}
r.f+" "+r.c},{k:"cb",l:"CB Rate",rn:r=>r.cb.toFixed(2)+"%"},{k:"y2",l:"2Y",rn:r=>r.y2!=null?r.y2.toFixed(2):"โ€”",cl:r=>r.y2?C.tx:C.txM},{k:"y10",l:"10Y",rn:r=>r.y10!=null?r.y10.toFixed(2):"โ€”",cl:r=>r.y10?C.tx:C.txM},{k:"s",l:"2s10s",rn:r=>r.y2&&r.y10?fb((r.y10-r.y2)*100):"โ€”",cl:r=>r.y2&&r.y10?cc(r.y10-r.y2):C.txM}]} rows={RT.map(r=>({...r,...(yld[r.c]||{})}))} sm/>
} +function YldTbl({yld,live}){return
{live?"US via FRED ยท EU via ECB":"No yield data"}
r.f+" "+r.c},{k:"cb",l:"CB Rate",rn:r=>r.cb!=null?r.cb.toFixed(2)+"%":"โ€”",cl:r=>r.cb!=null?C.tx:C.txM},{k:"y2",l:"2Y",rn:r=>r.y2!=null?r.y2.toFixed(2):"โ€”",cl:r=>r.y2?C.tx:C.txM},{k:"y10",l:"10Y",rn:r=>r.y10!=null?r.y10.toFixed(2):"โ€”",cl:r=>r.y10?C.tx:C.txM},{k:"s",l:"2s10s",rn:r=>r.y2&&r.y10?fb((r.y10-r.y2)*100):"โ€”",cl:r=>r.y2&&r.y10?cc(r.y10-r.y2):C.txM}]} rows={RT.map(r=>({...r,...(yld[r.c]||{})}))} sm/>
} function Cmdt({d}){const items=[{k:"gold",l:"Gold XAU",s:"TVC:GOLD"},{k:"wti",l:"WTI Crude",s:"TVC:USOIL"},{k:"brent",l:"Brent",s:"TVC:UKOIL"}];return
{items.map(it=>{const v=d[it.k];return
{it.l}
{v?.level!=null?"$"+Number(v.level).toLocaleString(undefined,{maximumFractionDigits:2}):"โ€”"}
{v?.chg!=null&&
{fc(v.chg)}
}
})}
{items.map(it=>
)}
} -function XCry({yld}){const g=RT.filter(r=>["US","Eurozone","UK","Japan","Switzerland","Australia","New Zealand","Canada","Sweden","Norway"].includes(r.c));const gY=c=>yld[c]?.y2??null;const pairs=[];for(let i=0;iyb?a:b,sc=ya>yb?b:a;pairs.push({lc:lc.ccy,sc:sc.ccy,lf:lc.f,sf:sc.f,ly:Math.max(ya,yb),sy:Math.min(ya,yb),carry:d})}return r.rk<=5?C.g:C.txD},{k:"t",l:"Trade",a:"left",nm:1,rn:r=>r.lf+" Long "+r.lc+" / "+r.sf+" Short "+r.sc},{k:"ly",l:"Long Yld",rn:r=>r.ly.toFixed(2)+"%"},{k:"sy",l:"Short Yld",rn:r=>r.sy.toFixed(2)+"%"},{k:"carry",l:"Carry",rn:r=>"+"+r.carry.toFixed(2)+"%",cl:r=>r.carry>3?C.g:r.carry>1?C.tl:C.txD},{k:"bp",l:"bps",rn:r=>"+"+(r.carry*100).toFixed(0),cl:r=>r.carry>3?C.g:r.carry>1?C.tl:C.txD}]} rows={pairs.sort((a,b)=>b.carry-a.carry).map((r,i)=>({...r,rk:i+1}))} sm/>} -function UCry({yld}){const uY=yld.US?.y2??5.5;return r.rk<=3?C.g:r.rk>=13?C.r:C.txD},{k:"c",l:"Currency",a:"left",nm:1,rn:r=>r.f+" "+r.ccy},{k:"cb",l:"CB Rate",rn:r=>r.cb.toFixed(2)+"%"},{k:"carry",l:"vs USD",rn:r=>fc(r.carry),cl:r=>cc(r.carry)},{k:"dir",l:"Direction",a:"left",nm:1,rn:r=>r.carry>0.3?"Long "+r.ccy:"Short "+r.ccy,cl:r=>r.carry>0.3?C.g:C.r}]} rows={RT.filter(r=>r.c!=="US").map(r=>({...r,carry:+((yld[r.c]?.y2??r.cb)-uY).toFixed(2)})).sort((a,b)=>b.carry-a.carry).map((r,i)=>({...r,rk:i+1}))} sm/>} +function XCry({yld}){const g=RT.filter(r=>["US","Eurozone","UK","Japan","Switzerland","Australia","New Zealand","Canada","Sweden","Norway"].includes(r.c));const gY=c=>yld[c]?.y2??null;const pairs=[];for(let i=0;iyb?a:b,sc=ya>yb?b:a;pairs.push({lc:lc.ccy,sc:sc.ccy,lf:lc.f,sf:sc.f,ly:Math.max(ya,yb),sy:Math.min(ya,yb),carry:d})}if(!pairs.length)return
Carry data requires live yield feeds (FRED / ECB)
;return r.rk<=5?C.g:C.txD},{k:"t",l:"Trade",a:"left",nm:1,rn:r=>r.lf+" Long "+r.lc+" / "+r.sf+" Short "+r.sc},{k:"ly",l:"Long Yld",rn:r=>r.ly.toFixed(2)+"%"},{k:"sy",l:"Short Yld",rn:r=>r.sy.toFixed(2)+"%"},{k:"carry",l:"Carry",rn:r=>"+"+r.carry.toFixed(2)+"%",cl:r=>r.carry>3?C.g:r.carry>1?C.tl:C.txD},{k:"bp",l:"bps",rn:r=>"+"+(r.carry*100).toFixed(0),cl:r=>r.carry>3?C.g:r.carry>1?C.tl:C.txD}]} rows={pairs.sort((a,b)=>b.carry-a.carry).map((r,i)=>({...r,rk:i+1}))} sm/>} +function UCry({yld}){const uY=yld.US?.y2;if(uY==null)return
Carry data requires live US yield feed (FRED)
;const rows=RT.filter(r=>r.c!=="US").map(r=>{const ry=yld[r.c]?.y2;return {...r,carry:ry!=null?+((ry-uY).toFixed(2)):null}}).filter(r=>r.carry!=null).sort((a,b)=>b.carry-a.carry).map((r,i)=>({...r,rk:i+1}));if(!rows.length)return
No foreign yield data available yet
;return r.rk<=3?C.g:r.rk>=13?C.r:C.txD},{k:"c",l:"Currency",a:"left",nm:1,rn:r=>r.f+" "+r.ccy},{k:"y",l:"2Y Yield",rn:r=>(yld[r.c]?.y2!=null?yld[r.c].y2.toFixed(2)+"%":"โ€”")},{k:"carry",l:"vs USD",rn:r=>fc(r.carry),cl:r=>cc(r.carry)},{k:"dir",l:"Direction",a:"left",nm:1,rn:r=>r.carry>0.3?"Long "+r.ccy:"Short "+r.ccy,cl:r=>r.carry>0.3?C.g:C.r}]} rows={rows} sm/>} function CarryP({yld}){const [t,sT]=useState("Cross G10");return
{t==="Cross G10"?:}
} function Markets({g10,em,fxL,yld,yL}){const [t,sT]=useState("G10 FX");return
{t==="G10 FX"&&}{t==="EM FX"&&}{t==="Rates"&&}{t==="Carry"&&}
} -function CorrMx(){const cC=v=>v>=.7?"rgba(34,197,94,"+v*.7+")":v>=.3?"rgba(34,197,94,"+v*.4+")":v>=-.3?"rgba(148,163,184,0.1)":v>=-.7?"rgba(239,68,68,"+Math.abs(v)*.4+")":"rgba(239,68,68,"+Math.abs(v)*.7+")";return
30-Day Correlation Matrix
{CP.map(p=>
{p}
)}
{CP.map((p,i)=>
{p}
{CM[i].map((v,j)=>
.5?C.tx:C.txM}}>{i===j?"1":v.toFixed(1)}
)}
)}
} +function CorrMx(){return
30-Day Correlation Matrix
โ€”
Correlation data not available โ€” requires a live feed
} /* โ•โ•โ• DEEP DIVE โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */ function Deep({ctry,g10,em,yld,news,nL,risk}){ @@ -345,7 +325,7 @@ function Deep({ctry,g10,em,yld,news,nL,risk}){ } /* โ•โ•โ• BRIEF โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */ -function genBr(g10,em,risk,yld,cal,cmd){const L=[];const vix=risk.VIX,dxy=risk.DXY;const vD=(vix?.chg||0)<0,dD=(dxy?.chg||0)<0;if(vD&&dD)L.push("Risk on โ€” VIX down "+Math.abs(vix?.chg||0).toFixed(1)+" at "+(vix?.level?.toFixed(1)||"โ€”")+", USD softer at "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). Supportive for carry.");else if(!vD&&!dD)L.push("Defensive tone โ€” VIX up at "+(vix?.level?.toFixed(1)||"โ€”")+", USD bid at "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). JPY/CHF finding support.");else L.push("Mixed โ€” VIX "+(vix?.level?.toFixed(1)||"โ€”")+" ("+fc(vix?.chg,"")+"), DXY "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). Positioning ahead of events.");const mv=[...g10,...em].filter(x=>x.d1!=null).sort((a,b)=>Math.abs(b.d1)-Math.abs(a.d1)).slice(0,4);if(mv.length)L.push("Movers: "+mv.map(x=>x.pair+" "+(x.d1>0?"โ–ฒ":"โ–ผ")+Math.abs(x.d1).toFixed(2)+"%").join(", ")+".");if(cmd.gold?.level)L.push("Gold $"+cmd.gold.level.toFixed(0)+(cmd.gold.chg!=null?" ("+fc(cmd.gold.chg)+")":"")+"."+(cmd.wti?.level?" WTI $"+cmd.wti.level.toFixed(2)+(cmd.wti.chg!=null?" ("+fc(cmd.wti.chg)+")":"")+".":" "));const u2=yld.US?.y2;if(u2!=null){const tc=RT.filter(r=>r.c!=="US").map(r=>({ccy:r.ccy,c:+((yld[r.c]?.y2??r.cb)-u2).toFixed(2)})).filter(x=>x.c>1).sort((a,b)=>b.c-a.c).slice(0,3);L.push("US 2Y "+u2.toFixed(2)+"%."+(tc.length?" Top carry: "+tc.map(x=>x.ccy+" +"+x.c+"%").join(", ")+".":" "))}const hi=cal.filter(e=>e.imp==="red").slice(0,4);if(hi.length)L.push("Watch: "+hi.map(e=>e.ctry+" "+e.ev+" ("+e.date+")").join(", ")+".");return L.join(" ")} +function genBr(g10,em,risk,yld,cal,cmd){const L=[];const vix=risk.VIX,dxy=risk.DXY;const vD=(vix?.chg||0)<0,dD=(dxy?.chg||0)<0;if(vD&&dD)L.push("Risk on โ€” VIX down "+Math.abs(vix?.chg||0).toFixed(1)+" at "+(vix?.level?.toFixed(1)||"โ€”")+", USD softer at "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). Supportive for carry.");else if(!vD&&!dD)L.push("Defensive tone โ€” VIX up at "+(vix?.level?.toFixed(1)||"โ€”")+", USD bid at "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). JPY/CHF finding support.");else L.push("Mixed โ€” VIX "+(vix?.level?.toFixed(1)||"โ€”")+" ("+fc(vix?.chg,"")+"), DXY "+(dxy?.level?.toFixed(1)||"โ€”")+" ("+fc(dxy?.chg)+"). Positioning ahead of events.");const mv=[...g10,...em].filter(x=>x.d1!=null).sort((a,b)=>Math.abs(b.d1)-Math.abs(a.d1)).slice(0,4);if(mv.length)L.push("Movers: "+mv.map(x=>x.pair+" "+(x.d1>0?"โ–ฒ":"โ–ผ")+Math.abs(x.d1).toFixed(2)+"%").join(", ")+".");if(cmd.gold?.level)L.push("Gold $"+cmd.gold.level.toFixed(0)+(cmd.gold.chg!=null?" ("+fc(cmd.gold.chg)+")":"")+"."+(cmd.wti?.level?" WTI $"+cmd.wti.level.toFixed(2)+(cmd.wti.chg!=null?" ("+fc(cmd.wti.chg)+")":"")+".":" "));const u2=yld.US?.y2;if(u2!=null){const tc=RT.filter(r=>r.c!=="US"&&yld[r.c]?.y2!=null).map(r=>({ccy:r.ccy,c:+((yld[r.c].y2)-u2).toFixed(2)})).filter(x=>x.c>1).sort((a,b)=>b.c-a.c).slice(0,3);L.push("US 2Y "+u2.toFixed(2)+"%."+(tc.length?" Top carry: "+tc.map(x=>x.ccy+" +"+x.c+"%").join(", ")+".":" "))}const hi=cal.filter(e=>e.imp==="red").slice(0,4);if(hi.length)L.push("Watch: "+hi.map(e=>e.ctry+" "+e.ev+" ("+e.date+")").join(", ")+".");return L.join(" ")} function Brief({g10,em,yld,risk,cal,cmd}){const [br,sBr]=useState(null);const [ts,sTs]=useState(null);const [ld,sLd]=useState(false);const gen=()=>{sLd(true);setTimeout(()=>{sBr(genBr(g10,em,risk,yld,cal,cmd));sTs(new Date().toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}));sLd(false)},600)};return
๐Ÿง 
AI Morning Brief
Live FX, yields, carry, commodities & calendar
{ts&&Generated {ts}}
{br?
{br}
:
Click "Generate Brief"
}
} function Cal({evts,live}){const [fl,sF]=useState("All");const gF=["๐Ÿ‡บ๐Ÿ‡ธ","๐Ÿ‡ช๐Ÿ‡บ","๐Ÿ‡ฌ๐Ÿ‡ง","๐Ÿ‡ฏ๐Ÿ‡ต","๐Ÿ‡จ๐Ÿ‡ญ","๐Ÿ‡ฆ๐Ÿ‡บ","๐Ÿ‡ณ๐Ÿ‡ฟ","๐Ÿ‡จ๐Ÿ‡ฆ","๐Ÿ‡ธ๐Ÿ‡ช","๐Ÿ‡ณ๐Ÿ‡ด"];return
{["All","G10","EM","CB"].map(f=>)}
r.imp==="red"?C.r:C.am},{k:"prev",l:"Prev"},{k:"fcast",l:"Fcst"},{k:"act",l:"Act",cl:r=>(r.act&&r.act!=="โ€”")?C.g:C.txM}]} rows={evts.filter(e=>{if(fl==="G10")return gF.includes(e.ctry);if(fl==="EM")return!gF.includes(e.ctry);if(fl==="CB")return(e.ev||"").toLowerCase().match(/rate|fomc|boj|ecb|rba|rbnz|boc/);return true})}/>
} function Sett({open,close,keys,save}){const [lk,sL]=useState(keys);useEffect(()=>sL(keys),[keys,open]);if(!open)return null;return
e.stopPropagation()}>
โš™ API Keys
{[{k:"finnhub",l:"Finnhub โ€” VIX, commodities, news, calendar",u:"https://finnhub.io/register"}].map(a=>
sL({...lk,[a.k]:e.target.value})} style={{width:"100%",padding:"8px 12px",background:C.bgC,border:"1px solid "+C.bd,borderRadius:4,color:C.tx,fontSize:12,fontFamily:Mn,boxSizing:"border-box"}}/>
)}
} @@ -359,7 +339,7 @@ function App(){ const [g10D,sG10]=useState([]);const [emD,sEM]=useState([]);const [fxL,sFxL]=useState(false); const [yld,sYld]=useState({});const [yL,sYL]=useState(false); const [risk,sRisk]=useState({DXY:{level:null,chg:null},VIX:{level:null,chg:null},Gold:{level:null,chg:null},WTI:{level:null,chg:null},Brent:{level:null,chg:null},"US 10Y":{level:null,chg:null}}); - const [rL,sRL]=useState(false);const [cal,sCal]=useState(DCAL);const [cL,sCL]=useState(false);const [news,sNews]=useState([]);const [nL,sNL]=useState(false); + const [rL,sRL]=useState(false);const [cal,sCal]=useState([]);const [cL,sCL]=useState(false);const [news,sNews]=useState([]);const [nL,sNL]=useState(false); const [cmd,sCmd]=useState({gold:{},wti:{},brent:{}});const [ld,sLd]=useState(false);const [lr,sLR]=useState(null); const svK=useCallback(nk=>{setKeys(nk);Object.entries(nk).forEach(([k,v])=>sk(k,v))},[]); const load=useCallback(async()=>{ diff --git a/netlify/functions/deep-dive-summary.js b/netlify/functions/deep-dive-summary.js index bd8df02..8461d4a 100644 --- a/netlify/functions/deep-dive-summary.js +++ b/netlify/functions/deep-dive-summary.js @@ -105,6 +105,7 @@ ${JSON.stringify(payload, null, 2)} text: { format: { type: "json_schema", + name: "country_deep_dive", strict: true, schema }