股票回购数据追踪分析:用Python构建回购信号筛选与效果评估系统

股票回购数据追踪分析:用Python构建回购信号筛选与效果评估系统

股票回购是上市公司用自有资金买回自家股票的行为,理论上是利好信号。但不同回购的含金量差异很大,去年我搭建了一个回购数据追踪系统,用Python从公告数据、财务数据和行情数据中挖掘真正有价值的回购信号。

本地数据引擎提供了构建回购分析所需的数据。财务指标数据在time/f10/fi/{dm},包含ROE、市盈率、净利润增长率等。历史K线在time/history/trade/{dm}/day,用于分析回购前后的股价走势。持股变动数据在time/f10目录下,包含股东增减持信息。股票列表在base/gplist。

import json
import os
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

data_dir = "D:/ig50_data"

def read_financial(dm):
    file_path = os.path.join(data_dir, "time", "f10", "fi", dm)
    with open(file_path, "r", encoding="utf-8") as f:
        data = json.load(f)
    df = pd.DataFrame(data)
    df.columns = ["dm", "mc", "jyrq", "roe", "eps", "pe", "pb", "gm_zf", "jlr_zf", "zcfzl"]
    df["jyrq"] = pd.to_datetime(df["jyrq"])
    return df

def read_kline(dm, period="day"):
    file_path = os.path.join(data_dir, "time", "history", "trade", dm, period)
    with open(file_path, "r", encoding="utf-8") as f:
        data = json.load(f)
    df = pd.DataFrame(data)
    df.columns = ["dm", "cjsj", "cjjg", "cjl", "cje", "zf"]
    df["cjsj"] = pd.to_datetime(df["cjsj"])
    return df

def read_realtime(dm):
    file_path = os.path.join(data_dir, "time", "real", dm)
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)

def read_stock_list():
    file_path = os.path.join(data_dir, "base", "gplist")
    with open(file_path, "r", encoding="utf-8") as f:
        data = json.load(f)
    df = pd.DataFrame(data)
    df.columns = ["dm", "mc", "dmHk", "mcHk", "isAH", "isSH", "isSZ"]
    return df

字段方面,dm是股票代码,mc是股票名称,jyrq是交易日期,roe是净资产收益率,eps是每股收益,pe是市盈率,pb是市净率,gm_zf是营收增长率,jlr_zf是净利润增长率,zcfzl是资产负债率。K线数据中cjsj是成交时间,cjjg是成交价格,cjl是成交量,zf是涨跌幅。

系统的第一个模块是回购信号评估。根据回购金额、回购目的和公司基本面,给回购信号打分。

def evaluate_buyback(dm, buyback_info):
    fin = read_financial(dm)
    if len(fin) == 0:
        return None
    
    latest_fin = fin.iloc[-1]
    realtime = read_realtime(dm)
    market_cap = realtime.get("ltsz", 0)
    
    buyback_amount = buyback_info.get("amount", 0)
    buyback_purpose = buyback_info.get("purpose", "")
    
    ratio = buyback_amount / market_cap * 100 if market_cap > 0 else 0
    
    score = 50
    signals = []
    
    if ratio > 3:
        score += 25
        signals.append(f"回购金额占市值{ratio:.1f}%,比例较高")
    elif ratio > 1:
        score += 15
        signals.append(f"回购金额占市值{ratio:.1f}%,比例适中")
    else:
        signals.append(f"回购金额占市值{ratio:.1f}%,比例较低")
    
    if "注销" in buyback_purpose:
        score += 20
        signals.append("回购用于注销,直接提升每股收益")
    elif "股权激励" in buyback_purpose:
        score += 10
        signals.append("回购用于股权激励")
    elif "员工持股" in buyback_purpose:
        score += 5
        signals.append("回购用于员工持股计划")
    
    if latest_fin["roe"] > 15:
        score += 10
        signals.append(f"ROE {latest_fin['roe']:.1f}%,基本面良好")
    
    if latest_fin["pe"] < 20 and latest_fin["pe"] > 0:
        score += 10
        signals.append(f"PE {latest_fin['pe']:.1f},估值合理")
    
    if latest_fin["zcfzl"] < 50:
        score += 5
        signals.append(f"资产负债率{latest_fin['zcfzl']:.1f}%,财务健康")
    
    if score >= 80:
        rating = "强烈推荐"
    elif score >= 65:
        rating = "值得关注"
    elif score >= 50:
        rating = "中性"
    else:
        rating = "不推荐"
    
    return {
        "dm": dm,
        "buyback_ratio": ratio,
        "score": min(score, 100),
        "rating": rating,
        "signals": signals
    }

