A股日线看不出方向?多周期 K 线做共振选股,趋势一目了然

用户头像sh_*2176oo
2026-07-17 发布

A股日线看不出方向?用 Python 多周期 K 线做共振选股,趋势一目了然

只看日线选股有一个致命问题:你不知道自己在做什么级别的交易。

日线金叉了,你买进去,结果周线还在往下走——日线级别的反弹被周线级别的下跌吞掉了。反过来也有:日线死叉了你吓得卖了,结果月线趋势完好,跌下去两天就拉回来。

专业做趋势的人会同时看多个周期。当日线、周线、月线同时指向同一个方向——这叫"多周期共振"——趋势的可靠性会大幅提高。

AlphaFeed 的 K 线接口支持 period="1d" / "1w" / "1M" 三种周期,可以用同一个接口拉日线、周线、月线数据。这篇文章用这三个周期做一套完整的共振选股系统。

1. 什么是多周期共振

简单说:大周期定方向,小周期找时机。

周期 看什么 对应交易级别
月线 长期趋势方向 中长线(持仓数月)
周线 中期趋势强度 波段(持仓数周)
日线 短期买卖时机 短线(持仓数天)

最理想的买入时机:月线多头 + 周线多头 + 日线刚刚翻多。

2. 单只票的三周期分析

先拿一只票演示,看看三个周期怎么配合:

from alphafeed import AlphaFeed
import pandas as pd

af = AlphaFeed()

symbol = "600519.SH"

# 用同一个接口拉三个周期的数据
df_daily = af.klines.get(symbol, period="1d", count=250, adjust="forward", to_dataframe=True)
df_weekly = af.klines.get(symbol, period="1w", count=100, adjust="forward", to_dataframe=True)
df_monthly = af.klines.get(symbol, period="1M", count=36, adjust="forward", to_dataframe=True)

def analyze_trend(df: pd.DataFrame, label: str) -> dict:
    """分析单个周期的趋势状态"""
    df = df.sort_values("trade_date").reset_index(drop=True)
    price = df["close"].iloc[-1]

    ma5 = df["close"].rolling(5).mean().iloc[-1]
    ma10 = df["close"].rolling(10).mean().iloc[-1]
    ma20 = df["close"].rolling(min(20, len(df))).mean().iloc[-1]

    # 趋势打分
    score = 0
    details = []

    if price > ma5:
        score += 1
        details.append(f"站上 MA5({ma5:.2f})")
    if price > ma10:
        score += 1
        details.append(f"站上 MA10({ma10:.2f})")
    if price > ma20:
        score += 1
        details.append(f"站上 MA20({ma20:.2f})")
    if ma5 > ma10 > ma20:
        score += 2
        details.append("均线多头排列")
    elif ma5 < ma10 < ma20:
        score -= 2
        details.append("均线空头排列")

    return {
        "周期": label,
        "现价": price,
        "得分": score,
        "状态": "多头" if score >= 3 else "空头" if score <= -1 else "震荡",
        "细节": " | ".join(details),
    }

daily_trend = analyze_trend(df_daily, "日线")
weekly_trend = analyze_trend(df_weekly, "周线")
monthly_trend = analyze_trend(df_monthly, "月线")

print(f"=== {symbol} 多周期分析 ===\n")
for t in [monthly_trend, weekly_trend, daily_trend]:
    print(f"  {t['周期']}: {t['状态']}(得分 {t['得分']})")
    print(f"        {t['细节']}")
    print()

# 共振判断
states = [monthly_trend["状态"], weekly_trend["状态"], daily_trend["状态"]]
if all(s == "多头" for s in states):
    print("🟢 三周期共振多头 —— 趋势非常强")
elif all(s == "空头" for s in states):
    print("🔴 三周期共振空头 —— 趋势非常弱")
elif monthly_trend["状态"] == "多头" and weekly_trend["状态"] == "多头":
    print("🟡 大周期偏多,日线待确认 —— 可以观察")
else:
    print("⚪ 各周期方向不一致 —— 暂时观望")

3. 批量多周期共振选股

对一批股票同时做三周期分析,筛选出"三线共振"的标的:

from alphafeed import AlphaFeed
import pandas as pd

af = AlphaFeed()

