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

遍历股票开平仓交易数组计算最终持仓状态的实现问题

股票交易持仓统计实现说明

需求背景

我们需要解析存储股票买卖记录的CSV文件,逐笔处理交易数据,最终输出剩余持仓的结构化记录。规则如下:

  • 买入操作生成状态为OPEN的开仓记录
  • 全额卖出对应持仓时,原开仓记录状态更新为CLOSED
  • 部分卖出对应持仓时,原开仓记录扣减对应卖出数量、状态保持OPEN,同时生成一条卖出数量的CLOSED记录
  • 加仓后全额卖出时,所有关联的持仓记录均标记为CLOSED

输入示例(CSV解析后结构)

[
  {
    Action: 'Buy',
    Symbol: 'SHOP',
    Quantity: '200',
    ...
  },
  {
    Action: 'Sell',
    Symbol: 'SHOP',
    Quantity: '200',
    ...
  },
  {
    Action: 'Buy',
    Symbol: 'SHOP',
    Quantity: '50',
    ...
  },
  {
    Action: 'Sell',
    Symbol: 'SHOP',
    Quantity: '25',
    ...
  },
  {
    Action: 'Sell',
    Symbol: 'SHOP',
    Quantity: '25',
    ...
  },
  {
    Action: 'Buy',
    Symbol: 'SHOP',
    Quantity: '1',
    ...
  }
]

输出示例

[
  {
    stockTicker: 'SHOP',
    positionStatus: 'CLOSED',
    quantity: 200,
    ...
  },
  {
    stockTicker: 'SHOP',
    positionStatus: 'CLOSED',
    quantity: 25,
    ...
  },
  {
    stockTicker: 'SHOP',
    positionStatus: 'CLOSED',
    quantity: 25,
    ...
  },
  {
    stockTicker: 'SHOP',
    positionStatus: 'OPEN',
    quantity: 1,
    ...
  }
]

匹配终止条件判断

你不需要递归遍历多次,只要遵循股票持仓常用的FIFO(先进先出)匹配规则,单次遍历即可完成处理,终止条件非常明确:

  1. 所有交易记录已全部处理完成
  2. 或剩余未匹配的卖出委托数量为0

核心实现逻辑

这里提供更简单的迭代实现逻辑,比递归更易维护也不会出现栈溢出问题:

  • 初始化两个队列:openPositions存储未平仓的开仓记录,result存储最终输出的所有持仓记录
  • 逐笔遍历所有交易记录:
    • 遇到买入记录:直接转为OPEN状态的持仓对象推入openPositions
    • 遇到卖出记录:取出当前待匹配的卖出数量,从openPositions队首开始逐笔扣减:
      • 如果待卖出数量 ≥ 当前开仓记录的数量:将当前开仓记录状态改为CLOSED推入result,待卖出数量扣减对应值,继续匹配下一笔开仓记录
      • 如果待卖出数量 < 当前开仓记录的数量:拆分当前开仓记录,生成一条待卖出数量的CLOSED记录推入result,原开仓记录扣减对应数量后留在openPositions队列中,清空待卖出数量结束本次卖出匹配
  • 所有交易处理完成后,将openPositions中剩余的OPEN状态记录全部推入result,就是你要的最终结果

代码示例(JavaScript)

function calculatePositions(trades) {
  const openPositions = [];
  const result = [];

  for (const trade of trades) {
    const qty = Number(trade.Quantity);
    if (trade.Action === 'Buy') {
      openPositions.push({
        stockTicker: trade.Symbol,
        positionStatus: 'OPEN',
        quantity: qty
        // 其他自定义字段自行补充
      });
      continue;
    }

    // 处理卖出逻辑
    let remainSellQty = qty;
    while (remainSellQty > 0 && openPositions.length > 0) {
      const currentOpen = openPositions[0];
      if (currentOpen.quantity <= remainSellQty) {
        // 全额平仓
        currentOpen.positionStatus = 'CLOSED';
        result.push(currentOpen);
        remainSellQty -= currentOpen.quantity;
        openPositions.shift();
      } else {
        // 部分平仓
        const closedPart = {
          ...currentOpen,
          positionStatus: 'CLOSED',
          quantity: remainSellQty
        };
        result.push(closedPart);
        currentOpen.quantity -= remainSellQty;
        remainSellQty = 0;
      }
    }
  }

  // 剩余未平仓的记录加入最终结果
  result.push(...openPositions);
  return result;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 02:42:02