You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas处理瑕疵公共交易数据实现关联交易条目分组

公共交易数据关联分组Pandas实现方案

前置依赖与数据预处理

先校准基础数据类型,避免字符串格式、浮点精度问题导致判定错误,预处理代码可直接复用:

import pandas as pd
import numpy as np
from collections import defaultdict

# 替换为实际数据读取逻辑
df = pd.read_excel("交易数据存储路径.xlsx")
# 处理带千分位逗号的数值字段
for col in ["Notional", "Premium"]:
    df[col] = df[col].astype(str).str.replace(",", "").astype(float)
# 转换数值、时间字段类型
df["Strike"] = df["Strike"].astype(float)
df["ExecutionTimestamp"] = pd.to_datetime(df["ExecutionTimestamp"])
for col in ["StartDate", "EndDate"]:
    df[col] = pd.to_datetime(df[col]).dt.date  # 日期保留年月日精度做匹配
# 初始化结果字段
df["RealStructure"] = df["Structure"]
df["StraddlePairID"] = None
df["GroupID"] = None

第一步:Straddle交易结构识别

识别逻辑严格匹配Straddle定义:名义本金、起止日期、行权价、标的指数、重置频率完全一致,且Call和Put成交时间差在60秒内(覆盖人工录入延迟);配对时按时间最近原则匹配,避免重复配对。

# Straddle固定匹配维度
straddle_match_cols = ["Notional", "StartDate", "EndDate", "Strike", "Index", "ResetFreq"]
straddle_pair_id = 0

for _, group in df.groupby(straddle_match_cols, dropna=False):
    # 拆分组内Call、Put条目并按成交时间排序
    call_rows = group[group["Structure"] == "Call"].sort_values("ExecutionTimestamp").index.tolist()
    put_rows = group[group["Structure"] == "Put"].sort_values("ExecutionTimestamp").index.tolist()
    # 双指针做最近时间配对
    c_idx = p_idx = 0
    while c_idx < len(call_rows) and p_idx < len(put_rows):
        c_time = df.loc[call_rows[c_idx], "ExecutionTimestamp"]
        p_time = df.loc[put_rows[p_idx], "ExecutionTimestamp"]
        time_diff = abs((c_time - p_time).total_seconds())
        if time_diff <= 60:
            # 配对成功标记为Straddle
            df.loc[call_rows[c_idx], "RealStructure"] = "Straddle"
            df.loc[put_rows[p_idx], "RealStructure"] = "Straddle"
            df.loc[call_rows[c_idx], "StraddlePairID"] = straddle_pair_id
            df.loc[put_rows[p_idx], "StraddlePairID"] = straddle_pair_id
            straddle_pair_id += 1
            c_idx += 1
            p_idx += 1
        elif c_time < p_time:
            c_idx += 1
        else:
            p_idx += 1

第二步:可配置关联交易分组

关联判定采用「硬规则筛候选+软规则算得分+并查集传递分组」的逻辑,规则权重、判定阈值均可按实际业务调整,避免硬编码适配性差的问题。

规则配置

# 硬匹配规则:必须全部满足才可能属于关联交易,先筛掉不可能的组合减少计算量
hard_match_cols = ["StartDate", "EndDate", "Index", "ResetFreq"]
# 软评分规则:满足即加对应权重,总分≥阈值判定为关联
score_rules = [
    # 规则1:成交时间差<5分钟,加40分
    (lambda r1, r2: abs((r1["ExecutionTimestamp"] - r2["ExecutionTimestamp"]).total_seconds()) < 300, 40),
    # 规则2:Strike*10000差值可被25整除(加浮点容差避免精度误差),加30分
    (lambda r1, r2: (abs(r1["Strike"]*10000 - r2["Strike"]*10000) + 1e-6) % 25 < 1e-3, 30),
    # 规则3:名义本金接近简单整数比(容差0.1,覆盖录入尾差,匹配1:1/2:1/3:1等常见对冲比例),加30分
    (lambda r1, r2: abs(max(r1["Notional"], r2["Notional"])/min(r1["Notional"], r2["Notional"]) - round(max(r1["Notional"], r2["Notional"])/min(r1["Notional"], r2["Notional"]))) < 0.1, 30)
]
SCORE_THRESHOLD = 80  # 关联得分阈值,可根据数据质量调整

并查集实现(处理关联传递性)

class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size))
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px != py:
            self.parent[py] = px

分组计算逻辑

uf = UnionFind(len(df))
# 生成行号作为条目唯一标识
df = df.reset_index(drop=True).reset_index().rename(columns={"index":"row_id"})

# 仅在硬规则匹配的组内做两两判定,提升计算效率
for _, hard_group in df.groupby(hard_match_cols, dropna=False):
    rows = hard_group.to_dict("records")
    for i in range(len(rows)):
        for j in range(i+1, len(rows)):
            r1, r2 = rows[i], rows[j]
            total_score = 0
            for rule_func, score in score_rules:
                if rule_func(r1, r2):
                    total_score += score
            if total_score >= SCORE_THRESHOLD:
                uf.union(r1["row_id"], r2["row_id"])

# 生成最终分组ID
df["GroupID"] = df["row_id"].apply(lambda x: f"G{uf.find(x)}")

样例数据运行效果

针对提供的10条样例数据,运行结果完全符合预期:

  • 序号10、11:识别为重复录入的Call交易,归属同一组,结构标记为Call
  • 序号12、13:识别为同参数Call交易(成交时间差56秒),归属同一组,结构标记为Call
  • 序号14、16、18:归属同一组,其中16+18配对为Straddle,和14的Put组成「1份Straddle对冲1份Put」的关联组
  • 序号15、17、19:归属同一组,其中17+19配对为Straddle,和15的Put组成第二组对冲关联组

可根据实际数据情况调整软规则权重、时间窗口、Strike整除基数、本金比例容差,适配不同业务场景。如果遇到录入误差更大的数据集,可适当降低得分阈值,或新增Premium比例匹配、StraddlePairID关联等规则,提升识别准确率。

内容的提问来源于stack exchange,提问作者keynesiancross

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:15:42