shared/economy.ts

export type EconomyDays=1|7|30;
export type EconomyVerdict='broad-rise'|'broad-fall'|'mixed'|'little-change'|'insufficient';
export interface EconomyPeriod {vwap:number|null;volume:number;gross:number;fills:number;activeBuckets:number;largestBucketShare:number|null;low:number|null;high:number|null}
export interface EconomyItem {id:number;name:string;previous:EconomyPeriod|null;current:EconomyPeriod|null;changePct:number|null;eligible:boolean;reasons:string[];sourceIds:string[]}
export interface EconomySource {id:string;url:string;fetchedAt:number|null;sourceUpdatedAt:number|null;servedFromSourceCache:boolean}
export interface EconomySnapshot {
 snapshotId:string;methodologyVersion:'economy-v1';state:'complete'|'partial';
 basket:{id:string;version:1;label:string;note:string;items:{id:number;name:string;weight:number}[]};periodDays:EconomyDays;
 previous:{from:number;toExclusive:number};current:{from:number;toExclusive:number};collectionStartedAt:number;collectionFinishedAt:number;oldestFetchedAt:number|null;newestFetchedAt:number|null;
 verdict:EconomyVerdict;breadth:{eligible:number;total:number;rising:number;falling:number;flat:number;medianChangePct:number|null};
 index:{referenceFrom:number;referenceToExclusive:number;points:{from:number;toExclusive:number;value:number|null;missingItemIds:number[]}[]};
 items:EconomyItem[];contributions:{unit:'log-percentage-points';complete:boolean;totalLogPoints:number|null;ordinaryChangePct:number|null;rows:{itemId:number;weight:number;logPoints:number|null;eligible:boolean}[]};
 basketComparisons:{basketId:string;label:string;eligible:number;total:number;missingItemIds:number[];index:number|null;changePct:number|null;verdict:EconomyVerdict}[];
 market:{catalogComplete:boolean;observed:number;expected:number|null;windowDays:number;windowKind:'rolling';summary:{tradedItems:number;twoSidedItems:number;unitsTraded:number;matchedFills:number;taxBurnedGp:number;tradeValue:{totalGp:number;top5Share:number|null};largestItemTurnoverShare:number|null;largestTurnoverItemId:number|null}};
 insights:{id:string;kind:'observation'|'hypothesis';text:string;itemIds:number[];evidencePaths:string[]}[];sources:EconomySource[];limitations:string[];
}
export interface EconomyJob {state:'queued'|'running';jobId:string;completedReads:number;plannedReads:number;retryAfterSeconds:2;previousSnapshotId:string|null;nextAttemptAt?:number;waitingReason?:string}
export interface EconomyAttempt {attemptId:string;state:'complete'|'partial'|'failed';snapshotId:string|null;finishedAt:number;error:{code:string;message:string}|null}
export interface EconomyDelivery {servedAt:number;cacheHit:boolean;fetchAgeMs:number|null;freshness:'fresh'|'stale'|'unknown';publicationAgeKnown:boolean;reasons:string[]}
export interface EconomyEnvelope {schemaVersion:1;data:EconomySnapshot;delivery:EconomyDelivery;refreshJob:EconomyJob|null;latestAttempt:EconomyAttempt|null}
export const economyVerdicts:Record<EconomyVerdict,string>={'broad-rise':'Broad rise within tracked basket','broad-fall':'Broad fall within tracked basket',mixed:'Mixed','little-change':'Little change',insufficient:'Insufficient evidence'};