When a trader reduces their trade size, the unrealizedPnlUsdX18 moves to a loss position even when the market price has not changed.
When a trader reduces the size of their open position, the protocol incorrectly starts with a loss even when the market price has not changed. This problem stems from the fact that the trader position is closed and a new position is created.
function testReducePositionSizeLeadToInitialLoss() public {
changePrank({ msgSender: users.sasuke.account });
uint256 amount = 10000 * 10 ** 6;
deal({ token: address(usdc), to: users.sasuke.account, give: amount });
uint128 tradingAccountId = createAccountAndDeposit(amount, address(usdc));
int128 size = 1 * 10 ** 18;
perpsEngine.createMarketOrder(
OrderBranch.CreateMarketOrderParams({
tradingAccountId: tradingAccountId,
marketId : BTC_USD_MARKET_ID,
sizeDelta: size
})
);
changePrank({ msgSender: marketOrderKeepers[1] });
bytes memory firstMockSignedReport =
getMockedSignedReport(0x00037da06d56d083fe599397a4769a042d63aa73dc4ef57709d31e9971a5b439, MOCK_BTC_USD_PRICE);
perpsEngine.fillMarketOrder(tradingAccountId, BTC_USD_MARKET_ID, firstMockSignedReport);
changePrank({ msgSender: users.sasuke.account });
Position.State memory position = perpsEngine.getPositionState(tradingAccountId,
BTC_USD_MARKET_ID,
MOCK_BTC_USD_PRICE
);
UD60x18 initialEntryPrice = position.entryPriceX18;
SD59x18 positionSize = position.sizeX18;
size = 0.5 * 10 ** 18;
perpsEngine.createMarketOrder(
OrderBranch.CreateMarketOrderParams({
tradingAccountId: tradingAccountId,
marketId: BTC_USD_MARKET_ID,
sizeDelta: -size
})
);
changePrank({ msgSender: marketOrderKeepers[1] });
bytes memory firstMockSignedReport2 =
getMockedSignedReport(0x00037da06d56d083fe599397a4769a042d63aa73dc4ef57709d31e9971a5b439, MOCK_BTC_USD_PRICE);
perpsEngine.fillMarketOrder(tradingAccountId, BTC_USD_MARKET_ID, firstMockSignedReport2);
changePrank({ msgSender: users.sasuke.account });
Position.State memory position3 = perpsEngine.getPositionState(
tradingAccountId,
BTC_USD_MARKET_ID,
MOCK_BTC_USD_PRICE
);
SD59x18 updatedPositionSize1 = position3.sizeX18;
SD59x18 unrealizedPnlUsdX181 = position3.unrealizedPnlUsdX18;
assert(unrealizedPnlUsdX181.intoInt256() < 0);
}
Update the calculation logic to ensure that when trader reduces their trader, the position does not start with a loss.