Add Binance live trading, anti-stuck open/close recovery, and configurable rate limits.
OKX/Binance LIVE share half_open and option_closed_perp_pending repair paths; private REST throttles default to 1s and are tunable in settings. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""实盘防卡状态:half_open / option_closed_perp_pending。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.sim.ledger import Ledger
|
||||
from app.sim.matcher import BLOCKING_STATUSES, Matcher
|
||||
|
||||
|
||||
def test_blocking_statuses_include_repair_states() -> None:
|
||||
assert "half_open" in BLOCKING_STATUSES
|
||||
assert "option_closed_perp_pending" in BLOCKING_STATUSES
|
||||
assert "open" in BLOCKING_STATUSES
|
||||
|
||||
|
||||
def test_has_open_position_blocks_half_open(tmp_path, monkeypatch) -> None:
|
||||
monkeypatch.setenv("MODE", "SIM")
|
||||
from app.models.db import Database
|
||||
|
||||
db = Database(tmp_path / "t.db")
|
||||
m = Matcher(db)
|
||||
assert m.has_open_position() is False
|
||||
|
||||
with db._lock:
|
||||
db._conn.execute(
|
||||
"""UPDATE positions SET
|
||||
group_id=?, option_inst_id=?, option_side=?, option_qty_eth=?,
|
||||
option_qty_contracts=?, option_entry_px=?, status=?
|
||||
WHERE id=1""",
|
||||
("G-test", "ETH-OPT", "call", 2.0, 200.0, 10.0, "half_open"),
|
||||
)
|
||||
db._conn.commit()
|
||||
|
||||
assert m.has_open_position() is True
|
||||
assert m.position_status() == "half_open"
|
||||
|
||||
with db._lock:
|
||||
db._conn.execute(
|
||||
"UPDATE positions SET status='option_closed_perp_pending' WHERE id=1"
|
||||
)
|
||||
db._conn.commit()
|
||||
assert m.has_open_position() is True
|
||||
|
||||
with db._lock:
|
||||
db._conn.execute(
|
||||
"""UPDATE positions SET
|
||||
group_id=NULL, option_inst_id=NULL, status='flat' WHERE id=1"""
|
||||
)
|
||||
db._conn.commit()
|
||||
assert m.has_open_position() is False
|
||||
db.close()
|
||||
|
||||
|
||||
def test_ledger_allow_negative(tmp_path) -> None:
|
||||
from app.models.db import Database
|
||||
|
||||
db = Database(tmp_path / "l.db")
|
||||
ledger = Ledger(db)
|
||||
# 掏空
|
||||
snap = ledger.snapshot()
|
||||
ledger.apply_cash(-snap["available"], kind="drain", note="drain")
|
||||
try:
|
||||
ledger.apply_cash(-1.0, kind="fail", note="should fail")
|
||||
assert False, "expected RuntimeError"
|
||||
except RuntimeError:
|
||||
pass
|
||||
# LIVE 镜像允许透支
|
||||
bal = ledger.apply_cash(-1.0, kind="live", note="ok", allow_negative=True)
|
||||
assert bal < 0
|
||||
db.close()
|
||||
Reference in New Issue
Block a user