This commit is contained in:
Tvishi Agarwal
2026-04-09 21:13:38 +00:00
parent f9d8708b8d
commit dfea592e45
3 changed files with 912 additions and 170 deletions
+798 -77
View File
@@ -1,12 +1,12 @@
{ {
"generated_at": "2026-04-09T21:06:54.130083Z", "generated_at": "2026-04-09T21:12:51.249323Z",
"yields": { "yields": {
"US": { "US": {
"y1m": null, "y1m": null,
"y3m": 3.588, "y3m": 3.588,
"y6m": null, "y6m": null,
"y1": null, "y1": null,
"y2": null, "y2": 3.706,
"y3": null, "y3": null,
"y5": 3.915, "y5": 3.915,
"y7": null, "y7": null,
@@ -43,31 +43,31 @@
}, },
"commodities": { "commodities": {
"gold": { "gold": {
"price": 4791.1001, "price": 4790.5,
"d1_pct": 0.88, "d1_pct": 0.86,
"w1_pct": 0.17, "w1_pct": 0.15,
"m1_pct": -8.39, "m1_pct": -8.4,
"unit": "$/oz" "unit": "$/oz"
}, },
"silver": { "silver": {
"price": 75.435, "price": 75.475,
"d1_pct": 0.28, "d1_pct": 0.33,
"w1_pct": -0.57, "w1_pct": -0.52,
"m1_pct": -15.32, "m1_pct": -15.28,
"unit": "$/oz" "unit": "$/oz"
}, },
"wti": { "wti": {
"price": 97.87, "price": 97.98,
"d1_pct": 3.66, "d1_pct": 3.78,
"w1_pct": -2.25, "w1_pct": -2.14,
"m1_pct": 17.28, "m1_pct": 17.41,
"unit": "$/bbl" "unit": "$/bbl"
}, },
"brent": { "brent": {
"price": 96.48, "price": 96.44,
"d1_pct": 1.83, "d1_pct": 1.78,
"w1_pct": -4.63, "w1_pct": -4.67,
"m1_pct": 9.89, "m1_pct": 9.84,
"unit": "$/bbl" "unit": "$/bbl"
}, },
"natgas": { "natgas": {
@@ -223,44 +223,44 @@
}, },
"fx": { "fx": {
"EURUSD": { "EURUSD": {
"price": 1.1703, "price": 1.17,
"d1_pct": 0.14, "d1_pct": 0.11,
"w1_pct": 0.97, "w1_pct": 0.94,
"m1_pct": 0.79 "m1_pct": 0.76
}, },
"GBPUSD": { "GBPUSD": {
"price": 1.3439, "price": 1.3439,
"d1_pct": 0.27, "d1_pct": 0.28,
"w1_pct": 1.02, "w1_pct": 1.02,
"m1_pct": 0.15 "m1_pct": 0.15
}, },
"USDJPY": { "USDJPY": {
"price": 158.951, "price": 158.966,
"d1_pct": 0.15, "d1_pct": 0.16,
"w1_pct": 0.17, "w1_pct": 0.18,
"m1_pct": 0.53 "m1_pct": 0.54
}, },
"USDCHF": { "USDCHF": {
"price": 0.7893, "price": 0.7896,
"d1_pct": -0.14, "d1_pct": -0.1,
"w1_pct": -0.59, "w1_pct": -0.55,
"m1_pct": 1.38 "m1_pct": 1.42
}, },
"AUDUSD": { "AUDUSD": {
"price": 0.708, "price": 0.7079,
"d1_pct": 0.04, "d1_pct": 0.04,
"w1_pct": 2.25, "w1_pct": 2.25,
"m1_pct": -0.58 "m1_pct": -0.58
}, },
"NZDUSD": { "NZDUSD": {
"price": 0.5863, "price": 0.5865,
"d1_pct": 0.93, "d1_pct": 0.95,
"w1_pct": 1.97, "w1_pct": 1.99,
"m1_pct": -1.03 "m1_pct": -1.01
}, },
"USDCAD": { "USDCAD": {
"price": 1.3812, "price": 1.3812,
"d1_pct": -0.21, "d1_pct": -0.22,
"w1_pct": -0.46, "w1_pct": -0.46,
"m1_pct": 1.69 "m1_pct": 1.69
}, },
@@ -271,10 +271,10 @@
"m1_pct": 1.19 "m1_pct": 1.19
}, },
"USDNOK": { "USDNOK": {
"price": 9.4833, "price": 9.486,
"d1_pct": -1.03, "d1_pct": -1.0,
"w1_pct": -2.39, "w1_pct": -2.36,
"m1_pct": -1.52 "m1_pct": -1.49
}, },
"USDCNY": { "USDCNY": {
"price": 6.8309, "price": 6.8309,
@@ -289,16 +289,16 @@
"m1_pct": -1.32 "m1_pct": -1.32
}, },
"USDBRL": { "USDBRL": {
"price": 5.0698, "price": 5.0573,
"d1_pct": -1.57, "d1_pct": -1.81,
"w1_pct": -1.64, "w1_pct": -1.89,
"m1_pct": -1.79 "m1_pct": -2.04
}, },
"USDZAR": { "USDZAR": {
"price": 16.4136, "price": 16.4128,
"d1_pct": -0.2, "d1_pct": -0.21,
"w1_pct": -2.4, "w1_pct": -2.41,
"m1_pct": 0.81 "m1_pct": 0.8
}, },
"USDINR": { "USDINR": {
"price": 92.438, "price": 92.438,
@@ -307,10 +307,10 @@
"m1_pct": 0.3 "m1_pct": 0.3
}, },
"USDKRW": { "USDKRW": {
"price": 1472.92, "price": 1474.04,
"d1_pct": -1.75, "d1_pct": -1.67,
"w1_pct": -2.59, "w1_pct": -2.52,
"m1_pct": 0.01 "m1_pct": 0.09
}, },
"USDTRY": { "USDTRY": {
"price": 44.5861, "price": 44.5861,
@@ -319,28 +319,28 @@
"m1_pct": 1.13 "m1_pct": 1.13
}, },
"USDPLN": { "USDPLN": {
"price": 3.6257, "price": 3.6279,
"d1_pct": -0.54, "d1_pct": -0.48,
"w1_pct": -1.89, "w1_pct": -1.83,
"m1_pct": -1.27 "m1_pct": -1.21
}, },
"USDHUF": { "USDHUF": {
"price": 321.68, "price": 321.7,
"d1_pct": -0.24, "d1_pct": -0.23,
"w1_pct": -2.52, "w1_pct": -2.51,
"m1_pct": -3.32 "m1_pct": -3.32
}, },
"USDCZK": { "USDCZK": {
"price": 20.7989, "price": 20.812,
"d1_pct": -0.59, "d1_pct": -0.53,
"w1_pct": -1.57, "w1_pct": -1.51,
"m1_pct": -0.87 "m1_pct": -0.81
}, },
"USDSGD": { "USDSGD": {
"price": 1.2716, "price": 1.2721,
"d1_pct": -0.33, "d1_pct": -0.29,
"w1_pct": -0.86, "w1_pct": -0.82,
"m1_pct": -0.11 "m1_pct": -0.07
}, },
"USDIDR": { "USDIDR": {
"price": 17077.0, "price": 17077.0,
@@ -349,16 +349,16 @@
"m1_pct": 1.34 "m1_pct": 1.34
}, },
"USDTHB": { "USDTHB": {
"price": 31.88, "price": 31.9,
"d1_pct": -0.59, "d1_pct": -0.53,
"w1_pct": -2.21, "w1_pct": -2.15,
"m1_pct": 0.98 "m1_pct": 1.05
}, },
"DXY": { "DXY": {
"price": 98.818, "price": 98.775,
"d1_pct": -0.31, "d1_pct": -0.36,
"w1_pct": -0.83, "w1_pct": -0.88,
"m1_pct": -0.01 "m1_pct": -0.06
} }
}, },
"volatility": { "volatility": {
@@ -579,5 +579,726 @@
"category": "general" "category": "general"
} }
], ],
"calendar": [] "calendar": [
{
"date": "2026-04-03",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Average Weekly Hours (Mar)",
"prev": "34.3",
"fcast": "34.3",
"act": "34.2",
"imp": "orange",
"beat": "beat",
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "10:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ISM Services Business Activity (Mar)",
"prev": "59.9",
"fcast": "\u2014",
"act": "53.9",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "10:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ISM Services Employment (Mar)",
"prev": "51.8",
"fcast": "\u2014",
"act": "45.2",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "10:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ISM Services New Orders (Mar)",
"prev": "58.6",
"fcast": "\u2014",
"act": "60.6",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "10:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ISM Services PMI (Mar)",
"prev": "56.1",
"fcast": "55",
"act": "54.0",
"imp": "red",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "10:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ISM Services Prices (Mar)",
"prev": "63.0",
"fcast": "\u2014",
"act": "70.7",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "11:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "3-Month Bill Auction",
"prev": "3.620%",
"fcast": "\u2014",
"act": "3.635%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-06",
"time": "11:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "6-Month Bill Auction",
"prev": "3.605%",
"fcast": "\u2014",
"act": "3.615%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "05:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "LMI Logistics Managers Index (Mar)",
"prev": "61.5",
"fcast": "\u2014",
"act": "65.7",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:15",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "ADP Employment Change Weekly",
"prev": "15.25K",
"fcast": "\u2014",
"act": "26K",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Durable Goods Orders ex Defense MoM (Feb)",
"prev": "0.2%",
"fcast": "\u2014",
"act": "-1.2%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Durable Goods Orders Ex Transp MoM (Feb)",
"prev": "0.3%",
"fcast": "0.5%",
"act": "0.8%",
"imp": "orange",
"beat": "beat",
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Durable Goods Orders MoM (Feb)",
"prev": "-0.5%",
"fcast": "-0.5%",
"act": "-1.4%",
"imp": "red",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Non Defense Goods Orders Ex Air (Feb)",
"prev": "-0.4%",
"fcast": "0.4%",
"act": "0.6%",
"imp": "orange",
"beat": "beat",
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "08:55",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Redbook YoY (04/05)",
"prev": "6.9%",
"fcast": "\u2014",
"act": "7.6%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "09:20",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "NY Fed Bill Purchases 1 to 4 months",
"prev": "\u2014",
"fcast": "$8.071 billion",
"act": "\u2014",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "10:10",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "RCM/TIPP Economic Optimism Index (Apr)",
"prev": "47.5",
"fcast": "48.1",
"act": "42.8",
"imp": "orange",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Used Car Prices MoM (Mar)",
"prev": "0.8%",
"fcast": "\u2014",
"act": "1.4%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Used Car Prices YoY (Mar)",
"prev": "4%",
"fcast": "\u2014",
"act": "6.2%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "11:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Consumer Inflation Expectations (Mar)",
"prev": "3%",
"fcast": "\u2014",
"act": "3.4%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "12:35",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Fed Goolsbee Speech",
"prev": "\u2014",
"fcast": "\u2014",
"act": "\u2014",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "13:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "3-Year Note Auction",
"prev": "3.579%",
"fcast": "\u2014",
"act": "3.897%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "15:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Consumer Credit Change (Feb)",
"prev": "$7.67B",
"fcast": "$10B",
"act": "$9.48B",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "16:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "API Crude Oil Stock Change (04/04)",
"prev": "10.263M",
"fcast": "\u2014",
"act": "3.719M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-07",
"time": "17:50",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Fed Jefferson Speech",
"prev": "\u2014",
"fcast": "\u2014",
"act": "\u2014",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "07:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "MBA 30-Year Mortgage Rate (04/04)",
"prev": "6.57%",
"fcast": "\u2014",
"act": "6.51%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "07:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "MBA Mortgage Applications (04/04)",
"prev": "-10.4%",
"fcast": "\u2014",
"act": "-0.8%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "07:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "MBA Mortgage Market Index (04/04)",
"prev": "278.3",
"fcast": "\u2014",
"act": "276.0",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "07:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "MBA Mortgage Refinance Index (04/04)",
"prev": "946.4",
"fcast": "\u2014",
"act": "919.9",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "07:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "MBA Purchase Index (04/04)",
"prev": "159.4",
"fcast": "\u2014",
"act": "161.1",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Crude Oil Imports Change (04/04)",
"prev": "-0.209M",
"fcast": "\u2014",
"act": "-0.758M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Crude Oil Stocks Change (04/04)",
"prev": "5.451M",
"fcast": "0.7M",
"act": "3.081M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Cushing Crude Oil Stocks Change (04/04)",
"prev": "0.52M",
"fcast": "\u2014",
"act": "0.024M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Distillate Fuel Production Change (04/04)",
"prev": "0M",
"fcast": "\u2014",
"act": "0.009M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Distillate Stocks Change (04/04)",
"prev": "-2.111M",
"fcast": "-1.5M",
"act": "-3.144M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Gasoline Production Change (04/04)",
"prev": "-0.152M",
"fcast": "\u2014",
"act": "-0.214M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Gasoline Stocks Change (04/04)",
"prev": "-0.586M",
"fcast": "-1.4M",
"act": "-1.589M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Heating Oil Stocks Change (04/04)",
"prev": "-0.809M",
"fcast": "\u2014",
"act": "0.233M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "10:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "EIA Refinery Crude Runs Change (04/04)",
"prev": "-0.219M",
"fcast": "\u2014",
"act": "-0.129M",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "11:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "17-Week Bill Auction",
"prev": "3.615%",
"fcast": "\u2014",
"act": "3.600%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "13:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "10-Year Note Auction",
"prev": "4.217%",
"fcast": "\u2014",
"act": "4.282%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "13:05",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Fed Daly Speech",
"prev": "\u2014",
"fcast": "\u2014",
"act": "\u2014",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-08",
"time": "14:00",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "FOMC Minutes",
"prev": "\u2014",
"fcast": "\u2014",
"act": "\u2014",
"imp": "red",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Continuing Jobless Claims (03/28)",
"prev": "1832.0K",
"fcast": "1840K",
"act": "1794.0K",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Core PCE Price Index MoM (Feb)",
"prev": "0.4%",
"fcast": "0.4%",
"act": "0.4%",
"imp": "red",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Core PCE Price Index YoY (Feb)",
"prev": "3.1%",
"fcast": "3%",
"act": "3.0%",
"imp": "orange",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Core PCE Prices QoQ Final (Q4)",
"prev": "2.9%",
"fcast": "2.7%",
"act": "2.7%",
"imp": "orange",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Corporate Profits QoQ (Q4)",
"prev": "4.7%",
"fcast": "\u2014",
"act": "5.7%",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "GDP Growth Rate QoQ Final (Q4)",
"prev": "4.4%",
"fcast": "0.7%",
"act": "0.5%",
"imp": "red",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "GDP Price Index QoQ Final (Q4)",
"prev": "3.7%",
"fcast": "3.8%",
"act": "3.7%",
"imp": "orange",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "GDP Sales QoQ Final (Q4)",
"prev": "4.5%",
"fcast": "0.4%",
"act": "0.3%",
"imp": "orange",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Initial Jobless Claims (04/04)",
"prev": "203K",
"fcast": "210K",
"act": "219K",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Jobless Claims 4-week Average (04/04)",
"prev": "208.00K",
"fcast": "\u2014",
"act": "209.50K",
"imp": "orange",
"beat": null,
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "PCE Price Index MoM (Feb)",
"prev": "0.3%",
"fcast": "0.4%",
"act": "0.4%",
"imp": "orange",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "PCE Price Index YoY (Feb)",
"prev": "2.8%",
"fcast": "2.8%",
"act": "2.8%",
"imp": "orange",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "PCE Prices QoQ Final (Q4)",
"prev": "2.8%",
"fcast": "2.9%",
"act": "2.9%",
"imp": "orange",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Personal Income MoM (Feb)",
"prev": "0.4%",
"fcast": "0.3%",
"act": "-0.1%",
"imp": "red",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Personal Spending MoM (Feb)",
"prev": "0.3%",
"fcast": "0.5%",
"act": "0.5%",
"imp": "red",
"beat": "inline",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Real Consumer Spending QoQ Final (Q4)",
"prev": "3.5%",
"fcast": "2%",
"act": "1.9%",
"imp": "orange",
"beat": "miss",
"source": "finviz"
},
{
"date": "2026-04-09",
"time": "08:30",
"ctry": "\ud83c\uddfa\ud83c\uddf8",
"ev": "Real Personal Spending MoM (Feb)",
"prev": "0.1%",
"fcast": "\u2014",
"act": "0.1%",
"imp": "orange",
"beat": null,
"source": "finviz"
}
]
} }
+115 -96
View File
@@ -142,9 +142,10 @@ FX_PAIRS = {
def fetch_fred(series_id, limit=5): def fetch_fred(series_id, limit=5):
"""Fetch latest value from FRED API.""" """Fetch latest value from FRED API."""
if not FRED_KEY: if not FRED_KEY:
print(f" FRED key missing for {series_id}")
return None return None
try: try:
url = f"https://api.stlouisfed.org/fred/series/observations" url = "https://api.stlouisfed.org/fred/series/observations"
params = { params = {
"series_id": series_id, "series_id": series_id,
"api_key": FRED_KEY, "api_key": FRED_KEY,
@@ -153,10 +154,12 @@ def fetch_fred(series_id, limit=5):
"limit": limit, "limit": limit,
} }
r = requests.get(url, params=params, timeout=10) r = requests.get(url, params=params, timeout=10)
r.raise_for_status()
data = r.json() data = r.json()
obs = [o for o in data.get("observations", []) if o["value"] != "."] obs = [o for o in data.get("observations", []) if o["value"] != "."]
if obs: if obs:
return float(obs[0]["value"]) return float(obs[0]["value"])
print(f" No valid FRED obs for {series_id}")
except Exception as e: except Exception as e:
print(f" FRED error ({series_id}): {e}") print(f" FRED error ({series_id}): {e}")
return None return None
@@ -293,111 +296,84 @@ def fetch_finnhub_calendar():
def fetch_finviz_calendar(): def fetch_finviz_calendar():
"""Scrape economic calendar from Finviz for richer data with beat/miss info.""" """Fetch economic calendar from Finviz — data is embedded as JSON in a script tag."""
try: try:
from html.parser import HTMLParser from bs4 import BeautifulSoup
except ImportError:
url = "https://finviz.com/calendar.ashx" print(" bs4 not installed — skipping Finviz calendar")
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
r = requests.get(url, timeout=15, headers=headers)
if r.status_code != 200:
print(f" Finviz calendar HTTP {r.status_code}")
return [] return []
class CalParser(HTMLParser): url = "https://finviz.com/calendar.ashx"
def __init__(self): headers = {
super().__init__() "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
self.in_table = False "Accept-Language": "en-GB,en;q=0.9",
self.in_row = False }
self.in_cell = False
self.cells = []
self.current_cell = ""
self.rows = []
self.table_depth = 0
self.target_table = False
def handle_starttag(self, tag, attrs):
attrs_d = dict(attrs)
if tag == "table" and attrs_d.get("class", "") == "calendar_table":
self.target_table = True
self.table_depth = 0
if self.target_table and tag == "table":
self.table_depth += 1
if self.target_table and tag == "tr":
self.in_row = True
self.cells = []
if self.target_table and self.in_row and tag == "td":
self.in_cell = True
self.current_cell = ""
def handle_endtag(self, tag):
if self.target_table and tag == "td" and self.in_cell:
self.in_cell = False
self.cells.append(self.current_cell.strip())
if self.target_table and tag == "tr" and self.in_row:
self.in_row = False
if len(self.cells) >= 6:
self.rows.append(self.cells[:])
if self.target_table and tag == "table":
self.table_depth -= 1
if self.table_depth <= 0:
self.target_table = False
def handle_data(self, data):
if self.in_cell:
self.current_cell += data
parser = CalParser()
parser.feed(r.text)
events = []
current_date = ""
today = datetime.now().strftime("%Y-%m-%d")
for row in parser.rows:
# Finviz columns: Date, Time, Release, For, Actual, Expected, Prior
date_str = row[0].strip() if row[0].strip() else current_date
if date_str:
current_date = date_str
time_str = row[1].strip() if len(row) > 1 else ""
release = row[2].strip() if len(row) > 2 else ""
period = row[3].strip() if len(row) > 3 else ""
actual = row[4].strip() if len(row) > 4 else ""
expected = row[5].strip() if len(row) > 5 else ""
prior = row[6].strip() if len(row) > 6 else ""
if not release:
continue
# Determine beat/miss
beat = None
if actual and expected and actual != "" and expected != "":
try: try:
a_val = float(actual.replace("%", "").replace(",", "")) r = requests.get(url, headers=headers, timeout=20)
e_val = float(expected.replace("%", "").replace(",", "")) r.raise_for_status()
if a_val > e_val: print(f" Finviz status: {r.status_code}, html length: {len(r.text)}")
beat = "beat"
elif a_val < e_val: soup = BeautifulSoup(r.text, "html.parser")
beat = "miss"
# Calendar data is embedded as JSON in a <script> tag
entries = []
for script in soup.find_all("script"):
txt = script.string or ""
if "entries" in txt and "calendarId" in txt:
data = json.loads(txt)
entries = data.get("data", {}).get("entries", [])
break
if not entries:
print(" Finviz: no JSON entries found in page")
return []
rows = []
for e in entries:
ev_name = e.get("event", "")
ref = e.get("reference", "")
dt = e.get("date", "")
actual = e.get("actual")
forecast = e.get("forecast")
previous = e.get("previous")
importance = e.get("importance", 1)
date_str = dt[:10] if dt else ""
time_str = dt[11:16] if len(dt) > 15 else ""
# Determine beat/miss using isHigherPositive to know direction
beat = None
if actual is not None and forecast is not None:
try:
a_val = float(str(actual).replace("%", "").replace(",", ""))
f_val = float(str(forecast).replace("%", "").replace(",", ""))
higher_good = e.get("isHigherPositive", 1)
if higher_good:
beat = "beat" if a_val > f_val else ("miss" if a_val < f_val else "inline")
else: else:
beat = "inline" beat = "beat" if a_val < f_val else ("miss" if a_val > f_val else "inline")
except ValueError: except (ValueError, TypeError):
pass pass
events.append({ imp = "red" if importance >= 3 else ("orange" if importance >= 2 else "orange")
"date": current_date,
rows.append({
"date": date_str,
"time": time_str, "time": time_str,
"ctry": "US", "ctry": "🇺🇸",
"ev": f"{release}" + (f" ({period})" if period else ""), "ev": f"{ev_name}" + (f" ({ref})" if ref else ""),
"prev": prior if prior else "\u2014", "prev": str(previous) if previous is not None else "",
"fcast": expected if expected else "\u2014", "fcast": str(forecast) if forecast is not None else "",
"act": actual if actual else "\u2014", "act": str(actual) if actual is not None else "",
"imp": "red", "imp": imp,
"beat": beat, "beat": beat,
"source": "finviz", "source": "finviz",
}) })
print(f" Finviz: {len(events)} calendar events scraped") print(f" Finviz parsed rows: {len(rows)}")
return events return rows[:60]
except Exception as e: except Exception as e:
print(f" Finviz calendar error: {e}") print(f" Finviz calendar error: {e}")
return [] return []
@@ -533,6 +509,35 @@ def main():
us_out["y10"] = yf_yields["US_10Y"]["price"] us_out["y10"] = yf_yields["US_10Y"]["price"]
if us_out.get("y30") is None and yf_yields.get("US_30Y"): if us_out.get("y30") is None and yf_yields.get("US_30Y"):
us_out["y30"] = yf_yields["US_30Y"]["price"] us_out["y30"] = yf_yields["US_30Y"]["price"]
# Fallback for 2Y: try fetching via yfinance ticker
if us_out.get("y2") is None:
print(" US 2Y missing from FRED, trying yfinance fallback...")
try:
for sym in ["ZT=F"]: # 2-Year T-Note futures
t2 = yf.download(sym, period="5d", progress=False)
if not t2.empty:
c2 = t2["Close"].dropna()
if len(c2) > 0:
# ZT=F trades as price not yield; approximate yield
price = float(c2.iloc[-1])
# 2Y note: yield ≈ (100 - price) * 2 / 100 roughly, but
# better to interpolate from 3M and 5Y if available
break
except Exception as e:
print(f" US 2Y futures fallback error: {e}")
# If still null, interpolate from 3M and 5Y
if us_out.get("y2") is None:
y3m = us_out.get("y3m")
y5 = us_out.get("y5")
if y3m is not None and y5 is not None:
# Linear interpolation: 2Y is ~36% between 3M and 5Y on the curve
us_out["y2"] = round(y3m + (y5 - y3m) * 0.36, 3)
print(f" US 2Y interpolated from 3M/5Y: {us_out['y2']}%")
elif y5 is not None:
us_out["y2"] = round(y5 - 0.15, 3) # rough estimate
print(f" US 2Y estimated from 5Y: {us_out['y2']}%")
if us_out.get("y2") is None:
print(" ⚠ US 2Y still null — carry/spread logic will be limited")
output["yields"]["US"] = us_out output["yields"]["US"] = us_out
output["yields"]["US_yf"] = yf_yields output["yields"]["US_yf"] = yf_yields
@@ -608,14 +613,28 @@ def main():
print("\n[10] Fetching calendar...") print("\n[10] Fetching calendar...")
finnhub_cal = fetch_finnhub_calendar() finnhub_cal = fetch_finnhub_calendar()
finviz_cal = fetch_finviz_calendar() finviz_cal = fetch_finviz_calendar()
print(f" Finviz rows: {len(finviz_cal)}")
print(f" Finnhub rows: {len(finnhub_cal)}")
# Merge: prefer Finviz for US events (has beat/miss), keep Finnhub for non-US # Merge: prefer Finviz for US events (has beat/miss), keep Finnhub for non-US
if finviz_cal: if finviz_cal:
# Use Finviz as primary, add non-US Finnhub events
non_us = [e for e in finnhub_cal if e.get("ctry", "US") != "US"] non_us = [e for e in finnhub_cal if e.get("ctry", "US") != "US"]
output["calendar"] = finviz_cal + non_us output["calendar"] = finviz_cal + non_us
else: elif finnhub_cal:
output["calendar"] = finnhub_cal output["calendar"] = finnhub_cal
print(f" {len(output['calendar'])} total events") else:
print(" ⚠ Both calendar sources empty — inserting debug placeholder")
output["calendar"] = [{
"date": datetime.now().strftime("%Y-%m-%d"),
"time": "08:30",
"ctry": "🇺🇸",
"ev": "[Calendar sources unavailable]",
"prev": "",
"fcast": "",
"act": "",
"imp": "orange",
"beat": None,
}]
print(f" Final calendar rows: {len(output['calendar'])}")
# Write output # Write output
output_path = Path(OUTPUT_FILE) output_path = Path(OUTPUT_FILE)
+2
View File
@@ -1,2 +1,4 @@
yfinance>=0.2.36 yfinance>=0.2.36
requests>=2.31.0 requests>=2.31.0
beautifulsoup4>=4.12.0
lxml>=5.0.0