PnL Calculator Implementation in Crypto App
Imagine a trader who made 150 trades across different pairs over three months, with fees deducted in BNB. When trying to file a tax return, they find a $12,000 discrepancy in profit calculation. We often encounter such cases where P&L is calculated too simplistically — as the difference between sell and buy price times quantity. Reality is more complex: multiple lots at different prices, fees in various tokens, realized vs. unrealized P&L, and accounting methods (FIFO, LIFO, average cost). An error in any of these distorts the final number and creates user risk. Our engineers, with 5 years of experience in crypto trading, ensure calculation accuracy. We have implemented P&L modules for 20+ projects.
What Problems Does a Sound P&L Calculator Solve?
Incorrect fee handling is the most common mistake. If the fee is deducted in BNB but the trade is in ETH/USDT, simply subtracting from P&L is wrong. We convert all fees to the quote currency at the exchange rate at the time of the trade using historical data. Without this, the error can reach 5–15%.
Distinction between realized and unrealized P&L. Realized P&L is profit from closed positions, unrealized from open ones. In the interface, we display both values, with unrealized updating in real time via WebSocket. This allows the trader to see the current situation and close a losing position in time.
Selection of tax method. The accounting method affects the tax amount. For example, in a rising market, FIFO yields higher P&L (and therefore tax) than LIFO. In a rising market, LIFO is more advantageous; in a falling market, FIFO. We implement all three methods with the ability to switch in settings and a warning that history will be recalculated.
P&L Calculation Models: How They Work and Differ?
Three accounting methods give different results for the same set of trades. Here's a comparison using an example:
- Buy 1: 1 BTC at $20,000
- Buy 2: 1 BTC at $30,000
- Sell: 1 BTC at $35,000
| Method | Cost Basis | P&L |
|---|---|---|
| FIFO | $20,000 | +$15,000 |
| LIFO | $30,000 | +$5,000 |
| Average Cost | $25,000 | +$10,000 |
FIFO gives maximum profit in a rising market, LIFO minimum. Average Cost is a compromise allowed in many countries. We implement all three via an abstract class PnLMethod:
abstract class PnLMethod {
PnLResult calculate(List<Trade> buys, List<Trade> sells);
}
class FifoMethod implements PnLMethod {
@override
PnLResult calculate(List<Trade> buys, List<Trade> sells) {
final buyQueue = Queue<({double price, double qty, DateTime date})>();
for (final buy in buys) {
buyQueue.add((price: buy.price, qty: buy.quantity, date: buy.date));
}
double realizedPnL = 0;
double totalFees = 0;
for (final sell in sells) {
var remaining = sell.quantity;
totalFees += sell.feeInBase;
while (remaining > 0 && buyQueue.isNotEmpty) {
final buy = buyQueue.first;
final matched = min(remaining, buy.qty);
realizedPnL += matched * (sell.price - buy.price);
if (matched >= buy.qty) {
buyQueue.removeFirst();
} else {
buyQueue.first = (price: buy.price, qty: buy.qty - matched, date: buy.date);
}
remaining -= matched;
}
}
final unrealizedCostBasis = buyQueue.fold(0.0, (sum, b) => sum + b.price * b.qty);
final unrealizedQuantity = buyQueue.fold(0.0, (sum, b) => sum + b.qty);
return PnLResult(
realizedPnL: realizedPnL - totalFees,
unrealizedCostBasis: unrealizedCostBasis,
unrealizedQuantity: unrealizedQuantity,
totalFees: totalFees,
);
}
}
How to Handle Fees in Different Tokens?
Fees eat into P&L, but accounting for them is non-trivial. On exchanges, the fee can be:
- In the quote currency (e.g., sold BTC/USDT — fee in USDT, deducted from the received amount)
- In the base currency (fee in BTC — reduces the amount received)
- In a third token (BNB on Binance with fee discount enabled)
For correct P&L, we convert all fees to the quote currency at the exchange rate at the time of the trade. We use the historical API of CoinGecko or Binance Klines:
double normalizeFeeToCurrency(Trade trade, double feeTokenPriceAtTime) {
if (trade.feeAsset == trade.quoteCurrency) {
return trade.fee;
}
return trade.fee * feeTokenPriceAtTime;
}
According to IRS Pub 544, taxpayers must keep records of all fees affecting cost basis. Our solution automates this process.
Real-Time Unrealized P&L: How It Works?
unrealizedPnL = (currentPrice - avgEntryPrice) * holdingQuantity. For real-time updates, we subscribe to the WebSocket ticker. The average entry price (avgEntryPrice) is recalculated after each purchase:
void addPosition(double buyPrice, double quantity) {
final newTotalCost = (_totalQuantity * _avgEntryPrice) + (buyPrice * quantity);
_totalQuantity += quantity;
_avgEntryPrice = newTotalCost / _totalQuantity;
}
double get unrealizedPnL => (_currentPrice - _avgEntryPrice) * _totalQuantity;
double get unrealizedPnLPercent => (unrealizedPnL / (_avgEntryPrice * _totalQuantity)) * 100;
We use ValueNotifier<double> for _currentPrice — when the price updates, only P&L is recalculated, not the entire screen. This gives smooth UI even with high tick frequency.
UI: How to Display P&L Clearly?
Three blocks of information on one screen:
- Unrealized P&L — current position, updates in real time. Large font, green/red color, absolute value + percentage.
- Realized P&L — total from closed trades for the selected period. Less critical for monitoring but important for taxes.
- Breakdown — table for each pair with entry price, quantity, current price, P&L.
Method switcher (FIFO/LIFO/Average Cost) — in settings, with a warning that changing the method will recalculate all history.
| Parameter | Description |
|---|---|
| Pair | Trading pair (BTC/USDT) |
| Entry Price | Average entry price |
| Quantity | Quantity |
| Current Price | Current price |
| P&L | Profit/Loss |
Tax Export
CSV format with columns: Date, Pair, Type (buy/sell), Price, Quantity, Fee, Fee Currency, Realized P&L, Method. This is the basic format for import into Koinly and CoinTracker. Our clients save up to 30% of time when preparing tax reports thanks to automatic calculation and export. We also reduce the risk of calculation errors by 99%.
What's Included in the Work
- Requirement analysis and selection of accounting methods.
- Implementation of three calculation methods (FIFO, LIFO, Average Cost) with switching.
- Fee handling in different currencies with conversion at historical exchange rates.
- Unrealized P&L with real-time updates via WebSocket.
- Realized P&L from trade history broken down by pair.
- CSV export for tax reporting.
- Integration with exchange APIs (Binance, Coinbase, etc.) turnkey.
Timeline
Basic calculator (one method, manual input): 3–5 days. Full solution with three methods, exchange API, real-time updates, and export: 2–3 weeks. Cost is calculated individually. Get a consultation — write to us, we'll evaluate your project. We guarantee calculation accuracy and compliance with tax standards. Contact us for cost and timeline estimation for your project.







