How to export Webull orders, and why the ledger comes out with holes in it

An order log rather than a statement: eleven columns, a clock that names its own zone, and no expiration row anywhere because the format has none.

The steps

step 1
In the app: Account at the bottom, then History, then the download icon at the top right and Export Orders. On desktop: Account, then the three lines at the top right of the Orders widget, then Export Orders.
step 2
Confirm the email address and submit. The file arrives from noreply@webull.com within five to ten minutes.
step 3
Drop the CSV in whole. Rows that are not option contracts are left alone rather than journaled.

What you get, and what it means

what you get
SPXW230606C04285000   Buy   Cancelled
Filled 1   Total Qty 2   Avg Price 4.00
06/06/2023 10:10:11 EDT
what it means
an order that was pulled after one contract printed
the contract is real and the account owned it
the zone is stated, so the minute is 14:10:11 UTC

read by its status, this is a fill thrown away

Traps in this file

This is an order log, and a statement is a different thing

It records what was placed and what became of it, and nothing else. There is no expiration row, no assignment, no exercise and no cash settlement anywhere in the format, so a contract sold here and left to expire worthless simply stops appearing. Positions closed by trading are complete and correct; positions that ended at expiry stay open in the ledger forever, because the file records no event that ends them. Every Webull import says so.

The Filled column decides, never the Status

An order marked Cancelled can still have filled part of what it asked for before it was pulled. One corpus file carries a Cancelled SPXW order with 1 of 2 contracts filled and another with 2 of 3. Reading the status would throw away contracts the account really owned, so the filled quantity is used and the cancellation is noted on the row instead.

The symbol is already an OCC string

No other broker here manages that. Root, expiry, right and strike come straight out of it, which is why a Webull file needs no symbol mapping and never guesses a root.

The clock names its own zone, which nothing else does

Timestamps read 10/03/2023 12:36:56 EDT. Every other export in this list either omits the time, or prints one and leaves the zone to be inferred, or -- in thinkorswim's case -- labels it in a way that does not survive checking. Webull writes it down, so the minute is converted honestly and Desk's execution quality works on these fills.

Avg Price is the fill; Price is what was asked for

The Price column carries the limit and an @ in front of it. Avg Price is what actually printed, and that is the number used.

Does this file support execution quality?

Yes. Every fill carries the second it printed and the zone that second is in, so Desk can price it against the quote that was standing at that minute.

The current Orders Records export, options and equities. Webull states no per-order cash, so it is derived from the fill rather than left at zero -- a zero would travel into the realised total and quietly understate it. We have not found a Webull export that carries expirations or assignments; if one exists we would read it, and the import warning would go away.

Drop your Webull file