OPG vs DAY Market Orders: Paper Trading Fill Analysis

Infrastructure

Background

On February 26, 2026 — the system's first live paper trade — MorningEdge submitted its initial batch of orders using TimeInForce.OPG (Market-on-Open) orders via the Alpaca paper trading API. The OPG order type is designed to participate in the opening auction at 9:30 AM ET, which is the standard institutional mechanism for capturing the opening print.

This report documents the failure of OPG orders in the Alpaca paper trading environment, the root cause analysis, the fix implemented, and the validation of the replacement approach.

Attempt 1: OPG Orders at 8:54 AM ET

Five OPG market orders were submitted at 08:54:40 AM ET:

TickerSharesResult
INTU260 filled — expired
CLBT7280 filled — expired
JOBY9640 filled — expired
IBIT259128 filled (49.4% partial)
TARA1,6750 filled — expired

Fill rate: 1/5 orders (20%), and even that was only a partial fill.

Root Cause Analysis

  • Narrow fill window: The paper engine's OPG simulation has approximately a 30-second window around 9:30 AM.
  • Limited simulated liquidity: The paper engine does not simulate full auction depth.
  • Not representative of live behavior: On a real exchange, OPG orders participate in the full opening auction order book.

Key insight: This was a platform limitation, not a strategy failure.

The Fix: DAY Market Orders + wait_for_market_open()

  1. Order type changed from TimeInForce.OPG to TimeInForce.DAY
  2. Added wait_for_market_open() — polls until 9:30:01 AM ET before submitting orders

Attempt 2: DAY Market Orders at 9:47 AM ET

TickerSharesFill PriceResult
NVAX914$10.96Filled instantly
STLA1,231$8.13Filled instantly
INTU25$395.85Filled instantly
OPEN1,912$5.24Filled instantly
RGTI538$18.59Filled instantly

Fill rate: 5/5 (100%). All five orders filled immediately.

Comparison

MetricOPG OrdersDAY Market Orders
Fill rate1/5 (20%)5/5 (100%)
Partial fills1 (IBIT: 128/259)0
Time to fill~36 min queue, then failedInstant
Ghost positionsYes (manual cleanup)None

Implications

  • Keep DAY market orders for paper validation. 100% fill rate eliminates execution uncertainty from the test results.
  • Phase C (live trading) will use marketable limit orders (Ask + $0.05) to control slippage while maintaining fill reliability.
  • wait_for_market_open() is permanent infrastructure. It ensures the opening print has established a market price before orders fire, regardless of order type.