函数未输出预期结果:股票SMA均线买卖信号价格异常排查
问题解决:股票SMA交叉买卖信号修正
问题说明
需要基于SMA30和SMA100的交叉生成股票买卖价格信号:
- 出现买入价的日期,卖出价为
NaN - 出现卖出价的日期,买入价为
NaN
原函数输出不符合预期,需修正代码。
原代码问题分析
- 列表长度不一致:买入信号分支的else块中,错误地两次向
sig_price_buy添加元素,导致sig_price_buy和sig_price_sell长度不匹配 - flag状态未更新:触发买入信号后未将
flag设为1,会导致重复生成买入信号 - 链式索引风险:直接用
qqq_df['close'][i]这种链式索引方式,可能引发Pandas警告和潜在的索引问题
解决步骤
- 修正列表元素添加逻辑:每个循环迭代必须同时给
sig_price_buy和sig_price_sell各添加一个元素 - 完善flag状态切换:触发买入信号时将
flag设为1,触发卖出信号时设为0,避免重复信号 - 使用
.iloc[i]访问DataFrame行元素,规避链式索引风险
修正后的代码
import numpy as np import pandas as pd def buy_sell(qqq_df): sig_price_buy = [] sig_price_sell = [] flag = -1 # -1: 初始状态, 1: 持有状态, 0: 空仓状态 for i in range(len(qqq_df)): # 金叉:SMA30上穿SMA100,触发买入信号 if qqq_df['sma_30'].iloc[i] > qqq_df['sma_100'].iloc[i]: if flag != 1: sig_price_buy.append(qqq_df['close'].iloc[i]) sig_price_sell.append(np.nan) print(f"买入日期: {qqq_df['date'].iloc[i]}") flag = 1 # 更新状态为持有 else: sig_price_buy.append(np.nan) sig_price_sell.append(np.nan) # 死叉:SMA30下穿SMA100,触发卖出信号 elif qqq_df['sma_30'].iloc[i] < qqq_df['sma_100'].iloc[i]: if flag != 0: sig_price_buy.append(np.nan) sig_price_sell.append(qqq_df['close'].iloc[i]) print(f"卖出日期: {qqq_df['date'].iloc[i]}") flag = 0 # 更新状态为空仓 else: sig_price_buy.append(np.nan) sig_price_sell.append(np.nan) # 均线持平,无信号 else: sig_price_buy.append(np.nan) sig_price_sell.append(np.nan) return sig_price_buy, sig_price_sell # 调用函数并将信号添加到原DataFrame buy_signals, sell_signals = buy_sell(qqq_df) qqq_df['buy_signal'] = buy_signals qqq_df['sell_signal'] = sell_signals # 输出有信号的行进行验证 print(qqq_df[['date', 'close', 'buy_signal', 'sell_signal']].dropna(how='all', subset=['buy_signal', 'sell_signal']))
代码说明
- 明确
flag的三种状态含义,提升代码可读性 - 使用
.iloc[i]安全访问行数据,避免索引错误 - 每次循环确保两个列表各添加一个元素,保证长度与原DataFrame一致
- 触发信号后立即更新
flag,防止同一状态下重复生成信号 - 将信号直接整合到原DataFrame,方便后续分析和可视化
内容的提问来源于stack exchange,提问作者Tese T.
相关产品推荐
相关产品推荐

