Crypto fund NAV (Net Asset Value) calculation system

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Crypto fund NAV (Net Asset Value) calculation system
Complex
~5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Developing a Crypto Fund NAV (Net Asset Value) Calculation System

NAV = (Asset Value − Liabilities) / Number of Fund Shares. The formula is simple. Complexity lies in the fact that for a crypto fund, each component requires non-trivial technical solutions. Asset value changes every second, assets can be locked in DeFi protocols, liabilities include accrued but unpaid management fees, and the number of shares changes with subscriptions and redemptions. A system that recalculates NAV once a day using CoinGecko data is not considered production-ready for a regulated fund.

Price Sources and Manipulation Risk

Choosing a price source is not a technical but a methodological question with technical consequences. Three categories of sources with different characteristics:

Centralized Exchange (CEX) Prices

Binance, Coinbase, Kraken APIs provide real-time prices with latency < 100ms. Problems:

  • API rate limits with many assets
  • Price divergence between exchanges (arbitrage window)
  • Manipulation risk on less liquid pairs
  • Exchange uptime dependency

For official NAV calculation (T-1 or T-0), better to use VWAP (Volume-Weighted Average Price) over the last 1–4 hours of trading on the top 3 exchanges by pair liquidity:

def calculate_vwap(trades: List[Trade], window_hours: int = 1) -> Decimal:
    cutoff = datetime.utcnow() - timedelta(hours=window_hours)
    recent = [t for t in trades if t.timestamp >= cutoff]
    
    total_volume = sum(t.volume for t in recent)
    if total_volume == 0:
        return recent[-1].price if recent else Decimal('0')
    
    return sum(t.price * t.volume for t in recent) / total_volume

On-Chain Oracle Prices

Chainlink Price Feeds — decentralized oracles with aggregation from professional data providers. Update when deviation > 0.5% or per heartbeat (1 hour). For on-chain NAV calculation — the only acceptable option.

Uniswap V3 TWAP — Time-Weighted Average Price from pool observation buffer. Resistant to flash loan manipulation, but vulnerable to sustained manipulation on illiquid pools:

function getTWAP(address pool, uint32 period) external view returns (uint256 price) {
    uint32[] memory secondsAgos = new uint32[](2);
    secondsAgos[0] = period; // e.g., 1800 = 30 minutes
    secondsAgos[1] = 0;
    
    (int56[] memory tickCumulatives,) = IUniswapV3Pool(pool).observe(secondsAgos);
    
    int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
    int24 arithmeticMeanTick = int24(tickCumulativesDelta / int56(uint56(period)));
    
    price = TickMath.getSqrtRatioAtTick(arithmeticMeanTick);
    // conversion from sqrtPriceX96 to decimal...
}

Composited Pricing Pipeline

For a production fund, a multi-level scheme is recommended:

Primary:   Chainlink / CoinGecko CoinAPI
Fallback1: CEX VWAP (Binance + Coinbase + Kraken weighted by volume)
Fallback2: On-chain TWAP (Uniswap V3, 30min window)
Stale:     Last known price + staleness flag + manual override required

DeFi Position Accounting

This is the most complex part for a crypto fund with active DeFi strategy. Fund assets can simultaneously be:

  • In Uniswap V3 liquidity positions (concentrated liquidity, not fungible)
  • In Aave/Compound as collateral (with accruing interest)
  • In lending positions (debt to subtract)
  • In staking with vesting/lock-up (cannot be sold instantly)
  • In Curve/Convex as LP tokens (multi-asset pools)

Uniswap V3 Positions

V3 positions are NFTs (ERC-721). Position value depends on current pool price and price range:

async function getUniswapV3PositionValue(
  positionId: number, 
  priceUSD: Record<string, number>
): Promise<number> {
  const position = await positionManager.positions(positionId);
  const pool = await getPool(position.token0, position.token1, position.fee);
  
  const { amount0, amount1 } = getAmountsForLiquidity(
    pool.sqrtPriceX96,
    getSqrtRatioAtTick(position.tickLower),
    getSqrtRatioAtTick(position.tickUpper),
    position.liquidity
  );
  
  // Plus accrued fees
  const { fees0, fees1 } = await collectableFees(positionId);
  
  return (
    (amount0 + fees0) * priceUSD[position.token0] +
    (amount1 + fees1) * priceUSD[position.token1]
  );
}

