@@ -432,24 +432,32 @@ export function registerArbManageCommands(
432432 const perpNotional = shortPos . size * shortPos . markPrice ;
433433 const spotValueUsd = spotAmount * shortPos . markPrice ; // approx using perp mark price
434434
435- // Funding income: spot has 0 funding, perp short receives when rate > 0
436- let estimatedFundingIncome = 0 ;
437- if ( holdDurationMs && hourlyRate !== 0 ) {
438- const holdHours = holdDurationMs / ( 1000 * 60 * 60 ) ;
439- // Short position: pays when rate < 0, receives when rate > 0
440- estimatedFundingIncome = Math . abs ( hourlyRate ) * perpNotional * holdHours ;
441- if ( hourlyRate < 0 ) estimatedFundingIncome = - estimatedFundingIncome ;
442- }
443- // Add persisted accumulated funding
444- if ( persisted ?. accumulatedFunding ) {
445- estimatedFundingIncome += persisted . accumulatedFunding ;
435+ // Funding income: fetch actual payments from exchange API
436+ let actualFundingIncome = 0 ;
437+ try {
438+ const perpAdapter = await getAdapterForExchange ( shortPos . exchange ) ;
439+ const payments = await perpAdapter . getFundingPayments ( 200 ) ;
440+ const entryTime = persisted ? new Date ( persisted . entryTime ) . getTime ( ) : ( holdDurationMs ? Date . now ( ) - holdDurationMs : 0 ) ;
441+ for ( const p of payments ) {
442+ if ( p . symbol . toUpperCase ( ) . includes ( perpSymbol ) && p . time >= entryTime ) {
443+ actualFundingIncome += Number ( p . payment ) ;
444+ }
445+ }
446+ } catch {
447+ // Fallback to estimate if API fails
448+ if ( holdDurationMs && hourlyRate !== 0 ) {
449+ const holdHours = holdDurationMs / ( 1000 * 60 * 60 ) ;
450+ actualFundingIncome = Math . abs ( hourlyRate ) * perpNotional * holdHours ;
451+ if ( hourlyRate < 0 ) actualFundingIncome = - actualFundingIncome ;
452+ }
446453 }
454+ const estimatedFundingIncome = actualFundingIncome ;
447455
448- // Fees: spot buy + spot sell + perp short entry + perp buy to close
456+ // Fees: entry only (exit not yet paid)
449457 const { getTakerFee } = await import ( "../../constants.js" ) ;
450458 const spotFee = getTakerFee ( spotEx ) ;
451459 const perpFee = getTakerFee ( shortPos . exchange ) ;
452- const totalFees = ( spotValueUsd * spotFee * 2 ) + ( perpNotional * perpFee * 2 ) ;
460+ const entryFees = ( spotValueUsd * spotFee ) + ( perpNotional * perpFee ) ;
453461
454462 const direction = hourlyRate >= 0 ? "long-spot-short-perp" as const : "sell-spot-long-perp" as const ;
455463 const dailyFundingEstimate = Math . abs ( hourlyRate ) * perpNotional * 24 ;
@@ -474,8 +482,8 @@ export function registerArbManageCommands(
474482 holdDuration,
475483 holdDurationMs,
476484 estimatedFundingIncome,
477- estimatedFees : totalFees ,
478- netPnl : ( spotValueUsd - shortPos . entryPrice * spotAmount ) + shortPos . unrealizedPnl + estimatedFundingIncome - totalFees ,
485+ estimatedFees : entryFees ,
486+ netPnl : ( spotValueUsd - shortPos . entryPrice * spotAmount ) + shortPos . unrealizedPnl + estimatedFundingIncome - entryFees ,
479487 dailyFundingEstimate,
480488 } ) ;
481489 }
0 commit comments