Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion dashboard/inject.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,19 @@ export async function synthesize(data) {
timestamp: yfData.summary?.timestamp || null,
};

const yfGold = yfQuotes['GC=F'];
const yfSilver = yfQuotes['SI=F'];
const metals = {
gold: yfGold?.price,
goldChange: yfGold?.change,
goldChangePct: yfGold?.changePct,
goldRecent: yfGold?.history?.map(h => h.close) || [],
silver: yfSilver?.price,
silverChange: yfSilver?.change,
silverChangePct: yfSilver?.changePct,
silverRecent: yfSilver?.history?.map(h => h.close) || [],
};

// Override stale EIA prices with live Yahoo Finance data if available
const yfWti = yfQuotes['CL=F'];
const yfBrent = yfQuotes['BZ=F'];
Expand All @@ -595,7 +608,7 @@ export async function synthesize(data) {
},
sdr: { total: sdrNet.totalReceivers || 0, online: sdrNet.online || 0, zones: sdrZones },
tg: { posts: tgData.totalPosts || 0, urgent: tgUrgent, topPosts: tgTop },
who, fred, energy, bls, treasury, gscpi, defense, noaa, epa, acled, gdelt, space, health, news,
who, fred, energy, metals, bls, treasury, gscpi, defense, noaa, epa, acled, gdelt, space, health, news,
markets, // Live Yahoo Finance market data
ideas: [], ideasSource: 'disabled',
// newsFeed for ticker (merged RSS + GDELT + Telegram)
Expand Down
9 changes: 8 additions & 1 deletion dashboard/public/jarvis.html
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,7 @@
const payrolls=D.bls.find(b=>b.id==='CES0000000001');
const gscpi=D.gscpi;
const mkt=D.markets||{};
const metals=D.metals||{};

const wtiH = D.energy.wtiRecent||[];
const wtiMax=Math.max(...wtiH),wtiMin=Math.min(...wtiH);
Expand All @@ -1365,11 +1366,15 @@
const vixFred = D.fred.find(f=>f.id==='VIXCLS');
const vixVal = vixLive?.value || vixFred?.value;
const vixChg = vixLive?.changePct != null ? `${vixLive.changePct>=0?'+':''}${vixLive.changePct}%` : '';
const fmtMarketPrice = (price) => price != null ? `$${price.toLocaleString(undefined,{maximumFractionDigits:2})}` : '--';
const dayMove = (pct) => pct != null ? `${pct>=0?'+':''}${pct}% today` : '';

const metrics=[
{l:'WTI Crude',v:`$${D.energy.wti}`,s:'$/bbl',p:70},
{l:'Brent',v:`$${D.energy.brent}`,s:'$/bbl',p:75},
{l:'Nat Gas',v:`$${D.energy.natgas||'--'}`,s:'$/MMBtu',p:30},
{l:'Gold',v:fmtMarketPrice(metals.gold),s:dayMove(metals.goldChangePct)||'COMEX proxy',p:58},
{l:'Silver',v:fmtMarketPrice(metals.silver),s:dayMove(metals.silverChangePct)||'COMEX proxy',p:54},
{l:'VIX',v:vixVal?vixVal.toFixed(1):'--',s:vixChg||'volatility index',p:vixVal?Math.min(vixVal*2.5,100):30},
{l:'Fed Funds',v:ff?`${ff.value}%`:'--',s:ff?.date||'',p:36},
{l:'GSCPI',v:gscpi?gscpi.value.toFixed(2):'--',s:gscpi?.interpretation||'',p:49},
Expand All @@ -1383,6 +1388,8 @@
return f?.recent?.length > 1 ? {spark: f.recent, sparkUp: up} : {};
};
metrics[0] = {...metrics[0], spark: D.energy.wtiRecent, sparkUp: false};
metrics[3] = {...metrics[3], spark: metals.goldRecent, sparkUp: (metals.goldChangePct ?? 0) >= 0};
metrics[4] = {...metrics[4], spark: metals.silverRecent, sparkUp: (metals.silverChangePct ?? 0) >= 0};

