Files
market_screener/server/controllers/screener.controller.ts
T
2026-06-05 23:02:21 -04:00

53 lines
1.7 KiB
TypeScript

import type { FastifyInstance, FastifyRequest } from 'fastify';
import { ScreenerEngine, CatalystAnalyst } from '../services/index';
import { noopLogger } from '../utils/logger';
import type { LiveAssetResult } from '../types';
import { screenSchema } from '../types/schemas';
export class ScreenerController {
constructor(private readonly engine: ScreenerEngine) {}
register(app: FastifyInstance): void {
app.post(
'/api/screen',
{ schema: screenSchema, config: { rateLimit: { max: 10, timeWindow: '1 minute' } } },
this.screen.bind(this),
);
app.get(
'/api/screen/catalysts',
{ config: { rateLimit: { max: 10, timeWindow: '1 minute' } } },
this.catalysts.bind(this),
);
}
private static serializeAssets(arr: LiveAssetResult[]) {
return arr.map((r) => ({
...r,
asset: {
ticker: r.asset.ticker,
type: r.asset.type,
currentPrice: r.asset.currentPrice,
metrics: r.asset.metrics,
displayMetrics: r.asset.getDisplayMetrics(),
},
}));
}
private async screen(req: FastifyRequest) {
const tickers = (req.body as { tickers: string[] }).tickers.map((t) => t.toUpperCase());
const results = await this.engine.screenTickers(tickers);
return {
...results,
STOCK: ScreenerController.serializeAssets(results.STOCK as LiveAssetResult[]),
ETF: ScreenerController.serializeAssets(results.ETF as LiveAssetResult[]),
BOND: ScreenerController.serializeAssets(results.BOND as LiveAssetResult[]),
};
}
private async catalysts() {
const catalyst = new CatalystAnalyst({ logger: noopLogger });
const { tickers, stories } = await catalyst.run();
return { tickers, stories };
}
}