areebithink's picture
Improve sentiment accuracy, add US macro signal, faster refresh
9231d8b
Raw
History Blame Contribute Delete
11.7 kB
"""
Central configuration: RSS feeds, subreddits, narrative keywords, API endpoints.
All sources are free — no paid API keys required.
"""
# ---------------------------------------------------------------------------
# RSS Feeds — no key required
# ---------------------------------------------------------------------------
RSS_FEEDS = {
# Tier-1 outlets
"CoinDesk": "https://www.coindesk.com/arc/outboundfeeds/rss/",
"CoinTelegraph": "https://cointelegraph.com/rss",
"Decrypt": "https://decrypt.co/feed",
"Bitcoin Magazine":"https://bitcoinmagazine.com/feed",
"The Block": "https://www.theblock.co/rss.xml",
"Blockworks": "https://blockworks.co/feed",
"CryptoSlate": "https://cryptoslate.com/feed/",
"NewsBTC": "https://www.newsbtc.com/feed/",
"AMBCrypto": "https://ambcrypto.com/feed/",
"CryptoNews": "https://cryptonews.com/news/feed/",
# Additional free outlets
"BeInCrypto": "https://beincrypto.com/feed/",
"CryptoPotato": "https://cryptopotato.com/feed/",
"Bitcoinist": "https://bitcoinist.com/feed/",
"U.Today": "https://u.today/rss",
"CoinGape": "https://coingape.com/feed/",
"DailyHodl": "https://dailyhodl.com/feed/",
"CoinJournal": "https://coinjournal.net/news/feed/",
"Crypto Briefing": "https://cryptobriefing.com/feed/",
"Coinpedia": "https://coinpedia.org/feed/",
"ZyCrypto": "https://zycrypto.com/feed/",
# Google News aggregators (free, no key — each pulls from hundreds of outlets)
"GoogleNews: Crypto": "https://news.google.com/rss/search?q=cryptocurrency+when:1d&hl=en-US&gl=US&ceid=US:en",
"GoogleNews: Bitcoin": "https://news.google.com/rss/search?q=bitcoin+when:1d&hl=en-US&gl=US&ceid=US:en",
"GoogleNews: Ethereum": "https://news.google.com/rss/search?q=ethereum+OR+%22ETH%22+crypto+when:1d&hl=en-US&gl=US&ceid=US:en",
"GoogleNews: Regulation": "https://news.google.com/rss/search?q=crypto+regulation+OR+SEC+when:1d&hl=en-US&gl=US&ceid=US:en",
}
# ---------------------------------------------------------------------------
# US Macro feeds — these move the whole risk-asset market (incl. crypto).
# Tracked as a SEPARATE signal (not mixed into crypto-native sentiment) but
# shown as the "macro backdrop" because it spills over into crypto.
# Sources here are tagged is_macro=True by the collector.
# ---------------------------------------------------------------------------
MACRO_FEEDS = {
"Macro: Fed": "https://news.google.com/rss/search?q=federal+reserve+interest+rates+when:1d&hl=en-US&gl=US&ceid=US:en",
"Macro: Inflation": "https://news.google.com/rss/search?q=US+inflation+CPI+when:1d&hl=en-US&gl=US&ceid=US:en",
"Macro: Economy": "https://news.google.com/rss/search?q=US+economy+recession+OR+jobs+report+when:1d&hl=en-US&gl=US&ceid=US:en",
"Macro: Markets": "https://news.google.com/rss/search?q=stock+market+S%26P+500+nasdaq+when:1d&hl=en-US&gl=US&ceid=US:en",
}
# ---------------------------------------------------------------------------
# Reddit — free, requires PRAW app credentials (see .env)
# ---------------------------------------------------------------------------
SUBREDDITS = [
"CryptoCurrency",
"Bitcoin",
"ethereum",
"CryptoMarkets",
"altcoin",
"defi",
"solana",
"binance",
"Ripple",
"dogecoin",
]
REDDIT_POST_LIMIT = 100 # posts per subreddit per fetch
REDDIT_COMMENT_LIMIT = 10 # top comments to fetch per post
# ---------------------------------------------------------------------------
# CoinGecko — free public API, no key needed
# ---------------------------------------------------------------------------
COINGECKO_BASE = "https://api.coingecko.com/api/v3"
COINGECKO_TRENDING_URL = f"{COINGECKO_BASE}/search/trending"
COINGECKO_GLOBAL_URL = f"{COINGECKO_BASE}/global"
COINGECKO_COINS_URL = f"{COINGECKO_BASE}/coins/markets"
TOP_COINS_TO_TRACK = [
"bitcoin", "ethereum", "solana", "binancecoin", "ripple",
"cardano", "dogecoin", "avalanche-2", "chainlink", "polkadot",
"sui", "aptos", "arbitrum", "optimism", "injective-protocol",
]
# ---------------------------------------------------------------------------
# Fear & Greed Index — free, no key
# ---------------------------------------------------------------------------
FEAR_GREED_URL = "https://api.alternative.me/fng/?limit=7"
# ---------------------------------------------------------------------------
# cryptocurrency.cv — free, no key
# ---------------------------------------------------------------------------
CRYPTOCV_NEWS_URL = "https://cryptocurrency.cv/api/v1/news"
# ---------------------------------------------------------------------------
# Narrative Definitions — keyword clusters mapped to narrative names
# ---------------------------------------------------------------------------
NARRATIVES: dict[str, list[str]] = {
"ETF Approval": [
"etf", "exchange traded fund", "spot etf", "bitcoin etf", "ethereum etf",
"sec approval", "blackrock etf", "fidelity etf", "etf launch", "etf inflows",
],
"AI & Crypto": [
"artificial intelligence", "ai token", "ai agent", "machine learning",
"gpt", "large language model", "llm", "ai narrative", "fetch.ai",
"bittensor", "render network", "ai crypto",
],
"RWA (Real World Assets)": [
"real world asset", "rwa", "tokenized asset", "tokenized bonds",
"tokenized real estate", "on-chain asset", "asset tokenization",
"blackrock tokenize", "ondo finance", "centrifuge",
],
"Memecoin": [
"memecoin", "meme coin", "meme token", "dogecoin", "shiba inu",
"pepe", "bonk", "wif", "floki", "meme rally", "casino narrative",
],
"DeFi": [
"defi", "decentralized finance", "yield farming", "liquidity pool",
"dex", "uniswap", "aave", "compound", "tvl", "total value locked",
"lending protocol", "automated market maker",
],
"Layer 2 Scaling": [
"layer 2", "l2", "rollup", "optimistic rollup", "zk rollup",
"arbitrum", "optimism", "zksync", "polygon", "base", "scaling solution",
],
"Institutional Adoption": [
"institutional", "hedge fund", "wall street", "treasury", "corporate bitcoin",
"microstrategy", "grayscale", "fidelity", "morgan stanley", "goldman sachs",
"blackrock bitcoin", "institutional investor",
],
"Regulation": [
"regulation", "sec", "cftc", "enforcement", "lawsuit", "crackdown",
"compliance", "legal", "ban", "legislation", "congress", "senate",
"regulatory", "policy", "finra",
],
"Exchange Listing": [
"listed on", "exchange listing", "coinbase listing", "binance listing",
"kraken listing", "new listing", "ipo", "token launch",
],
"Security Breach / Hack": [
"hack", "exploit", "breach", "stolen funds", "rug pull", "exit scam",
"smart contract vulnerability", "attack", "drained", "flash loan attack",
],
"Ecosystem Upgrade": [
"upgrade", "hard fork", "soft fork", "protocol upgrade", "migration",
"eip", "bip", "taproot", "merge", "shapella", "dencun", "pectra",
],
"Bitcoin Halving": [
"halving", "halvening", "bitcoin supply", "block reward", "miner reward",
"post halving", "halving cycle",
],
"Staking & Yield": [
"staking", "stake", "validator", "proof of stake", "liquid staking",
"lido", "rocketpool", "staking yield", "restaking", "eigenlayer",
],
"Cross-chain / Interoperability": [
"cross-chain", "bridge", "interoperability", "multichain", "cosmos",
"polkadot", "ibc protocol", "wormhole", "layerzero", "chainlink ccip",
],
"NFT": [
"nft", "non fungible token", "opensea", "nft market", "ordinals",
"nft collection", "blue chip nft", "nft gaming",
],
"GameFi / Play-to-Earn": [
"gamefi", "play to earn", "p2e", "blockchain game", "axie infinity",
"gaming token", "gaming narrative", "metaverse",
],
}
# ---------------------------------------------------------------------------
# Ensemble sentiment: how much each model contributes to the blended score
# ---------------------------------------------------------------------------
ENSEMBLE_WEIGHTS = {
"cryptobert": 0.65, # transformer, more reliable on crypto slang/context
"vader": 0.35, # lexicon, fast sanity check
}
# ---------------------------------------------------------------------------
# Source credibility — multiplier applied when aggregating 24h sentiment.
# Established outlets count more than anonymous social posts.
# Matched as a case-insensitive substring of the item's "source" field.
# ---------------------------------------------------------------------------
SOURCE_WEIGHTS = {
"CoinDesk": 1.6,
"The Block": 1.6,
"Bloomberg": 1.7,
"Reuters": 1.7,
"Blockworks": 1.4,
"CoinTelegraph": 1.3,
"Decrypt": 1.3,
"Bitcoin Magazine": 1.2,
"CryptoSlate": 1.1,
"NewsBTC": 1.0,
"AMBCrypto": 1.0,
"CryptoNews": 1.0,
"NewsData": 1.1,
"BeInCrypto": 1.0,
"CryptoPotato": 0.95,
"Bitcoinist": 0.95,
"U.Today": 0.95,
"CoinGape": 0.9,
"DailyHodl": 0.9,
"CoinJournal": 1.0,
"Crypto Briefing": 1.1,
"Coinpedia": 0.9,
"ZyCrypto": 0.85,
"GoogleNews": 1.2, # aggregator across many outlets
"Reddit": 0.7, # social signal, noisier
"_default": 1.0,
}
# ---------------------------------------------------------------------------
# Spike detection thresholds
# ---------------------------------------------------------------------------
SPIKE = {
"baseline_snapshots": 8, # how many past snapshots form the baseline
"volume_ratio": 2.0, # mentions >= 2x baseline avg → spike
"sentiment_swing": 0.30, # net sentiment moved >= 0.30 → swing
"new_min_volume": 4, # min mentions for a NEW_NARRATIVE alert
"max_alerts": 8, # cap alerts per refresh
}
# ---------------------------------------------------------------------------
# Scoring Weights
# ---------------------------------------------------------------------------
SCORING = {
"recency_decay_hours": 24, # articles older than this lose full score
"reddit_upvote_weight": 0.3,
"news_volume_weight": 0.4,
"sentiment_weight": 0.3,
"trending_coin_bonus": 1.5, # multiplier if coin is trending on CoinGecko
}
# ---------------------------------------------------------------------------
# Google Trends — keywords to track interest over time
# ---------------------------------------------------------------------------
TREND_KEYWORDS = [
"bitcoin etf",
"crypto regulation",
"AI crypto",
"real world assets crypto",
"memecoin",
"bitcoin halving",
"DeFi",
"layer 2 crypto",
]
# ---------------------------------------------------------------------------
# Storage
# ---------------------------------------------------------------------------
DB_PATH = "narrative_analysis.db"
MAX_ARTICLE_AGE_HOURS = 72 # keep articles in cache for 3 days
# ---------------------------------------------------------------------------
# Display
# ---------------------------------------------------------------------------
REFRESH_INTERVAL_MINUTES = 30 # auto-refresh interval for live mode
TOP_NARRATIVES_TO_SHOW = 10