
在计算股票常用指标时,原来一直用talib或则pandas_ta,但是talib几乎不更新,而且不支持numpy 2.0以上版本,于是自己用纯pandas重写了,也顺便重新学习了一下每个指标的计算方法和常用指标,不废话,直接上代码
SMA:简单移动平均
EMA:指数移动平均
至于为什么要计算这么多不同周期的均值,后面就知道了
df['SMA_3'] = df['close'].rolling(3).mean()
df['SMA_6'] = df['close'].rolling(6).mean()
df['SMA_12'] = df['close'].rolling(12).mean()
df['SMA_24'] = df['close'].rolling(24).mean()
df['SMA_26'] = df['close'].rolling(26).mean()
df['SMA_5'] = df['close'].rolling(5).mean()
df['SMA_10'] = df['close'].rolling(10).mean()
df['SMA_20'] = df['close'].rolling(20).mean()
df['SMA_100'] = df['close'].rolling(100).mean()
df['EMA_5'] = df['close'].ewm(span=5).mean()
df['EMA_10'] = df['close'].ewm(span=10).mean()
df['EMA_20'] = df['close'].ewm(span=20).mean()
df['EMA_60'] = df['close'].ewm(span=60).mean()
BBI多空指标
BBI指标,即多空指标,英文全名为”Bull And Bear lndex”,简称BBI,是一种将不同日数移动平均线加权平均之后的综合指标,
属于均线型指标,一般选用3日、6日、12日、24日等4条平均线。在使用移动平均线时,投资者往往对参数值选择有不同的偏好,
而多空指标恰好解决了中短期移动平均线的期间长短合理性问题。很明显,在BBI指标中,近期数据较多,远期数据利用次数较少,
因而是一种变相的加权计算。由于多空指标是一条混合平均线,所以既有短期移动平均线的灵敏,又有明显的中期趋势特征,
适于稳健的投资者。
df['BBI'] = df[['SMA_3','SMA_6','SMA_12','SMA_24']].mean(axis=1)
RSI指标
RSI 指标(相对强弱指标,Relative Strength Index)是一种通过计算股价涨跌幅度来判断市场超买超卖状态的动量指标。它由威尔斯・怀尔德(Welles Wilder)于 1978 年提出,广泛应用于股票、期货、外汇等市场,帮助交易者识别价格可能的反转点。RSI 通过比较一段时期内股价的上涨幅度和下跌幅度,衡量多空双方的力量对比,进而判断市场是否处于超买或超卖状态。当股价持续上涨时,RSI 值升高,若涨幅过大则可能形成 “超买”,预示价格可能回调;当股价持续下跌时,RSI 值降低,若跌幅过大则可能形成 “超卖”,预示价格可能反弹。RSI 指标的核心价值在于通过 “动量反转” 逻辑,帮助交易者识别市场情绪的极端状态及趋势动能的变化,尤其在震荡行情和背离信号中具有较高的参考价值。
def getRSI(data, length, vol='close'):
# 将收盘价列赋值给变量close
close = data[vol]
# 计算价格变动
delta = close.diff()
delta = delta.dropna()
# 分类上涨和下跌
up = delta.copy()
down = delta.copy()
up[up < 0] = 0
down[down > 0] = 0
# 计算平均上涨收益和平均下跌收益
avg_up = up.rolling(window=length).mean()
avg_down = abs(down.rolling(window=length).mean())
# 计算RSI指标
rs = avg_up / avg_down
rsi = 100.0 - (100.0 / (1 + rs))
return rsi
df['RSI_6'] = getRSI(df, 6, vol='close')
df['RSI_12'] = getRSI(df, 12, vol='close')
df['RSI_24'] = getRSI(df, 24, vol='close')
CCI指标
CCI 指标(顺势指标,Commodity Channel Index)是一种衡量价格是否偏离常态分布的超买超卖指标,由唐纳德・兰伯特(Donald Lambert)于 20 世纪 80 年代提出。该指标不仅适用于股票市场,还广泛应用于期货、外汇等品种,其独特之处在于通过计算价格与移动平均线的偏离程度,判断市场是否处于极端状态。CCI 指标通过统计价格与周期内平均价格的偏离程度,判断资产价格是否进入异常区域(超买或超卖),进而预测趋势反转的可能性。当价格持续上涨或下跌时,会逐渐偏离其正常波动范围,CCI 指标值随之升高或降低;若偏离程度过大(进入极端区域),则预示价格可能回归均值或反转。CCI 指标的核心价值在于通过 “价格偏离均值” 的逻辑,帮助交易者识别市场极端状态及趋势动能的变化,尤其在强势趋势行情和背离信号中具有较高的参考价值。与 RSI 等指标相比,它对极端行情更敏感,但也更易在震荡市中产生假信号。
df['TP'] = (df['high'] + df['low'] + df['close'])/3.0
df['TPMA'] = df['TP'].rolling(14).mean()
df['MAD'] = (df['TP'] - df['TPMA']).abs().rolling(14).mean()
df['CCI'] = (df['TP'] - df['TPMA']) / (0.0015 * df['MAD'])
MACD指标
MACD(Moving Average Convergence Divergence,移动平均线收敛发散指标)是技术分析中最经典的趋势跟踪指标之一,由杰拉尔德・阿佩尔(Gerald Appel)于 20 世纪 70 年代提出。它通过计算不同周期移动平均线的差值,揭示价格趋势的强度、方向及潜在反转点,广泛应用于股票、期货、外汇等市场。MACD 本质上是 “均线的均线”,通过快速均线与慢速均线的聚合与分离(即 “收敛” 与 “发散”),判断多空力量的转化。当短期均线向上穿越长期均线(金叉),表明多头力量增强;当短期均线向下穿越长期均线(死叉),表明空头力量占优。MACD 将这种关系转化为柱状图和信号线,直观展示趋势动能。
df['DIF'] = df['SMA_12']-df['SMA_26']
df['DEA'] = df['DIF'].ewm(span=9).mean()
df['MACD'] = 2.0*(df['DIF']-df['DEA'])
ATR指标
ATR(Average True Range)即 “平均真实波幅”,由技术分析大师威尔斯・威尔德(J. Welles Wilder)在 1978 年提出,是衡量市场波动性的重要指标。它不反映价格涨跌方向,而是通过计算价格波动的幅度,帮助交易者判断市场活跃程度、设置止损位或制定交易策略。
df['last_high'] = df['high'].shift(1)
df['last_low'] = df['low'].shift(1)
df['TR'] = df.apply(lambda x: max(x['high']-x['low'],
abs(x['close']-x['last_high']),
abs(x['close']-x['last_low'])), axis=1)
df['ATR'] = df['TR'].rolling(14).mean()
ADX指标
ADX(Average Directional Index)由技术分析大师威尔斯・威尔德(J. Welles Wilder)在 1978 年提出,是衡量市场趋势强度的经典指标。它不判断趋势方向(上涨或下跌),而是通过计算价格波动的方向性差异,量化趋势的 “强弱程度”,适用于趋势交易策略的确认与管理。ADX 指标如同市场趋势的 “强度计”,帮助交易者在复杂行情中识别真正的趋势机会,避开震荡陷阱。
# ADX指标
df['+DM'] = df['high'].diff()
df['-DM'] = -df['low'].diff()
df['+DM'] = df['+DM'].where(
(df['+DM'] > df['-DM']) & (df['+DM'] > 0.0), 0.0)
df['-DM'] = df['-DM'].where(
(df['-DM'] > df['+DM']) & (df['-DM'] > 0.0), 0.0)
df['+ADM'] = df['+DM'].rolling(14).mean()
df['-ADM'] = df['-DM'].rolling(14).mean()
df['+DI'] = 100.0*(df['+ADM'] / df['ATR'])
df['-DI'] = 100.0*(df['-ADM'] / df['ATR'])
df['DX'] = 100.0*(abs(df['+DI']-df['-DI']) / (df['+DI']+df['-DI']))
df['ADX'] = df['DX'].rolling(14).mean()
EMV指标
EMV(Ease of Movement Value)由技术分析专家理查德・阿姆斯(Richard W. Arms Jr.)于 1970 年代提出,是一种结合价格波动与成交量的技术指标。其核心逻辑是:在成交量放大时,价格波动应更显著;若成交量小而价格波动大,则可能预示趋势乏力。EMV 通过量化 “价格移动的难易程度”,判断市场趋势的动能强弱,尤其适用于识别量价配合的真实趋势。
df['average'] = df[['open','close','high','low']].mean(axis=1)
df['EM'] = (df['average'] - df['average'].shift(1)) *
(df['high'] - df['low']) / df['volume']
df['EMV'] = df['EM'].rolling(14).mean()
df['MAEMV'] = df['EMV'].rolling(9).mean()
最后顺便打印一下K线图和均线图,同样不借助第三方库
# 打印最近60日的数据
hist=hist.tail(60)
hist.reset_index(drop=True, inplace=True)
majorIndex = hist.index[hist.index%10 == 0]
majorTicks = hist['trade_date'][hist.index%10 == 0]
#K线图
plt.figure(figsize=(16, 8))
hist['EMA_5'].plot(color='red', label='EMA5')
hist['EMA_20'].plot(color='blue', label='EMA20')
hist['EMA_60'].plot(color='green', label='EMA60')
hist['BBI'].plot(color='grey', label='BBI')
for _, row in hist.iterrows():
if row['close'] >= row['open']:
plt.vlines(row['trade_date'], row['low'], row['high'],
color='red', linestyles='solid')
plt.bar(row['trade_date'], row['close']-row['open'],
width=0.5, bottom=row['open'], color='red')
else:
plt.vlines(row['trade_date'], row['low'], row['high'],
color='green', linestyles='solid')
plt.bar(row['trade_date'], row['open']-row['close'],
width=0.5, bottom=row['close'], color='green')
plt.xticks(majorIndex, majorTicks, rotation=30)
plt.grid(linestyle='-.')
plt.title(STOCK_ID)
plt.legend(loc='best')
plt.show()
下一篇文章,讲如何用随机森林来预测股价走势