Реализация PnL-калькулятора в крипто-приложении
Представьте: трейдер за три месяца совершил 150 сделок с разными парами, комиссии списывались в BNB, а при попытке подать налоговую декларацию обнаружилось, что расчёт прибыли не сходится на $12 000. Мы часто встречаем такие кейсы, когда P&L считают упрощённо — как разность цены продажи и покупки, умноженную на количество. Реальность сложнее: несколько лотов по разным ценам, комиссии в разных токенах, разделение реализованного и нереализованного P&L, а также методы учёта (FIFO, LIFO, средняя стоимость). Ошибка в любом из этих пунктов искажает итоговую цифру и создаёт риски для пользователя. Наши инженеры с 5-летним опытом в крипто-трейдинге гарантируют точность расчётов. Мы уже реализовали P&L-модули для 20+ проектов.
Какие проблемы решает грамотный P&L-калькулятор?
Некорректный учёт комиссий — самая частая ошибка. Если комиссия списана в BNB, а сделка в ETH/USDT, простое вычитание из P&L неверно. Мы конвертируем все комиссии в валюту котировки по курсу на момент сделки, используя исторические данные. Без этого погрешность может достигать 5–15%.
Различие между реализованным и нереализованным P&L. Реализованный — это прибыль по закрытым позициям, нереализованный — по открытым. В интерфейсе мы показываем оба значения, причём нереализованный обновляется в реальном времени через WebSocket. Это позволяет трейдеру видеть текущую ситуацию и вовремя закрыть убыточную позицию.
Выбор налогового метода. От метода учёта зависит сумма налога. Например, при росте рынка FIFO даёт более высокий P&L (и, соответственно, налог), чем LIFO. На растущем рынке LIFO выгоднее, на падающем — FIFO. Мы реализуем все три метода с возможностью переключения в настройках и предупреждением о пересчёте истории.
Модели расчёта P&L: как они работают и чем отличаются?
Три метода учёта дают разный результат для одинакового набора сделок. Вот сравнение на примере:
- Покупка 1: 1 BTC по $20,000
- Покупка 2: 1 BTC по $30,000
- Продажа: 1 BTC по $35,000
| Метод | Себестоимость | P&L |
|---|---|---|
| FIFO | $20,000 | +$15,000 |
| LIFO | $30,000 | +$5,000 |
| Average Cost | $25,000 | +$10,000 |
FIFO даёт максимальную прибыль на растущем рынке, LIFO — минимальную. Average Cost — компромисс, разрешённый в ряде стран. Мы реализуем все три через абстрактный класс 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,
);
}
}
Как учесть комиссии в разных токенах?
Комиссии режут P&L, но их учёт нетривиален. На биржах комиссия может быть:
- В валюте котировки (например, продал BTC/USDT — комиссия в USDT, вычитается из полученной суммы)
- В базовой валюте (комиссия в BTC — уменьшает количество полученного)
- В третьем токене (BNB на Binance при включённом fee discount)
Для корректного P&L конвертируем все комиссии в quote currency по курсу на момент сделки. Используем исторический API CoinGecko или Binance Klines:
double normalizeFeeToCurrency(Trade trade, double feeTokenPriceAtTime) {
if (trade.feeAsset == trade.quoteCurrency) {
return trade.fee;
}
return trade.fee * feeTokenPriceAtTime;
}
Согласно IRS Pub 544, налогоплательщики обязаны вести учёт всех комиссий, влияющих на себестоимость. Наше решение автоматизирует этот процесс.
Нереализованный P&L в реальном времени: как это работает?
unrealizedPnL = (currentPrice - avgEntryPrice) * holdingQuantity. Для обновления в реальном времени подписываемся на WebSocket тикер. Средняя цена входа (avgEntryPrice) пересчитывается после каждой покупки:
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;
Используем ValueNotifier<double> для _currentPrice — при обновлении цены пересчитывается только P&L, не весь экран. Это даёт плавность UI даже при высокой частоте тиков.
UI: как показывать P&L понятно?
Три блока информации на одном экране:
- Нереализованный P&L — текущая позиция, обновляется в реальном времени. Крупный шрифт, зелёный/красный цвет, абсолютное значение + процент.
- Реализованный P&L — итог по закрытым сделкам за выбранный период. Менее критичен для мониторинга, но важен для налогов.
- Breakdown — таблица по каждой паре с entry price, количеством, текущей ценой, P&L.
Переключатель метода (FIFO/LIFO/Average Cost) — в настройках, с предупреждением, что смена метода пересчитает всю историю.
| Параметр | Описание |
|---|---|
| Pair | Торговая пара (BTC/USDT) |
| Entry Price | Средняя цена входа |
| Quantity | Количество |
| Current Price | Текущая цена |
| P&L | Прибыль/убыток |
Экспорт для налогов
Формат CSV с колонками: Date, Pair, Type (buy/sell), Price, Quantity, Fee, Fee Currency, Realized P&L, Method. Это базовый формат для импорта в Koinly и CoinTracker. Наши клиенты экономят до 30% времени при подготовке налоговой отчётности благодаря автоматическому расчёту и экспорту. Также снижаем риск ошибок в расчётах на 99%.
Что входит в работу
- Анализ требований и выбор методов учёта.
- Реализация трёх методов расчёта (FIFO, LIFO, Average Cost) с переключением.
- Учёт комиссий в разных валютах с конвертацией по историческому курсу.
- Нереализованный P&L с real-time обновлением через WebSocket.
- Реализованный P&L по истории сделок с разбивкой по парам.
- Экспорт CSV для налоговой отчётности.
- Интеграция с API бирж (Binance, Coinbase, etc.) под ключ.
Сроки
Базовый калькулятор (один метод, manual input): 3–5 дней. Полноценный с тремя методами, биржевым API, реальным временем и экспортом: 2–3 недели. Стоимость рассчитывается индивидуально. Получите консультацию — пишите, оценим ваш проект. Мы гарантируем точность расчётов и соответствие налоговым стандартам. Свяжитесь с нами для расчёта стоимости и сроков под ваш проект.







