首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何量化识别股票底部形态(三)

如何量化识别股票底部形态(三)

作者头像
子晓聊技术
发布2026-04-23 16:32:15
发布2026-04-23 16:32:15
1400
举报
文章被收录于专栏:子晓AI量化子晓AI量化

前2篇文章写了 底分型、双重底、头肩底、圆弧底, 这里继续往下写一写V形底、三重底。

前2篇文章链接:

如何量化识别股票底部形态(一)

如何量化识别股票底部形态(二)

五、V形底:急跌后的“暴力反转”

1. 形态定义与特征

V形底,又称“尖底”,是股价急跌后急跌后快速反弹,形成的“V”字形态。其核心特征:

  • 下跌/上涨角度陡峭:左侧下跌和右侧上涨的均线(如5日均线)斜率超过45度;
  • 成交量“底放量”:最低点附近成交量突然放大(较前5日平均高2倍以上);
  • 无明显盘整:从下跌到反转几乎没有横盘整理,直接V型反转。

2. 市场含义

V形底是“恐慌性反转”形态,多由重大利好(如政策刺激、行业拐点)触发。左侧是恐慌盘杀跌,右侧是聪明资金快速抄底,反转速度快、幅度大,但风险也高(容易二次探底)。

3、写一个例子演示

代码语言:javascript
复制
import numpy as np
import pandas as pd
import akshare as ak
def find_v_bottom(df, min_drop=0.15, min_rise=0.15, volume_ratio=2.0, window=10):
    v_bottoms = []
    for i in range(window, len(df) - window):
        current_low = df['最低'].iloc[i]
        current_date = df.index[i]
        # 左侧:window天内跌幅超过min_drop
        left_df = df.iloc[i - window:i]
        left_drop = (left_df['开盘'].iloc[0] - current_low) / left_df['开盘'].iloc[0]
        # 右侧:window天内涨幅超过min_rise
        right_df = df.iloc[i + 1:i + 1 + window]
        if len(right_df) < window:
            continue
        right_rise = (right_df['收盘'].iloc[-1] - current_low) / current_low
        # 条件1:左侧跌幅+右侧涨幅达标
        if (left_drop < min_drop) or (right_rise < min_rise):
            continue
        # 条件2:最低点成交量放大(较前5日平均)
        current_volume = df['成交量'].iloc[i]
        avg_volume_5 = df['成交量'].iloc[i - 5:i].mean()
        if current_volume < avg_volume_5 * volume_ratio:
            continue
        # 条件3:左侧和右侧均线斜率陡峭(5日均线)
        left_df['MA5'] = left_df['收盘'].rolling(5).mean()
        right_df['MA5'] = right_df['收盘'].rolling(5).mean()
        # 左侧MA5斜率(负,且绝对值大)
        left_x = np.arange(len(left_df))
        left_ma5 = left_df['MA5'].dropna()
        if len(left_ma5) < 5:
            continue
        left_slope = np.polyfit(left_x[-len(left_ma5):], left_ma5, 1)[0]
        # 右侧MA5斜率(正,且大)
        right_x = np.arange(len(right_df))
        right_ma5 = right_df['MA5'].dropna()
        if len(right_ma5) < 5:
            continue
        right_slope = np.polyfit(right_x[:len(right_ma5)], right_ma5, 1)[0]
        if (left_slope > -0.5) or (right_slope < 0.5):  # 斜率阈值需根据股票调整
            continue
        v_bottoms.append({
            'V底日期': current_date,
            '最低价': current_low,
            '左侧跌幅': f"{left_drop:.2%}",
            '右侧涨幅': f"{right_rise:.2%}",
            '成交量倍数': current_volume / avg_volume_5
        })
    return v_bottoms
# 获取股票数据(以平安银行000001为例)
def get_stock_data(symbol="000001", start_date="20250101", end_date="20250921"):
    df = ak.stock_zh_a_hist(symbol=symbol, period="daily",
                            start_date=start_date, end_date=end_date, adjust="qfq")
    df['日期'] = pd.to_datetime(df['日期'])
    df.set_index('日期', inplace=True)
    return df[['开盘', '收盘', '最高', '最低', '成交量']]
df_ningde = get_stock_data(symbol="300750", start_date="20220101", end_date="20251231")
v_bottoms = find_v_bottom(df_ningde)
if v_bottoms:
    for vb in v_bottoms:
        print(f"V形底确认:\n日期:{vb['V底日期']}(最低价:{vb['最低价']:.2f})")
        print(f"左侧跌幅:{vb['左侧跌幅']},右侧涨幅:{vb['右侧涨幅']}")
        print(f"成交量倍数:{vb['成交量倍数']:.2f}倍\n")
else:
    print("未识别出符合条件的V形底形态")

六、三重底:W底的“加强版”

1. 形态定义与特征

三重底是W底的变体,由三个低点和两个反弹高点构成,形似“三个连在一起的碗”。其核心特征:

  • 三个低点价格相近:三个低点价格差异不超过5%;
  • 两个颈线位平行:第一个低点与第二个低点之间的反弹高点、第二个低点与第三个低点之间的反弹高点,连线几乎水平;
  • 放量突破:突破第二个颈线位时成交量显著放大。

2. 市场含义

三重底是“多重探底”形态,比W底更扎实:三个低点意味着空方三次打压均未成功,多方力量占据绝对优势。突破后上涨幅度通常大于W底,目标价为“颈线位+低点到颈线位距离”。

3、写一个例子演示

代码语言:javascript
复制
import numpy as np
import pandas as pd
import akshare as ak
def find_triple_bottom(df, min_distance=15, price_tolerance=0.05, breakout_ratio=0.03):
    # 第一步:找出局部低点
    df['局部低点'] = False
    for i in range(5, len(df) - 5):
        if df['最低'].iloc[i] == df['最低'].iloc[i - 5:i + 5].min():
            df.at[df.index[i], '局部低点'] = True
    local_lows = df[df['局部低点']]
    triple_bottoms = []
    # 第二步:匹配三个连续低点
    for i in range(len(local_lows) - 2):
        low1 = local_lows.iloc[i]
        low2 = local_lows.iloc[i + 1]
        low3 = local_lows.iloc[i + 2]
        # 条件1:三个低点间隔足够
        days_12 = (low2.name - low1.name).days
        days_23 = (low3.name - low2.name).days
        if (days_12 < min_distance) or (days_23 < min_distance):
            continue
        # 条件2:三个低点价格相近
        price_diff_12 = abs(low2['最低'] - low1['最低']) / low1['最低']
        price_diff_23 = abs(low3['最低'] - low2['最低']) / low2['最低']
        if (price_diff_12 > price_tolerance) or (price_diff_23 > price_tolerance):
            continue
        # 条件3:计算两个颈线位(low1-low2之间的高点,low2-low3之间的高点)
        neckline1 = df[(df.index > low1.name) & (df.index < low2.name)]['最高'].max()
        neckline2 = df[(df.index > low2.name) & (df.index < low3.name)]['最高'].max()
        # 颈线位需平行(差异不超过5%)
        neckline_diff = abs(neckline2 - neckline1) / neckline1
        if neckline_diff > 0.05:
            continue
        # 条件4:突破第二个颈线位
        after_low3 = df[df.index > low3.name]
        if len(after_low3) == 0:
            continue
        breakout_close = neckline2 * (1 + breakout_ratio)
        breakout_signals = after_low3[after_low3['收盘'] > breakout_close]
        if len(breakout_signals) > 0:
            triple_bottoms.append({
                '第一个低点': low1.name,
                '第二个低点': low2.name,
                '第三个低点': low3.name,
                '颈线位1': neckline1,
                '颈线位2': neckline2,
                '突破日期': breakout_signals.index[0]
            })
    return triple_bottoms
def get_stock_data(symbol="000001", start_date="20250101", end_date="20250921"):
    df = ak.stock_zh_a_hist(symbol=symbol, period="daily",
                            start_date=start_date, end_date=end_date, adjust="qfq")
    df['日期'] = pd.to_datetime(df['日期'])
    df.set_index('日期', inplace=True)
    return df[['开盘', '收盘', '最高', '最低', '成交量']]
df_byd = get_stock_data(symbol="002594", start_date="20220101", end_date="20250921")
triple_bottoms = find_triple_bottom(df_byd)
if triple_bottoms:
    for tb in triple_bottoms:
        print(
            f"三重底确认:\n三个低点日期:{tb['第一个低点'].date()}、{tb['第二个低点'].date()}、{tb['第三个低点'].date()}")
        print(f"颈线位1:{tb['颈线位1']:.2f},颈线位2:{tb['颈线位2']:.2f}")
        print(f"突破日期:{tb['突破日期'].date()}\n")
else:
    print("未识别出符合条件的股票")

如果我的分享对你投资有所帮助,不吝啬给个点赞关注呗。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 子晓聊技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 五、V形底:急跌后的“暴力反转”
    • 1. 形态定义与特征
    • 2. 市场含义
  • 六、三重底:W底的“加强版”
    • 1. 形态定义与特征
    • 2. 市场含义
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档