A Submission Is Not An Outcome
Most trading interfaces collapse the moment of ordering into one gesture. You press a button, a spinner turns, and a row appears. The row implies that something happened. What actually happened is at least four separate things, and any one of them can be the last thing that happens.
This matters most in the case nobody designs for: the request leaves, and the answer does not come back. The connection drops, the venue returns a code that means try again rather than no, or the process restarts between one step and the next. At that moment the only honest statement about the account is that its state is unknown. Software that treats an unknown as a nothing will submit again. Submitting again is how one intended position becomes two real ones.
CVEST records the order lifecycle as four states, and the rule that connects them is short: persist intent before submission, and reconcile uncertainty before any retry. This article follows one order through those states, using what the execution service actually does.
Four States, Not One Event
An order in the defined-risk options loop belongs to one leg of one cycle, and it carries a status and a submission state that answer different questions. The status is about the venue: pending, filled, canceled or rejected. The submission state is about the request itself: intent, acknowledged, or submission unknown.
The pair is deliberate. An order can be acknowledged and still unfilled, which is ordinary. An order can be an intent and never acknowledged, which means the venue may or may not have seen it. Reading only one of the two fields produces a confident answer to a question you did not ask.
The execution tick runs every five seconds, in-process. Each tick either advances the cycle or refuses to, and refusing is a normal outcome rather than a failure to be retried past.
Why The Intent Is Written First
Before a live order is sent, the executor builds the order record, gives it an identifier of its own, marks its submission state as intent, and attaches a decision-context record describing the cycle, the leg and the phase. It then writes that record to the database inside a transaction, together with the capital the cycle reserves. Only after the transaction commits does anything reach the venue.
The row it writes is an order intent, and it holds the exact request that will be sent: the instrument, the margin mode, the client order identifier, the side, the order type, the size and the limit price. The insert does nothing on conflict, and if a record with the same identifier exists with a different cycle or a different request body, the write fails with the message that an immutable order intent cannot be changed or reused. There is no path that edits an intent after the fact.
The reason for the ordering is recoverability. If the process dies immediately after the venue accepts the order, the durable record of what was attempted already exists, written before the attempt. A record written after a successful response would be missing in exactly the case where it is needed.
The capital reservation carries the same honesty. While an order is pending and not yet acknowledged, the cycle’s reservation is marked uncertain. Capital tied to an order whose outcome is unknown is not free capital, and it is not reported as free capital.
The Three Answers A Venue Can Give
Submission produces one of three results, and the executor treats them differently. If the venue returns its own order identifier, the order is marked acknowledged and the identifier is stored beside the intent. Acknowledgement means the venue has the order. It says nothing about fills.
If the venue returns a definite rejection, the order is marked rejected and the cycle moves to closing, with a reason recorded. For an entry the reason says the exchange rejected the entry. For an exit it says the exchange rejected the exit and that the owned contracts remain open, which is the more consequential of the two and is written down as such.
The third result is the one that decides whether the design is serious. A small set of venue codes, a missing response and a response without an order identifier are all classified as ambiguous rather than negative. In that case the order is marked submission unknown, the record is saved, and the error is raised so the tick ends. Nothing is resubmitted. The next tick finds an outstanding order and goes to reconciliation instead of to a new order.
Double Submission, In Plain Words
Idempotency has a plain meaning here: doing the same thing twice must not produce two positions. Two mechanisms carry that weight, and neither of them is a retry counter.
The first is naming. The identifier CVEST generates for the order is sent to the venue as the client order identifier, so the venue knows the order by the same name the journal does. That name is what makes an unknown outcome answerable. Reconciliation asks the venue about that exact identifier, matches the instrument, the side and the venue’s own order identifier against the stored intent, and refuses to accept a record whose identity does not line up.
The second is refusal. A new order cannot be created while any order on the cycle is still pending; the attempt fails with a message saying an outstanding order requires reconciliation before another intent. Settlement is blocked by the same condition. When a reconciliation attempt cannot complete, the error text is explicit that no order was resubmitted, because that is the fact a reader most needs at that moment.
The safe response to an unknown outcome is to ask the venue by name, not to send the order again.
Reconciliation also refuses to move backwards. Cumulative filled quantity may not decrease or exceed the ordered quantity, the fee currency must be the expected one, and the individual fills must sum to the cumulative quantity, sum to the reported fee, and produce the reported average price. If the venue’s own records do not yet agree with each other, the order stays pending and the tick ends with a message about waiting for complete fill history. The venue response and the fill records are stored on the order as evidence.
Partial Fills And The Order Of The Legs
Orders in the options loop are sent as immediate-or-cancel limit orders. They do not rest in the book. Whatever is available at the limit fills at once, and the remainder is canceled by the venue. A partial fill therefore arrives as a terminal order with a filled quantity smaller than the quantity that was asked for, not as a working order you could wait on.
When that happens during entry, the cycle stops building and moves to closing, with the reason recorded as a partial fill or rejection on entry. The loop does not top up the missing contracts at a worse price. It unwinds what it has.
Leg order is a safety property, not a preference. During entry, protective buys are sorted ahead of short sells, and every short order is checked against the protective contracts already confirmed filled; a short that would exceed that protection is refused. During an exit the sort is reversed, shorts first, and an attempt to close a protective leg while any short leg still has exposure is refused outright. Exits are attempted with limit orders, so quotes can move and liquidity can disappear between one tick and the next.
Paper and replay modes fill at the limit immediately and record a synthetic fill, which is the point: they show the shape of the workflow, not the fill a real book would have given. An interrupted simulation order is marked canceled on recovery and the cycle is closed out, because there is no venue to ask.
Reading What Is Still Outstanding
Each cycle in Position history lists its orders individually: side, quantity, instrument and strike, whether it was an entry or an exit, the order identifier, the filled quantity over the quantity ordered, the average price and the status. Remaining exposure on a leg is the sum of its entry fills minus its exit fills, which is why the per-order lines are shown rather than a single net figure.
The table below is a reading aid for those lines. It is not a score and not a health indicator. Read across from the state you are looking at to the column that says what it does not establish, because that column is where mistaken conclusions are usually made.
| State on the record | What it establishes | What it does not establish |
|---|---|---|
| Intent, not yet acknowledged | The exact request was persisted, under an identifier the venue also uses | That anything reached the venue at all |
| Acknowledged, still pending | The venue returned its own identifier for that request | That any contract has changed hands |
| Submission unknown | The attempt happened and the outcome is not yet evidence | That nothing filled; only reconciliation settles that |
| Terminal, filled below quantity | The fills the venue proved, with their fees and average price | That the missing quantity is still working somewhere |
| Reconciled and terminal | Fills, average price and fees agreed against venue records | What the position is worth at this moment |
Account, venue and live-or-paper identity stay attached to every one of those records, and reconciliation re-checks them: if the account bound to a cycle is no longer the account observed, the executor stops and says so rather than acting on the wrong book.
First Steps
- Open the cycle in Position history and read each order line on its own — filled over quantity, average price, status — before reading any total for the cycle.
- If any order is not terminal, stop there and download that cycle’s decision context as JSONL; the order intent and the reconciliation records are in it, with the venue evidence attached.
- Take the order identifier printed on the line and look up that same identifier at the venue, in the account named on the record, before drawing any conclusion about the position.
What The Record Will Not Do For You
Automated live execution is paused. The live-execution flag defaults to off, and with it off the executor refuses to place an order and says that existing positions remain monitored. What you can inspect today is the record and its structure, in paper and replay, and any history a live account has already produced.
The options loop has no cancel and no amend, and this is a consequence of the order type rather than a gap: an immediate-or-cancel order leaves nothing resting to cancel. The separate IBKR ticket path does submit day limit orders, and there a cancel is available on an order that is still working at the broker and owned by CVEST. That path also blocks a second submission from the same preview outright, and when a broker warning expires it says plainly that the original order must be reconciled and no replacement should be sent.
None of this makes an execution outcome predictable. It makes the outcome legible: at any moment you can say what was intended, what was sent, what the venue confirmed, and what is still unresolved. When the honest answer is that something is unresolved, the system is built to keep saying so rather than to produce a tidier one.
Read the risk information and check the current product scope before evaluating a workflow.
