From 25d31ff75a126412485f30f0477456e047992f61 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Thu, 30 Oct 2025 07:37:10 +0100 Subject: [PATCH] Fix: Save MAE/MFE values when trades exit Bug: MAE/MFE was tracked in memory during trades but not saved to database on exit Cause: updateTradeExit() wasn't receiving or saving MAE/MFE parameters Changes: - Added MAE/MFE fields to UpdateTradeExitParams interface - Modified updateTradeExit() to save maxFavorableExcursion, maxAdverseExcursion, maxFavorablePrice, maxAdversePrice - Updated both updateTradeExit() calls in Position Manager to pass MAE/MFE values - Enhanced exit logging to show final MAE/MFE percentages Impact: Future trades will now properly save MAE/MFE data for analytics Note: Past 2 trades (from before this fix) don't have MAE/MFE saved --- lib/database/trades.ts | 10 ++++++++++ lib/trading/position-manager.ts | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/database/trades.ts b/lib/database/trades.ts index 8798869..2ef5416 100644 --- a/lib/database/trades.ts +++ b/lib/database/trades.ts @@ -77,6 +77,11 @@ export interface UpdateTradeExitParams { holdTimeSeconds: number maxDrawdown?: number maxGain?: number + // MAE/MFE final values + maxFavorableExcursion?: number + maxAdverseExcursion?: number + maxFavorablePrice?: number + maxAdversePrice?: number } export async function createTrade(params: CreateTradeParams) { @@ -165,6 +170,11 @@ export async function updateTradeExit(params: UpdateTradeExitParams) { holdTimeSeconds: params.holdTimeSeconds, maxDrawdown: params.maxDrawdown, maxGain: params.maxGain, + // Save final MAE/MFE values + maxFavorableExcursion: params.maxFavorableExcursion, + maxAdverseExcursion: params.maxAdverseExcursion, + maxFavorablePrice: params.maxFavorablePrice, + maxAdversePrice: params.maxAdversePrice, status: 'closed', }, }) diff --git a/lib/trading/position-manager.ts b/lib/trading/position-manager.ts index 1c72c6d..a78f1c0 100644 --- a/lib/trading/position-manager.ts +++ b/lib/trading/position-manager.ts @@ -348,8 +348,13 @@ export class PositionManager { holdTimeSeconds, maxDrawdown: 0, maxGain: trade.peakPnL, + // Save final MAE/MFE values + maxFavorableExcursion: trade.maxFavorableExcursion, + maxAdverseExcursion: trade.maxAdverseExcursion, + maxFavorablePrice: trade.maxFavorablePrice, + maxAdversePrice: trade.maxAdversePrice, }) - console.log(`💾 External closure recorded: ${exitReason} at $${currentPrice} | P&L: $${realizedPnL.toFixed(2)}`) + console.log(`💾 External closure recorded: ${exitReason} at $${currentPrice} | P&L: $${realizedPnL.toFixed(2)} | MFE: ${trade.maxFavorableExcursion.toFixed(2)}% | MAE: ${trade.maxAdverseExcursion.toFixed(2)}%`) } catch (dbError) { console.error('❌ Failed to save external closure:', dbError) } @@ -616,8 +621,13 @@ export class PositionManager { holdTimeSeconds, maxDrawdown: 0, // TODO: Track this maxGain: trade.peakPnL, + // Save final MAE/MFE values + maxFavorableExcursion: trade.maxFavorableExcursion, + maxAdverseExcursion: trade.maxAdverseExcursion, + maxFavorablePrice: trade.maxFavorablePrice, + maxAdversePrice: trade.maxAdversePrice, }) - console.log('💾 Trade saved to database') + console.log('💾 Trade saved to database with MAE: ' + trade.maxAdverseExcursion.toFixed(2) + '% | MFE: ' + trade.maxFavorableExcursion.toFixed(2) + '%') } catch (dbError) { console.error('❌ Failed to save trade exit to database:', dbError) // Don't fail the close if database fails