feat: add confluence.signalHistory API route
Returns signal fire history for a symbol (last 6 months) with slot names and body types. Used by the upcoming confluence chart to plot signal markers on price data.
This commit is contained in:
@@ -33,7 +33,7 @@ import { computeOwnershipPercentages, fetchAndPersistFloat } from '../services/s
|
||||
import { EdgarAdapter } from '../adapters/EdgarAdapter.ts';
|
||||
import { OptionsAdapter, parseOptionChainRows } from '../adapters/OptionsAdapter.ts';
|
||||
import type { OptionChainRow, OptionGreeks } from '../adapters/OptionsAdapter.ts';
|
||||
import { CONFLUENCE_SLOTS, slotsByFamily, type SlotFamily } from '../confluence/confluenceSlots.ts';
|
||||
import { CONFLUENCE_SLOTS, slotsByFamily, type SlotFamily, confluenceslotById } from '../confluence/confluenceSlots.ts';
|
||||
import { CONFLUENCE_SLOT_IDS } from '../confluence/confluenceSlots.ts';
|
||||
import { ConfluenceRepository, rackFromSlots } from '../db/confluenceRepository.ts';
|
||||
import { runSlotBacktest, signalHistoryToStats, type ConfluenceFireEvent } from '../confluence/confluenceBacktest.ts';
|
||||
@@ -5473,6 +5473,32 @@ const confluenceRouter = router({
|
||||
};
|
||||
}),
|
||||
|
||||
/** Signal fire history for a symbol (last 6 months). Used by the confluence chart. */
|
||||
signalHistory: publicProcedure
|
||||
.input(z.object({ symbol: z.string().min(1).max(12) }))
|
||||
.query(({ ctx, input }) => {
|
||||
const symbol = input.symbol.toUpperCase();
|
||||
const repo = new ConfluenceRepository(ctx.db);
|
||||
const allFires = repo.listSignalsForSymbol(symbol);
|
||||
// Filter to last 6 months
|
||||
const cutoff = new Date();
|
||||
cutoff.setMonth(cutoff.getMonth() - 6);
|
||||
const cutoffStr = cutoff.toISOString();
|
||||
const fires = allFires
|
||||
.filter((f) => f.firedAt >= cutoffStr)
|
||||
.map((f) => {
|
||||
const meta = confluenceslotById.get(f.slotId);
|
||||
return {
|
||||
slotId: f.slotId,
|
||||
slotName: meta?.name ?? f.slotId,
|
||||
body: (meta?.body ?? 'bull') as 'bull' | 'bear' | 'exit',
|
||||
firedAt: f.firedAt,
|
||||
qualityAtFire: f.qualityAtFire,
|
||||
};
|
||||
});
|
||||
return { fires };
|
||||
}),
|
||||
|
||||
/** Create or update a user-owned rack. */
|
||||
saveRack: protectedProcedure
|
||||
.input(z.object({
|
||||
|
||||
@@ -1472,6 +1472,16 @@ export const api = {
|
||||
}>("confluence.backtest", { symbol, ...(opts?.weeks ? { weeks: opts.weeks } : {}) }),
|
||||
scorecard: (symbol?: string) =>
|
||||
trpcQuery<{ slots: unknown[]; note: string }>("confluence.scorecard", symbol ? { symbol } : {}),
|
||||
signalHistory: (symbol: string) =>
|
||||
trpcQuery<{
|
||||
fires: Array<{
|
||||
slotId: string;
|
||||
slotName: string;
|
||||
body: 'bull' | 'bear' | 'exit';
|
||||
firedAt: string;
|
||||
qualityAtFire: string;
|
||||
}>;
|
||||
}>("confluence.signalHistory", { symbol }),
|
||||
saveRack: (input: { id?: string; name: string; description?: string; slotIds: string[] }) =>
|
||||
trpcMutate<{ id: string; name: string; slotIds: string[]; isSystem: boolean; description: string | null }>("confluence.saveRack", input),
|
||||
corridorSnapshot: (symbol: string) =>
|
||||
|
||||
Reference in New Issue
Block a user