openpondai/agents/news-bot
OpenTool app
typescript
import { describe, expect, test } from "bun:test";
import { resolveRuntimeConfig, type SimpleNewsBotConfig } from "./config";
import { resolveNewsTradeDecision } from "./news-trade";
function buildPropositionSignal(overrides: Record<string, unknown> = {}) {
return {
question: "Netanyahu out by March 31?",
query: null,
propositionType: null,
propositionStatus: "unclear",
answer: "unclear",
propositionConfidence: 0,
reasoning: "No matching news event resolved.",
evidenceWindowSummary: "",
resolvedEventId: null,
resolvedEventKey: null,
resolvedEventTitle: null,
eventState: null,
eventConfidence: null,
confidenceBreakdown: null,
supportingEvidence: [],
rebuttingEvidence: [],
supportingEvidenceArticleIds: [],
rebuttingEvidenceArticleIds: [],
operatorReviewRecommended: false,
dataAgeMs: 0,
predictionMarketContext: {
matchedMarkets: [
{
marketId: "1484949",
title: "Netanyahu out by March 31?",
yesProbability: 0.0125,
noProbability: 0.9875,
leadingOutcome: "No",
leadingProbability: 0.9875,
volume: 62_009_950.08,
liquidity: 1_662_635.15,
fetchedAt: new Date().toISOString(),
},
],
consensusProbability: 0.9875,
dataAgeMs: 0,
},
...overrides,
};
}
describe("resolveNewsTradeDecision prediction market signal", () => {
test("uses the configured preferred outcome threshold to buy", () => {
const config = resolveRuntimeConfig({
question: "Netanyahu out by March 31?",
predictionMarketSignal: {
preferredOutcome: "no",
minProbability: 0.9,
action: "buy",
onNoMatch: "hold",
},
});
const decision = resolveNewsTradeDecision(
config,
buildPropositionSignal(),
null,
);
expect(decision.signal).toBe("buy");
expect(decision.reason).toContain("prediction market no");
expect(decision.reason).toContain("Netanyahu out by March 31?");
expect(decision.confidence).toBeCloseTo(0.9875, 4);
});
test("returns the configured no-match action when the threshold is not met", () => {
const config = resolveRuntimeConfig({
question: "Netanyahu out by March 31?",
predictionMarketSignal: {
preferredOutcome: "no",
minProbability: 0.995,
action: "buy",
onNoMatch: "hold",
},
});
const decision = resolveNewsTradeDecision(
config,
buildPropositionSignal(),
null,
);
expect(decision.signal).toBe("hold");
expect(decision.reason).toContain("below 0.9950");
});
test("preserves the legacy proposition answer path when no prediction market signal is configured", () => {
const config = resolveRuntimeConfig({
question: "Is the US still at war with Iran?",
}) as SimpleNewsBotConfig;
const decision = resolveNewsTradeDecision(
config,
buildPropositionSignal({
answer: "yes",
propositionStatus: "yes",
propositionConfidence: 0.82,
reasoning: "Matched proposition evidence.",
}),
null,
);
expect(decision.signal).toBe("buy");
expect(decision.reason).toBe("proposition answer yes");
});
});