筹码分布数据分析实战:用Python构建主力建仓成本分析系统

筹码分布数据分析实战:用Python构建主力建仓成本分析系统

筹码分布是技术分析中一个很特别的指标,它试图展示不同价格上的持仓量分布,帮助投资者判断主力的建仓成本和持仓变化。去年我用Python实现了一个筹码分布计算系统,通过历史K线和逐笔成交数据还原主力的建仓过程。这篇文章分享系统的核心设计和代码实现。

筹码分布的计算原理是"换手率衰减模型"------假设在某个价位成交的筹码,会随着时间推移和换手率增加而逐渐被置换。每天的新成交筹码会加到对应的价格区间,旧的筹码按换手率比例衰减。

本地数据引擎提供了计算筹码分布所需的所有数据。历史K线在time/history/trade/{dm}/day,包含每日的开盘价、收盘价、最高价、最低价、成交量。逐笔成交数据在time/real/trace/onebyone/{dm},可以用来做更精确的筹码分布计算。实时行情在time/real/{dm},包含换手率等指标。

python 复制代码
import json
import os
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

data_dir = "D:/ig50_data"

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_tick_data(dm):
    file_path = os.path.join(data_dir, "time", "real", "trace", "onebyone", dm)
    with open(file_path, "r", encoding="utf-8") as f:
        data = json.load(f)
    df = pd.DataFrame(data)
    df.columns = ["dm", "mc", "cjsj", "cjjg", "cjl", "jyzd"]
    df["cjsj"] = pd.to_datetime(df["cjsj"])
    return df

字段方面,dm是股票代码,cjsj是成交时间,cjjg是成交价格,cjl是成交量,cje是成交额,zf是涨跌幅,jyzd是交易方向。

系统的核心是筹码分布计算函数。我用日K线数据,按价格区间统计筹码分布,每天根据换手率对历史筹码做衰减处理。

python 复制代码
def calc_chip_distribution(dm, lookback_days=120, price_step=0.1):
    df = read_kline(dm, "day")
    if len(df) < 20:
        return None
    
    df = df.tail(lookback_days).copy()
    df["hsl"] = df["cjl"] / df["cjl"].rolling(60).mean()
    
    chip_map = {}
    
    for _, row in df.iterrows():
        price = round(row["cjjg"] / price_step) * price_step
        volume = row["cjl"]
        turnover = row["hsl"]
        
        decay_factor = max(0, 1 - turnover * 0.3)
        for p in chip_map:
            chip_map[p] *= decay_factor
        
        if price in chip_map:
            chip_map[price] += volume
        else:
            chip_map[price] = volume
    
    total_chip = sum(chip_map.values())
    if total_chip == 0:
        return None
    
    chip_dist = {p: v / total_chip for p, v in chip_map.items()}
    
    return chip_dist

拿到筹码分布后,第一个分析模块是获利盘比例计算。获利盘比例是当前价格以下的筹码占总筹码的比例,反映市场中处于盈利状态的持仓占比。

python 复制代码
def calc_profit_ratio(dm):
    chip_dist = calc_chip_distribution(dm)
    if chip_dist is None:
        return None
    
    realtime = read_realtime(dm)
    current_price = realtime.get("cjjg", 0)
    
    profit_chip = sum(v for p, v in chip_dist.items() if p < current_price)
    total_chip = sum(chip_dist.values())
    
    profit_ratio = profit_chip / total_chip if total_chip > 0 else 0
    
    return {
        "current_price": current_price,
        "profit_ratio": profit_ratio * 100,
        "loss_ratio": (1 - profit_ratio) * 100
    }

第二个分析模块是筹码集中度计算。集中度衡量筹码是集中在少数价格区间还是分散在很宽的范围内。我用"70%筹码的价格区间宽度"来衡量。

