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

基于指定日期投资组合及后续交易生成每日投资组合快照方案咨询

Python股票投资组合追踪器实现思路

一、先把数据理清楚

  • 用pandas读取起始组合表和交易记录表,注意处理样例里的索引列(比如读的时候加index_col=0参数)
  • 把交易记录里的Date/Time转成日期格式,只保留日期部分(毕竟要的是每日数据,具体交易时间没用),用pd.to_datetime(trades['Date/Time']).dt.date就能快速处理
  • 自己指定起始日期,比如样例里最早的交易是2022-06-28,起始日期可以设为2022-06-27

二、搭好每日持仓的时间线

  • 确定时间范围:从起始日期到交易记录里的最晚日期,用pd.date_range生成连续的每日日期序列
  • 合并当日同股票交易:把同一天同一股票的交易数量、手续费分别求和,用groupby(['Date', 'Symbol']).agg就能实现
  • 逐日更新持仓:
    1. 先把起始组合转成字典,比如{'NVDA':52, 'NFLX':18...}
    2. 遍历每一天:如果当天有交易,对应调整股票持仓量(正数值为买入,负数值为卖出),持仓变0的股票可以直接从字典里移除
    3. 把每天的持仓状态存下来,最后转成DataFrame格式

三、拿到每日股票收盘价

  • 用yfinance库批量拉取所有涉及股票(起始组合+交易记录里的全部Symbol)的历史收盘价,直接pip install yfinance就能安装使用
  • 如果涉及非USD货币,需要额外获取每日汇率,把非USD的收盘价转换成基准货币(比如USD)
  • 把每日持仓和对应日期的收盘价匹配,为后续计算单股票价值做准备

四、计算每日组合总价值

  • 单股票当日价值:持仓数量 × 当日收盘价
  • 每日总价值:所有股票当日价值之和,再减去累计的手续费(也可以选择逐日扣除当日手续费)
  • 最终生成的表格需包含日期、各股票持仓量、各股票当日价值、当日总价值、当日手续费等字段

五、分析个股对涨跌的影响

  • 计算每日组合涨跌幅:(当日总价值 - 前一日总价值)/前一日总价值
  • 计算个股贡献度:可以用(个股当日价值 - 个股前一日价值)/前一日总价值,或者持仓数量×(当日收盘价-前一日收盘价)/前一日总价值,能直观看出哪只股票拉动了组合涨跌
  • 把个股贡献度字段加入每日价值表,方便查看每日涨跌的核心影响个股

关键代码片段

1. 数据读取与预处理

import pandas as pd
import yfinance as yf

# 读取起始组合表
start_portfolio = pd.read_csv('start_portfolio.csv', index_col=0)
# 自定义起始日期
start_date = '2022-06-27'

# 读取交易记录表
trades = pd.read_csv('trades.csv', index_col=0)
# 提取交易日期部分
trades['Date'] = pd.to_datetime(trades['Date/Time']).dt.date
# 按日期和股票合并交易数据
daily_trades = trades.groupby(['Date', 'Symbol']).agg({'Quantity': 'sum', 'Comm/Fee': 'sum'}).reset_index()

2. 构建逐日持仓数据

# 初始化起始持仓字典
current_holdings = start_portfolio.set_index('Symbol')['Quantity'].to_dict()
# 确定交易记录的最晚日期
end_date = trades['Date'].max()
# 生成连续日期序列
date_range = pd.date_range(start=start_date, end=end_date).date

# 存储每日持仓和手续费数据
daily_holdings = []
daily_fees = []

for date in date_range:
    # 筛选当日交易
    day_trades = daily_trades[daily_trades['Date'] == date]
    total_fee = day_trades['Comm/Fee'].sum() if not day_trades.empty else 0
    # 更新持仓
    for _, trade in day_trades.iterrows():
        symbol = trade['Symbol']
        qty_change = trade['Quantity']
        if symbol in current_holdings:
            current_holdings[symbol] += qty_change
        else:
            current_holdings[symbol] = qty_change
        # 持仓为0则移除该股票
        if current_holdings[symbol] == 0:
            del current_holdings[symbol]
    # 保存当日数据
    daily_holdings.append({'Date': date, **current_holdings.copy()})
    daily_fees.append({'Date': date, 'Total_Fee': total_fee})

# 转成DataFrame格式
daily_holdings_df = pd.DataFrame(daily_holdings).fillna(0).set_index('Date')
daily_fees_df = pd.DataFrame(daily_fees).set_index('Date')

3. 计算每日组合价值与个股贡献度

# 获取所有涉及的股票代码
all_symbols = list(set(start_portfolio['Symbol'].tolist() + trades['Symbol'].tolist()))
# 下载历史收盘价数据
price_data = yf.download(all_symbols, start=start_date, end=pd.to_datetime(end_date)+pd.Timedelta(days=1))['Close']
price_data.index = price_data.index.date

# 计算单股票每日价值
daily_value_df = daily_holdings_df * price_data
# 计算组合总价值(扣除累计手续费)
daily_value_df['Total_Value'] = daily_value_df.sum(axis=1) - daily_fees_df['Total_Fee'].cumsum()

# 计算每日组合涨跌幅
daily_value_df['Daily_Return'] = daily_value_df['Total_Value'].pct_change()
# 计算个股对每日涨跌的贡献度
for symbol in all_symbols:
    if symbol in daily_value_df.columns:
        daily_value_df[f'{symbol}_Contribution'] = (daily_value_df[symbol].diff()) / daily_value_df['Total_Value'].shift(1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:07:07