Pnl Controller

PnL Controller - Portfolio Profit & Loss Calculation

Demo

Portfolio PnL Calculation

Overview

The PnlController is a C++ REST API controller that calculates Profit and Loss (PnL) for investment portfolios. It integrates with MongoDB for portfolio data and QuotesService for real-time market prices, providing accurate PnL calculations across multiple assets.

Features

  • Real-time PnL Calculation: Calculates profit/loss using current market prices
  • Portfolio Analytics: Tracks individual asset performance within portfolios
  • Batch Processing: Updates PnL for all portfolios in one operation
  • MongoDB Integration: Stores and retrieves portfolio data
  • Quotes Service Integration: Gets current market prices with caching

Architecture

Data Models

AssetQuote

struct AssetQuote {
    std::string sravz_id;
    double last_price;
    std::string price_capture_time;
};

PortfolioAsset

struct PortfolioAsset {
    std::string id;
    std::string sravz_id;
    double quantity;
    double weight;
    double purchase_price;
    double current_price;
    double purchase_value;
    double current_value;
    double pnl;
    double pnl_percent;
    std::string pnl_calculation_dt;
};

Portfolio

struct Portfolio {
    std::string id;
    std::string name;
    std::vector<std::string> portfolio_assets;
    double value;
    double pnl;
    double pnl_percent;
    std::string pnl_calculation_dt;
};

API Endpoints

Calculate Portfolio PnL

Endpoint: POST /api/pnl/calculate/{portfolio_id}

Calculates PnL for a specific portfolio.

Response:

{
    "portfolio_id": "60a1b2c3d4e5f6g7h8i9j0k1",
    "name": "Tech Portfolio",
    "total_value": 125000.50,
    "total_pnl": 15000.50,
    "pnl_percent": 13.64,
    "calculation_time": "2024-11-24T10:30:00Z",
    "assets": [
        {
            "sravz_id": "AAPL",
            "quantity": 100,
            "purchase_price": 150.00,
            "current_price": 175.50,
            "pnl": 2550.00,
            "pnl_percent": 17.00
        }
    ]
}

Update All Portfolios

Endpoint: POST /api/pnl/update-all

Updates PnL calculations for all portfolios in the system.

Response:

{
    "status": "success",
    "portfolios_updated": 25,
    "total_value": 5250000.00,
    "total_pnl": 450000.00,
    "update_time": "2024-11-24T10:30:00Z"
}

Implementation Details

PnL Calculation Logic

The controller calculates PnL using the following formulas:

  1. Purchase Value = quantity × purchase_price
  2. Current Value = quantity × current_price
  3. PnL (Dollar) = current_value - purchase_value
  4. PnL (Percentage) = (pnl / purchase_value) × 100

Workflow

  1. Load Portfolio Data: Retrieve portfolio and asset information from MongoDB
  2. Fetch Current Prices: Get latest prices from QuotesService (with caching)
  3. Calculate Asset PnL: Compute PnL for each asset in the portfolio
  4. Aggregate Portfolio PnL: Sum up all asset PnL values
  5. Update Database: Store calculated PnL values in MongoDB
  6. Return Results: Send PnL report as JSON response

Usage Example

Calculate Single Portfolio

#include <pnl_controller.hpp>

auto mongoClient = std::make_shared<MongoClient>();
auto quotesService = std::make_shared<QuotesService>(mongoClient);
auto pnlController = std::make_shared<PnlController>(mongoClient, quotesService);

// Calculate PnL for specific portfolio
std::string result = pnlController->calculatePortfolioPnl("portfolio_id_123");

Update All Portfolios

// Update PnL for all portfolios
std::string result = pnlController->updateAllPortfoliosPnl();

Integration with Router

The PnlController is integrated with the Boost Beast REST API router:

// In router.cpp
void router::handle_post_pnl_calculate(http::request<http::string_body> &req, 
                                       http::response<http::string_body> &res) {
    std::string portfolio_id = extract_path_param(req.target(), "portfolio_id");
    std::string result = pnlController_->calculatePortfolioPnl(portfolio_id);
    res.body() = result;
    res.set(http::field::content_type, "application/json");
}

Dependencies

  • MongoClient: For portfolio and asset data storage
  • QuotesService: For real-time market price data
  • Boost.JSON: For JSON serialization/deserialization
  • DependencyContainer: For dependency injection

See Also