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

如何为按symbol和date排序的DataFrame添加独立交易编号列

为交易订单分配独立交易编号

给定一个已按symbol和date排序的DataFrame,需要新增一列用于标识每笔独立交易。每笔独立交易指从**开仓(position opened)到平仓(position closed)**的一组买卖(buy/sell)订单,未平仓的交易也需要分配对应的交易编号。


输入数据

原始交易数据(带开平仓注释):

time           symbol        side      price     size
08-19-2021      AAPL          buy        150       1 ----> position opened here
08-20-2021      AAPL          buy        100       1
08-21-2021      AAPL          buy        200       1
08-22-2021      AAPL          sell        300      1
08-23-2021      AAPL          sell       350       0.5
08-24-2021      AAPL          sell        400      1.5 ----> position closed here
08-25-2021      AAPL          buy        150       2  -----> position opened here
08-26-2021      AAPL          sell        100      2  ----> position closed here
08-27-2021      AAPL          buy        100       2 ---> position opened here
08-28-2021      AAPL          sell        150      1.5
08-29-2021      AAPL          buy        100       0.5
08-29-2021      AAPL          sell        50       0.5
08-29-2021      AAPL          sell       50        0.5 ---> position closed here
08-29-2021      AAPL          buy        100       1 ----> position opened here
08-29-2021      AAPL          sell        50       0.5 ---> position still open here

预期输出

新增trade #列后的结果:

time           symbol        side      price     size   trade #
08-19-2021      AAPL          buy        150       1      0
08-20-2021      AAPL          buy        100       1      0
08-21-2021      AAPL          buy        200       1      0
08-22-2021      AAPL          sell        300      1      0
08-23-2021      AAPL          sell       350       0.5    0
08-24-2021      AAPL          sell        400      1.5    0
-------------------------------
08-25-2021      AAPL          buy        150       2      1
08-27-2021      AAPL          sell        100      2      1 
-------------------------------    
08-28-2021      AAPL          buy        100       2      2
08-29-2021      AAPL          sell        150      1.5    2
08-29-2021      AAPL          buy        100       0.5    2
08-29-2021      AAPL          sell        50       0.5    2
08-29-2021      AAPL          sell       50        0.5    2
------------------------------
08-29-2021      AAPL          buy        100       1      3
08-29-2021      AAPL          sell        50       0.5    3

最后一笔交易尚未平仓,仍需为其分配交易编号。

输入DataFrame构造代码

import pandas as pd

df = pd.DataFrame.from_dict({
    'symbol': ['AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL'], 
    'side': ['buy', 'buy', 'buy', 'sell', 'sell', 'sell', 'buy', 'sell', 'buy', 'sell', 'buy', 'sell', 'sell', 'buy', 'sell'], 
    'size': [1,1,1,1,0.5,1.5,2,2,2,1.5, 0.5, 0.5, 0.5, 1, 0.5]
})

解决方案

核心思路

  1. 计算每笔订单的持仓变化:buy为正增量,sell为负增量
  2. 计算累计持仓,跟踪当前持仓状态
  3. 识别开仓信号:当累计持仓从0变为正数时,标记为新交易的起点
  4. 基于开仓信号的累计求和,生成唯一的交易编号

代码实现

import pandas as pd

# 构造输入DataFrame
df = pd.DataFrame.from_dict({
    'symbol': ['AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL', 'AAPL'], 
    'side': ['buy', 'buy', 'buy', 'sell', 'sell', 'sell', 'buy', 'sell', 'buy', 'sell', 'buy', 'sell', 'sell', 'buy', 'sell'], 
    'size': [1,1,1,1,0.5,1.5,2,2,2,1.5, 0.5, 0.5, 0.5, 1, 0.5]
})

# 1. 计算每笔订单的持仓变化量
df['position_change'] = df.apply(lambda x: x['size'] if x['side'] == 'buy' else -x['size'], axis=1)

# 2. 计算累计持仓
df['cum_position'] = df['position_change'].cumsum()

# 3. 标记新交易的开仓点:前一行持仓为0,当前持仓转为正数
df['is_new_trade'] = (df['cum_position'] > 0) & (df['cum_position'].shift(1).fillna(0) == 0)

# 4. 生成交易编号
df['trade #'] = df['is_new_trade'].cumsum() - 1

# 查看最终结果(按需保留或删除中间列)
print(df[['symbol', 'side', 'size', 'trade #']])

结果验证

运行代码后,生成的trade #列与预期输出完全匹配,未平仓的最后一笔交易也被正确分配了编号3。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:42:24