fix(longbridge): keep GTC/GTD orders alive on transient Expired status - #1125
fix(longbridge): keep GTC/GTD orders alive on transient Expired status#1125FaintGhost wants to merge 2 commits into
Conversation
Longbridge marks US-equity GTC/GTD orders as Expired (status 16) between trading sessions; the state reverts to New once the market reopens. The previous mapping treated Expired as Inactive, which the UTA sync loop interpreted as a terminal rejection — the order was dropped from the pending queue and never re-observed, even though it was still alive at the broker (observed live: an NVDA GTC limit filled later and a NET GTC limit stayed open, both misreported as rejected). Disambiguate with timeInForce: Day orders (1) really expire at close and stay Inactive; GTC (2) / GTD (3) Expired maps to Submitted so the sync poller keeps watching until the order fills, cancels, or truly dies.
|
@FaintGhost is attempting to deploy a commit to the luokerenx4's Team Team on Vercel. A member of the Team first needs to authorize it. |
|
Thanks for the detailed live evidence here — the GTC failure mode is convincing, especially the order that later filled after UTA had already made the transient Before we reproduce this on a maintainer-owned branch, could you help us pin down a few Longbridge-specific semantics? We do not currently have a Longbridge test account, and this is a trading state-machine boundary where we would rather use venue evidence than infer behavior.
Our external contribution policy means we will not directly merge a cross-repository trading-surface branch; we use strong external PRs as implementation proposals and reimplement accepted changes on a maintainer-owned branch. Your report and analysis will be credited in |
… to fill Address maintainer review on TraderAlice#1125: 1. GTD is inferred, not observed — only the verified long-lived GTC TIF stays alive on Expired. Day(1) and GTD(3) now return Inactive so genuinely-dead orders (Day close-time expiry, GTD configured-date expiry) do not become permanently-pending UTA orders. Unknown/missing TIF is conservative. 2. Map executedQuantity -> order.filledQuantity so a recovered fill carries its full cost basis. Longbridge orderDetail returns executedQuantity on every non-zero fill (observed: NVDA 3 @ 218.99, ARM 2 @ 286.68); the previous mapping only surfaced avgFillPrice, leaving UTA's fill/cost-basis record incomplete even after the terminal-state fix. Live evidence (sanitized, longbridge-main, via SDK orderDetail): NVDA (later-filled): status=5, timeInForce=2(GTC), qty=3, executedQty=3, executedPrice=218.99 NET (still open): status=1, timeInForce=2, qty=1, executedQty=0 ARM (filled ok): status=5, timeInForce=2, qty=2, executedQty=2, executedPrice=286.68
|
Thanks for the detailed review — all five points are fair, and the code has been revised to address them. To get you venue evidence (not inference), I queried the live account's SDK directly and sanitized the response. All evidence is from On the revised commit ( 1. GTC transition evidence Direct
I did not capture a 2. GTD behavior — you're right, it was inferred. I had no GTD observation. Per your guidance I've narrowed the override to 3. Unknown/missing TIF. In the three observed responses, 4. Fill fidelity — confirmed, and fixed. 5. Safe acceptance path / paper. These observations are from a real-money live account. I have not verified the same after-hours transition on Longbridge paper/demo — I don't have GTC test orders on the paper account. I'd treat the live observation as venue evidence and, if it helps, I can submit a small GTC order on the paper/demo account to reproduce it without real-money exposure (say a far-OTM limit that would never fill). Let me know if you'd like me to run that. The account-side evidence is intentionally kept out of the repo — happy to provide more sanitized field dumps if useful. Thanks again for the tight review; the GTD narrowing and the fill-quantity gap were both good catches. |
Problem
Longbridge reports US-equity GTC/GTD limit orders as
Expired(status 16) between trading sessions — a transient venue state that reverts toNewonce the market reopens. The broker adapter mappedExpired → Inactive, and the UTA order-sync loop treats any non-Submittedstate as terminal (rejected). The order was then dropped from the pending queue and never re-observed.Live evidence (longbridge-main account): three GTC limits submitted together:
So the UTA state machine and the broker disagreed, and the discrepancy was only discoverable by querying the broker directly.
Fix
Disambiguate
Expiredwith the order'stimeInForce:Expired+ Day (1) →Inactive(a Day order genuinely expires unfilled at close)Expired+ GTC (2) / GTD (3) →Submitted(transient between sessions; keep the order in the pending queue so the sync poller keeps observing it until it fills, cancels, or truly terminates)makeOrderStatenow accepts and forwardstimeInForce;mapOpenOrdersupplies it from the broker response.Verification
LongbridgeBroker.spec.ts, including 4 new cases covering the Expired/TIF matrix