1Branch0Tags
GL
glucryptoRefresh package-lock for opentool 0.19.5
01acdef14 hours ago17Commits
typescript
import { NewsSignalClient, evaluateNewsContinuationGate, type NewsContinuationGateResult, type NewsEventSignal, type NewsPropositionSignal, } from "opentool/adapters/news"; import type { SimpleNewsBotBacktest, SimpleNewsBotConfig } from "./config"; export type SimpleNewsBotSignal = NewsEventSignal | NewsPropositionSignal; export type SimpleNewsBotBacktestPoint = { asOf: string; signal: SimpleNewsBotSignal; gate: NewsContinuationGateResult | null; }; function parseBoundaryDate(value: string, endOfDay: boolean): Date { const trimmed = value.trim(); if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) { const suffix = endOfDay ? "T23:59:59.000Z" : "T00:00:00.000Z"; return new Date(`${trimmed}${suffix}`); } return new Date(trimmed); } export function buildBacktestCheckpoints(backtest: SimpleNewsBotBacktest): string[] { const start = parseBoundaryDate(backtest.startDate, false); const end = parseBoundaryDate(backtest.endDate ?? new Date().toISOString(), true); if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) { throw new Error("backtest startDate/endDate must be valid dates."); } if (end.getTime() < start.getTime()) { throw new Error("backtest endDate must be on or after startDate."); } const stepHours = backtest.stepHours ?? 24; const stepMs = stepHours * 60 * 60 * 1000; const checkpoints: string[] = []; for (let cursor = start.getTime(); cursor <= end.getTime(); cursor += stepMs) { checkpoints.push(new Date(cursor).toISOString()); if (checkpoints.length > 366) { throw new Error("backtest produced too many checkpoints; reduce the date range."); } } return checkpoints; } export async function fetchSignal( config: SimpleNewsBotConfig, asOf?: string | null, ): Promise<SimpleNewsBotSignal> { const client = new NewsSignalClient(); if (config.mode === "event") { return client.eventSignal({ ...(config.query ? { query: config.query } : {}), ...(config.eventKey ? { eventKey: config.eventKey } : {}), ...(asOf ? { asOf } : {}), includePredictionMarkets: config.includePredictionMarkets, ingestOnRequest: config.ingestOnRequest, maxAgeHours: config.maxAgeHours, ...(config.gate?.mode === "event" && typeof config.gate.minConfidence === "number" ? { minConfidence: config.gate.minConfidence } : {}), ...(config.gate?.mode === "event" && typeof config.gate.minIndependentSources === "number" ? { minIndependentSources: config.gate.minIndependentSources } : {}), ...(config.gate?.mode === "event" && typeof config.gate.minTierASources === "number" ? { minTierASources: config.gate.minTierASources } : {}), }); } return client.propositionSignal({ question: config.question, ...(config.query ? { query: config.query } : {}), ...(config.eventKey ? { eventKey: config.eventKey } : {}), ...(config.propositionType ? { propositionType: config.propositionType } : {}), ...(asOf ? { asOf } : {}), includePredictionMarkets: config.includePredictionMarkets, ingestOnRequest: config.ingestOnRequest, maxAgeHours: config.maxAgeHours, candidateLimit: config.candidateLimit, }); } export function evaluateGate( config: SimpleNewsBotConfig, signal: SimpleNewsBotSignal, ): NewsContinuationGateResult | null { if (!config.gate) return null; return evaluateNewsContinuationGate(signal, config.gate); }