
为什么你拿到的股票指标总是不准
很多人看盘软件里的MACD、KDJ、RSI,换个软件数值就不一样。根源在于计算参数和复权方式不同。开盘价、收盘价用前复权还是后复权,均线用简单移动平均还是指数移动平均,结果能差出好几个点。想拿到真正属于自己的指标,用Python从头算一遍最踏实。
第一步 找到能直接用的数据源头
股票原始数据分两类:行情数据(开高低收、成交量)和财务数据(利润、负债)。期货还多一层合约乘数、保证金、主力连续。

免费接口里,这几个最顺手:
Tushare:老牌选手,积分制。日线、分钟线、复权因子都有。注册后拿token,一行代码拉数据。
AKShare:完全免费,爬虫封装得干净。股票、期货、期权、基金全包。接口名字直白,
stock_zh_a_hist就是A股历史行情。yfinance:美股、港股、外汇、期货都能用。缺点是国内访问偶尔抽风。
以AKShare为例,拿贵州茅台日线:
import akshare as ak
df = ak.stock_zh_a_hist(symbol="600519", period="daily", start_date="20240101", end_date="20241231", adjust="qfq")
print(df.head())
adjust="qfq" 就是前复权。不加这个参数,除权除息那天价格会断崖,算出来的均线全是错的。
第二步 指标不用等软件 自己算更靠谱
拿到原始数据后,均线、MACD、RSI这些经典指标,用pandas和ta库几行就能出。
均线:简单但别用错
df["MA5"] = df["收盘"].rolling(5).mean()
df["MA20"] = df["收盘"].rolling(20).mean()
rolling(5).mean() 就是最近5天收盘价的算术平均。有人问为啥不用ewm,那是指数加权,反应更快但更容易被单日暴涨暴跌带偏。做趋势跟踪用rolling,做短线捕捉用ewm,没有绝对好坏。
MACD:慢线快线加柱状图
def macd(close, fast=12, slow=26, signal=9):
ema_fast = close.ewm(span=fast, adjust=False).mean()
ema_slow = close.ewm(span=slow, adjust=False).mean()
dif = ema_fast - ema_slow
dea = dif.ewm(span=signal, adjust=False).mean()
hist = (dif - dea) * 2
return dif, dea, hist
df["DIF"], df["DEA"], df["MACD"] = macd(df["收盘"])
adjust=False 是多数软件默认的递推算法。改成True,结果跟通达信、同花顺就对不上。这点小细节,能让回测收益差出十几个百分点。
RSI:超买超卖没那么神
delta = df["收盘"].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(14).mean()
avg_loss = loss.rolling(14).mean()
rs = avg_gain / avg_loss
df["RSI"] = 100 - (100 / (1 + rs))
RSI低于30叫超卖,高于70叫超买。震荡市管用,单边趋势里能钝化到让你怀疑人生。用Python算的好处是,你可以把14改成7、21,回测哪个参数适合当前品种。
第三步 期货指标要多留个心眼
期货跟股票不一样,主力合约会换月。直接拿单个合约算均线,换月跳空能把指标打乱。
处理办法是拼接主力连续。Tushare有fut_mapping接口,AKShare有futures_main_sina。拿到连续价格后,再算指标就跟股票一样了。
期货还有夜盘,日线收盘价按15:00算还是23:00算,不同软件不一样。自己用Python算,统一按白天收盘价,回测逻辑才干净。
# 期货主力连续示例
fut = ak.futures_main_sina(symbol="RB0", start_date="20240101", end_date="20241231")
fut["MA10"] = fut["收盘价"].rolling(10).mean()
第四步 批量拿全市场指标
单只股票算指标没意思,要扫全市场才能选股。思路是:先拿股票列表,循环拉数据,算完指标存本地。
import pandas as pd
stock_list = ak.stock_zh_a_spot_em()["代码"].tolist()
all_data = []
for code in stock_list[:100]: # 先跑100只试试
try:
df = ak.stock_zh_a_hist(symbol=code, period="daily", start_date="20240101", end_date="20241231", adjust="qfq")
df["MA20"] = df["收盘"].rolling(20).mean()
df["代码"] = code
all_data.append(df)
except:
continue
result = pd.concat(all_data)
result.to_csv("全市场指标.csv", index=False)
循环里加try except,防止某只票停牌或接口超时把整个程序打断。跑完存CSV,下次直接读,不用重复请求。
几个容易踩的坑
接口频率限制。AKShare免费但别往死里跑,每秒几十次请求会被封IP。加个time.sleep(0.5),慢就是快。
复权方式混用。拿前复权数据算指标,又拿不复权价格看K线,买卖点会对不上。统一用前复权,或者统一用后复权,别来回换。
指标未来函数。用rolling算均线不会偷看未来,但有人用shift(-1)做信号,回测收益漂亮,实盘一用就废。写策略时多看一眼有没有负向shift。
期货保证金和杠杆。股票指标直接看价格,期货指标要换算成保证金比例。10%保证金意味着价格波动1%,账户波动10%。指标信号一样,仓位管理完全不同。
把指标变成自己的武器
用Python直接获取股票指标,核心就三件事:拿干净数据、用对参数、避开未来函数。软件里现成的指标是别人嚼过的馍,自己算一遍才知道哪里松哪里紧。
股票和期货市场里,真正赚钱的信号往往不在默认参数里。把MACD的快慢线改成8和17,把RSI周期改成9,回测一遍,可能就找到别人没注意的角落。Python给了你这个自由,剩下的靠动手。