How Price Is Calculated in Poly Data Trades: A Deep Dive into the Live-Trade Processor

Poly Data calculates trade prices by dividing the USDC-filled amount by the non-USDC token amount, with the ratio direction determined by which side of the trade receives USDC.

This article explains the exact price calculation logic used in the warproxxx/poly_data repository. The computation happens inside the get_processed_df function in update_utils/process_live.py, where raw on-chain order fill data gets transformed into human-readable trade prices denominated in USDC.


Where the Price Calculation Lives

The core price logic is implemented in update_utils/process_live.py at lines 91–95. This file contains the Live-trade processor, which ingests raw Polygon order fill events and produces a cleaned dataset with computed price columns.

The get_processed_df function performs several transformations in sequence:

  1. Normalizes token amounts by dividing by 10⁶ (USDC and most tokens use 6 decimals)
  2. Identifies which side of the trade is USDC
  3. Determines trade direction (BUY vs SELL)
  4. Computes the price ratio based on which party received USDC

The Price Formula: USDC per Token

The price calculation uses a conditional expression that checks whether the taker received USDC:

price = pl.when(pl.col("takerAsset") == "USDC") \
           .then(pl.col("takerAmountFilled") / pl.col("makerAmountFilled")) \
           .otherwise(pl.col("makerAmountFilled") / pl.col("takerAmountFilled")) \
           .cast(pl.Float64) \
           .alias("price")

This logic implements two cases:

Scenario Taker Direction Price Formula Result
Taker receives USDC SELL takerAmountFilled / makerAmountFilled USDC received per token sold
Maker receives USDC BUY makerAmountFilled / takerAmountFilled USDC paid per token bought

The price always represents the exchange rate of the non-USDC token in USDC terms, regardless of which party initiated the trade.


Step-by-Step Processing Pipeline

1. Amount Normalization

Before price calculation, raw on-chain amounts are converted to human-readable units:


# Raw amounts are in base units (1e6 for USDC)

makerAmountFilled = event["makerAmountFilled"] / 1_000_000
takerAmountFilled = event["takerAmountFilled"] / 1_000_000

2. USDC Side Detection

The pipeline identifies which asset is USDC to set up the price ratio correctly:


# Identify which side is USDC and set trade direction

is_taker_usdc = pl.col("takerAsset") == "USDC"
maker_direction = pl.when(is_taker_usdc).then("SELL").otherwise("BUY")
taker_direction = pl.when(is_taker_usdc).then("BUY").otherwise("SELL")

3. Price Computation

The final price column is computed using the conditional logic shown earlier, then cast to Float64 for precision.


Working Code Example

Here's a minimal reproduction of the price calculation using Polars:

import polars as pl

# Simulated trade data (amounts already normalized)

trades = pl.DataFrame({
    "makerAsset": ["USDC", "WETH", "USDC"],
    "takerAsset": ["WETH", "USDC", "DAI"],
    "makerAmountFilled": [500.0, 2.0, 1000.0],   # e.g., 500 USDC, 2 WETH, 1000 USDC

    "takerAmountFilled": [0.25, 3000.0, 2000.0],  # e.g., 0.25 WETH, 3000 USDC, 2000 DAI

})

# Apply Poly Data's price calculation

price_df = trades.with_columns(
    pl.when(pl.col("takerAsset") == "USDC")
      .then(pl.col("takerAmountFilled") / pl.col("makerAmountFilled"))
      .otherwise(pl.col("makerAmountFilled") / pl.col("takerAmountFilled"))
      .alias("price")
)

print(price_df.select(["makerAsset", "takerAsset", "price"]))

Output:


shape: (3, 3)
┌────────────┬────────────┬────────┐
│ makerAsset ┆ takerAsset ┆ price  │
│ ---        ┆ ---        ┆ ---    │
│ str        ┆ str        ┆ f64    │
╞════════════╪════════════╪════════╡
│ USDC       ┆ WETH       ┆ 2000.0 │  # 500 USDC / 0.25 WETH = 2000 USDC/WETH

│ WETH       ┆ USDC       ┆ 1500.0 │  # 3000 USDC / 2 WETH = 1500 USDC/WETH

│ USDC       ┆ DAI        ┆ 0.5    │  # 1000 USDC / 2000 DAI = 0.5 USDC/DAI

└────────────┴────────────┴────────┘


Key Files in the Price Calculation Pipeline

File Purpose Key Function
update_utils/process_live.py Core live-trade processing get_processed_df — contains the price calculation at lines 91–95
poly_utils/utils.py Market metadata helpers get_markets — provides token-pair mappings used before price calc
update_utils/update_markets.py Market data synchronization Ensures token symbols are current for USDC detection

Summary

  • Price calculation location: update_utils/process_live.py, lines 91–95, inside get_processed_df
  • Core formula: Ratio of USDC amount to non-USDC token amount, with direction determined by which party received USDC
  • Taker receives USDC: price = takerAmountFilled / makerAmountFilled
  • Maker receives USDC: price = makerAmountFilled / takerAmountFilled
  • Normalization: All amounts are divided by 10⁶ before calculation to handle USDC's 6-decimal precision
  • Output: Price always represents USDC per token for the non-USDC asset

Frequently Asked Questions

How does Poly Data handle tokens with different decimal places?

The current implementation assumes 6 decimal places (dividing by 10⁶) since the pipeline is optimized for USDC-centric markets. For tokens with different decimals, you would need to extend the normalization step in process_live.py to read each token's decimals field from the contract or metadata before dividing.

What happens if neither side of the trade is USDC?

The price calculation logic in get_processed_df expects one side to be USDC for the ratio to produce a meaningful price. If neither makerAsset nor takerAsset equals "USDC", the otherwise branch would still execute (makerAmountFilled / takerAmountFilled), but the resulting "price" would lack a stable reference unit and likely be filtered out or flagged in downstream analysis.

Can I modify the price calculation to use a different base currency?

Yes. To use a different base currency (e.g., WETH or DAI), modify the conditional in process_live.py at lines 91–95. Change pl.col("takerAsset") == "USDC" to your target asset, and ensure the ratio direction aligns with your chosen base. You may also need to update the normalization factor if the new base token uses a different decimal precision than 6.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →