Реалізація 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
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Реалізація 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 для податкової звітності

Строки

Базовий калькулятор (один метод, ручний ввід): 3–5 днів. Повнофункціональний з трьома методами, біржевим API, реальним часом та експортом: 2–3 тижні. Вартість розраховується індивідуально.