1Branch0Tags
GL
glucryptoRefresh package-lock for opentool 0.19.5
01acdef14 hours ago17Commits
typescript
import type { NewsContinuationGateResult, NewsEventSignal, NewsPredictionMarketMatchedMarket, NewsPropositionSignal, } from "opentool/adapters/news"; import type { NewsTradeSignal, SimpleNewsBotConfig } from "./config"; import type { SimpleNewsBotSignal } from "./news-core"; export type NewsTradeDecision = { signal: NewsTradeSignal; reason: string; blockedByGate: boolean; eventState: string | null; propositionAnswer: string | null; confidence: number | null; }; function resolveBlockedSignal(config: SimpleNewsBotConfig): NewsTradeSignal { return config.tradePolicy?.blockAction === "close" ? "sell" : "hold"; } function includes<T extends string>(value: readonly T[] | undefined, target: string): boolean { return Boolean(value?.includes(target as T)); } function parsePredictionMarketProbability( market: NewsPredictionMarketMatchedMarket, preferredOutcome: "yes" | "no", ): number | null { return preferredOutcome === "no" ? (market.noProbability ?? null) : (market.yesProbability ?? null); } function selectBestPredictionMarket( signal: SimpleNewsBotSignal, ): NewsPredictionMarketMatchedMarket | null { const markets = signal.predictionMarketContext?.matchedMarkets ?? []; if (markets.length === 0) return null; return [...markets].sort((left, right) => { const leftLiquidity = left.liquidity ?? left.volume ?? 0; const rightLiquidity = right.liquidity ?? right.volume ?? 0; if (rightLiquidity !== leftLiquidity) return rightLiquidity - leftLiquidity; const leftProbability = left.leadingProbability ?? 0; const rightProbability = right.leadingProbability ?? 0; return rightProbability - leftProbability; })[0] ?? null; } function resolvePredictionMarketSignalDecision( config: SimpleNewsBotConfig, signal: SimpleNewsBotSignal, ): NewsTradeDecision | null { const policy = config.predictionMarketSignal; if (!policy) return null; const topMarket = selectBestPredictionMarket(signal); if (!topMarket) { return { signal: policy.onNoMatch ?? "unknown", reason: "prediction market not found", blockedByGate: false, eventState: "question" in signal ? signal.eventState : signal.eventState, propositionAnswer: "question" in signal ? signal.answer : null, confidence: "question" in signal ? signal.propositionConfidence : signal.eventConfidence, }; } const liquidity = topMarket.liquidity ?? topMarket.volume ?? 0; if (typeof policy.minLiquidity === "number" && liquidity < policy.minLiquidity) { return { signal: policy.onNoMatch ?? "unknown", reason: `prediction market liquidity ${liquidity.toFixed(2)} below minimum ${policy.minLiquidity.toFixed(2)}`, blockedByGate: false, eventState: "question" in signal ? signal.eventState : signal.eventState, propositionAnswer: "question" in signal ? signal.answer : null, confidence: "question" in signal ? signal.propositionConfidence : signal.eventConfidence, }; } const probability = parsePredictionMarketProbability(topMarket, policy.preferredOutcome); if (probability == null || probability < policy.minProbability) { return { signal: policy.onNoMatch ?? "unknown", reason: probability == null ? `prediction market missing ${policy.preferredOutcome} probability` : `prediction market ${policy.preferredOutcome} probability ${probability.toFixed(4)} below ${policy.minProbability.toFixed(4)}`, blockedByGate: false, eventState: "question" in signal ? signal.eventState : signal.eventState, propositionAnswer: "question" in signal ? signal.answer : null, confidence: "question" in signal ? signal.propositionConfidence : signal.eventConfidence, }; } return { signal: policy.action ?? "buy", reason: `prediction market ${policy.preferredOutcome} ${probability.toFixed(4)} on ${topMarket.title}`, blockedByGate: false, eventState: "question" in signal ? signal.eventState : signal.eventState, propositionAnswer: "question" in signal ? signal.answer : null, confidence: probability, }; } function resolveEventSignalDecision( config: SimpleNewsBotConfig, signal: NewsEventSignal, gate: NewsContinuationGateResult | null, ): NewsTradeDecision { if (gate && !gate.allowed) { return { signal: resolveBlockedSignal(config), reason: gate.reason, blockedByGate: true, eventState: signal.eventState, propositionAnswer: null, confidence: signal.eventConfidence, }; } const entrySignals = config.tradePolicy?.eventEntrySignals ?? ["escalation"]; const exitSignals = config.tradePolicy?.eventExitSignals ?? ["de_escalation", "resolved", "contradiction"]; if (includes(entrySignals, signal.signal) || includes(entrySignals, signal.eventState)) { return { signal: "buy", reason: `event signal ${signal.signal}`, blockedByGate: false, eventState: signal.eventState, propositionAnswer: null, confidence: signal.eventConfidence, }; } if (includes(exitSignals, signal.signal) || includes(exitSignals, signal.eventState)) { return { signal: "sell", reason: `event signal ${signal.signal}`, blockedByGate: false, eventState: signal.eventState, propositionAnswer: null, confidence: signal.eventConfidence, }; } return { signal: signal.triggerPassed ? "hold" : "unknown", reason: signal.whyNotTriggered ?? `event signal ${signal.signal}`, blockedByGate: false, eventState: signal.eventState, propositionAnswer: null, confidence: signal.eventConfidence, }; } function resolvePropositionDecision( config: SimpleNewsBotConfig, signal: NewsPropositionSignal, gate: NewsContinuationGateResult | null, ): NewsTradeDecision { if (gate && !gate.allowed) { return { signal: resolveBlockedSignal(config), reason: gate.reason, blockedByGate: true, eventState: signal.eventState, propositionAnswer: signal.answer, confidence: signal.propositionConfidence, }; } const entryAnswers = config.tradePolicy?.propositionEntryAnswers ?? ["yes"]; const exitAnswers = config.tradePolicy?.propositionExitAnswers ?? ["no", "unclear"]; if (includes(entryAnswers, signal.answer)) { return { signal: "buy", reason: `proposition answer ${signal.answer}`, blockedByGate: false, eventState: signal.eventState, propositionAnswer: signal.answer, confidence: signal.propositionConfidence, }; } if (includes(exitAnswers, signal.answer)) { return { signal: "sell", reason: `proposition answer ${signal.answer}`, blockedByGate: false, eventState: signal.eventState, propositionAnswer: signal.answer, confidence: signal.propositionConfidence, }; } return { signal: signal.answer === "unclear" ? "hold" : "unknown", reason: signal.reasoning, blockedByGate: false, eventState: signal.eventState, propositionAnswer: signal.answer, confidence: signal.propositionConfidence, }; } export function resolveNewsTradeDecision( config: SimpleNewsBotConfig, signal: SimpleNewsBotSignal, gate: NewsContinuationGateResult | null, ): NewsTradeDecision { const predictionMarketDecision = resolvePredictionMarketSignalDecision(config, signal); if (predictionMarketDecision) { return predictionMarketDecision; } if ("question" in signal) { return resolvePropositionDecision(config, signal, gate); } return resolveEventSignalDecision(config, signal, gate); }