Skip to content

fix: OKX spot orders below 1 unit rejected with 51000 (sz precision misread as 0 for small lotSz)#1

Merged
lollipopkit merged 2 commits into
mainfrom
fix/okx-lotsz-precision
Jul 2, 2026
Merged

fix: OKX spot orders below 1 unit rejected with 51000 (sz precision misread as 0 for small lotSz)#1
lollipopkit merged 2 commits into
mainfrom
fix/okx-lotsz-precision

Conversation

@lollipopkit

@lollipopkit lollipopkit commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Internal review PR before submitting upstream (brokermr810#159).

Problem

Spot market orders below one whole base unit fail with OKX error 51000 (Parameter sz error) — e.g. a 50 USDT quick-trade buy of BTC/USDT (~0.0008 BTC).

Root cause

OkxClient._normalize_order_size() infers size precision by string-parsing lot_sz.normalize(). Decimal('0.00000001').normalize() renders as 1E-8 (no '.'), so precision falls back to 0 and _dec_str(sz, strict_precision=0) quantizes the size to "0".

Fix

Derive precision from the Decimal exponent: min(max(0, -exp), 18). Handles 0.00000001 → 8, 0.000001 → 6, 1 → 0, 10 → 0.

Testing

  • 3 regression tests in tests/test_okx_order_size_precision.py (instrument cache pre-seeded, no network); first case fails on old code.
  • Verified end-to-end on OKX demo trading via /api/quick-trade/place-order: previously-failing 50 USDT BTC/USDT market buy now fills (0.00081677 BTC @ 61246).

Summary by CodeRabbit

  • Bug Fixes
    • 修复下单数量精度推断在极小 lotSz 被归一化为科学计数法时的误判,避免将小于 1 的数量错误格式化为 0
    • 继续保持按交易步长向下取整,并遵守最小下单数量限制。
  • Tests
    • 新增/扩展回归测试,覆盖现货极小与常规 lotSz、整数合约 lotSz 以及正指数归一化的精度与格式化表现。

Decimal.normalize() renders lotSz values like 0.00000001 in scientific
notation (1E-8). The string-based precision parser found no '.' in
'1E-8' and fell back to precision 0, so any spot order below one whole
unit was quantized to sz="0" and rejected by OKX with error 51000
(Parameter sz error). Derive precision from the Decimal exponent
instead, and add regression tests.
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9e069599-9baf-4e9d-9e35-9f80921a46f9

📥 Commits

Reviewing files that changed from the base of the PR and between c1fce5b and 0f779ec.

📒 Files selected for processing (1)
  • backend_api_python/tests/test_okx_order_size_precision.py
📜 Recent review details
🔇 Additional comments (1)
backend_api_python/tests/test_okx_order_size_precision.py (1)

52-62: LGTM!


📝 Walkthrough

Walkthrough

修改了 OkxClient._normalize_order_sizelotSz 精度推断方式,并新增回归测试覆盖科学计数法、整数步长和正指数场景。

Changes

OKX 下单精度修复

Layer / File(s) Summary
精度推断逻辑修复
backend_api_python/app/services/live_trading/okx.py
lotSz 精度推断改为读取 Decimal.normalize().as_tuple().exponent,修正科学计数法表示被误判为 0 精度的问题。
回归测试覆盖
backend_api_python/tests/test_okx_order_size_precision.py
新增测试辅助函数和多个用例,覆盖极小步长、常规步长、整数步长及正指数步长下的精度推断与字符串渲染。

相关问题:未提供。

建议标签:bug, backend, tests

建议审阅者:未提供。


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
backend_api_python/tests/test_okx_order_size_precision.py (1)

43-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

建议补充 lotSz="10" 的回归测试。

PR 目标中明确提到修复需覆盖 0.000000010.000001110 这几类 lotSz 值,但当前测试仅覆盖了 lotSz="1"(exponent=0)的整数场景,未覆盖 lotSz="10"(正 exponent,走 max(0, -exp) 钳位到 0 的分支)。这是一条与 lotSz="1" 不同的代码路径,建议补充一个用例以确认该分支同样正确。

♻️ 建议新增的测试用例
 def test_swap_integer_lot_sz_precision_zero():
     # Swap contracts: lotSz=1 must keep precision 0 (whole contracts).
     c = _client_with_instrument("BTC-USDT-SWAP", "SWAP", "1", "1")
     c._inst_cache["SWAP:BTC-USDT-SWAP"][1]["ctVal"] = "0.01"
     sz, precision = c._normalize_order_size(
         inst_id="BTC-USDT-SWAP", market_type="swap", size=0.05
     )
     assert precision == 0
     assert c._dec_str(sz, strict_precision=precision) == "5"
+
+
+def test_swap_lot_sz_ten_precision_zero():
+    # lotSz=10 exercises the positive-exponent branch of max(0, -exp).
+    c = _client_with_instrument("XYZ-USDT-SWAP", "SWAP", "10", "10")
+    c._inst_cache["SWAP:XYZ-USDT-SWAP"][1]["ctVal"] = "1"
+    sz, precision = c._normalize_order_size(
+        inst_id="XYZ-USDT-SWAP", market_type="swap", size=25
+    )
+    assert precision == 0
+    assert c._dec_str(sz, strict_precision=precision) == "20"

As per the PR objectives which state the fix "correctly handles small lotSz values such as 0.00000001, 0.000001, 1, and 10", this branch should also be covered by a regression test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend_api_python/tests/test_okx_order_size_precision.py` around lines 43 -
51, Add a regression test in test_okx_order_size_precision to cover the
lotSz="10" case mentioned in the PR goals. Reuse _client_with_instrument and
_normalize_order_size to build a SWAP instrument with ctVal set so the precision
path exercises the positive exponent branch that clamps to 0, and assert the
returned precision remains 0 and the normalized size string is correct. Keep the
new test alongside test_swap_integer_lot_sz_precision_zero so the coverage is
easy to find.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend_api_python/tests/test_okx_order_size_precision.py`:
- Around line 43-51: Add a regression test in test_okx_order_size_precision to
cover the lotSz="10" case mentioned in the PR goals. Reuse
_client_with_instrument and _normalize_order_size to build a SWAP instrument
with ctVal set so the precision path exercises the positive exponent branch that
clamps to 0, and assert the returned precision remains 0 and the normalized size
string is correct. Keep the new test alongside
test_swap_integer_lot_sz_precision_zero so the coverage is easy to find.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 536cdef8-a2fb-4329-81fe-4b9acbb26810

📥 Commits

Reviewing files that changed from the base of the PR and between 31dde00 and c1fce5b.

📒 Files selected for processing (2)
  • backend_api_python/app/services/live_trading/okx.py
  • backend_api_python/tests/test_okx_order_size_precision.py
📜 Review details
🧰 Additional context used
🪛 Ruff (0.15.20)
backend_api_python/tests/test_okx_order_size_precision.py

[error] 15-15: Possible hardcoded password assigned to argument: "secret_key"

(S106)


[error] 15-15: Possible hardcoded password assigned to argument: "passphrase"

(S106)

🔇 Additional comments (3)
backend_api_python/app/services/live_trading/okx.py (1)

257-276: LGTM!

backend_api_python/tests/test_okx_order_size_precision.py (2)

1-21: LGTM!


23-40: LGTM!

@lollipopkit lollipopkit merged commit 19fc0aa into main Jul 2, 2026
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.

1 participant