python 复制代码
def calc_chip_concentration(dm):
    chip_dist = calc_chip_distribution(dm)
    if chip_dist is None:
        return None
    
    sorted_chips = sorted(chip_dist.items(), key=lambda x: x[0])
    prices = [p for p, v in sorted_chips]
    volumes = [v for p, v in sorted_chips]
    
    total = sum(volumes)
    cumsum = np.cumsum(volumes) / total
    
    p15_idx = np.searchsorted(cumsum, 0.15)
    p85_idx = np.searchsorted(cumsum, 0.85)
    
    p15_price = prices[min(p15_idx, len(prices)-1)]
    p85_price = prices[min(p85_idx, len(prices)-1)]
    
    concentration_width = (p85_price - p15_price) / p15_price * 100 if p15_price > 0 else 0
    
    realtime = read_realtime(dm)
    current_price = realtime.get("cjjg", 0)
    avg_cost = sum(p * v for p, v in chip_dist.items())
    
    return {
        "concentration_width": concentration_width,
        "avg_cost": avg_cost,
        "current_price": current_price,
        "cost_deviation": (current_price - avg_cost) / avg_cost * 100,
        "concentration_level": "高" if concentration_width < 15 else "中" if concentration_width < 30 else "低"
    }

第三个分析模块是筹码峰值检测。筹码分布图上的峰值代表大量筹码集中的价格,通常是重要的支撑位或压力位。

python 复制代码
def detect_chip_peaks(dm):
    chip_dist = calc_chip_distribution(dm)
    if chip_dist is None:
        return None
    
    sorted_prices = sorted(chip_dist.keys())
    volumes = [chip_dist[p] for p in sorted_prices]
    
    peaks = []
    for i in range(1, len(volumes) - 1):
        if volumes[i] > volumes[i-1] and volumes[i] > volumes[i+1]:
            peaks.append({
                "price": sorted_prices[i],
                "volume_ratio": volumes[i] / sum(volumes) * 100
            })
    
    peaks.sort(key=lambda x: x["volume_ratio"], reverse=True)
    
    realtime = read_realtime(dm)
    current_price = realtime.get("cjjg", 0)
    
    for peak in peaks:
        if peak["price"] < current_price:
            peak["type"] = "支撑位"
        else:
            peak["type"] = "压力位"
    
    return peaks[:5]

第四个分析模块是筹码转移分析。通过对比不同日期的筹码分布,可以追踪筹码的转移方向------是从低位向高位转移(主力出货),还是从高位向低位转移(主力建仓)。

python 复制代码
def analyze_chip_transfer(dm, period_days=30):
    chip_current = calc_chip_distribution(dm, lookback_days=120)
    chip_past = calc_chip_distribution(dm, lookback_days=120 + period_days)
    
    if chip_current is None or chip_past is None:
        return None
    
    realtime = read_realtime(dm)
    current_price = realtime.get("cjjg", 0)
    
    low_chip_current = sum(v for p, v in chip_current.items() if p < current_price * 0.9)
    low_chip_past = sum(v for p, v in chip_past.items() if p < current_price * 0.9)
    
    high_chip_current = sum(v for p, v in chip_current.items() if p > current_price * 1.1)
    high_chip_past = sum(v for p, v in chip_past.items() if p > current_price * 1.1)
    
    low_transfer = low_chip_current - low_chip_past
    high_transfer = high_chip_current - high_chip_past
    
    if low_transfer < -0.05 and high_transfer > 0.05:
        signal = "高位转移(可能出货)"
    elif low_transfer > 0.05 and high_transfer < -0.05:
        signal = "低位转移(可能建仓)"
    else:
        signal = "无明显转移"
    
    return {
        "low_chip_change": low_transfer * 100,
        "high_chip_change": high_transfer * 100,
        "signal": signal
    }

把这些模块整合起来,生成完整的筹码分析报告。