Aave Positions

Aave returns data via getUserAccountData(address):

(
    uint256 totalCollateralBase,  // in USD * 10^8
    uint256 totalDebtBase,        // in USD * 10^8
    uint256 availableBorrowsBase,
    uint256 currentLiquidationThreshold,
    uint256 ltv,
    uint256 healthFactor
) = aaveLendingPool.getUserAccountData(fundAddress);

int256 netAavePosition = int256(totalCollateralBase) - int256(totalDebtBase);

Management Fee Accounting

Typical hedge fund fee structure (2/20 model):

  • Management fee: 2% annually from NAV, accrued daily (2% / 365 = 0.00548% per day)
  • Performance fee: 20% of NAV gain above High Water Mark (HWM)

Accrued but unpaid fees are fund liability, reducing NAV.

class NAVCalculator:
    def calculate_daily_management_fee(self, nav: Decimal, date: date) -> Decimal:
        daily_rate = Decimal('0.02') / Decimal('365')
        return nav * daily_rate
    
    def calculate_performance_fee(
        self, 
        current_nav_per_share: Decimal,
        high_water_mark: Decimal
    ) -> Decimal:
        if current_nav_per_share <= high_water_mark:
            return Decimal('0')
        
        gain_above_hwm = current_nav_per_share - high_water_mark
        return gain_above_hwm * Decimal('0.20')
    
    def calculate_nav(self, gross_assets: Decimal, accrued_fees: Decimal) -> Decimal:
        return gross_assets - accrued_fees

Subscriptions and Redemptions

When an investor enters the fund (subscription), new shares are issued at NAV on the subscription date. On exit (redemption) — shares are redeemed at NAV on redemption date. This requires atomic operations:

T+0: Investor transfers USDC → fund wallet
T+0: Pending subscription record is created
T+1: Official NAV is calculated (cut-off time)
T+1: Shares are issued: shares = usdcAmount / navPerShare
T+2: Investor receives confirmation and registry entry

Share registry can be on-chain (ERC-20, ERC-1400 for security tokens) or off-chain with traditional transfer agent. For regulated funds — ERC-1400/ST-20 with KYC/AML modules and transfer restrictions.

Audit and Reconciliation

Daily NAV should be reproducible and auditable. Architectural requirement: all data used in NAV calculation must be preserved:

CREATE TABLE nav_calculation_snapshots (
    id UUID PRIMARY KEY,
    calculation_date DATE NOT NULL,
    fund_id UUID NOT NULL,
    nav_per_share NUMERIC(28, 10) NOT NULL,
    total_nav NUMERIC(28, 10) NOT NULL,
    total_shares NUMERIC(28, 10) NOT NULL,
    price_sources JSONB NOT NULL,     -- all prices with sources
    positions_snapshot JSONB NOT NULL, -- state of each position
    accrued_fees NUMERIC(28, 10) NOT NULL,
    calculated_at TIMESTAMPTZ NOT NULL,
    calculated_by VARCHAR(100) NOT NULL,
    UNIQUE(fund_id, calculation_date)
);

Independent NAV verification (fund administrator) should have access to the same raw data. Divergence > 0.1% requires manual investigation.

System Architecture

Data collection layer: Go services for price collection (CEX websockets + oracle polling) with writing to TimescaleDB. Collection frequency — every minute for top assets.

NAV calculation engine: Python (numpy/pandas) for financial mathematics, runs on schedule and on-demand. Separate calculators for each position type (spot, DeFi LP, staking).

Admin dashboard: React + REST API data. Display NAV breakdown by position, NAV history, pending subscriptions/redemptions.

Reporting: automatic NAV report generation in PDF for investors and regulators.

Developing a system for a fund with 10–20 assets and basic DeFi positions (Aave, Uniswap) — 8–12 weeks. Support for complex strategies (options, structured products, cross-chain) requires additional 4–8 weeks.