# 股票池(可以扩展到几百只)
stock_pool = [
    "600519.SH", "000001.SZ", "300750.SZ", "002594.SZ", "601318.SH",
    "000858.SZ", "600036.SH", "000333.SZ", "601012.SH", "600276.SH",
    "600900.SH", "601398.SH", "600030.SH", "000651.SZ", "002415.SZ",
    "600887.SH", "601166.SH", "000568.SZ", "600809.SH", "002304.SZ",
    "601888.SH", "600809.SH", "300059.SZ", "002475.SZ", "000725.SZ",
    "601899.SH", "600031.SH", "002714.SZ", "600585.SH", "000002.SZ",
]

# 批量拉三个周期的 K 线
print("拉取日线...")
daily_data = af.klines.batch(
    stock_pool, period="1d", count=60,
    adjust="forward", to_dataframe=True, show_progress=True,
)

print("拉取周线...")
weekly_data = af.klines.batch(
    stock_pool, period="1w", count=30,
    adjust="forward", to_dataframe=True, show_progress=True,
)

print("拉取月线...")
monthly_data = af.klines.batch(
    stock_pool, period="1M", count=12,
    adjust="forward", to_dataframe=True, show_progress=True,
)

print(f"\n数据拉取完成: {len(stock_pool)} 只票 × 3 个周期\n")

三个 batch 调用,自动并发,30 只票 × 3 个周期 = 90 次请求,但实际只需要几秒。

4. 定义趋势判断函数

def get_trend_score(df: pd.DataFrame) -> int:
    """
    趋势打分: -5 到 +5
    正数 = 多头,负数 = 空头,0 附近 = 震荡
    """
    if df is None or len(df) < 10:
        return 0

    df = df.sort_values("trade_date").reset_index(drop=True)
    price = df["close"].iloc[-1]

    ma5 = df["close"].rolling(5).mean().iloc[-1]
    ma10 = df["close"].rolling(10).mean().iloc[-1]
    ma20 = df["close"].rolling(min(20, len(df))).mean().iloc[-1]

    score = 0
    if price > ma5: score += 1
    else: score -= 1
    if price > ma10: score += 1
    else: score -= 1
    if price > ma20: score += 1
    else: score -= 1
    if ma5 > ma10: score += 1
    else: score -= 1
    if ma10 > ma20: score += 1
    else: score -= 1

    return score


def classify_trend(score: int) -> str:
    if score >= 3:
        return "多头"
    elif score <= -3:
        return "空头"
    else:
        return "震荡"

5. 筛选共振标的

results = []

for sym in stock_pool:
    d_score = get_trend_score(daily_data.get(sym))
    w_score = get_trend_score(weekly_data.get(sym))
    m_score = get_trend_score(monthly_data.get(sym))

    d_trend = classify_trend(d_score)
    w_trend = classify_trend(w_score)
    m_trend = classify_trend(m_score)

    # 综合得分 = 月线权重最大
    total_score = m_score * 3 + w_score * 2 + d_score * 1

    results.append({
        "代码": sym,
        "月线": m_trend,
        "周线": w_trend,
        "日线": d_trend,
        "月得分": m_score,
        "周得分": w_score,
        "日得分": d_score,
        "综合分": total_score,
    })

rdf = pd.DataFrame(results).sort_values("综合分", ascending=False)

# 三周期共振多头
resonance_bull = rdf[
    (rdf["月线"] == "多头") &
    (rdf["周线"] == "多头") &
    (rdf["日线"] == "多头")
]

# 月线周线多头,日线待确认(潜在买入时机)
potential_buy = rdf[
    (rdf["月线"] == "多头") &
    (rdf["周线"] == "多头") &
    (rdf["日线"] != "多头")
]

# 三周期共振空头
resonance_bear = rdf[
    (rdf["月线"] == "空头") &
    (rdf["周线"] == "空头") &
    (rdf["日线"] == "空头")
]

print(f"=== 多周期共振选股结果 ===\n")

print(f"🟢 三周期共振多头: {len(resonance_bull)} 只")
if len(resonance_bull) > 0:
    print(resonance_bull[["代码", "月线", "周线", "日线", "综合分"]].to_string(index=False))

print(f"\n🟡 大周期多头 + 日线待确认: {len(potential_buy)} 只")
if len(potential_buy) > 0:
    print(potential_buy[["代码", "月线", "周线", "日线", "综合分"]].to_string(index=False))

print(f"\n🔴 三周期共振空头: {len(resonance_bear)} 只")
if len(resonance_bear) > 0:
    print(resonance_bear[["代码", "月线", "周线", "日线", "综合分"]].to_string(index=False))

print(f"\n完整排名:")
print(rdf[["代码", "月线", "周线", "日线", "综合分"]].to_string(index=False))

