feat: Position Manager persistence + order cleanup + improved stop loss
- Add Position Manager state persistence to survive restarts - Auto-restore open trades from database on startup - Save state after TP1, SL adjustments, profit locks - Persist to configSnapshot JSON field - Add automatic order cancellation - Cancel all TP/SL orders when position fully closed - New cancelAllOrders() function in drift/orders.ts - Prevents orphaned orders after manual closes - Improve stop loss management - Move SL to +0.35% after TP1 (was +0.15%) - Gives more breathing room for retracements - Still locks in half of TP1 profit - Add database sync when Position Manager closes trades - Auto-update Trade record with exit data - Save P&L, exit reason, hold time - Fix analytics showing stale data - Add trade state management functions - updateTradeState() for Position Manager persistence - getOpenTrades() for startup restoration - getInitializedPositionManager() for async init - Create n8n database analytics workflows - Daily report workflow (automated at midnight) - Pattern analysis (hourly/daily performance) - Stop loss effectiveness analysis - Database analytics query workflow - Complete setup guide (N8N_DATABASE_SETUP.md)
This commit is contained in:
@@ -45,6 +45,19 @@ export interface CreateTradeParams {
|
||||
isTestTrade?: boolean
|
||||
}
|
||||
|
||||
export interface UpdateTradeStateParams {
|
||||
positionId: string
|
||||
currentSize: number
|
||||
tp1Hit: boolean
|
||||
slMovedToBreakeven: boolean
|
||||
slMovedToProfit: boolean
|
||||
stopLossPrice: number
|
||||
realizedPnL: number
|
||||
unrealizedPnL: number
|
||||
peakPnL: number
|
||||
lastPrice: number
|
||||
}
|
||||
|
||||
export interface UpdateTradeExitParams {
|
||||
positionId: string
|
||||
exitPrice: number
|
||||
@@ -144,6 +157,66 @@ export async function updateTradeExit(params: UpdateTradeExitParams) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update active trade state (for Position Manager persistence)
|
||||
*/
|
||||
export async function updateTradeState(params: UpdateTradeStateParams) {
|
||||
const prisma = getPrismaClient()
|
||||
|
||||
try {
|
||||
const trade = await prisma.trade.update({
|
||||
where: { positionId: params.positionId },
|
||||
data: {
|
||||
// Store Position Manager state in configSnapshot
|
||||
configSnapshot: {
|
||||
...(await prisma.trade.findUnique({
|
||||
where: { positionId: params.positionId },
|
||||
select: { configSnapshot: true }
|
||||
}))?.configSnapshot as any,
|
||||
// Add Position Manager state
|
||||
positionManagerState: {
|
||||
currentSize: params.currentSize,
|
||||
tp1Hit: params.tp1Hit,
|
||||
slMovedToBreakeven: params.slMovedToBreakeven,
|
||||
slMovedToProfit: params.slMovedToProfit,
|
||||
stopLossPrice: params.stopLossPrice,
|
||||
realizedPnL: params.realizedPnL,
|
||||
unrealizedPnL: params.unrealizedPnL,
|
||||
peakPnL: params.peakPnL,
|
||||
lastPrice: params.lastPrice,
|
||||
lastUpdate: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
return trade
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to update trade state:', error)
|
||||
// Don't throw - state updates are non-critical
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all open trades (for Position Manager recovery)
|
||||
*/
|
||||
export async function getOpenTrades() {
|
||||
const prisma = getPrismaClient()
|
||||
|
||||
try {
|
||||
const trades = await prisma.trade.findMany({
|
||||
where: { status: 'open' },
|
||||
orderBy: { entryTime: 'asc' },
|
||||
})
|
||||
|
||||
console.log(`📊 Found ${trades.length} open trades to restore`)
|
||||
return trades
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to get open trades:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add price update for a trade (for tracking max gain/drawdown)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user