Compare commits

..

No commits in common. '63192e67d18298b22b72a4c67d7d5c69bed8c7ab' and '015f00da638edd952de982a26208fa2d0b1b5111' have entirely different histories.

@ -101,8 +101,6 @@ async def batch_import_settlement(
total_skipped_all = 0
processed_count = 0
failed_count = 0
# 维护跨文件的去重键集合,用于文件间去重
batch_existing_keys = set()
for file in files:
if not file.filename.endswith(('.xls', '.xlsx')):
@ -127,12 +125,7 @@ async def batch_import_settlement(
failed_count += 1
continue
# 传入已处理文件的去重键,实现文件间去重
result = save_to_db(db, df_futures, df_options, file.filename, batch_existing_keys)
# 将本次导入的新记录去重键加入集合,供后续文件去重使用
if 'new_keys' in result:
batch_existing_keys.update(result['new_keys'])
result = save_to_db(db, df_futures, df_options, file.filename)
file_new = result['futures_count'] + result['options_count']
file_skipped = result['futures_skipped'] + result['options_skipped']

@ -270,16 +270,13 @@ def save_to_db(
df_futures: pd.DataFrame,
df_options: pd.DataFrame,
filename: str,
batch_existing_keys: set = None,
) -> dict:
"""
将解析后的交易记录保存到数据库含逐条去重校验
去重规则同一交易日 + 同一品种 + 同一交易时间 + 同一价格 => 视为重复跳过
:param batch_existing_keys: 批量导入时已处理文件的去重键集合用于文件间去重
:return: {
"batch_id": str, "futures_count": int, "options_count": int, "trade_dates": str,
"futures_skipped": int, "options_skipped": int, "total_parsed": int,
"new_keys": set # 本次导入新增的去重键(用于批量导入时传递给下一个文件)
"futures_skipped": int, "options_skipped": int, "total_parsed": int
}
"""
_load_variety_name_map()
@ -312,12 +309,9 @@ def save_to_db(
# 批量加载已有记录的去重键
existing_keys = _load_existing_dedup_keys(db, all_dates)
# 合并批量导入时已处理文件的去重键
if batch_existing_keys:
existing_keys = existing_keys | batch_existing_keys
records = []
new_keys_in_batch = set() # 本次导入新增的去重键
new_keys_in_batch = set() # 防止本次导入文件内部重复
skipped_details = [] # 记录被跳过的重复记录详情
# 处理期货记录
@ -337,7 +331,7 @@ def save_to_db(
price = safe_float(row.get('成交价'))
dedup_key = _build_dedup_key(trade_date, variety, trade_time, price)
if dedup_key in existing_keys:
if dedup_key in existing_keys or dedup_key in new_keys_in_batch:
futures_skipped += 1
skipped_details.append({
'type': '期货',
@ -348,7 +342,7 @@ def save_to_db(
})
continue
# 记录前几笔期货去重键用于调试
# 记录前几条的去重键用于调试
if futures_parsed <= 3:
logger.info(f"[去重校验] 期货记录 #{futures_parsed}: raw_date={raw_date!r}, trade_date={trade_date!r}, variety={variety!r}, time={trade_time!r}, price={price!r} => key={dedup_key!r}")
@ -389,7 +383,7 @@ def save_to_db(
price = safe_float(row.get('权利金单价'))
dedup_key = _build_dedup_key(trade_date, variety, trade_time, price)
if dedup_key in existing_keys:
if dedup_key in existing_keys or dedup_key in new_keys_in_batch:
options_skipped += 1
skipped_details.append({
'type': '期权',
@ -400,9 +394,9 @@ def save_to_db(
})
continue
new_keys_in_batch.add(dedup_key)
# 期权盈亏来自权利金(带正负号:卖为正,买为负)
premium = safe_float(row.get('权利金'))
new_keys_in_batch.add(dedup_key)
rec = TradeRecord(
trade_type='期权',
symbol=contract,
@ -463,7 +457,6 @@ def save_to_db(
"futures_parsed": futures_parsed,
"options_parsed": options_parsed,
"skipped_details": skipped_details, # 被跳过的重复记录详情
"new_keys": new_keys_in_batch,
}

@ -1193,8 +1193,8 @@
<div id="tr-tab-stats" class="tr-tab-panel active">
<!-- 快捷日期 -->
<div class="tr-quick-dates" id="tr-quick-dates">
<button class="tr-quick-date" data-range="today">当日</button>
<button class="tr-quick-date active" data-range="week">近一周</button>
<button class="tr-quick-date active" data-range="today">当日</button>
<button class="tr-quick-date" data-range="week">近一周</button>
<button class="tr-quick-date" data-range="half-month">近半月</button>
<button class="tr-quick-date" data-range="month">近一月</button>
<button class="tr-quick-date" data-range="quarter">近三月</button>

@ -1632,10 +1632,20 @@ function initTradeReview() {
}
async function trInitDefaultDate() {
try {
const res = await fetch(`${TR_API_BASE}/latest-trade-date`);
const json = await res.json();
if (json.success && json.data.trade_date) {
const dateStr = json.data.trade_date;
document.getElementById('tr-start-date').value = dateStr;
document.getElementById('tr-end-date').value = dateStr;
}
} catch (e) {
console.error('获取最后交易日失败', e);
}
// 初始化快捷日期按钮
trInitQuickDates();
// 默认加载近一周数据
trSetDateRange('week');
trLoadAllData();
}
function trInitQuickDates() {

Binary file not shown.

@ -1,13 +0,0 @@
# 批量导入跨文件去重
## 动机
当前批量导入时,每个文件独立处理,文件之间没有重复性校验。如果多个文件包含相同的交易记录,会导致数据重复。同时,一个文件内部的一次委托分多次成交不应被误判为重复。
## 目标
1. 单文件导入时,文件内部不去重,允许一次委托分多次成交
2. 批量导入时,跨文件进行去重,避免重复导入
3. 数据库中已有记录仍需去重
## 范围
- `app/services/trade_parser.py``save_to_db` 增加 `batch_existing_keys` 参数,返回新增去重键
- `app/api/trade_review.py` — 批量导入时维护跨文件去重键集合
Loading…
Cancel
Save