chore(predictions): extract shared tags and remove unused open_interest (#1512)

- Move GEOPOLITICAL_TAGS, TECH_TAGS, FINANCE_TAGS, and EXCLUDE_KEYWORDS
  to shared/prediction-tags.json so seed, RPC handler, and client all
  reference a single source of truth
- Remove open_interest proto field (always 0 for Polymarket, never
  displayed in UI) and corresponding openInterest assignments

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
This commit is contained in:
RaulC
2026-03-13 04:59:12 +01:00
committed by GitHub
parent 50f8a0f66f
commit bfcf7d88ec
8 changed files with 41 additions and 57 deletions

View File

@@ -36,6 +36,5 @@ message PredictionMarket {
string category = 7;
// Source platform (Polymarket, Kalshi, etc.).
MarketSource source = 8;
// Open interest (number of outstanding contracts). Zero if unavailable.
double open_interest = 9;
reserved 9;
}

View File

@@ -1,11 +1,6 @@
export const EXCLUDE_KEYWORDS = [
'nba', 'nfl', 'mlb', 'nhl', 'fifa', 'world cup', 'super bowl', 'championship',
'playoffs', 'oscar', 'grammy', 'emmy', 'box office', 'movie', 'album', 'song',
'streamer', 'influencer', 'celebrity', 'kardashian',
'bachelor', 'reality tv', 'mvp', 'touchdown', 'home run', 'goal scorer',
'academy award', 'bafta', 'golden globe', 'cannes', 'sundance',
'documentary', 'feature film', 'tv series', 'season finale',
];
import predictionTags from '../shared/prediction-tags.json' with { type: 'json' };
export const EXCLUDE_KEYWORDS = predictionTags.excludeKeywords;
export const MEME_PATTERNS = [
/\b(lebron|kanye|oprah|swift|rogan|dwayne|kardashian|cardi\s*b)\b/i,

View File

@@ -5,6 +5,7 @@ import {
isExcluded, isMemeCandidate, tagRegions, parseYesPrice,
shouldInclude, scoreMarket, filterAndScore, isExpired,
} from './_prediction-scoring.mjs';
import predictionTags from '../shared/prediction-tags.json' with { type: 'json' };
loadEnvFile(import.meta.url);
@@ -17,22 +18,9 @@ const KALSHI_ENABLED = process.env.KALSHI_API_KEY !== undefined && process.env.K
const FETCH_TIMEOUT = 10_000;
const TAG_DELAY_MS = 300;
const GEOPOLITICAL_TAGS = [
'politics', 'geopolitics', 'elections', 'world',
'ukraine', 'china', 'middle-east', 'europe',
'economy', 'fed', 'inflation',
];
const TECH_TAGS = [
'ai', 'tech', 'crypto', 'science',
'elon-musk', 'business', 'economy',
];
const FINANCE_TAGS = [
'economy', 'fed', 'inflation', 'interest-rates', 'recession',
'trade', 'tariffs', 'debt-ceiling',
'crypto', 'business', 'markets',
];
const GEOPOLITICAL_TAGS = predictionTags.geopolitical;
const TECH_TAGS = predictionTags.tech;
const FINANCE_TAGS = predictionTags.finance;
async function fetchEventsByTag(tag, limit = 20) {
const params = new URLSearchParams({

View File

@@ -18,6 +18,7 @@ import {
import { CHROME_UA, clampInt } from '../../../_shared/constants';
import { cachedFetchJson, getCachedJson } from '../../../_shared/redis';
import predictionTags from '../../../../shared/prediction-tags.json';
const REDIS_CACHE_KEY = 'prediction:markets:v1';
const REDIS_CACHE_TTL = 600; // 10 min
@@ -96,18 +97,9 @@ interface BootstrapData {
finance?: BootstrapMarket[];
}
const EXCLUDE_KEYWORDS = [
'nba', 'nfl', 'mlb', 'nhl', 'fifa', 'world cup', 'super bowl', 'championship',
'playoffs', 'oscar', 'grammy', 'emmy', 'box office', 'movie', 'album', 'song',
'streamer', 'influencer', 'celebrity', 'kardashian',
'bachelor', 'reality tv', 'mvp', 'touchdown', 'home run', 'goal scorer',
'academy award', 'bafta', 'golden globe', 'cannes', 'sundance',
'documentary', 'feature film', 'tv series', 'season finale',
];
function isExcluded(title: string): boolean {
const lower = title.toLowerCase();
return EXCLUDE_KEYWORDS.some(kw => lower.includes(kw));
return predictionTags.excludeKeywords.some(kw => lower.includes(kw));
}
const KALSHI_VOLUME_THRESHOLD = 5000;
@@ -146,7 +138,7 @@ function mapEvent(event: GammaEvent, category: string): PredictionMarket {
closesAt: Number.isFinite(closesAtMs) ? closesAtMs : 0,
category: category || '',
source: MarketSource.MARKET_SOURCE_POLYMARKET,
openInterest: 0,
};
}
@@ -162,7 +154,7 @@ function mapMarket(market: GammaMarket): PredictionMarket {
closesAt: Number.isFinite(closesAtMs) ? closesAtMs : 0,
category: '',
source: MarketSource.MARKET_SOURCE_POLYMARKET,
openInterest: 0,
};
}
@@ -179,7 +171,6 @@ function mapKalshiMarket(market: KalshiMarket, category: string, eventTitle?: st
closesAt: Number.isFinite(closesAtMs) ? closesAtMs : 0,
category: category || '',
source: MarketSource.MARKET_SOURCE_KALSHI,
openInterest: parseFloat(market.open_interest_fp || '0'),
};
}
@@ -259,7 +250,7 @@ export const listPredictionMarkets: PredictionServiceHandler['listPredictionMark
closesAt: m.endDate ? Date.parse(m.endDate) : 0,
category: category || '',
source: m.source === 'kalshi' ? MarketSource.MARKET_SOURCE_KALSHI : MarketSource.MARKET_SOURCE_POLYMARKET,
openInterest: 0,
}));
return { markets, pagination: undefined };
}

