phase-2: extract shared utils
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { YahooClient } from '../market/YahooClient.js';
|
||||
|
||||
const NEWS_QUERIES = ['stock market today', 'earnings report', 'market news'];
|
||||
const MAX_STORIES = 15;
|
||||
const TICKER_REGEX = /^[A-Z]{1,6}$/;
|
||||
|
||||
export class CatalystAnalyst {
|
||||
constructor({ logger } = {}) {
|
||||
this.client = new YahooClient();
|
||||
this.logger = logger ?? { write: (msg) => process.stdout.write(msg) };
|
||||
}
|
||||
|
||||
async run() {
|
||||
this.logger.write('🔍 Fetching market news...');
|
||||
const stories = await this._fetchNews();
|
||||
const tickers = this._extractTickers(stories);
|
||||
this.logger.write(` ${stories.length} stories, ${tickers.length} tickers\n`);
|
||||
return { tickers, stories };
|
||||
}
|
||||
|
||||
async _fetchNews() {
|
||||
const seen = new Map();
|
||||
for (const query of NEWS_QUERIES) {
|
||||
try {
|
||||
const { news = [] } = await this.client.yf.search(query, { newsCount: 8, quotesCount: 0 });
|
||||
for (const s of news) {
|
||||
if (!seen.has(s.title)) {
|
||||
seen.set(s.title, {
|
||||
title: s.title,
|
||||
publisher: s.publisher,
|
||||
link: s.link,
|
||||
relatedTickers: s.relatedTickers ?? [],
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* skip failed query */
|
||||
}
|
||||
}
|
||||
return [...seen.values()].slice(0, MAX_STORIES);
|
||||
}
|
||||
|
||||
_extractTickers(stories) {
|
||||
const tickers = new Set();
|
||||
for (const { relatedTickers } of stories) {
|
||||
for (const t of relatedTickers) {
|
||||
const clean = t.split(':')[0].toUpperCase();
|
||||
if (TICKER_REGEX.test(clean)) tickers.add(clean);
|
||||
}
|
||||
}
|
||||
return [...tickers];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user