// Build live market cards from Yahoo Finance
const indexCards = (mkt.indexes||[]).map(mktCard).join('');
Expand Down Expand Up @@ -1456,7 +1463,7 @@
<div class="metrics-row">${cryptoCards}</div>
</div>`:''}
<div style="margin-bottom:8px">
<div style="font-family:var(--mono);font-size:9px;color:var(--dim);margin-bottom:4px;letter-spacing:1px">ENERGY + MACRO</div>
<div style="font-family:var(--mono);font-size:9px;color:var(--dim);margin-bottom:4px;letter-spacing:1px">ENERGY + METALS + MACRO</div>
<div class="metrics-row">${metrics.map(m=>{
const sparkSvg = m.spark ? mkSparkSvg(m.spark, m.sparkUp) : '';
return `<div class="mc"><div class="ml">${m.l}</div><span class="mv">${m.v}${sparkSvg}</span><span class="ms">${m.s}</span><div class="mbar"><span style="width:${m.p}%"></span></div></div>`;
Expand Down
2 changes: 1 addition & 1 deletion lib/alerts/discord.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ export class DiscordAlerter {
const highs = signals.filter(s => s.severity === 'high');
const nukeSignal = signals.find(s => s.key === 'nuke_anomaly');
const osintNew = signals.filter(s => s.key?.startsWith('tg_urgent'));
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', '10y2y'].includes(s.key));
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', 'natgas', 'gold', 'silver', '10y2y'].includes(s.key));
const conflictSignals = signals.filter(s => ['conflict_events', 'conflict_fatalities', 'thermal_total'].includes(s.key));

if (nukeSignal) {
Expand Down
4 changes: 2 additions & 2 deletions lib/alerts/telegram.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export class TelegramAlerter {
const highs = signals.filter(s => s.severity === 'high');
const nukeSignal = signals.find(s => s.key === 'nuke_anomaly');
const osintNew = signals.filter(s => s.key?.startsWith('tg_urgent'));
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', '10y2y'].includes(s.key));
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', 'natgas', 'gold', 'silver', '10y2y'].includes(s.key));
const conflictSignals = signals.filter(s => ['conflict_events', 'conflict_fatalities', 'thermal_total'].includes(s.key));

// FLASH: nuclear anomaly, or ≥3 critical signals across domains
Expand Down Expand Up @@ -667,7 +667,7 @@ Respond with ONLY valid JSON:
const sections = [];

// Categorize signals
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', 'natgas', '10y2y', 'fed_funds', '10y_yield', 'usd_index'].includes(s.key));
const marketSignals = signals.filter(s => ['vix', 'hy_spread', 'wti', 'brent', 'natgas', 'gold', 'silver', '10y2y', 'fed_funds', '10y_yield', 'usd_index'].includes(s.key));
const osintSignals = signals.filter(s => s.key === 'tg_urgent' || s.item?.channel);
const conflictSignals = signals.filter(s => ['conflict_events', 'conflict_fatalities', 'thermal_total'].includes(s.key));
const otherSignals = signals.filter(s => !marketSignals.includes(s) && !osintSignals.includes(s) && !conflictSignals.includes(s));
Expand Down
4 changes: 4 additions & 0 deletions lib/delta/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const DEFAULT_NUMERIC_THRESHOLDS = {
wti: 3,
brent: 3,
natgas: 5,
gold: 2,
silver: 3,
unemployment: 2,
fed_funds: 1,
'10y_yield': 3,
Expand Down Expand Up @@ -41,6 +43,8 @@ const NUMERIC_METRICS = [
{ key: 'wti', extract: d => d.energy?.wti, label: 'WTI Crude' },
{ key: 'brent', extract: d => d.energy?.brent, label: 'Brent Crude' },
{ key: 'natgas', extract: d => d.energy?.natgas, label: 'Natural Gas' },
{ key: 'gold', extract: d => d.metals?.gold, label: 'Gold' },
{ key: 'silver', extract: d => d.metals?.silver, label: 'Silver' },
{ key: 'unemployment', extract: d => d.bls?.find(b => b.id === 'LNS14000000' || b.id === 'UNRATE')?.value, label: 'Unemployment' },
{ key: 'fed_funds', extract: d => d.fred?.find(f => f.id === 'DFF')?.value, label: 'Fed Funds Rate' },
{ key: '10y_yield', extract: d => d.fred?.find(f => f.id === 'DGS10')?.value, label: '10Y Yield' },
Expand Down
9 changes: 9 additions & 0 deletions lib/llm/ideas.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ function compactSweepForLLM(data, delta, previousIdeas) {
sections.push(`ENERGY: WTI=$${data.energy.wti}, Brent=$${data.energy.brent}, NatGas=$${data.energy.natgas}, CrudeStocks=${data.energy.crudeStocks}bbl`);
}

// Metals
if (data.metals?.gold != null || data.metals?.silver != null) {
const gold = data.metals?.gold != null ? `$${data.metals.gold}` : 'n/a';
const silver = data.metals?.silver != null ? `$${data.metals.silver}` : 'n/a';
const goldChg = data.metals?.goldChangePct != null ? ` (${data.metals.goldChangePct >= 0 ? '+' : ''}${data.metals.goldChangePct}%)` : '';
const silverChg = data.metals?.silverChangePct != null ? ` (${data.metals.silverChangePct >= 0 ? '+' : ''}${data.metals.silverChangePct}%)` : '';
sections.push(`METALS: Gold=${gold}${goldChg}, Silver=${silver}${silverChg}`);
}

// BLS
if (data.bls?.length) {
sections.push(`LABOR: ${data.bls.map(b => `${b.id}=${b.value}`).join(', ')}`);
Expand Down
12 changes: 8 additions & 4 deletions server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ if (telegramAlerter.isConfigured) {

const tg = currentData.tg || {};
const energy = currentData.energy || {};
const metals = currentData.metals || {};
const delta = memory.getLastDelta();
const ideas = (currentData.ideas || []).slice(0, 3);

Expand All @@ -106,9 +107,10 @@ if (telegramAlerter.isConfigured) {
// Key metrics
const vix = currentData.fred?.find(f => f.id === 'VIXCLS');
const hy = currentData.fred?.find(f => f.id === 'BAMLH0A0HYM2');
if (vix || energy.wti) {
if (vix || energy.wti || metals.gold || metals.silver) {
sections.push(`📊 VIX: ${vix?.value || '--'} | WTI: $${energy.wti || '--'} | Brent: $${energy.brent || '--'}`);
if (hy) sections.push(` HY Spread: ${hy.value} | NatGas: $${energy.natgas || '--'}`);
sections.push(` Gold: $${metals.gold || '--'} | Silver: $${metals.silver || '--'}${hy ? ` | HY Spread: ${hy.value}` : ''}`);
sections.push(` NatGas: $${energy.natgas || '--'}`);
sections.push('');
}

Expand Down Expand Up @@ -182,6 +184,7 @@ if (discordAlerter.isConfigured) {

const tg = currentData.tg || {};
const energy = currentData.energy || {};
const metals = currentData.metals || {};
const delta = memory.getLastDelta();
const ideas = (currentData.ideas || []).slice(0, 3);

Expand All @@ -194,9 +197,10 @@ if (discordAlerter.isConfigured) {

const vix = currentData.fred?.find(f => f.id === 'VIXCLS');
const hy = currentData.fred?.find(f => f.id === 'BAMLH0A0HYM2');
if (vix || energy.wti) {
if (vix || energy.wti || metals.gold || metals.silver) {
sections.push(`📊 VIX: ${vix?.value || '--'} | WTI: $${energy.wti || '--'} | Brent: $${energy.brent || '--'}`);
if (hy) sections.push(` HY Spread: ${hy.value} | NatGas: $${energy.natgas || '--'}`);
sections.push(` Gold: $${metals.gold || '--'} | Silver: $${metals.silver || '--'}${hy ? ` | HY Spread: ${hy.value}` : ''}`);
sections.push(` NatGas: $${energy.natgas || '--'}`);
sections.push('');
}

Expand Down
Loading