View File

@@ -0,0 +1,24 @@
{
"geopolitical": [
"politics", "geopolitics", "elections", "world",
"ukraine", "china", "middle-east", "europe",
"economy", "fed", "inflation"
],
"tech": [
"ai", "tech", "crypto", "science",
"elon-musk", "business", "economy"
],
"finance": [
"economy", "fed", "inflation", "interest-rates", "recession",
"trade", "tariffs", "debt-ceiling",
"crypto", "business", "markets"
],
"excludeKeywords": [
"nba", "nfl", "mlb", "nhl", "fifa", "world cup", "super bowl", "championship",
"playoffs", "oscar", "grammy", "emmy", "box office", "movie", "album", "song",
"streamer", "influencer", "celebrity", "kardashian",
"bachelor", "reality tv", "mvp", "touchdown", "home run", "goal scorer",
"academy award", "bafta", "golden globe", "cannes", "sundance",
"documentary", "feature film", "tv series", "season finale"
]
}

View File

@@ -29,7 +29,6 @@ export interface PredictionMarket {
closesAt: number;
category: string;
source: MarketSource;
openInterest: number;
}
export interface PaginationResponse {

View File

@@ -29,7 +29,6 @@ export interface PredictionMarket {
closesAt: number;
category: string;
source: MarketSource;
openInterest: number;
}
export interface PaginationResponse {

View File

@@ -24,22 +24,11 @@ const breaker = createCircuitBreaker<PredictionMarket[]>({ name: 'Polymarket', c
const client = new PredictionServiceClient(getRpcBaseUrl(), { fetch: (...args) => globalThis.fetch(...args) });
const GEOPOLITICAL_TAGS = [
'politics', 'geopolitics', 'elections', 'world',
'ukraine', 'china', 'middle-east', 'europe',
'economy', 'fed', 'inflation',
];
import predictionTags from '../../../shared/prediction-tags.json';
const TECH_TAGS = [
'ai', 'tech', 'crypto', 'science',
'elon-musk', 'business', 'economy',
];
const FINANCE_TAGS = [
'economy', 'fed', 'inflation', 'interest-rates', 'recession',
'trade', 'tariffs', 'debt-ceiling',
'crypto', 'business', 'markets',
];
const GEOPOLITICAL_TAGS = predictionTags.geopolitical;
const TECH_TAGS = predictionTags.tech;
const FINANCE_TAGS = predictionTags.finance;
interface BootstrapPredictionData {
geopolitical: PredictionMarket[];