Support Board
Date/Time: Mon, 10 Aug 2026 07:39:39 +0000
Post From: custom DTC trading service — new order not correlating with local order record
| [2026-08-10 04:01:52] |
| User144502 - Posts: 7 |
|
Setup Running a custom DTC Protocol trading server (Python, JSON encoding) that bridges Sierra Chart to the Schwab Trader API. `Server Address = 127.0.0.1:11099`, `Primary Connection Encoding = JSON`, `Skip Encoding Request for Primary Connection = Yes`, `Trade Simulation Mode` unchecked. Symptom After `SUBMIT_NEW_SINGLE_ORDER` and a correct, prompt `ORDER_UPDATE` reply, Sierra Chart does not update the order record it created locally when the order was placed. Instead it creates a **second, separate** internal order record from the `ORDER_UPDATE`, leaving the original stuck at `Order Sent` until it independently times out (~55–65 seconds later) with a "Trade Order Error - Order timed-out waiting for response from service/exchange server... Service Order ID: (none)" message — even though the server's reply was already received and processed correctly, just not matched to the original. Concrete example (BULL, 1 share, limit buy @ 6.94) Entry Time Symbol Status Internal Order ID Service Order ID LastOrderActionSource 22:52:55.085 BULL Order Sent 59876 (empty) BULL[M] Daily #1 | User order entry | Last: 7.3199997 | AOE=false | AOU=false 22:52:55.507 BULL- Open 59877 1007524020155 schwab-dtc-bridge (New) | New order originated from external service Both records carry the same `ClientOrderID` value (`59876.50810`, sent by Sierra Chart in the original `SUBMIT_NEW_SINGLE_ORDER` and echoed back unchanged in the server's `ORDER_UPDATE`). The second record (59877) appeared **422ms** after the first, at essentially the same instant the server's `ORDER_UPDATE` was sent — so the reply is fast and is being processed, just not correlated to 59876. 59876 subsequently produced, in Sierra Chart's Trade Service Log: ``` Requesting order status for non-responsive order. Time since last action: 62.9 seconds | Symbol: BULL | TradeAccount: roth_haiyang | InternalOrderID: 59876 | Current Status: Order Sent Trade Order Error - Order timed-out waiting for response from service/exchange server. Internal Order ID: 59876. Service Order ID: (none). Symbol: BULL. Account: roth_haiyang ``` 59877 shows correctly (`Open`, correct price/quantity/`Service Order ID`) and can be canceled reliably from the Trade Orders Window. What's been verified on the server side The server's `ORDER_UPDATE` for the immediate acknowledgment (sent right after the order is confirmed placed, before any other network activity) contains: ```json { "Type": 301, "TotalNumMessages": 1, "MessageNumber": 1, "ClientOrderID": "59876.50810", "ServerOrderID": "1007524020155", "TradeAccount": "brokerage", "Symbol": "BULL", "OrderStatus": 4, "OrderUpdateReason": 2, "OrderType": 2, "BuySell": 1, "Price1": 6.94, "Price2": null, "TimeInForce": 2, "OrderQuantity": 1, "FilledQuantity": 0.0, "RemainingQuantity": 1 } ``` - `ClientOrderID` matches exactly what Sierra Chart sent in `SUBMIT_NEW_SINGLE_ORDER`. - `ServerOrderID` is a proper string (this was previously sent as a bare JSON number by mistake and has been corrected — the symptom persisted either way). - `OrderStatus = 4` (`ORDER_STATUS_OPEN`, "order is open and working" per the documented enum) and `OrderUpdateReason = 2` (`NEW_ORDER_ACCEPTED`) — both per the ORDER_UPDATE documentation. - `TotalNumMessages = 1`, `MessageNumber = 1` per the documented value for an unsolicited report. - Confirmed via socket-level timing instrumentation that the message is written and drained to the TCP socket in ~0ms every time — the delay is not on the server's send side. Also tried and reverted: sending an initial `OrderStatus = ORDER_STATUS_ORDER_SENT` (1) handshake before the real acknowledgment, on the theory that Sierra Chart's local record (which starts in that state) might need to see it echoed back first. This made things worse — it created a **third**, separate, incomplete order record (`Order Type: Unknown`, since the handshake carries no order details), confirming (per your own documentation) that a server should never set that status, and that the correlation mechanism isn't reacting to status value at all. Two additional experiments tried since the above, both disproven live **1. Lossy JSON number encoding for `ClientOrderID`.** Theory: if `ClientOrderID` (shaped like `"59876.50810"`) were sent as a bare/unquoted JSON number rather than a quoted string, Python's default JSON parser would silently drop the trailing zero and reformat it slightly differently on the way back out (confirmed via direct repro: `59876.50810` round-trips to `59876.5081`), which could break an exact-text-match correlation. Added diagnostic logging of `ClientOrderID`'s raw value and type on receipt. Result on a fresh live order (INTC, `ClientOrderID = "61218.54096"`): logged as `python type: str`, byte-identical both directions. Sierra Chart does send this field as a proper JSON string. Same duplicate-record symptom occurred anyway. This is ruled out. **2. Order status lifecycle sequencing.** Theory: every acknowledgment sent so far jumped straight to `OrderStatus = 4` (`ORDER_STATUS_OPEN`), skipping a `ORDER_STATUS_PENDING_OPEN` (2) step that a real broker/DTC server would normally send first (New → PendingNew → Open). Changed the server to send `OrderStatus = 2` as the immediate acknowledgment (still a single, complete message with full order details — not an empty handshake), followed shortly after by a second `ORDER_UPDATE` transitioning to the real status (`OrderUpdateReason = 3`, `GENERAL_ORDER_UPDATE`) once available. Result on a fresh live order (GOOG): same duplicate-record symptom (`InternalOrderID 61889` stuck at "Order Sent"; a second record `61890` created as `Open`). One interesting new observation: the duplicate record's `LastOrderActionSource` text changed from the earlier "(New) | New order originated from external service" to **"(Order update)"** — it now appears the row-creation was triggered by the *second* message (`OrderUpdateReason = 3`) rather than the first (`OrderUpdateReason = 2`), i.e. the `PENDING_OPEN` message seems to have been silently ignored entirely rather than acted on. Either way, a new, uncorrelated row was still created rather than the original being updated in place. This is also ruled out as the mechanism, though the `LastOrderActionSource` label tracking `OrderUpdateReason` this precisely may be a useful clue for your engineers. Question What determines whether an incoming `ORDER_UPDATE` is matched to the pending order record Sierra Chart created locally when it sent `SUBMIT_NEW_SINGLE_ORDER`, versus being treated as an independently-discovered order from the external service? Is there a field, timing requirement, or connection setting involved beyond matching `ClientOrderID` that isn't covered in the DTC Messages and Procedures documentation? We've now ruled out message field correctness (every field checked against the documented spec), JSON encoding/type fidelity of `ClientOrderID`, `TotalNumMessages`/`MessageNumber` values, and `OrderStatus` lifecycle sequencing (`PENDING_OPEN` before `OPEN`) as explanations — the correlation failure appears to happen regardless of any of these. |
