Skip to content

docs(trade): add DelayedNotReported order status - #1263

Merged
hogan-yuan merged 2 commits into
longbridge:mainfrom
shinexia:feature-add-delayed-not-reported-state
Oct 14, 2026
Merged

hogan-yuan merged 2 commits into
longbridge:mainfrom
shinexia:feature-add-delayed-not-reported-state

Conversation

@shinexia

Copy link
Copy Markdown
Contributor

Documents the new time-conditional order monitoring state across all three locales.

Documents the new time-conditional order monitoring state across all three locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@shinexia
shinexia force-pushed the feature-add-delayed-not-reported-state branch from 93da28b to d079c44 Compare October 13, 2026 11:12
hogan-yuan added a commit that referenced this pull request Oct 13, 2026
#1286 (Cloudflare Pages) was merged while **Check text autocorrect** was
failing, so every PR opened since then fails the same 11 errors in files
it doesn't touch — e.g. #1263 and #1289.

This adds the CJK/ASCII spacing autocorrect asks for, in exactly the 11
places the CI job reports:

- `astro.config.ts` (1)
- `src/integrations/prebuild-skills.ts` (4) — log message strings only,
no behavior change
- `docs/superpowers/plans/2026-09-16-openapi-nginx-decommission.md` (6)

Once this is merged, re-running the autocorrect check on #1263 / #1289
should pass, since PR checks run against the merge with `main`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
hogan-yuan added a commit to longbridge/openapi that referenced this pull request Oct 14, 2026
…rders (#595)

Follows
[longbridge/developers#1263](longbridge/developers#1263)
(the new `DelayedNotReported` order status) and
[longbridge/developers#1289](longbridge/developers#1289)
(time-condition orders).

## 1. `OrderStatus::DelayedNotReported`

**Monitoring (time-condition order)**: the state a time-condition order
sits in before it is reported to the exchange.

No SDK enum variant matched that wire value. `OrderStatus` deserializes
through `impl_serde_for_enum_string!`, which falls back to
`unwrap_or_default()` → `OrderStatus::Unknown`, so nothing failed
loudly. Monitored time-condition orders simply became indistinguishable
from a genuinely unrecognized status in `today_orders` /
`history_orders` / `order_detail` and the order-changed push.

The variant is **appended after `PartialWithdrawal`** rather than
grouped with the other `*NotReported` values. The C/C++ and Node.js
enums use implicit discriminants:

- `lb_order_status_t` has no explicit values, so inserting mid-list
would shift every following value. That is an ABI break for anything
linked against a prebuilt C/C++ library.
- `nodejs/index.d.ts` emits a `const enum`, which TypeScript inlines at
the consumer's compile time. Renumbering would silently change
already-compiled code. Appending keeps every existing discriminant
stable (`DelayedNotReported = 18`).

## 2. Time-condition orders (`delayed_until`)

| Endpoint | SDK |
|---|---|
| Submit order / submit multi-leg order | `delayed_until`: hold the
order in `DelayedNotReported` and submit it at that time (later than
now, at most 90 days ahead; multi-leg supports only `LO` / `MO`) |
| Replace order | `delayed_until` moves the time; `clear_delayed_until`
turns it back into a regular order (wire `1`); leaving both unset keeps
the current time condition |
| `today_orders` / `history_orders` / `order_detail` |
`Order.delayed_until` / `OrderDetail.delayed_until`, unset when the
server returns `"0"` or omits it |

Per layer:

- **Rust:** `delayed_until(OffsetDateTime)` builders and
`ReplaceOrderOptions::clear_delayed_until()` (last call wins);
`Option<OffsetDateTime>` response fields.
- **C:** `const int64_t *delayed_until` (Unix seconds) on the three
option structs, plus `bool clear_delayed_until` on replace. Also on
`lb_order_t` / `lb_order_detail_t`. **Every new field is appended at the
end of its struct**, so existing field offsets are unchanged.
- **C++:** `std::optional<int64_t> delayed_until`, plus `bool
clear_delayed_until = false`.
- **Java:** `setDelayedUntil(OffsetDateTime)`,
`ReplaceOrderOptions.clearDelayedUntil()`, `getDelayedUntil()`.
- **Node.js:** `delayedUntil?: Date`, `clearDelayedUntil?: boolean`,
`get delayedUntil(): Date | null`.
- **Python:** `delayed_until: Optional[datetime]` /
`clear_delayed_until: bool = False` keyword arguments (appended, so
positional callers are unaffected), and `Order.delayed_until` /
`OrderDetail.delayed_until`.

In the bindings, clear takes precedence over a time when both are set.

### Edge cases handled

- **Wire sentinels:** a time at or before `1970-01-01T00:00:01Z` would
map to `0` (no condition) or `1` (clear), so it is sent as `2` instead.
The server then rejects it as a past time rather than silently placing a
regular order or clearing the condition.
- **Out-of-range timestamps:**
- C reports the error through the callback instead of panicking across
the FFI boundary.
- Node.js returns an `InvalidArg` error instead of aborting the process.
- **Lenient response parsing:** the response field also accepts a JSON
integer. A malformed, negative or out-of-range value reads as unset
instead of failing the whole `today_orders` / `history_orders` /
`order_detail` call, so users who upgrade are not exposed to a field the
server never sent before.
- **Python time zones:** `delayed_until` uses a dedicated converter.
- A timezone-aware `datetime` (one whose `utcoffset()` is not `None`)
converts by its real offset; a naive one is read as UTC.
- Other `datetime` parameters keep their existing wall-clock semantics.
For example, `history_candlesticks_by_offset(time=...)` relies on that.

## Second commit: regenerated `nodejs/index.js`

`npm run build:debug` regenerates `index.js` alongside `index.d.ts`. The
committed copy predated the `@napi-rs/cli@3.8.6` that the release
workflow pins, so it was regenerated separately (`38184a7`); it is
loader churn unrelated to the API changes.

## Verification

- `cargo clippy --all --all-features`: no new warnings. `cargo +nightly
fmt --all` applied.
- `cargo test -p longbridge --lib`: 70 passed. New tests cover:
  - request serialization for submit / multi-leg / replace
  - the sentinel clamp, and last-call-wins on replace
  - `"0"` / absent / `null` / integer / malformed responses
  - the new status
- `cargo build -p longbridge-c` (header regenerated); `clang++
-fsyntax-only` on `cpp/src/trade_context.cpp`.
- `cargo build -p longbridge-java` and `mvn compile` for the Java
classes.
- `npm run build:debug`: `index.d.ts` regenerated. Checked with a script
that an out-of-range `delayedUntil` returns `InvalidArg` and the process
stays alive.
- Python: built the wheel and called `submit_order` / `replace_order`
against a local fake HTTP server.
  - Aware `+08:00`, aware UTC and naive inputs all send `1767225600`.
  - The epoch is sent as `2`.
  - Clear sends `1` and wins over a time.
  - The field is omitted when unset.
- Not verified: an end-to-end order against a real account.

Go SDK counterpart: longbridge/openapi-go#123.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: 袁章洪 <zhanghong.yuan@longbridge-inc.com>
hogan-yuan added a commit to longbridge/openapi-go that referenced this pull request Oct 14, 2026
…(DelayedUntil) (#123)

Ports longbridge/openapi#595: the `DelayedNotReported` order status
([longbridge/developers#1263](longbridge/developers#1263))
and time-condition orders
([longbridge/developers#1289](longbridge/developers#1289)).

## Changes

- **`trade.OrderDelayedNotReported`:** a new `OrderStatus` constant for
the wire value `"DelayedNotReported"`, meaning a time-condition order
that is held and not yet reported to the exchange. `OrderStatus` is a
plain string, so the value was already passed through; the constant lets
callers compare against it instead of a literal.
- **`DelayedUntil int64`** (Unix seconds; `0` is not sent) on
`SubmitOrder`, `SubmitMultiLegOrder` and `ReplaceOrder`.
- On submit, the order is held in `OrderDelayedNotReported` and
submitted at that time (later than now, at most 90 days ahead; multi-leg
supports only `LO` / `MO`).
- On replace, `0` keeps the current time condition, the new
`ClearDelayedUntil` constant (`1`) clears it, and any other value sets a
new time.
- **`DelayedUntil string`** on `Order` / `OrderDetail`: the raw
Unix-seconds string from `TodayOrders` / `HistoryOrders` /
`OrderDetail`. It is `"0"`, or empty if the server omits the field, when
the order is not a time-condition order. This mirrors the existing
`TriggerAt string`. The wire field also accepts a JSON number (or
`null`), so a server-side type change in this new field cannot fail the
whole response.

Raw `int64` seconds follow the SDK's existing request conventions
(`ExpireTime`, `GetCashFlow.StartAt`). The mapping to the wire types
goes through `util.Copy`, the same as the neighbouring fields.

## Verification

- `go build ./...`, `go vet ./trade/...` and `go test ./trade/...` pass.
- `trade/delayed_until_test.go` exercises the real `util.Copy` +
`encoding/json` path:
- the wire values for submit / multi-leg / replace, including
`ClearDelayedUntil` and a new time
  - the field is omitted at zero for all three request types
- responses with `"0"`, a timestamp, a JSON number, `null`, and no field

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@hogan-yuan
hogan-yuan merged commit 1b2b58b into longbridge:main Oct 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants