← back to Bertha
chore(alshi-dash): update 1 file (.js) [+249/-6]
d107bf66e1da980624ba64f6c22dc22f60cc4c76 · 2026-02-27 15:04:00 +0000 · DW Commit Agent
Files touched
Diff
commit d107bf66e1da980624ba64f6c22dc22f60cc4c76
Author: DW Commit Agent <commit-agent@dw-agents.com>
Date: Fri Feb 27 15:04:00 2026 +0000
chore(alshi-dash): update 1 file (.js) [+249/-6]
---
kalshi-dash/server.js | 255 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 249 insertions(+), 6 deletions(-)
diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index b11b5fe..953d056 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -1603,6 +1603,61 @@ const routes = {
}
},
+ // ── Live Markets (all active with snapshots) ──
+ 'GET /api/markets': async (req, res) => {
+ try {
+ const { rows } = await kenQ(`
+ SELECT DISTINCT ON (ticker) ticker, event_ticker, title, subtitle, category,
+ yes_bid, yes_ask, no_bid, no_ask, last_price, volume, volume_24h, open_interest, spread,
+ captured_at
+ FROM ken_market_snapshots
+ WHERE captured_at > NOW() - INTERVAL '1 hour'
+ ORDER BY ticker, captured_at DESC
+ `);
+ json(res, { markets: rows, count: rows.length, cached: cachedActiveMarkets.length });
+ } catch (err) {
+ json(res, { error: err.message }, 500);
+ }
+ },
+
+ // ── Energy/LNG Arbitrage Opportunities ──
+ 'GET /api/energy-arb': async (req, res) => {
+ try {
+ const arbs = await energyArbitrageScan(cachedActiveMarkets);
+ // Also get recent energy-related signals
+ const { rows: energySignals } = await kenQ(`
+ SELECT ticker, title, signal_type, side, confidence, entry_price, edge_bps, reasoning, sources, created_at
+ FROM ken_predictions
+ WHERE signal_type IN ('energy_arb', 'polymarket_arb')
+ OR reasoning ILIKE '%energy%' OR reasoning ILIKE '%oil%' OR reasoning ILIKE '%gas%' OR reasoning ILIKE '%lng%'
+ ORDER BY created_at DESC LIMIT 50
+ `);
+ json(res, {
+ arbitrage_opportunities: arbs,
+ energy_signals: energySignals,
+ scan_time: new Date().toISOString(),
+ markets_scanned: cachedActiveMarkets.length,
+ });
+ } catch (err) {
+ json(res, { error: err.message }, 500);
+ }
+ },
+
+ // ── All Active Signals (for trading) ──
+ 'GET /api/signals': async (req, res) => {
+ try {
+ const { rows } = await kenQ(`
+ SELECT market_id as ticker, direction, expected_edge, confidence, reasoning, sources, risk_approved, created_at
+ FROM ken_strategy_signals
+ WHERE created_at > NOW() - INTERVAL '2 hours'
+ ORDER BY created_at DESC LIMIT 200
+ `);
+ json(res, { signals: rows, count: rows.length });
+ } catch (err) {
+ json(res, { error: err.message }, 500);
+ }
+ },
+
// ════════════════════════════════════════
// MEMORY / SYSTEM STATUS
// ════════════════════════════════════════
@@ -4250,6 +4305,11 @@ const server = http.createServer(async (req, res) => {
'/api/portfauxlio',
'/api/portfauxlio/charts',
'/api/portfauxlio/swot',
+ '/api/markets',
+ '/api/signals',
+ '/api/energy-arb',
+ '/api/predictions',
+ '/api/portfolios',
];
const isPublic = publicPaths.includes(urlPath);
@@ -6466,6 +6526,144 @@ async function polymarketCrossRef(kalshiMarkets) {
}
}
+// ══════════════════════════════════════════════
+// LNG / ENERGY CROSS-MARKET ARBITRAGE
+// Compares energy-related predictions across Kalshi, Polymarket, and Manifold
+// ══════════════════════════════════════════════
+const ENERGY_SEARCH_TERMS = [
+ 'oil price', 'crude oil', 'natural gas', 'LNG', 'OPEC',
+ 'energy price', 'gas price', 'heating oil', 'petroleum',
+ 'electricity price', 'EIA', 'oil production', 'pipeline',
+ 'renewable energy', 'solar', 'wind energy', 'nuclear',
+ 'carbon price', 'emissions', 'electric vehicle', 'EV',
+ 'barrel', 'WTI', 'Brent', 'refinery',
+];
+
+async function energyArbitrageScan(kalshiMarkets) {
+ const arbs = [];
+ try {
+ // 1. Get energy markets from Manifold
+ const manifoldEnergy = await scrapeManifold(ENERGY_SEARCH_TERMS.slice(0, 8));
+ console.log(`[Ken/Energy] Manifold: ${manifoldEnergy.length} energy-related markets`);
+
+ // 2. Get energy events from Polymarket
+ let polyEnergy = [];
+ try {
+ const polyAll = await scrapePolymarketEvents(200);
+ polyEnergy = polyAll.filter(p => {
+ const t = (p.event_title + ' ' + p.question).toLowerCase();
+ return /oil|gas|lng|opec|energy|crude|barrel|petroleum|electric|solar|wind|nuclear|carbon|emission|ev market|renewable/i.test(t);
+ });
+ console.log(`[Ken/Energy] Polymarket: ${polyEnergy.length} energy-related markets`);
+ } catch {}
+
+ // 3. Filter Kalshi markets for energy/commodities
+ const kalshiEnergy = kalshiMarkets.filter(m => {
+ const t = ((m.title || '') + ' ' + (m.subtitle || '') + ' ' + (m.category || '')).toLowerCase();
+ return /oil|gas|lng|opec|energy|crude|barrel|petroleum|electric|solar|wind|nuclear|carbon|emission|ev |renewable|consumption|climate/i.test(t);
+ });
+ console.log(`[Ken/Energy] Kalshi: ${kalshiEnergy.length} energy-related markets`);
+
+ // 4. Cross-reference Manifold vs Kalshi
+ for (const mf of manifoldEnergy) {
+ for (const km of kalshiEnergy) {
+ const score = fuzzyMatchScore(mf.title, (km.title + ' ' + (km.subtitle || '')).toLowerCase());
+ if (score >= 0.25) {
+ const priceDiff = mf.probability - km.yes_ask;
+ if (Math.abs(priceDiff) >= 3) {
+ arbs.push({
+ type: 'manifold_kalshi',
+ kalshi_ticker: km.ticker,
+ event_ticker: km.event_ticker,
+ kalshi_title: km.title,
+ kalshi_price: km.yes_ask,
+ other_title: mf.title,
+ other_price: mf.probability,
+ other_source: 'Manifold',
+ other_url: mf.url,
+ other_volume: mf.volume,
+ price_diff: priceDiff,
+ match_score: Math.round(score * 100),
+ category: 'energy',
+ });
+ }
+ }
+ }
+ }
+
+ // 5. Cross-reference Polymarket vs Kalshi (energy-specific)
+ for (const pm of polyEnergy) {
+ for (const km of kalshiEnergy) {
+ const score = fuzzyMatchScore(pm.event_title + ' ' + pm.question, (km.title + ' ' + (km.subtitle || '')).toLowerCase());
+ if (score >= 0.25) {
+ const priceDiff = pm.price - km.yes_ask;
+ if (Math.abs(priceDiff) >= 3) {
+ arbs.push({
+ type: 'poly_kalshi_energy',
+ kalshi_ticker: km.ticker,
+ event_ticker: km.event_ticker,
+ kalshi_title: km.title,
+ kalshi_price: km.yes_ask,
+ other_title: pm.question,
+ other_price: pm.price,
+ other_source: 'Polymarket',
+ other_url: `https://polymarket.com/event/${pm.slug}`,
+ other_volume: pm.volume,
+ price_diff: priceDiff,
+ match_score: Math.round(score * 100),
+ category: 'energy',
+ });
+ }
+ }
+ }
+ }
+
+ // 6. Cross-reference Manifold vs Polymarket (energy only, no Kalshi needed)
+ for (const mf of manifoldEnergy) {
+ for (const pm of polyEnergy) {
+ const score = fuzzyMatchScore(mf.title, pm.event_title + ' ' + pm.question);
+ if (score >= 0.3) {
+ const priceDiff = mf.probability - pm.price;
+ if (Math.abs(priceDiff) >= 5) {
+ arbs.push({
+ type: 'manifold_poly_energy',
+ kalshi_ticker: null,
+ event_ticker: null,
+ kalshi_title: `${mf.title} (cross-platform)`,
+ kalshi_price: mf.probability,
+ other_title: pm.question,
+ other_price: pm.price,
+ other_source: 'Manifold↔Polymarket',
+ other_url: mf.url,
+ other_volume: Math.max(mf.volume, pm.volume),
+ price_diff: priceDiff,
+ match_score: Math.round(score * 100),
+ category: 'energy',
+ });
+ }
+ }
+ }
+ }
+
+ // Dedupe by best price diff per Kalshi ticker
+ const seen = new Map();
+ for (const arb of arbs) {
+ const key = arb.kalshi_ticker || arb.other_title;
+ if (!seen.has(key) || Math.abs(arb.price_diff) > Math.abs(seen.get(key).price_diff)) {
+ seen.set(key, arb);
+ }
+ }
+ const result = [...seen.values()].sort((a, b) => Math.abs(b.price_diff) - Math.abs(a.price_diff));
+ if (result.length > 0) {
+ console.log(`[Ken/Energy] Found ${result.length} energy arbitrage opportunities (top: ${result[0].kalshi_title} ${result[0].price_diff > 0 ? '+' : ''}${result[0].price_diff}¢)`);
+ }
+ return result;
+ } catch (e) {
+ console.log(`[Ken/Energy] Arbitrage scan error: ${e.message}`);
+ return [];
+ }
+}
+
// ══════════════════════════════════════════════
// AUTO-TRADER ($20 budget, risk-managed)
// ══════════════════════════════════════════════
@@ -6822,7 +7020,7 @@ async function autonomousScan() {
// Sort by 24h volume to find what's hot
const activeMarkets = allMarkets
- .filter(m => m.volume_24h > 50 && m.yes_bid > 0 && m.yes_ask > 0 && m.yes_ask < 100)
+ .filter(m => m.yes_bid > 0 && m.yes_ask > 0 && m.yes_ask < 100 && m.last_price > 0)
.sort((a, b) => b.volume_24h - a.volume_24h);
// Cache for 5-minute signal pipeline
@@ -6880,7 +7078,7 @@ async function autonomousScan() {
}
} catch (e) { console.log('[Ken] Price movement alert error:', e.message); }
- for (const m of activeMarkets.slice(0, 75)) {
+ for (const m of activeMarkets.slice(0, 200)) {
const spread = m.yes_ask - m.yes_bid;
const noPrice = 100 - m.yes_ask;
const momentum = momentumMap[m.ticker] || { delta_2h: 0, delta_6h: 0 };
@@ -7003,8 +7201,8 @@ async function autonomousScan() {
logMemory('scan-after-signals');
- // 5. Store market snapshots in DB (batch of 50 to limit memory)
- for (const m of activeMarkets.slice(0, 50)) {
+ // 5. Store market snapshots in DB (batch of 150 to capture more markets)
+ for (const m of activeMarkets.slice(0, 150)) {
try {
await kenQ(`
INSERT INTO ken_market_snapshots (ticker, event_ticker, title, subtitle, category, yes_bid, yes_ask, no_bid, no_ask, last_price, volume, volume_24h, open_interest, spread)
@@ -7053,6 +7251,14 @@ async function autonomousScan() {
console.log('[Ken] Polymarket cross-ref failed:', e.message);
}
+ // 7b. Energy/LNG cross-market arbitrage scan
+ let energyArbs = [];
+ try {
+ energyArbs = await energyArbitrageScan(activeMarkets);
+ } catch (e) {
+ console.log('[Ken] Energy arb scan failed:', e.message);
+ }
+
// 8. Combine ALL signals with confidence scoring
const buySignals = predictions.filter(p => p.edge_bps > 200);
const shortSignals = predictions.filter(p => p.edge_bps < -200);
@@ -7120,6 +7326,21 @@ async function autonomousScan() {
sources: ['polymarket_crossref'],
});
}
+ // Energy/LNG cross-market arb signals
+ for (const arb of energyArbs) {
+ if (arb.kalshi_ticker) {
+ allSignals.push({
+ market: arb.kalshi_title, ticker: arb.kalshi_ticker, event_ticker: arb.event_ticker,
+ side: arb.price_diff > 0 ? 'YES' : 'NO',
+ confidence: Math.min(92, 60 + Math.abs(arb.price_diff) * 2),
+ entry_price: arb.kalshi_price,
+ edge_bps: arb.price_diff * 100,
+ signal_type: 'energy_arb',
+ reason: `ENERGY ARB: Kalshi ${arb.kalshi_price}¢ vs ${arb.other_source} ${arb.other_price}¢ (${arb.price_diff > 0 ? '+' : ''}${arb.price_diff}¢ gap) — BUY ${arb.price_diff > 0 ? 'Kalshi' : arb.other_source}, SELL ${arb.price_diff > 0 ? arb.other_source : 'Kalshi'}`,
+ sources: ['energy_crossmarket_arb', arb.other_source.toLowerCase()],
+ });
+ }
+ }
// 10. Store predictions in DB
for (const sig of allSignals) {
@@ -7142,6 +7363,28 @@ async function autonomousScan() {
console.log(`[Ken] Auto-trader error: ${e.message}`);
}
+ // 10c. PORTFOLIO TRADER: Feed scan signals into paper portfolios
+ let portfolioTradesPlaced = 0;
+ for (const sig of allSignals.filter(s => s.confidence >= 40 && s.ticker)) {
+ try {
+ await autoPortfolioTrade({
+ marketId: sig.ticker,
+ market_title: sig.market || sig.ticker,
+ direction: sig.side === 'YES' ? 'BUY_YES' : 'BUY_NO',
+ expectedEdge: (sig.edge_bps || 0) / 10000,
+ confidence: (sig.confidence || 50) / 100,
+ reasoning: sig.reason || sig.reasoning || sig.signal_type,
+ signal_type: sig.signal_type,
+ aiEnhanced: (sig.sources || []).includes('gemini'),
+ mcSimulation: { consistent: true, stdDev: 0.05 },
+ num_articles: (sig.sources || []).length,
+ agreement: (sig.confidence || 50) / 100,
+ });
+ portfolioTradesPlaced++;
+ } catch {}
+ }
+ if (portfolioTradesPlaced > 0) console.log(`[Ken] Portfolio trades: ${portfolioTradesPlaced} signals fed to paper portfolios`);
+
const scanDuration = Date.now() - scanStart;
// 11. Log performance
@@ -7750,12 +7993,12 @@ async function autoPortfolioTrade(signal) {
if (!strategy(sigData)) continue;
- // Skip dupes: don't trade same market twice in same portfolio today
+ // Skip dupes: max 3 trades per market per portfolio per day
const { rows: dupes } = await kenQ(`
SELECT id FROM ken_portfolio_trades
WHERE portfolio_id = $1 AND market_id = $2 AND created_at::date = CURRENT_DATE
`, [pf.id, signal.marketId || signal.market_id]);
- if (dupes.length > 0) continue;
+ if (dupes.length >= 3) continue;
// Per-strategy position sizing
const absEdge = Math.abs(parseFloat(sigData.edge));
← 8e9ef18 chore(alshi-dash): update 1 file (.js) [+16/-13]
·
back to Bertha
·
chore(alshi-dash): update 1 file (.js) [+75/-39] fa964a3 →