okx
This commit is contained in:
@@ -85,6 +85,8 @@ KEY_ALERT_INTERVAL_MINUTES=5
|
|||||||
BALANCE_REFRESH_SECONDS=60
|
BALANCE_REFRESH_SECONDS=60
|
||||||
# 后台监控轮询周期(秒)
|
# 后台监控轮询周期(秒)
|
||||||
MONITOR_POLL_SECONDS=3
|
MONITOR_POLL_SECONDS=3
|
||||||
|
# 移动保本同步交易所止盈止损的最小间隔(秒),避免频繁撤挂叠单
|
||||||
|
BREAKEVEN_EXCHANGE_MIN_INTERVAL_SEC=60
|
||||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||||
FULL_MARGIN_BUFFER_RATIO=0.98
|
FULL_MARGIN_BUFFER_RATIO=0.98
|
||||||
|
|
||||||
|
|||||||
+20
-16
@@ -47,7 +47,7 @@ from fib_key_monitor_lib import (
|
|||||||
key_signal_type_for_trade_record,
|
key_signal_type_for_trade_record,
|
||||||
stored_key_signal_type,
|
stored_key_signal_type,
|
||||||
)
|
)
|
||||||
from okx_orders_lib import fetch_okx_all_open_orders
|
from okx_orders_lib import cancel_okx_all_open_orders, fetch_okx_all_open_orders
|
||||||
from journal_chart_lib import (
|
from journal_chart_lib import (
|
||||||
JOURNAL_CHART_DEFAULT_LIMIT,
|
JOURNAL_CHART_DEFAULT_LIMIT,
|
||||||
JOURNAL_CHART_DEFAULT_TF1,
|
JOURNAL_CHART_DEFAULT_TF1,
|
||||||
@@ -202,6 +202,10 @@ AUTO_TRANSFER_BJ_HOUR = int(os.getenv("AUTO_TRANSFER_BJ_HOUR", "8"))
|
|||||||
WECHAT_TIMEOUT_SECONDS = int(os.getenv("WECHAT_TIMEOUT_SECONDS", "10"))
|
WECHAT_TIMEOUT_SECONDS = int(os.getenv("WECHAT_TIMEOUT_SECONDS", "10"))
|
||||||
AI_TIMEOUT_SECONDS = int(os.getenv("AI_TIMEOUT_SECONDS", "120"))
|
AI_TIMEOUT_SECONDS = int(os.getenv("AI_TIMEOUT_SECONDS", "120"))
|
||||||
MONITOR_POLL_SECONDS = int(os.getenv("MONITOR_POLL_SECONDS", "3"))
|
MONITOR_POLL_SECONDS = int(os.getenv("MONITOR_POLL_SECONDS", "3"))
|
||||||
|
BREAKEVEN_EXCHANGE_MIN_INTERVAL_SEC = max(
|
||||||
|
15, int(os.getenv("BREAKEVEN_EXCHANGE_MIN_INTERVAL_SEC", "60"))
|
||||||
|
)
|
||||||
|
_BREAKEVEN_LAST_EX_SYNC: dict[int, float] = {}
|
||||||
KLINE_TIMEFRAME = os.getenv("KLINE_TIMEFRAME", "5m")
|
KLINE_TIMEFRAME = os.getenv("KLINE_TIMEFRAME", "5m")
|
||||||
FULL_MARGIN_BUFFER_RATIO = float(os.getenv("FULL_MARGIN_BUFFER_RATIO", "0.98"))
|
FULL_MARGIN_BUFFER_RATIO = float(os.getenv("FULL_MARGIN_BUFFER_RATIO", "0.98"))
|
||||||
TRANSFER_CCY = os.getenv("TRANSFER_CCY", "USDT")
|
TRANSFER_CCY = os.getenv("TRANSFER_CCY", "USDT")
|
||||||
@@ -2579,18 +2583,7 @@ def cancel_okx_swap_open_orders(exchange_symbol):
|
|||||||
return
|
return
|
||||||
ensure_markets_loaded()
|
ensure_markets_loaded()
|
||||||
try:
|
try:
|
||||||
exchange.cancel_all_orders(exchange_symbol)
|
cancel_okx_all_open_orders(exchange, exchange_symbol)
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
for o in fetch_okx_all_open_orders(exchange, exchange_symbol):
|
|
||||||
oid = o.get("id")
|
|
||||||
if oid is None:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
exchange.cancel_order(str(oid), exchange_symbol)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2867,7 +2860,11 @@ def cancel_okx_tpsl_slot(exchange_symbol, slot):
|
|||||||
if not oid:
|
if not oid:
|
||||||
return
|
return
|
||||||
ensure_markets_loaded()
|
ensure_markets_loaded()
|
||||||
exchange.cancel_order(str(oid), exchange_symbol)
|
cancel_id = str(oid).split(":", 1)[0]
|
||||||
|
try:
|
||||||
|
exchange.cancel_order(cancel_id, exchange_symbol, {"stop": True})
|
||||||
|
except Exception:
|
||||||
|
exchange.cancel_order(str(oid), exchange_symbol, {"stop": True})
|
||||||
|
|
||||||
|
|
||||||
def replace_active_monitor_tpsl_on_exchange(order_row, stop_loss, take_profit):
|
def replace_active_monitor_tpsl_on_exchange(order_row, stop_loss, take_profit):
|
||||||
@@ -2877,7 +2874,9 @@ def replace_active_monitor_tpsl_on_exchange(order_row, stop_loss, take_profit):
|
|||||||
raise RuntimeError(reason or "实盘未就绪")
|
raise RuntimeError(reason or "实盘未就绪")
|
||||||
ex_sym = resolve_monitor_exchange_symbol(order_row)
|
ex_sym = resolve_monitor_exchange_symbol(order_row)
|
||||||
direction = order_row["direction"]
|
direction = order_row["direction"]
|
||||||
cancel_okx_swap_open_orders(ex_sym)
|
cancelled = cancel_okx_all_open_orders(exchange, ex_sym)
|
||||||
|
if cancelled > 0:
|
||||||
|
time.sleep(0.12)
|
||||||
pos_amt = get_live_position_contracts(ex_sym, direction)
|
pos_amt = get_live_position_contracts(ex_sym, direction)
|
||||||
if pos_amt is None or float(pos_amt) <= 0:
|
if pos_amt is None or float(pos_amt) <= 0:
|
||||||
try:
|
try:
|
||||||
@@ -4687,10 +4686,15 @@ def check_order_monitors():
|
|||||||
tp_ex = float(take_profit or 0)
|
tp_ex = float(take_profit or 0)
|
||||||
ok_live, _live_reason = ensure_okx_live_ready()
|
ok_live, _live_reason = ensure_okx_live_ready()
|
||||||
synced_ex = not ok_live
|
synced_ex = not ok_live
|
||||||
if ok_live and tp_ex > 0:
|
last_ex_sync = float(_BREAKEVEN_LAST_EX_SYNC.get(pid, 0))
|
||||||
|
interval_ok = (
|
||||||
|
time.time() - last_ex_sync
|
||||||
|
) >= BREAKEVEN_EXCHANGE_MIN_INTERVAL_SEC
|
||||||
|
if ok_live and tp_ex > 0 and interval_ok:
|
||||||
try:
|
try:
|
||||||
replace_active_monitor_tpsl_on_exchange(r, new_sl, tp_ex)
|
replace_active_monitor_tpsl_on_exchange(r, new_sl, tp_ex)
|
||||||
synced_ex = True
|
synced_ex = True
|
||||||
|
_BREAKEVEN_LAST_EX_SYNC[pid] = time.time()
|
||||||
_clear_breakeven_exchange_warn(pid)
|
_clear_breakeven_exchange_warn(pid)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(
|
||||||
|
|||||||
@@ -14,6 +14,31 @@ def _order_dedupe_key(order: dict) -> str:
|
|||||||
return str(order.get("id") or info.get("algoId") or info.get("ordId") or "")
|
return str(order.get("id") or info.get("algoId") or info.get("ordId") or "")
|
||||||
|
|
||||||
|
|
||||||
|
def _okx_algo_cancel_id(order_id: str) -> str:
|
||||||
|
oid = str(order_id or "")
|
||||||
|
if ":" in oid:
|
||||||
|
return oid.split(":", 1)[0]
|
||||||
|
return oid
|
||||||
|
|
||||||
|
|
||||||
|
def _okx_order_needs_stop_cancel_param(order: dict) -> bool:
|
||||||
|
"""OKX 条件/算法单撤单须 params.stop=True,否则 cancel_order 走普通单接口会静默失败。"""
|
||||||
|
if not isinstance(order, dict):
|
||||||
|
return False
|
||||||
|
info = order.get("info") or {}
|
||||||
|
if not isinstance(info, dict):
|
||||||
|
info = {}
|
||||||
|
if order.get("stopLossPrice") is not None or order.get("takeProfitPrice") is not None:
|
||||||
|
return True
|
||||||
|
if info.get("algoId") or info.get("slTriggerPx") or info.get("tpTriggerPx"):
|
||||||
|
return True
|
||||||
|
typ = str(order.get("type") or info.get("ordType") or "").lower()
|
||||||
|
for token in ("conditional", "oco", "trigger", "move_order_stop", "iceberg"):
|
||||||
|
if token in typ:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def fetch_okx_all_open_orders(ex, exchange_symbol: str) -> list[dict]:
|
def fetch_okx_all_open_orders(ex, exchange_symbol: str) -> list[dict]:
|
||||||
"""合并 OKX 普通挂单与算法挂单(去重)。"""
|
"""合并 OKX 普通挂单与算法挂单(去重)。"""
|
||||||
if not exchange_symbol:
|
if not exchange_symbol:
|
||||||
@@ -51,3 +76,41 @@ def fetch_okx_all_open_orders(ex, exchange_symbol: str) -> list[dict]:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def cancel_okx_all_open_orders(ex, exchange_symbol: str) -> int:
|
||||||
|
"""
|
||||||
|
撤销某合约全部挂单(普通 + 条件/算法)。
|
||||||
|
OKX 止盈止损在 orders-algo-pending,必须用 stop=True 才能撤掉。
|
||||||
|
"""
|
||||||
|
if not exchange_symbol:
|
||||||
|
return 0
|
||||||
|
ex.load_markets()
|
||||||
|
sym = exchange_symbol
|
||||||
|
try:
|
||||||
|
sym = ex.market(exchange_symbol)["symbol"]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
n = 0
|
||||||
|
for o in fetch_okx_all_open_orders(ex, sym):
|
||||||
|
oid = _order_dedupe_key(o)
|
||||||
|
if not oid:
|
||||||
|
continue
|
||||||
|
cancel_id = _okx_algo_cancel_id(oid)
|
||||||
|
params = {"stop": True} if _okx_order_needs_stop_cancel_param(o) else None
|
||||||
|
try:
|
||||||
|
ex.cancel_order(cancel_id, sym, params)
|
||||||
|
n += 1
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ex.cancel_order(oid, sym, params)
|
||||||
|
n += 1
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ex.cancel_all_orders(sym)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return n
|
||||||
|
|||||||
Reference in New Issue
Block a user