feat: add bullish and bearish researcher agents
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { BullishResearcher, BearishResearcher } from "../researchers";
|
||||
import type { AnalystReport } from "../../types/agents";
|
||||
|
||||
describe("Researchers", () => {
|
||||
const mockClient = {
|
||||
createChatCompletion: vi.fn().mockResolvedValue({
|
||||
choices: [{ message: { content: "Bullish thesis content" } }],
|
||||
}),
|
||||
};
|
||||
|
||||
const mockReports: AnalystReport[] = [
|
||||
{
|
||||
analyst: "fundamentals",
|
||||
report: "Strong earnings growth",
|
||||
signal: {
|
||||
agent: "fundamentals",
|
||||
signal: "bullish",
|
||||
confidence: 0.8,
|
||||
reasoning: "Revenue up 20%",
|
||||
timestamp: "2024-01-01",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
it("should create bullish researcher", async () => {
|
||||
const researcher = new BullishResearcher(mockClient as any);
|
||||
const result = await researcher.research("AAPL", mockReports);
|
||||
expect(result.researcher).toBe("bullish");
|
||||
});
|
||||
|
||||
it("should create bearish researcher", async () => {
|
||||
const researcher = new BearishResearcher(mockClient as any);
|
||||
const result = await researcher.research("AAPL", mockReports);
|
||||
expect(result.researcher).toBe("bearish");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
import { OpenRouterClient } from "../lib/openrouter";
|
||||
import type { AnalystReport, DebateRound } from "../types/agents";
|
||||
|
||||
type ChatResponse = {
|
||||
choices?: Array<{ message?: { content?: string } }>;
|
||||
};
|
||||
|
||||
export class BullishResearcher {
|
||||
private client: OpenRouterClient;
|
||||
private model: string;
|
||||
|
||||
constructor(client: OpenRouterClient, model?: string) {
|
||||
this.client = client;
|
||||
this.model = model ?? "google/gemini-2.0-flash-exp:free";
|
||||
}
|
||||
|
||||
async research(ticker: string, reports: AnalystReport[]): Promise<DebateRound> {
|
||||
const reportSummaries = reports
|
||||
.map((r) => `${r.analyst}: ${r.signal.signal} - ${r.report}`)
|
||||
.join("\n");
|
||||
|
||||
const prompt = `Analyze these analyst reports for ${ticker} and synthesize a bullish thesis:
|
||||
${reportSummaries}
|
||||
|
||||
Provide a bullish view based on the positive signals and reasoning.`;
|
||||
|
||||
const response = await this.client.createChatCompletion(
|
||||
[
|
||||
{ role: "system", content: "You are a bullish equity researcher who finds the positive investment case." },
|
||||
{ role: "user", content: prompt },
|
||||
],
|
||||
this.model
|
||||
);
|
||||
|
||||
const content = ((response as ChatResponse).choices?.[0]?.message?.content) ?? "";
|
||||
|
||||
return {
|
||||
bullishView: content,
|
||||
bearishView: "",
|
||||
researcher: "bullish",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class BearishResearcher {
|
||||
private client: OpenRouterClient;
|
||||
private model: string;
|
||||
|
||||
constructor(client: OpenRouterClient, model?: string) {
|
||||
this.client = client;
|
||||
this.model = model ?? "google/gemini-2.0-flash-exp:free";
|
||||
}
|
||||
|
||||
async research(ticker: string, reports: AnalystReport[]): Promise<DebateRound> {
|
||||
const reportSummaries = reports
|
||||
.map((r) => `${r.analyst}: ${r.signal.signal} - ${r.report}`)
|
||||
.join("\n");
|
||||
|
||||
const prompt = `Analyze these analyst reports for ${ticker} and synthesize a bearish thesis:
|
||||
${reportSummaries}
|
||||
|
||||
Provide a bearish view based on the risks and negative signals.`;
|
||||
|
||||
const response = await this.client.createChatCompletion(
|
||||
[
|
||||
{ role: "system", content: "You are a bearish equity researcher who identifies investment risks." },
|
||||
{ role: "user", content: prompt },
|
||||
],
|
||||
this.model
|
||||
);
|
||||
|
||||
const content = ((response as ChatResponse).choices?.[0]?.message?.content) ?? "";
|
||||
|
||||
return {
|
||||
bullishView: "",
|
||||
bearishView: content,
|
||||
researcher: "bearish",
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user