refactor(backend): extract shared trading persistence types from SupabaseService

Made-with: Cursor
This commit is contained in:
Saravana Achu Mac 2026-04-04 18:56:20 -07:00
parent 774541289a
commit b306f3264e
6 changed files with 171 additions and 146 deletions

View File

@ -15,6 +15,29 @@ import {
type AlpacaSubTagIntent
} from '../utils/alpacaSubTag.js';
import { SymbolMapper } from '../utils/symbolMapper.js';
import type {
FilledLifecycleOrderRow,
ReconciliationBackfillAuditInsert,
ReconciliationBackfillAuditQuery,
ReconciliationBackfillAuditRow,
ReconciliationBackfillBatchSummary,
ReconciliationBackfillOrderInsert,
ReconciliationSubTagRepairSummary,
StaleOrderScope,
VirtualOpenPosition
} from './tradingPersistenceTypes.js';
export type {
FilledLifecycleOrderRow,
ReconciliationBackfillAuditInsert,
ReconciliationBackfillAuditQuery,
ReconciliationBackfillAuditRow,
ReconciliationBackfillBatchSummary,
ReconciliationBackfillOrderInsert,
ReconciliationSubTagRepairSummary,
StaleOrderScope,
VirtualOpenPosition
} from './tradingPersistenceTypes.js';
export interface UserConfig {
user_id: string;
@ -32,145 +55,6 @@ export interface UserConfig {
market_poll_interval_in_seconds: number;
}
export interface VirtualOpenPosition {
profileId: string;
symbol: string;
side: 'BUY' | 'SELL';
qty: number;
entryPrice: number;
stopLoss: number;
takeProfit: number;
userId?: string;
tradeId: string;
tradeIds: string[];
}
export interface StaleOrderScope {
profileId?: string;
userId?: string;
includeOrphanUserOrders?: boolean;
profileNullOnly?: boolean;
}
export interface FilledLifecycleOrderRow {
id?: string;
order_id?: string | null;
user_id?: string | null;
profile_id?: string | null;
symbol?: string | null;
trade_id?: string | null;
action?: string | null;
side?: string | null;
qty?: number | string | null;
quantity?: number | string | null;
price?: number | string | null;
status?: string | null;
source?: string | null;
sub_tag?: string | null;
stop_loss?: number | string | null;
take_profit?: number | string | null;
timestamp?: number | string | null;
created_at?: string | null;
filled_at?: string | null;
type?: string | null;
}
export interface ReconciliationBackfillOrderInsert {
user_id: string;
profile_id: string;
order_id: string;
symbol: string;
type: string;
side: string;
qty: number;
quantity: number;
price: number;
status: string;
timestamp: number;
filled_at?: string;
trade_id: string;
action: 'EXIT';
source: 'BOT';
sub_tag?: string;
}
export interface ReconciliationBackfillAuditInsert {
batch_id: string;
profile_id: string;
symbol: string;
trade_id: string;
exchange_order_id?: string | null;
exchange_client_order_id?: string | null;
backfill_order_id?: string | null;
filled_qty?: number | null;
filled_price?: number | null;
filled_at?: string | null;
dry_run: boolean;
decision: string;
reason?: string | null;
metadata?: Record<string, any> | null;
applied_at?: string | null;
reverted_at?: string | null;
}
export interface ReconciliationBackfillAuditQuery {
profileId?: string;
symbol?: string;
batchId?: string;
decisions?: string[];
fromIso?: string;
toIso?: string;
limit?: number;
offset?: number;
}
export interface ReconciliationBackfillAuditRow {
id: number;
batch_id: string;
profile_id: string;
symbol: string;
trade_id: string;
exchange_order_id?: string | null;
exchange_client_order_id?: string | null;
backfill_order_id?: string | null;
filled_qty?: number | null;
filled_price?: number | null;
filled_at?: string | null;
dry_run: boolean;
decision: string;
reason?: string | null;
metadata?: Record<string, any> | null;
applied_at?: string | null;
reverted_at?: string | null;
created_at: string;
}
export interface ReconciliationBackfillBatchSummary {
batchId: string;
firstSeenAt: string;
lastSeenAt: string;
profileIds: string[];
symbols: string[];
totalRows: number;
byDecision: Record<string, number>;
dryRunRows: number;
appliedRows: number;
revertedRows: number;
}
export interface ReconciliationSubTagRepairSummary {
attempted: boolean;
unsupported?: boolean;
scannedRows: number;
eligibleRows: number;
updatedRows: number;
skippedNoProfile: number;
skippedNoTrade: number;
skippedTagDisabled: number;
skippedAlreadyTagged: number;
dryRun: boolean;
}
class SupabaseService {
private client: SupabaseClient | null = null;
private tradeHistorySupportsSource: boolean | null = null;

View File

@ -1,4 +1,4 @@
import type { FilledLifecycleOrderRow } from './SupabaseService.js';
import type { FilledLifecycleOrderRow } from './tradingPersistenceTypes.js';
export type CanonicalLifecycleState = 'OPEN' | 'PARTIAL_EXIT' | 'CLOSED' | 'ORPHAN_EXIT';
export type CanonicalSide = 'BUY' | 'SELL';

View File

@ -4,11 +4,11 @@ import logger from '../utils/logger.js';
import { normalizeOrderAction, normalizeOrderStatus, normalizeTradeSide } from '../domain/tradingEnums.js';
import { healthTracker } from './healthTracker.js';
import { observabilityService } from './observabilityService.js';
import {
import type {
FilledLifecycleOrderRow,
ReconciliationBackfillAuditInsert,
ReconciliationBackfillOrderInsert
} from './SupabaseService.js';
} from './tradingPersistenceTypes.js';
import * as runtimeOrderRepository from './runtimeOrderRepository.js';
import type { TradeExecutor } from './TradeExecutor.js';
import {

View File

@ -1,9 +1,7 @@
import { config } from '../config/index.js';
import logger from '../utils/logger.js';
import { observabilityService } from './observabilityService.js';
import {
type ReconciliationSubTagRepairSummary
} from './SupabaseService.js';
import type { ReconciliationSubTagRepairSummary } from './tradingPersistenceTypes.js';
import { repairMissingSubTagsForProfile } from './runtimeOrderRepository.js';
export interface ReconciliationSubTagRepairContext {

View File

@ -25,7 +25,7 @@ import type {
ReconciliationSubTagRepairSummary,
StaleOrderScope,
VirtualOpenPosition
} from './SupabaseService.js';
} from './tradingPersistenceTypes.js';
import {
ORDER_CONTAINER,
RECONCILIATION_AUDIT_CONTAINER,

View File

@ -0,0 +1,143 @@
/**
* Shared shapes for orders, reconciliation audit, and virtual positions.
* Used by Cosmos-first repositories and legacy SupabaseService persistence.
*/
export interface VirtualOpenPosition {
profileId: string;
symbol: string;
side: 'BUY' | 'SELL';
qty: number;
entryPrice: number;
stopLoss: number;
takeProfit: number;
userId?: string;
tradeId: string;
tradeIds: string[];
}
export interface StaleOrderScope {
profileId?: string;
userId?: string;
includeOrphanUserOrders?: boolean;
profileNullOnly?: boolean;
}
export interface FilledLifecycleOrderRow {
id?: string;
order_id?: string | null;
user_id?: string | null;
profile_id?: string | null;
symbol?: string | null;
trade_id?: string | null;
action?: string | null;
side?: string | null;
qty?: number | string | null;
quantity?: number | string | null;
price?: number | string | null;
status?: string | null;
source?: string | null;
sub_tag?: string | null;
stop_loss?: number | string | null;
take_profit?: number | string | null;
timestamp?: number | string | null;
created_at?: string | null;
filled_at?: string | null;
type?: string | null;
}
export interface ReconciliationBackfillOrderInsert {
user_id: string;
profile_id: string;
order_id: string;
symbol: string;
type: string;
side: string;
qty: number;
quantity: number;
price: number;
status: string;
timestamp: number;
filled_at?: string;
trade_id: string;
action: 'EXIT';
source: 'BOT';
sub_tag?: string;
}
export interface ReconciliationBackfillAuditInsert {
batch_id: string;
profile_id: string;
symbol: string;
trade_id: string;
exchange_order_id?: string | null;
exchange_client_order_id?: string | null;
backfill_order_id?: string | null;
filled_qty?: number | null;
filled_price?: number | null;
filled_at?: string | null;
dry_run: boolean;
decision: string;
reason?: string | null;
metadata?: Record<string, any> | null;
applied_at?: string | null;
reverted_at?: string | null;
}
export interface ReconciliationBackfillAuditQuery {
profileId?: string;
symbol?: string;
batchId?: string;
decisions?: string[];
fromIso?: string;
toIso?: string;
limit?: number;
offset?: number;
}
export interface ReconciliationBackfillAuditRow {
id: number;
batch_id: string;
profile_id: string;
symbol: string;
trade_id: string;
exchange_order_id?: string | null;
exchange_client_order_id?: string | null;
backfill_order_id?: string | null;
filled_qty?: number | null;
filled_price?: number | null;
filled_at?: string | null;
dry_run: boolean;
decision: string;
reason?: string | null;
metadata?: Record<string, any> | null;
applied_at?: string | null;
reverted_at?: string | null;
created_at: string;
}
export interface ReconciliationBackfillBatchSummary {
batchId: string;
firstSeenAt: string;
lastSeenAt: string;
profileIds: string[];
symbols: string[];
totalRows: number;
byDecision: Record<string, number>;
dryRunRows: number;
appliedRows: number;
revertedRows: number;
}
export interface ReconciliationSubTagRepairSummary {
attempted: boolean;
unsupported?: boolean;
scannedRows: number;
eligibleRows: number;
updatedRows: number;
skippedNoProfile: number;
skippedNoTrade: number;
skippedTagDisabled: number;
skippedAlreadyTagged: number;
dryRun: boolean;
}