feat: add trading graph orchestrator
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { TradingGraph } from "../tradingGraph";
|
||||
|
||||
describe("TradingGraph", () => {
|
||||
const mockClient = {
|
||||
createChatCompletion: vi.fn().mockResolvedValue({
|
||||
choices: [{ message: { content: '{"signal":"bullish","confidence":0.8,"reasoning":"Test"}' } }],
|
||||
}),
|
||||
};
|
||||
|
||||
const mockInput = {
|
||||
financialData: "Revenue: 1B, Growth: 10%, Debt: low",
|
||||
technicalData: {
|
||||
prices: [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
|
||||
sma: 105,
|
||||
ema: 106,
|
||||
rsi: 65,
|
||||
macd: 2.5,
|
||||
},
|
||||
sentimentData: {
|
||||
headlines: ["Company beats earnings expectations"],
|
||||
source: "news" as const,
|
||||
},
|
||||
};
|
||||
|
||||
it("should run full analysis", async () => {
|
||||
const graph = new TradingGraph(mockClient as any);
|
||||
const decision = await graph.propagate("AAPL", mockInput);
|
||||
expect(decision).toHaveProperty("action");
|
||||
expect(decision).toHaveProperty("confidence");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import { OpenRouterClient } from "../lib/openrouter";
|
||||
import { FundamentalsAnalyst } from "./fundamentals";
|
||||
import { TechnicalAnalyst } from "./technical";
|
||||
import { SentimentAnalyst } from "./sentiment";
|
||||
import { BullishResearcher, BearishResearcher } from "./researchers";
|
||||
import { Trader } from "./trader";
|
||||
import type { AnalystReport, DebateRound, TradingDecision, AgentSignal } from "../types/agents";
|
||||
|
||||
export class TradingGraph {
|
||||
private client: OpenRouterClient;
|
||||
private model: string;
|
||||
private fundamentalsAnalyst: FundamentalsAnalyst;
|
||||
private technicalAnalyst: TechnicalAnalyst;
|
||||
private sentimentAnalyst: SentimentAnalyst;
|
||||
private bullishResearcher: BullishResearcher;
|
||||
private bearishResearcher: BearishResearcher;
|
||||
private trader: Trader;
|
||||
|
||||
constructor(client: OpenRouterClient, model?: string) {
|
||||
this.client = client;
|
||||
this.model = model ?? "google/gemini-2.0-flash-exp:free";
|
||||
|
||||
this.fundamentalsAnalyst = new FundamentalsAnalyst(client, { model: this.model });
|
||||
this.technicalAnalyst = new TechnicalAnalyst(client, { model: this.model });
|
||||
this.sentimentAnalyst = new SentimentAnalyst(client, { model: this.model });
|
||||
this.bullishResearcher = new BullishResearcher(client, this.model);
|
||||
this.bearishResearcher = new BearishResearcher(client, this.model);
|
||||
this.trader = new Trader(client, this.model);
|
||||
}
|
||||
|
||||
async propagate(
|
||||
ticker: string,
|
||||
input: {
|
||||
financialData: string;
|
||||
technicalData: { prices: number[]; sma: number; ema: number; rsi: number; macd: number };
|
||||
sentimentData: { headlines: string[]; source?: "news" | "social" | "stocktwits" };
|
||||
}
|
||||
): Promise<TradingDecision> {
|
||||
const reports = await this.runAnalysts(ticker, input);
|
||||
const debates = await this.runDebate(ticker, reports);
|
||||
const decision = await this.trader.decide(ticker, reports, debates);
|
||||
return decision;
|
||||
}
|
||||
|
||||
private async runAnalysts(
|
||||
ticker: string,
|
||||
input: {
|
||||
financialData: string;
|
||||
technicalData: { prices: number[]; sma: number; ema: number; rsi: number; macd: number };
|
||||
sentimentData: { headlines: string[]; source?: "news" | "social" | "stocktwits" };
|
||||
}
|
||||
): Promise<AnalystReport[]> {
|
||||
const [fundamentals, technical, sentiment] = await Promise.all([
|
||||
this.fundamentalsAnalyst.analyze(ticker, input.financialData),
|
||||
this.technicalAnalyst.analyze(ticker, input.technicalData),
|
||||
this.sentimentAnalyst.analyze(ticker, input.sentimentData),
|
||||
]);
|
||||
|
||||
return [fundamentals, technical, sentiment];
|
||||
}
|
||||
|
||||
private async runDebate(ticker: string, reports: AnalystReport[]): Promise<DebateRound[]> {
|
||||
const [bullish, bearish] = await Promise.all([
|
||||
this.bullishResearcher.research(ticker, reports),
|
||||
this.bearishResearcher.research(ticker, reports),
|
||||
]);
|
||||
|
||||
return [
|
||||
{
|
||||
bullishView: bullish.bullishView,
|
||||
bearishView: bearish.bearishView,
|
||||
researcher: "bullish",
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user