如何打印包含UPPER_VWAP、LOWER_VWAP字段的完整DataFrame结果
问题原因及解决方案
核心问题1:字段大小写不匹配
你代码中定义的key值为大写的'VWAP',但你提供的DataFrame中对应字段为小写的'vwap',大小写不一致导致计算标准差时无法找到对应列,所有逻辑走到异常捕获分支,自然不会生成三个新字段的值。
核心问题2:日期筛选条件未同步更新
外层遍历num_days的循环中,你仅更新了curr_position的日期,但是筛选当日数据的条件始终为最初传入的固定curr_date,从第二个交易日开始,day_data筛选结果为空,后续所有计算都会失效。
核心问题3:时间索引格式不匹配
你给出的DataFrame索引是带时区的datetime类型(示例为UTC-4时区),但代码中生成的curr_position是无时区的datetime对象,转换为字符串后和索引格式不匹配,df.loc[str(curr_position)]无法定位到对应行,赋值操作不会写入原DataFrame。
核心问题4:未提前初始化新增列
如果没有提前在DataFrame中定义UPPER_VWAP、LOWER_VWAP、STD_VWAP三个列,直接用.loc给指定行赋值时,pandas可能会判定为对临时副本的操作,变更不会同步到原df。
修正后的参考代码
import pandas as pd import datetime from datetime import time, timedelta def caclulate_vwap_bands(self, df, curr_date, num_days): # 和df中的字段名保持一致,用小写vwap key = 'vwap' def stdev(df_slice): return df_slice[key].values.std(ddof=0) # 提前初始化三个新列,避免赋值不生效 df['UPPER_VWAP'] = pd.NA df['LOWER_VWAP'] = pd.NA df['STD_VWAP'] = pd.NA # 给curr_position加上和df一致的时区,避免索引匹配失败 tz = df.index.tz curr_position = datetime.datetime.combine(curr_date, time(hour=9, minute=31)).replace(tzinfo=tz) for day_offset in range(0, num_days): # 动态取当前curr_position对应的日期筛选当日数据 current_calc_date = curr_position.date() day_data = df[current_calc_date == df.index.date].copy() # 处理9:31到9:59的时段 for _ in range(31, 60): try: std = stdev(day_data[day_data.index.time <= curr_position.time()]) df.loc[curr_position, 'UPPER_VWAP'] = df.loc[curr_position, key] + (2 * std) df.loc[curr_position, 'LOWER_VWAP'] = df.loc[curr_position, key] - (2 * std) df.loc[curr_position, 'STD_VWAP'] = std except Exception as e: print(curr_position, "doesn't exist, skipping") curr_position += timedelta(minutes=1) # 处理10:00到16:00的时段 for _ in range(10, 17): while True: if curr_position.time() >= time(hour=16, minute=1): break try: std = stdev(day_data[day_data.index.time <= curr_position.time()]) df.loc[curr_position, 'UPPER_VWAP'] = df.loc[curr_position, key] + (2 * std) df.loc[curr_position, 'LOWER_VWAP'] = df.loc[curr_position, key] - (2 * std) df.loc[curr_position, 'STD_VWAP'] = std except Exception as e: print(curr_position, "doesn't exist, skipping") curr_position += timedelta(minutes=1) # 切换到下一个交易日 curr_position += timedelta(days=1) curr_position = curr_position.replace(hour=9, minute=31) return df
内容的提问来源于stack exchange,提问作者user16233760
相关产品推荐
相关产品推荐

