๐ Weighted Average Cost (WAC)
๐ก What is WAC?
The Weighted Average Cost (WAC) is the average unit cost of an asset in a portfolio, weighted by the quantity acquired at each price.
It answers the question: "On average, how much did I pay per unit for this asset?"
Other names
- PMC โ Prezzo Medio di Carico (Italy)
- ACB โ Average Cost Basis (Canada, US)
- CMP โ Coรปt Moyen Pondรฉrรฉ (France)
๐งฎ Formula
The WAC is computed iteratively as each transaction is processed chronologically:
Where:
- \(WAC_{current}\) = current weighted average cost before this transaction
- \(Q_{pool}\) = total quantity held in the pool before this transaction
- \(Cost_{unit}\) = per-unit acquisition cost of the new transaction
- \(Q_{tx}\) = quantity added by the new transaction
โ๏ธ How LibreFolio Computes WAC
LibreFolio uses an inventory-aware iterative algorithm that processes all qualifying transactions for a given (broker, asset) pair in chronological order.
๐ท๏ธ Transaction Effects
Each transaction contributes to the WAC computation in one of these ways:
| Effect | Condition | Impact on WAC |
|---|---|---|
| Weighted | qty > 0 and unit_cost > 0 |
WAC moves toward the new acquisition cost |
| Quantity reduced | qty < 0 |
Exits at current WAC โ WAC unchanged, pool shrinks |
| Dilution | qty > 0 but unit_cost = 0 |
Pool grows, numerator unchanged โ WAC decreases |
๐ Same-Day Ordering
When multiple transactions occur on the same date:
- Additions first (qty > 0) โ processed before reductions
- Reductions second (qty < 0) โ ensures the pool doesn't go transiently negative
๐ป Pool Depletion
- When
new_qty = 0: WAC resets to 0 (position closed) - When
new_qty < 0(rounding edge case): clamped to 0
๐ Practical Examples
Example 1: Two Buys โ WAC rises
| Date | Type | Qty | Unit Cost | Pool Qty | WAC |
|---|---|---|---|---|---|
| Apr 1 | BUY | 10 | $150 | 10 | $150.00 |
| Apr 15 | BUY | 5 | $180 | 15 | $160.00 |
The second buy at a higher price pulls the WAC up.
Example 2: Buy then Sell โ WAC unchanged
| Date | Type | Qty | Unit Cost | Pool Qty | WAC |
|---|---|---|---|---|---|
| Apr 1 | BUY | 10 | $150 | 10 | $150.00 |
| Apr 15 | SELL | -5 | (at WAC) | 5 | $150.00 |
The SELL removes units at the current WAC ($150). The WAC stays unchanged โ only the pool shrinks.
Example 3: Zero-Cost Acquisition โ Dilution
| Date | Type | Qty | Unit Cost | Pool Qty | WAC |
|---|---|---|---|---|---|
| Apr 1 | BUY | 10 | $150 | 10 | $150.00 |
| May 1 | ADJUSTMENT | +5 | $0 | 15 | $100.00 |
The WAC is diluted because 5 units entered at zero cost (e.g. stock split, airdrop, gift).
๐ Cost Basis Override
For transfers and adjustments, LibreFolio supports a cost basis override: a user-specified unit cost that represents the historical cost of the transferred units.
When set:
- The transaction enters the WAC computation as a normal weighted acquisition
- This preserves cost continuity across brokers (e.g., when transferring from broker A to broker B)
When not set:
- The transaction enters with
unit_cost = 0(dilution effect) - This is appropriate for stock splits, gifts, or airdrops where no purchase price exists
๐ Multi-Currency Handling
When a portfolio contains acquisitions in different currencies, LibreFolio:
- Determines the target currency (most frequent among acquisitions)
- Converts all unit costs to the target currency using historical FX rates
- Computes WAC in the unified target currency
FX Rate Availability
If a required FX rate is missing, the WAC computation may be incomplete. The UI warns about missing FX pairs and provides quick-actions to add or sync them.
๐ฏ Where WAC is Used in LibreFolio
- Transfer form: auto-suggests cost_basis_override for outgoing transfers
- P&L computation: realized gains = sell_price โ WAC (FIFO at runtime, WAC for cost basis)
- Portfolio view: average entry price per holding