fix模拟盘流水重算VWAP按合约分段,避免两笔卖回混算。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-13 11:56:47 +08:00
parent 11a083470d
commit 57ca5ebc8f
@@ -37,56 +37,72 @@ def _ledger_buy_sell(
"""在开仓前后窗口内汇总 USDT→币 与 平仓后币→USDT.""" """在开仓前后窗口内汇总 USDT→币 与 平仓后币→USDT."""
u = (underly or "").upper() u = (underly or "").upper()
inst = str(inst_id or "").strip() inst = str(inst_id or "").strip()
buys = conn.execute(
"""
SELECT amount, ts FROM sim_ledger_entries
WHERE ccy='USDT' AND account='trading' AND kind='convert'
AND amount < 0 AND note LIKE ?
AND ts >= datetime(?, '-14 hour')
AND ts <= datetime(?, '+14 hour')
ORDER BY id
""",
(f"{u}/USDT%", open_ts, open_ts),
).fetchall()
buy_usdt = 0.0 buy_usdt = 0.0
buy_coin = 0.0 buy_coin = 0.0
for row in buys: opens = conn.execute(
"""
SELECT id, ts FROM sim_ledger_entries
WHERE kind='option_open' AND note LIKE ?
ORDER BY id
""",
(f"%{inst}%",),
).fetchall() if inst else []
if opens:
open_id = int(opens[0]["id"])
# 开仓前最近一笔 USDT→币(含缓冲买币)
buy_row = conn.execute(
"""
SELECT id, amount, ts FROM sim_ledger_entries
WHERE ccy='USDT' AND account='trading' AND kind='convert'
AND amount < 0 AND note LIKE ? AND id < ?
ORDER BY id DESC LIMIT 1
""",
(f"{u}/USDT%", open_id),
).fetchone()
if buy_row:
coin_row = conn.execute( coin_row = conn.execute(
""" """
SELECT amount FROM sim_ledger_entries SELECT amount FROM sim_ledger_entries
WHERE ccy=? AND account='trading' AND kind='convert' AND amount > 0 WHERE ccy=? AND account='trading' AND kind='convert' AND amount > 0
AND ts=? AND note LIKE 'from usdt%' AND ts=? AND note LIKE 'from usdt%' AND id < ?
ORDER BY id LIMIT 1
""",
(u, row["ts"]),
).fetchone()
if not coin_row:
continue
buy_usdt += abs(float(row["amount"]))
buy_coin += float(coin_row["amount"])
sell_usdt = 0.0
sell_coin = 0.0
last_close = None
if inst:
last_close = conn.execute(
"""
SELECT ts FROM sim_ledger_entries
WHERE kind='option_close' AND note LIKE ?
ORDER BY id DESC LIMIT 1 ORDER BY id DESC LIMIT 1
""", """,
(f"%{inst}%",), (u, buy_row["ts"], open_id),
).fetchone() ).fetchone()
if last_close or close_ts: if coin_row:
close_anchor = str(last_close["ts"]) if last_close else str(close_ts) buy_usdt = abs(float(buy_row["amount"]))
sells = conn.execute( buy_coin = float(coin_row["amount"])
sell_usdt = 0.0
sell_coin = 0.0
# 该合约 option_close 的 id 区间:本笔最后一笔 close → 下一笔任意 option_open/close 之前
closes = conn.execute(
""" """
SELECT amount, ts FROM sim_ledger_entries SELECT id, ts FROM sim_ledger_entries
WHERE ccy=? AND account='trading' AND kind='convert' WHERE kind='option_close' AND note LIKE ?
AND amount < 0 AND note LIKE ?
AND ts >= ?
ORDER BY id ORDER BY id
""", """,
(u, f"{u}/USDT%", close_anchor), (f"%{inst}%",),
).fetchall() if inst else []
if closes:
start_id = int(closes[-1]["id"])
nxt = conn.execute(
"""
SELECT id FROM sim_ledger_entries
WHERE id > ? AND kind IN ('option_open','option_close')
ORDER BY id LIMIT 1
""",
(start_id,),
).fetchone()
end_id = int(nxt["id"]) if nxt else 10**12
sells = conn.execute(
"""
SELECT id, amount, ts FROM sim_ledger_entries
WHERE ccy=? AND account='trading' AND kind='convert'
AND amount < 0 AND note LIKE ?
AND id > ? AND id < ?
ORDER BY id
""",
(u, f"{u}/USDT%", start_id, end_id),
).fetchall() ).fetchall()
for row in sells: for row in sells:
usdt_row = conn.execute( usdt_row = conn.execute(
@@ -94,9 +110,10 @@ def _ledger_buy_sell(
SELECT amount FROM sim_ledger_entries SELECT amount FROM sim_ledger_entries
WHERE ccy='USDT' AND account='trading' AND kind='convert' WHERE ccy='USDT' AND account='trading' AND kind='convert'
AND amount > 0 AND ts=? AND note LIKE 'from %' AND amount > 0 AND ts=? AND note LIKE 'from %'
AND id > ? AND id < ?
ORDER BY id LIMIT 1 ORDER BY id LIMIT 1
""", """,
(row["ts"],), (row["ts"], start_id, end_id),
).fetchone() ).fetchone()
if not usdt_row: if not usdt_row:
continue continue