User edition: prune docs, license gate, obfuscate core lib.

Keep deploy/basic docs only; integrate sq.bz121.com license client; encrypt strategy/trade/key_monitor/options/hedge_plan for release.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-17 16:30:58 +08:00
parent 53863559f4
commit 16ef0f31e3
154 changed files with 1998 additions and 27914 deletions
+12 -124
View File
@@ -1,124 +1,12 @@
"""期权限价挂单:展示 enrichment + 超时自动撤单."""
from __future__ import annotations
import time
from typing import Any
def _safe_float(v: Any) -> float | None:
if v is None or v == "":
return None
try:
return float(v)
except (TypeError, ValueError):
return None
def order_age_seconds(order: dict[str, Any], *, now_ms: float | None = None) -> float | None:
"""根据交易所 cTime(ms) 估算挂单时长(秒)."""
ct = _safe_float(order.get("c_time") or order.get("cTime"))
if ct is None or ct <= 0:
return None
# OKX 一般为毫秒时间戳
if ct < 1e12:
ct *= 1000.0
now = float(now_ms if now_ms is not None else time.time() * 1000.0)
age = (now - ct) / 1000.0
return age if age >= 0 else 0.0
def is_close_pending_order(order: dict[str, Any]) -> bool:
"""平仓向限价挂单:卖出 / reduceOnly."""
side = str(order.get("side") or "").lower()
if side == "sell":
return True
return bool(order.get("reduce_only"))
def enrich_pending_orders(
orders: list[dict[str, Any]] | None,
*,
ttl_seconds: float = 600.0,
now_ms: float | None = None,
) -> list[dict[str, Any]]:
"""为 UI 附加挂单时长与自动撤倒计时."""
ttl = max(0.0, float(ttl_seconds or 0))
now = float(now_ms if now_ms is not None else time.time() * 1000.0)
out: list[dict[str, Any]] = []
for raw in orders or []:
o = dict(raw)
age = order_age_seconds(o, now_ms=now)
is_close = is_close_pending_order(o)
o["age_sec"] = round(age, 1) if age is not None else None
o["is_close_order"] = is_close
o["auto_cancel_enabled"] = bool(is_close and ttl > 0)
if age is not None and is_close and ttl > 0:
remain = max(0.0, ttl - age)
o["ttl_seconds"] = ttl
o["expire_in_sec"] = round(remain, 1)
o["stale"] = remain <= 0
else:
o["ttl_seconds"] = ttl if is_close else None
o["expire_in_sec"] = None
o["stale"] = False
out.append(o)
return out
def cancel_stale_close_pending_orders(
*,
fetch_pending: Any,
cancel_order: Any,
ttl_seconds: float = 600.0,
now_ms: float | None = None,
ex: Any = None,
) -> dict[str, Any]:
"""
平仓限价挂单超过 ttl 自动撤销.
fetch_pending(ex) -> list; cancel_order(ex, inst_id=..., ord_id=...).
"""
ttl = float(ttl_seconds or 0)
if ttl <= 0:
return {"ok": True, "cancelled": 0, "checked": 0, "skipped": "ttl_disabled"}
try:
orders = fetch_pending(ex) if ex is not None else fetch_pending()
except TypeError:
orders = fetch_pending(ex)
except Exception as e:
return {"ok": False, "msg": str(e), "cancelled": 0, "checked": 0}
enriched = enrich_pending_orders(orders or [], ttl_seconds=ttl, now_ms=now_ms)
cancelled: list[dict[str, Any]] = []
errors: list[str] = []
checked = 0
for o in enriched:
if not o.get("is_close_order"):
continue
checked += 1
if not o.get("stale"):
continue
inst = str(o.get("inst_id") or "").strip()
oid = str(o.get("ord_id") or "").strip()
if not inst or not oid:
continue
try:
if ex is not None:
res = cancel_order(ex, inst_id=inst, ord_id=oid)
else:
res = cancel_order(inst_id=inst, ord_id=oid)
except TypeError:
res = cancel_order(ex, inst_id=inst, ord_id=oid)
except Exception as e:
errors.append(f"{oid}:{e}")
continue
if res.get("ok"):
cancelled.append({"inst_id": inst, "ord_id": oid, "age_sec": o.get("age_sec")})
else:
errors.append(f"{oid}:{res.get('msg') or 'cancel_failed'}")
return {
"ok": True,
"cancelled": len(cancelled),
"checked": checked,
"orders": cancelled,
"errors": errors,
"ttl_seconds": ttl,
}
# obfuscated module — do not edit
import base64, marshal, zlib
_B = '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'
_K = '5eb9e6dda894c57a4e02d809ae440d49'
def _d(b, k):
raw = zlib.decompress(base64.b64decode(b))
key = k.encode("utf-8") if isinstance(k, str) else k
out = bytearray(len(raw))
for i, c in enumerate(raw):
out[i] = c ^ key[i % len(key)]
return bytes(out)
exec(marshal.loads(_d(_B, _K)), globals())