feat: bootstrap personal stock agent
This commit is contained in:
76
tests/report.test.ts
Normal file
76
tests/report.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { generateDailyReport } from "../src/agent/report";
|
||||
import type { MarketDataProvider, WatchStock } from "../src/shared/types";
|
||||
|
||||
const watchlist: WatchStock[] = [
|
||||
{
|
||||
id: "AAPL",
|
||||
symbol: "AAPL",
|
||||
display: "AAPL",
|
||||
market: "US",
|
||||
name: "Apple",
|
||||
addedAt: "2026-05-11T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
id: "00700.HK",
|
||||
symbol: "00700",
|
||||
display: "00700.HK",
|
||||
market: "HK",
|
||||
name: "Tencent",
|
||||
addedAt: "2026-05-11T00:00:00.000Z"
|
||||
}
|
||||
];
|
||||
|
||||
const provider: MarketDataProvider = {
|
||||
async snapshot(stock) {
|
||||
if (stock.display === "AAPL") {
|
||||
return {
|
||||
price: 100,
|
||||
currency: "USD",
|
||||
pe: 12,
|
||||
forwardPe: 11,
|
||||
revenueGrowth: 0.08,
|
||||
profitGrowth: 0.05,
|
||||
nextEarningsDate: "2026-05-13",
|
||||
peers: [
|
||||
{ display: "MSFT", pe: 28 },
|
||||
{ display: "GOOGL", pe: 24 }
|
||||
],
|
||||
news: [{ title: "Apple supplier raises shipment guidance", url: "https://example.test/aapl" }]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
price: 380,
|
||||
currency: "HKD",
|
||||
pe: 22,
|
||||
forwardPe: 20,
|
||||
revenueGrowth: 0.02,
|
||||
profitGrowth: -0.01,
|
||||
nextEarningsDate: "2026-06-30",
|
||||
peers: [{ display: "9988.HK", pe: 18 }],
|
||||
news: []
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
describe("generateDailyReport", () => {
|
||||
it("ranks earnings, related news, valuation mismatch, and buy advice across markets", async () => {
|
||||
const report = await generateDailyReport(watchlist, provider, new Date("2026-05-11T00:00:00.000Z"));
|
||||
|
||||
expect(report.generatedAt).toBe("2026-05-11T00:00:00.000Z");
|
||||
expect(report.items).toHaveLength(2);
|
||||
expect(report.summary).toContain("US: 1");
|
||||
expect(report.summary).toContain("HK: 1");
|
||||
|
||||
const apple = report.items.find((item) => item.stock.display === "AAPL");
|
||||
expect(apple?.earnings.status).toBe("soon");
|
||||
expect(apple?.valuation.label).toBe("discount");
|
||||
expect(apple?.recommendation.action).toBe("buy_watch");
|
||||
expect(apple?.news[0]?.title).toContain("supplier");
|
||||
|
||||
const tencent = report.items.find((item) => item.stock.display === "00700.HK");
|
||||
expect(tencent?.valuation.label).toBe("premium");
|
||||
expect(tencent?.recommendation.action).toBe("hold");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user