84 lines
2.4 KiB
JavaScript
84 lines
2.4 KiB
JavaScript
/**
|
|
* bin/screen.js — Market Screener CLI
|
|
*
|
|
* Fetches today's catalyst tickers from Yahoo Finance news,
|
|
* screens them under both Market-Adjusted and Fundamental lenses,
|
|
* and saves a full HTML report.
|
|
*
|
|
* Usage:
|
|
* npm start → Yahoo news → catalyst tickers → screen
|
|
* npm start -- watch → default watchlist
|
|
* npm start -- AAPL MSFT VOO → specific tickers
|
|
*/
|
|
|
|
import 'dotenv/config';
|
|
import { CatalystAnalyst } from '../src/analyst/CatalystAnalyst.js';
|
|
import { ScreenerEngine } from '../src/screener/ScreenerEngine.js';
|
|
import { HtmlReporter } from '../src/reporters/HtmlReporter.js';
|
|
|
|
const DEFAULT_WATCHLIST = [
|
|
// Stocks
|
|
'PLTR',
|
|
'AAPL',
|
|
'MSFT',
|
|
'TSLA',
|
|
'O',
|
|
// ETFs
|
|
'VOO',
|
|
'QQQ',
|
|
// Bonds
|
|
'BND',
|
|
'LQD',
|
|
'TLT',
|
|
'IEF',
|
|
'SHY',
|
|
'GOVT',
|
|
'AGG',
|
|
'MUB',
|
|
];
|
|
|
|
async function main() {
|
|
const args = process.argv.slice(2);
|
|
let tickers = [];
|
|
|
|
if (args.length > 0 && args[0] !== 'watch') {
|
|
tickers = args.map((t) => t.toUpperCase());
|
|
console.log(`📋 Screening: ${tickers.join(', ')}\n`);
|
|
} else if (args[0] === 'watch') {
|
|
tickers = DEFAULT_WATCHLIST;
|
|
console.log(`📋 Screening default watchlist (${tickers.length} tickers)\n`);
|
|
} else {
|
|
try {
|
|
const { tickers: newsTickers, stories } = await new CatalystAnalyst().run();
|
|
|
|
if (newsTickers.length === 0) {
|
|
console.warn("⚠ No tickers in today's news — using default watchlist\n");
|
|
tickers = DEFAULT_WATCHLIST;
|
|
} else {
|
|
tickers = newsTickers;
|
|
console.log("\n📰 Stories driving today's screen:");
|
|
stories.slice(0, 5).forEach((s) => {
|
|
const tags = s.relatedTickers.slice(0, 3).join(', ');
|
|
console.log(` • ${s.title}${tags ? ` [${tags}]` : ''}`);
|
|
});
|
|
console.log(`\n📋 Tickers: ${tickers.join(', ')}\n`);
|
|
}
|
|
} catch (err) {
|
|
console.warn(`⚠ Catalyst analysis failed (${err.message}) — using default watchlist\n`);
|
|
tickers = DEFAULT_WATCHLIST;
|
|
}
|
|
}
|
|
|
|
try {
|
|
const { STOCK, ETF, BOND, ERROR, marketContext } =
|
|
await new ScreenerEngine().screenWithProgress(tickers);
|
|
const reportPath = new HtmlReporter().generate({ STOCK, ETF, BOND, ERROR }, marketContext);
|
|
console.log(`\n✅ Done — report saved to: ${reportPath}\n`);
|
|
} catch (err) {
|
|
console.error('Screener failed:', err.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|