import { tool } from "@opencode-ai/plugin"; import path from "path"; const SCRIPTS_DIR = (ctx: { worktree: string }) => path.join(ctx.worktree, "scripts"); async function runPython( ctx: { worktree: string }, fn: string, args: Record, ): Promise { const scriptPath = path.join(SCRIPTS_DIR(ctx), "stock_screener.py"); const argsJson = JSON.stringify(args); const result = await Bun.$`python3 ${scriptPath} ${fn} ${argsJson}`.text(); return result.trim(); } export const multi_factor = tool({ description: "Screen stocks using multi-factor scoring model (technical + capital flow + fundamental + sentiment)", args: { strategy: tool.schema.enum(["comprehensive", "momentum", "value", "breakout"]).default("comprehensive").describe("Screening strategy"), sector: tool.schema.string().optional().describe("Filter by sector/industry name"), market_cap: tool.schema.enum(["large", "medium", "small", "all"]).default("all").describe("Market cap filter"), top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"), }, async execute(args, context) { return runPython(context, "multi_factor", args); }, }); export const strong = tool({ description: "Screen for strong-trend stocks (MA bull alignment + relative strength)", args: { sector: tool.schema.string().optional().describe("Filter by sector/industry name"), top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"), }, async execute(args, context) { return runPython(context, "strong", args); }, }); export const breakout = tool({ description: "Screen for volume breakout stocks (price breaking resistance with expanding volume)", args: { lookback_days: tool.schema.number().default(60).describe("Lookback period for resistance identification"), top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"), }, async execute(args, context) { return runPython(context, "breakout", args); }, }); export const oversold = tool({ description: "Screen for oversold stocks with potential rebound signals", args: { top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"), }, async execute(args, context) { return runPython(context, "oversold", args); }, });