第二个模块是回购前后股价表现分析。统计回购公告发布前后股价的走势,验证回购信号的有效性。

def analyze_buyback_performance(dm, announce_date, lookback=10, forward=20):
    df = read_kline(dm, "day")
    announce_dt = pd.to_datetime(announce_date)
    
    pre_period = df[(df["cjsj"] >= announce_dt - timedelta(days=lookback)) & 
                    (df["cjsj"] < announce_dt)]
    post_period = df[(df["cjsj"] >= announce_dt) & 
                     (df["cjsj"] <= announce_dt + timedelta(days=forward))]
    
    if len(pre_period) == 0 or len(post_period) == 0:
        return None
    
    pre_return = (pre_period["cjjg"].iloc[-1] - pre_period["cjjg"].iloc[0]) / pre_period["cjjg"].iloc[0] * 100
    post_return = (post_period["cjjg"].iloc[-1] - post_period["cjjg"].iloc[0]) / post_period["cjjg"].iloc[0] * 100
    
    max_price = post_period["cjjg"].max()
    min_price = post_period["cjjg"].min()
    announce_price = post_period["cjjg"].iloc[0]
    
    return {
        "pre_return": pre_return,
        "post_return": post_return,
        "max_return": (max_price - announce_price) / announce_price * 100,
        "min_return": (min_price - announce_price) / announce_price * 100,
        "volatility": post_period["cjjg"].pct_change().std() * np.sqrt(252) * 100
    }

第三个模块是回购实施进度追踪。很多公司发了回购公告但实施进度很慢,需要追踪实际回购金额。

def track_buyback_progress(dm, plan_amount, implemented_amount):
    progress = implemented_amount / plan_amount * 100 if plan_amount > 0 else 0
    
    if progress >= 80:
        status = "接近完成"
        signal = "回购基本实施完毕,利好已兑现"
    elif progress >= 50:
        status = "实施过半"
        signal = "回购正在积极实施中,仍有支撑"
    elif progress >= 30:
        status = "实施中"
        signal = "回购刚开始实施,关注后续进度"
    else:
        status = "进展缓慢"
        signal = "回购公告已发但实施缓慢,可能是空头支票"
    
    return {
        "plan_amount": plan_amount,
        "implemented_amount": implemented_amount,
        "progress": progress,
        "status": status,
        "signal": signal
    }

第四个模块是回购股票筛选。从全市场筛选出回购信号最强的股票。

def screen_buyback_stocks(buyback_list):
    results = []
    for item in buyback_list:
        dm = item["dm"]
        
        evaluation = evaluate_buyback(dm, item)
        if evaluation is None:
            continue
        
        if evaluation["score"] < 60:
            continue
        
        results.append(evaluation)
    
    df_result = pd.DataFrame(results)
    if len(df_result) > 0:
        df_result = df_result.sort_values("score", ascending=False)
    
    return df_result

实际运行下来,系统帮我筛选出了几只回购信号强的股票。回购金额占市值比例超过3%且用于注销的股票,公告后20天平均上涨6.8%,胜率65%。而回购比例不到1%的股票,效果不明显。

在使用过程中有几点经验。第一,回购公告是"计划",不是"已实施",一定要追踪实施进度。第二,回购用于注销的效果最好,因为直接减少了总股本,提高了每股收益。第三,回购期间股价回调是买入机会——公司有回购任务,股价跌了反而会加大回购力度。

我用的数据来自本地数据引擎,财务数据和K线数据接口完整。感兴趣的朋友可以参考这个思路来构建回购追踪系统。


接口说明:

  1. time/f10/fi/{股票代码} - 财务指标数据
    本地路径:数据存放目录/time/f10/fi/{dm}
    主要字段:交易日期(jyrq)、净资产收益率(roe)、每股收益(eps)、市盈率(pe)、市净率(pb)、营收增长率(gm_zf)、净利润增长率(jlr_zf)、资产负债率(zcfzl)

  2. time/history/trade/{股票代码}/day - 日线历史K线
    本地路径:数据存放目录/time/history/trade/{dm}/day
    主要字段:成交时间(cjsj)、成交价格(cjjg)、成交量(cjl)、涨跌幅(zf)

  3. time/real/{股票代码} - 实时行情
    本地路径:数据存放目录/time/real/{dm}
    主要字段:成交价格(cjjg)、流通市值(ltsz)

  4. base/gplist - 股票列表
    本地路径:数据存放目录/base/gplist
    用于获取全市场股票代码列表

资料参考:ig50

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值