Реализация PnL-калькулятора (прибыль/убыток) в мобильном криптоприложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация PnL-калькулятора (прибыль/убыток) в мобильном криптоприложении
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация PnL-калькулятора (прибыль/убыток) в мобильном криптоприложении

P&L в крипте — не просто (цена продажи - цена покупки) × количество. Несколько покупок по разным ценам, комиссии в разных токенах, реализованный и нереализованный P&L, налоговые методы учёта (FIFO vs LIFO vs средняя стоимость) — каждый из этих факторов меняет итоговую цифру. Ошибка в расчёте обнаруживается при подаче налоговой декларации.

Модели расчёта P&L

Три метода учёта, которые дают разный результат для одинакового набора сделок:

FIFO (First In, First Out) — продаём сначала самые ранние купленные единицы. Стандарт для большинства юрисдикций.

LIFO (Last In, First Out) — продаём последние купленные. Выгоднее при растущем рынке (продаём дорого купленные недавно).

Average Cost (средняя стоимость) — делим общую стоимость позиции на количество. Проще для понимания, разрешён в ряде стран.

Пример с реальными числами — разница наглядна:

  • Покупка 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

Реализуем все три, с переключением в настройках:

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;
      }
    }

    // Нереализованный P&L по остатку в очереди
    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, и их учёт нетривиален. На биржах комиссия может быть:

  • В quote currency (продал BTC/USDT — комиссия в USDT, вычитается из полученной суммы)
  • В base currency (комиссия в BTC — уменьшает количество полученного)
  • В третьем токене (BNB на Binance при включённом fee discount)

Для корректного P&L — конвертируем все комиссии в quote currency по курсу на момент сделки:

double normalizeFeeToCurrency(Trade trade, double feeTokenPriceAtTime) {
  if (trade.feeAsset == trade.quoteCurrency) {
    return trade.fee; // уже в нужной валюте
  }
  // Комиссия в другом токене (BNB и т.д.)
  return trade.fee * feeTokenPriceAtTime;
}

Цена feeTokenPriceAtTime — из исторического API CoinGecko или Binance Klines для точной даты сделки.

Нереализованный P&L в реальном времени

unrealizedPnL = (currentPrice - avgEntryPrice) * holdingQuantity

Для обновления в реальном времени подписываемся на WebSocket тикер. avgEntryPrice после каждой покупки:

// При новой покупке пересчитываем среднюю цену (методом average cost)
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: как показывать P&L понятно

Три блока информации на одном экране:

  1. Нереализованный P&L — текущая позиция, обновляется в реальном времени. Крупный шрифт, зелёный/красный цвет, абсолютное значение + процент.

  2. Реализованный P&L — итог по закрытым сделкам за выбранный период. Менее критичен для мониторинга, но важен для налогов.

  3. Breakdown — таблица по каждой паре с entry price, количеством, текущей ценой, P&L.

Переключатель метода (FIFO/LIFO/Average Cost) — в настройках, с предупреждением что смена метода пересчитает всю историю.

Экспорт для налогов

Формат CSV с колонками: Date, Pair, Type (buy/sell), Price, Quantity, Fee, Fee Currency, Realized P&L, Method. Это базовый формат для большинства криптоналоговых сервисов (Koinly, CoinTracker) при импорте.

Что входит в работу

  • Реализация трёх методов расчёта (FIFO, LIFO, Average Cost) с переключением
  • Учёт комиссий в разных валютах
  • Нереализованный P&L с real-time обновлением через WebSocket
  • Реализованный P&L по истории сделок
  • Разбивка по торговым парам
  • Экспорт CSV для налоговой отчётности

Сроки

Базовый калькулятор (один метод, manual input): 3–5 дней. Полноценный с тремя методами, биржевым API, реальным временем и экспортом: 2–3 недели. Стоимость рассчитывается индивидуально.