6. 加入动量确认

光看均线位置还不够,加入动量指标让筛选更精确:

def get_momentum(df: pd.DataFrame, period: int = 20) -> float:
    """计算近 N 根 K 线的动量(涨幅)"""
    if df is None or len(df) < period:
        return 0
    df = df.sort_values("trade_date").reset_index(drop=True)
    return df["close"].iloc[-1] / df["close"].iloc[-period] - 1


# 给共振多头的票加上动量排序
if len(resonance_bull) > 0:
    momentum_data = []
    for _, row in resonance_bull.iterrows():
        sym = row["代码"]
        mom_d = get_momentum(daily_data.get(sym), 20)   # 日线 20 日动量
        mom_w = get_momentum(weekly_data.get(sym), 8)    # 周线 8 周动量
        momentum_data.append({
            "代码": sym,
            "20日动量": f"{mom_d:+.1%}",
            "8周动量": f"{mom_w:+.1%}",
            "综合分": row["综合分"],
        })

    mom_df = pd.DataFrame(momentum_data)
    print(f"\n🟢 共振多头标的动量排序:")
    print(mom_df.to_string(index=False))

7. 一个更实际的选股流程

把多周期共振嵌入日常选股工作流:

# resonance_scan.py
"""多周期共振选股扫描"""

from alphafeed import AlphaFeed
import pandas as pd

af = AlphaFeed()

def resonance_scan(symbols: list) -> pd.DataFrame:
    """对一组标的做多周期共振扫描"""

    daily = af.klines.batch(
        symbols, period="1d", count=60,
        adjust="forward", to_dataframe=True,
    )
    weekly = af.klines.batch(
        symbols, period="1w", count=30,
        adjust="forward", to_dataframe=True,
    )
    monthly = af.klines.batch(
        symbols, period="1M", count=12,
        adjust="forward", to_dataframe=True,
    )

    results = []
    for sym in symbols:
        ds = get_trend_score(daily.get(sym))
        ws = get_trend_score(weekly.get(sym))
        ms = get_trend_score(monthly.get(sym))
        dt = classify_trend(ds)
        wt = classify_trend(ws)
        mt = classify_trend(ms)

        resonance = "共振多头" if dt == wt == mt == "多头" else \
                    "共振空头" if dt == wt == mt == "空头" else \
                    "大周期多头" if mt == "多头" and wt == "多头" else \
                    "方向不一致"

        results.append({
            "代码": sym,
            "月线": mt,
            "周线": wt,
            "日线": dt,
            "共振": resonance,
            "综合分": ms * 3 + ws * 2 + ds,
        })

    return pd.DataFrame(results).sort_values("综合分", ascending=False)

# 使用
my_stocks = ["600519.SH", "000001.SZ", "300750.SZ", "002594.SZ",
             "601318.SH", "000858.SZ", "600036.SH", "000333.SZ"]

result = resonance_scan(my_stocks)
print(result.to_string(index=False))

8. 为什么这个方法有效

多周期共振不是万能的,但它解决了一个很实际的问题:降低逆势交易的概率。

场景 只看日线 三周期共振
日线金叉买入,周线还在跌 会买 ❌ 不买 ✅
日线死叉卖出,月线趋势完好 会卖 ❌ 不卖 ✅
三个周期都翻多 可能买也可能没注意 明确信号 ✅
月线空头反弹 可能当反转 ❌ 大周期空头,不参与 ✅

本质上,它帮你过滤掉了大量"日线看着不错但大周期不配合"的假信号。

9. AlphaFeed 在这件事里的价值

多周期分析需要同时拉日线、周线、月线三套数据。用 AlphaFeed 做这件事很顺畅:

# 同一个接口,只改 period 参数
df_d = af.klines.get(sym, period="1d",  count=60,  adjust="forward", to_dataframe=True)
df_w = af.klines.get(sym, period="1w",  count=30,  adjust="forward", to_dataframe=True)
df_m = af.klines.get(sym, period="1M",  count=12,  adjust="forward", to_dataframe=True)

不需要自己从日线合成周线月线(很多数据源只提供日线,周线月线要自己算——日期对齐、跨周处理、节假日,坑很多)。AlphaFeed 直接给你计算好的周线和月线 K 线,开高低收都是准的。

再加上 batch 批量接口,30 只票 × 3 个周期 = 90 次请求,SDK 内部并发处理,几秒钟全部拉完。


评论