From 56f58c2b52a0eaf8ba0084e4169746648ddf20ff Mon Sep 17 00:00:00 2001 From: dekun Date: Sun, 17 May 2026 16:39:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=BB=E5=8F=96=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E4=BB=93=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crypto_monitor_binance/app.py | 30 +++++++++++----------- crypto_monitor_gate/app.py | 48 +++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 306c452..ebb269b 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -1732,8 +1732,12 @@ def to_effective_trade_dict(row): item["effective_hold_seconds"] = get_effective_trade_field(row, "reviewed_hold_seconds", "hold_seconds", item.get("hold_seconds")) er_eff = get_effective_trade_field(row, "reviewed_entry_reason", "entry_reason", item.get("entry_reason")) item["effective_entry_reason"] = (str(er_eff).strip() if er_eff is not None else "") or "" - reviewed_pnl = get_effective_trade_field(row, "reviewed_pnl_amount", "pnl_amount", None) - has_reviewed_pnl = reviewed_pnl is not None and str(reviewed_pnl).strip() != "" + try: + _keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + _keys = [] + _reviewed_pnl_raw = row["reviewed_pnl_amount"] if "reviewed_pnl_amount" in _keys else None + has_reviewed_pnl = _reviewed_pnl_raw is not None and str(_reviewed_pnl_raw).strip() != "" ex_pnl = item.get("exchange_realized_pnl") if not has_reviewed_pnl and ex_pnl is not None and str(ex_pnl).strip() != "": try: @@ -4508,25 +4512,21 @@ def _coerce_ts_ms(val): if v > 1e12: return int(v) if v > 1e9: - return int(v) + return int(v * 1000.0) return int(v * 1000.0) def _unified_symbol_for_match(symbol_str): - if not symbol_str: - return "" - s = str(symbol_str).strip() + s = (symbol_str or "").strip().upper() if not s: return "" - try: - return normalize_exchange_symbol(s).split(":")[0] - except Exception: - x = s.upper().replace(" ", "") - if "/" in x: - return x.split(":")[0] - if x.endswith("USDT") and len(x) > 4: - return f"{x[:-4]}/USDT" - return x + if ":" in s: + s = s.split(":")[0] + if "_" in s and "/" not in s: + s = s.replace("_", "/") + if s.endswith("USDT") and "/" not in s and len(s) > 4: + s = f"{s[:-4]}/USDT" + return s def exchange_position_sync_since_ms(): diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index ef8a01a..b025dbd 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -1691,8 +1691,12 @@ def to_effective_trade_dict(row): item["effective_hold_seconds"] = get_effective_trade_field(row, "reviewed_hold_seconds", "hold_seconds", item.get("hold_seconds")) er_eff = get_effective_trade_field(row, "reviewed_entry_reason", "entry_reason", item.get("entry_reason")) item["effective_entry_reason"] = (str(er_eff).strip() if er_eff is not None else "") or "" - reviewed_pnl = get_effective_trade_field(row, "reviewed_pnl_amount", "pnl_amount", None) - has_reviewed_pnl = reviewed_pnl is not None and str(reviewed_pnl).strip() != "" + try: + _keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + _keys = [] + _reviewed_pnl_raw = row["reviewed_pnl_amount"] if "reviewed_pnl_amount" in _keys else None + has_reviewed_pnl = _reviewed_pnl_raw is not None and str(_reviewed_pnl_raw).strip() != "" ex_pnl = item.get("exchange_realized_pnl") if not has_reviewed_pnl and ex_pnl is not None and str(ex_pnl).strip() != "": try: @@ -3246,9 +3250,8 @@ def try_persist_exchange_margin_for_order(conn, order_id, exchange_symbol, direc def opened_at_str_to_ms(opened_at_str): if not opened_at_str: return None - try: - dt = datetime.strptime(str(opened_at_str).strip()[:19], "%Y-%m-%d %H:%M:%S") - except ValueError: + dt = parse_dt_for_trading_day(opened_at_str) + if dt is None: return None try: aware = dt.replace(tzinfo=APP_TZ) @@ -4651,25 +4654,22 @@ def _coerce_ts_ms(val): if v > 1e12: return int(v) if v > 1e9: - return int(v) + return int(v * 1000.0) return int(v * 1000.0) def _unified_symbol_for_match(symbol_str): - if not symbol_str: - return "" - s = str(symbol_str).strip() + """统一 ETH/USDT:USDT、ETH_USDT、ETH/USDT 便于与 trade_records 比对。""" + s = (symbol_str or "").strip().upper() if not s: return "" - try: - return normalize_exchange_symbol(s).split(":")[0] - except Exception: - x = s.upper().replace(" ", "") - if "/" in x: - return x.split(":")[0] - if x.endswith("USDT") and len(x) > 4: - return f"{x[:-4]}/USDT" - return x + if ":" in s: + s = s.split(":")[0] + if "_" in s and "/" not in s: + s = s.replace("_", "/") + if s.endswith("USDT") and "/" not in s and len(s) > 4: + s = f"{s[:-4]}/USDT" + return s def exchange_position_sync_since_ms(): @@ -4696,7 +4696,11 @@ def _normalize_gate_position_history_entry(p): return None info = p.get("info") or {} sym = p.get("symbol") or "" - side = (p.get("side") or "").strip().lower() + if not sym: + c_alt = str(info.get("contract") or "").strip() + if c_alt: + sym = c_alt.replace("_", "/") + side = (p.get("side") or info.get("side") or "").strip().lower() if side not in ("long", "short"): sz = info.get("accum_size") if info.get("accum_size") is not None else info.get("size") try: @@ -4780,11 +4784,11 @@ def sync_trade_records_from_exchange(conn): return candidates = conn.execute( """ - SELECT id, symbol, direction, closed_at, opened_at, opened_at_ms + 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) = '') ORDER BY id DESC - LIMIT 120 + LIMIT 200 """ ).fetchall() if not candidates: @@ -4825,7 +4829,7 @@ def sync_trade_records_from_exchange(conn): if best_d is None or d < best_d: best_d = d best = h - if best is None or best_d is None or best_d > 25 * 60 * 1000: + if best is None or best_d is None or best_d > 90 * 60 * 1000: continue sk = best["sync_key"] if sk in used: