autotrade execute.rs — pre-POST assertion and fee accounting helpers

Date: 2026-06-15 File: crates/polymarket-fetch/src/pmv2/autotrade/execute.rs

Purpose

Houses the pre-flight order validation gate and fee/P&L accounting helpers used by the autotrade engine before posting any order to the CLOB.

Key Functions

assert_amounts

assert_amounts(
    got_maker, got_taker, got_contract,
    expected_maker, expected_taker,
    limit, neg_risk
)

Pre-flight gate executed before any order POST. Checks:

  1. Amount equality — got_maker == expected_maker and got_taker == expected_taker
  2. Verifying contract — compares got_contract against polymarket_clob::verifying_contract(neg_risk)
  3. Zero-taker guard — rejects if got_taker == 0
  4. Implied price ceiling — rejects if implied > limit + 0.0001 (see rounding artifact below)

cost_basis_usd

cost_basis_usd(filled_size, avg_fill_price, buy_fee_usd) -> Decimal

Computes cost basis using the real fill price, not the limit price, plus the buy-side fee. Correct accounting for positions that filled at a price different from the order limit.

realized_pnl

realized_pnl(sell_proceeds, sell_fee, cost_basis) -> Decimal

Net P&L = sell proceeds minus sell fee minus cost basis.

is_resolution_only

is_resolution_only(filled_size, avg_fill_price, min_fill_usd) -> bool

Returns true when filled_size * avg_fill_price < min_fill_usd. Signals that the notional is too small to warrant active management — position should be held to resolution rather than exited.

Critical Finding: Rounding Artifact in Price Ceiling Check

For a properly quantized BUY order where taker = floor(maker / limit), the ratio maker / taker can be slightly above limit by approximately 0.00001 at tick=0.01.

Why it happens: taker is truncated down (floor), meaning fewer shares → maker / taker overshoots the true limit by dust.

Concrete example:

  • maker = 6_250_000, taker = 7_621_900
  • implied = 6_250_000 / 7_621_900 ≈ 0.82001
  • limit = 0.82
  • Overshoot ≈ 0.00001

Fix: Tolerance of Decimal::new(1, 4) = 0.0001. Reject condition: implied > limit + 0.0001.

Without this tolerance, valid quantized orders would be incorrectly rejected by the pre-flight gate.

Clippy Note

The suboptimal_flops lint fires on a * b + c patterns in f64 arithmetic. Use a.mul_add(b, c) instead to satisfy the lint and potentially improve FP performance.

Other Notes

  • Decimal::from(u128) works fine — already established as a pattern in pricing.rs
  • All 7 tests in the module pass with exit 0
  • polymarket_clob::verifying_contract(neg_risk) is the canonical source for contract address; do not hardcode