修复读取

This commit is contained in:
dekun
2026-05-17 17:12:02 +08:00
parent 56f58c2b52
commit a250c28ceb
2 changed files with 106 additions and 35 deletions
+78 -35
View File
@@ -4742,59 +4742,83 @@ def fetch_gate_positions_close_history():
return []
ensure_markets_loaded()
since_ms = exchange_position_sync_since_ms()
try:
rows = exchange.fetch_positions_history(
None,
since=int(since_ms),
limit=int(EXCHANGE_POSITION_HISTORY_LIMIT),
params={"settle": "usdt"},
)
except Exception:
try:
rows = exchange.fetch_positions_history(
None,
since=int(since_ms),
limit=int(EXCHANGE_POSITION_HISTORY_LIMIT),
params={},
)
except Exception:
return []
until_ms = int(time.time() * 1000)
out = []
for p in rows or []:
h = _normalize_gate_position_history_entry(p)
if h and h["close_ms"] and h["side"] in ("long", "short") and h["symbol_u"]:
out.append(h)
return out
offset = 0
page_limit = min(100, int(EXCHANGE_POSITION_HISTORY_LIMIT))
max_total = int(EXCHANGE_POSITION_HISTORY_LIMIT)
def _pull(params_extra):
nonlocal offset
offset = 0
while len(out) < max_total:
params = dict(params_extra)
params["offset"] = offset
params["until"] = until_ms
try:
rows = exchange.fetch_positions_history(
None,
since=int(since_ms),
limit=page_limit,
params=params,
)
except Exception:
return False
if not rows:
break
for p in rows:
h = _normalize_gate_position_history_entry(p)
if h and h["close_ms"] and h["side"] in ("long", "short") and h["symbol_u"]:
out.append(h)
offset += len(rows)
if len(rows) < page_limit:
break
return True
if not _pull({"settle": "usdt"}):
_pull({})
return out[:max_total]
def sync_trade_records_from_exchange(conn):
"""为未同步的 trade_records 回填 Gate 平仓历史中的已实现盈亏。"""
def sync_trade_records_from_exchange(conn, force=False):
"""为未同步的 trade_records 回填 Gate 平仓历史中的已实现盈亏。返回统计 dict。"""
global _LAST_EXCHANGE_PNL_SYNC_AT
stats = {"ok": False, "hist_count": 0, "matched": 0, "pending": 0, "skipped": False}
if not exchange_private_api_configured():
return
stats["reason"] = "未配置 GATE_API_KEY / GATE_API_SECRET"
return stats
now = time.time()
if now - _LAST_EXCHANGE_PNL_SYNC_AT < 25.0:
return
if not force and now - _LAST_EXCHANGE_PNL_SYNC_AT < 25.0:
stats["ok"] = True
stats["skipped"] = True
return stats
try:
hist = fetch_gate_positions_close_history()
except Exception:
return
except Exception as e:
stats["reason"] = str(e)
return stats
stats["hist_count"] = len(hist)
if not hist:
_LAST_EXCHANGE_PNL_SYNC_AT = now
return
stats["ok"] = True
stats["reason"] = "交易所平仓历史为空(请检查 API 权限或 EXCHANGE_POSITION_SYNC_FROM_BJ"
return stats
candidates = conn.execute(
"""
SELECT id, symbol, direction, closed_at, closed_at_ms, opened_at, opened_at_ms
FROM trade_records
WHERE (exchange_sync_key IS NULL OR TRIM(exchange_sync_key) = '')
OR exchange_realized_pnl IS NULL
ORDER BY id DESC
LIMIT 200
"""
).fetchall()
stats["pending"] = len(candidates)
if not candidates:
stats["ok"] = True
_LAST_EXCHANGE_PNL_SYNC_AT = now
return
return stats
used = set()
matched = 0
for tr in candidates:
close_ms_trade = _to_ms_with_fallback(
tr["closed_at_ms"] if "closed_at_ms" in tr.keys() else None, tr["closed_at"]
@@ -4848,11 +4872,15 @@ def sync_trade_records_from_exchange(conn):
(float(pnl_val), eo, ec, sk, int(tr["id"])),
)
used.add(sk)
matched += 1
stats["matched"] = matched
stats["ok"] = True
_LAST_EXCHANGE_PNL_SYNC_AT = now
try:
conn.commit()
except Exception:
pass
return stats
# ====================== 主页面 ======================
@@ -4874,11 +4902,12 @@ def render_main_page(page="trade"):
order_list = []
for o in raw_order_list:
order_list.append(enrich_order_item(row_to_dict(o), current_capital))
exchange_pnl_sync = {}
if exchange_private_api_configured():
try:
sync_trade_records_from_exchange(conn)
except Exception:
pass
exchange_pnl_sync = sync_trade_records_from_exchange(conn) or {}
except Exception as e:
exchange_pnl_sync = {"ok": False, "reason": str(e)}
raw_records = conn.execute("SELECT * FROM trade_records ORDER BY id DESC").fetchall()
records = [to_effective_trade_dict(r) for r in raw_records]
total = len(records)
@@ -4947,9 +4976,23 @@ def render_main_page(page="trade"):
key_auto_min_planned_rr=KEY_AUTO_MIN_PLANNED_RR,
key_gate_rule_text=key_gate_rule_text,
kline_timeframe=KLINE_TIMEFRAME,
exchange_pnl_sync=exchange_pnl_sync,
)
@app.route("/api/sync_exchange_pnl")
@login_required
def api_sync_exchange_pnl():
conn = get_db()
stats = sync_trade_records_from_exchange(conn, force=True)
try:
conn.commit()
except Exception:
pass
conn.close()
return jsonify(stats)
@app.route("/")
@login_required
def index():