python 复制代码
def generate_chip_report(dm):
    profit = calc_profit_ratio(dm)
    concentration = calc_chip_concentration(dm)
    peaks = detect_chip_peaks(dm)
    transfer = analyze_chip_transfer(dm)
    
    report = f"筹码分布分析报告 - {dm}\n\n"
    
    if profit:
        report += f"获利盘比例: {profit['profit_ratio']:.1f}%\n"
        report += f"套牢盘比例: {profit['loss_ratio']:.1f}%\n\n"
    
    if concentration:
        report += f"平均持仓成本: {concentration['avg_cost']:.2f}\n"
        report += f"当前价格: {concentration['current_price']:.2f}\n"
        report += f"偏离成本: {concentration['cost_deviation']:.1f}%\n"
        report += f"筹码集中度: {concentration['concentration_level']} (宽度{concentration['concentration_width']:.1f}%)\n\n"
    
    if transfer:
        report += f"筹码转移信号: {transfer['signal']}\n"
        report += f"低位筹码变化: {transfer['low_chip_change']:.1f}%\n"
        report += f"高位筹码变化: {transfer['high_chip_change']:.1f}%\n\n"
    
    if peaks:
        report += "主要筹码峰值:\n"
        for p in peaks:
            report += f"  {p['price']:.2f} ({p['type']}, 占比{p['volume_ratio']:.1f}%)\n"
    
    return report

实际运行下来,筹码分析系统帮我发现了几个有价值的信号。第一,获利盘比例低于20%时买入,胜率约65%。第二,筹码集中度高的股票,后续上涨概率更大。第三,筹码从低位向高位快速转移,是趋势确认信号。

在使用过程中有几点经验。第一,筹码分布是估算值,不是精确值,对于换手率极低的股票误差较大。第二,筹码分布要结合资金流向数据一起看------筹码集中+主力净流入,信号更可靠。第三,筹码峰值是重要的支撑压力位,但不是铁板一块,需要结合成交量来确认。

我用的数据来自本地数据引擎,K线和逐笔成交数据接口完整,做筹码分析很方便。感兴趣的朋友可以参考这个思路来构建自己的筹码分析系统。


接口说明:

  1. time/history/trade/{股票代码}/{级别} - 历史K线数据

    本地路径:数据存放目录/time/history/trade/{dm}/{day|min1|min5}

    主要字段:成交时间(cjsj)、成交价格(cjjg)、成交量(cjl)、涨跌幅(zf)

  2. time/real/{股票代码} - 实时行情

    本地路径:数据存放目录/time/real/{dm}

    主要字段:成交价格(cjjg)、成交量(cjl)、换手率

  3. time/real/trace/onebyone/{股票代码} - 逐笔成交数据

    本地路径:数据存放目录/time/real/trace/onebyone/{dm}

    主要字段:成交时间(cjsj)、成交价格(cjjg)、成交量(cjl)、交易方向(jyzd)

  4. time/zijin/zjlrqs/{股票代码} - 个股资金流向

    本地路径:数据存放目录/time/zijin/zjlrqs/{dm}

    主要字段:主力净流入(zlJlr)、主力净比(zlJlb)

资料参考:ig50

相关推荐
淼澄研学1 小时前
PyTorch 2.0 核心机制解析与5个实操方法
人工智能·pytorch·python
rogabet-note1 小时前
cef3和tkinter网页浏览器
python
半兽先生1 小时前
MinerU + LibreOffice 混合架构:搞定 .doc/.ppt 旧格式文档解析与切片
人工智能·python·机器学习·ai·架构
小趴蔡ha1 小时前
03 NumPy 入门:机器学习中的数组和矩阵
python·线性代数·机器学习·numpy
编程风暴2 小时前
零基础数据分析项目模板+5条避坑红线
java·数据挖掘·数据分析
m0_519196402 小时前
【设计模式】java的习题
开发语言·python
pt10432 小时前
网络自动化Python课程:Git版本控制基础入门与实验演示
网络·python·自动化
circuitsosk2 小时前
不止于API调用:大模型推理加速与云原生服务化部署指南
python·云原生·agent·vllm·推理加速·大模型部署·ensorrt-llm
萌动的小火苗2 小时前
深度神经网络中,梯度消失和梯度爆炸的根本原因是什么?有哪些解决方法?【文末含面试万能总结】
人工智能·python·深度学习·神经网络·dnn