You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python中合并多Regime对应的Volume Profile与Candlestick图表为单图的实现需求

Python中合并多Regime对应的Volume Profile与Candlestick图表为单图的实现需求

看起来你现在需要把三个不同Regime对应的成交量分布(Volume Profile)和5分钟K线图合并到同一个可视化图表里,而不是生成三个独立的图。我来帮你调整原代码,实现这个需求👇

首先,我们会统一所有Regime的价格区间计算,用不同颜色区分每个Regime的成交量分布、K线主体和POC(成交量密集点),最终在同一个画布上展示所有内容:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 初始DataFrame创建
ds = {
    'Date' : ['2025-08-22 16:00:00', '2025-08-22 16:01:00', '2025-08-22 16:02:00', '2025-08-22 16:03:00', '2025-08-22 16:04:00', '2025-08-22 16:05:00', '2025-08-22 16:06:00', '2025-08-22 16:07:00', '2025-08-22 16:08:00', '2025-08-22 16:09:00', '2025-08-22 16:10:00', '2025-08-22 16:11:00', '2025-08-22 16:12:00', '2025-08-22 16:13:00', '2025-08-22 16:14:00', '2025-08-22 16:15:00', '2025-08-22 16:16:00', '2025-08-22 16:17:00', '2025-08-22 16:18:00', '2025-08-22 16:19:00', '2025-08-22 16:20:00', '2025-08-22 16:21:00', '2025-08-22 16:22:00', '2025-08-22 16:23:00', '2025-08-22 16:24:00'],
    'Open': [ 11717.9, 11717.95, 11716.6, 11717.4, 11719.5, 11727.25, 11725.55, 11724.35, 11725.45, 11724.15, 11728.2, 11726.6, 11727.6, 11729.1, 11724.1, 11722.8, 11721.8, 11720.8, 11718.8, 11716.7, 11716.9, 11722.5, 11721.6, 11727.8, 11728.1],
    'Low': [ 11715.9, 11716, 11715.35, 11716.45, 11719.5, 11724.3, 11723.55, 11723.15, 11723.85, 11724.15, 11725.2, 11726.6, 11727.6, 11724.2, 11722.6, 11721.6, 11719.7, 11715.8, 11716.5, 11716, 11716.9, 11721.3, 11721.4, 11726.35, 11727],
    'High': [ 11718.1, 11718.1, 11717.9, 11719.4, 11727.15, 11727.45, 11726, 11725.65, 11727.2, 11727.85, 11728.2, 11728.7, 11729.5, 11729.1, 11725.5, 11723.9, 11722, 11720.8, 11719.8, 11717.7, 11722.9, 11724.3, 11727.8, 11728.3, 11728.8],
    'Close' : [11718.05, 11716.5, 11717, 11719.3, 11727.15, 11725.65, 11724.15, 11725.35, 11724.05, 11727.65, 11726.7, 11727.8, 11729.2, 11724.2, 11722.6, 11721.7, 11721.2, 11718.7, 11716.6, 11716.8, 11722.6, 11721.5, 11727.6, 11728, 11727.2],
    'Volume': [ 130, 88, 125, 93, 154, 102, 118, 92, 105, 116, 84, 88, 108, 99, 82, 109, 98, 130, 71, 86, 96, 83, 80, 93, 73],
    'Regime': [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3],
}
df = pd.DataFrame(data=ds)

# 数据预处理
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)

# 重采样为5分钟K线
df_5min = df.resample('5T').agg({
    'Open': 'first', 
    'High': 'max', 
    'Low': 'min', 
    'Close': 'last', 
    'Volume': 'sum',
    'Regime':'last'
})
df_5min = df_5min.dropna().reset_index()

# 颜色映射(区分不同Regime)
regime_colors = {1: '#1f77b4', 2: '#ff7f0e', 3: '#2ca02c'}

# 计算全局价格区间(统一所有Regime的bin,保证可比性)
global_min = df['Low'].min()
global_max = df['High'].max()
num_bins = 200
bins = np.linspace(global_min, global_max, num_bins + 1)
bin_size = bins[1] - bins[0]
bin_centers = (bins[:-1] + bins[1:]) / 2
chart_width = len(df_5min)

# 预计算每个Regime的成交量分布和POC
regime_profiles = {}
for regime in df['Regime'].unique():
    subset_1min = df[df['Regime'] == regime]
    vol_profile = np.zeros(num_bins)
    
    # 计算成交量分布
    for _, row in subset_1min.iterrows():
        low, high, vol = row['Low'], row['High'], row['Volume']
        if high == low:
            bin_idx = np.digitize(low, bins) - 1
            if 0 <= bin_idx < num_bins:
                vol_profile[bin_idx] += vol
        else:
            vol_per_unit = vol / (high - low)
            start_bin, end_bin = np.digitize(low, bins), np.digitize(high, bins)
            for b in range(start_bin, end_bin + 1):
                if 0 < b <= num_bins:
                    bin_start, bin_end = bins[b-1], bins[b]
                    overlap_start, overlap_end = max(low, bin_start), min(high, bin_end)
                    vol_profile[b-1] += (overlap_end - overlap_start) * vol_per_unit
    
    # 缩放成交量到图表宽度
    scaled_vol = vol_profile / vol_profile.max() * chart_width if vol_profile.max() > 0 else vol_profile
    # 找到POC(成交量最大的价格)
    poc_idx = np.argmax(vol_profile)
    poc_price = bin_centers[poc_idx]
    
    regime_profiles[regime] = {
        'scaled_vol': scaled_vol,
        'poc_price': poc_price,
        'color': regime_colors[regime]
    }

# 创建合并图表
fig, ax = plt.subplots(figsize=(12,7))

# 1. 绘制各Regime的成交量分布背景(带透明度,避免遮挡)
for regime in sorted(regime_profiles.keys(), reverse=True):
    profile = regime_profiles[regime]
    ax.fill_betweenx(
        bin_centers, 0, profile['scaled_vol'],
        color=profile['color'], alpha=0.25, step='mid',
        label=f'Regime {regime} 成交量分布'
    )

# 2. 绘制各Regime的POC线
for regime in regime_profiles.keys():
    profile = regime_profiles[regime]
    ax.axhline(
        profile['poc_price'], color=profile['color'],
        linestyle='--', linewidth=1.5,
        label=f'Regime {regime} POC: {profile["poc_price"]:.2f}'
    )

# 3. 绘制5分钟K线
xdates = np.arange(len(df_5min))
candle_width = 0.6
for i in range(len(df_5min)):
    o, h, l, c, regime = df_5min.loc[i, ['Open','High','Low','Close','Regime']]
    color = regime_colors[regime]
    
    # 影线(统一黑色,保证清晰)
    ax.vlines(xdates[i], l, h, color='black', linewidth=0.7)
    # K线主体
    if c > o:
        ax.bar(xdates[i], c-o, candle_width, o, color=color, edgecolor='black', linewidth=0.5)
    else:
        ax.bar(xdates[i], o-c, candle_width, c, color=color, edgecolor='black', linewidth=0.5)

# 图表样式调整
ax.set_xlim(-1, chart_width+1)
ax.set_ylim(global_min - bin_size, global_max + bin_size)
ax.set_xticks(xdates)
ax.set_xticklabels(df_5min['Date'].dt.strftime('%H:%M'), rotation=45)
ax.set_title('合并多Regime的5分钟K线与成交量分布图表', fontsize=14)
ax.set_xlabel('时间', fontsize=12)
ax.set_ylabel('价格', fontsize=12)
ax.legend(loc='upper right', bbox_to_anchor=(1.18,1))
plt.tight_layout()
plt.show()

关键修改说明

  • 统一价格区间:基于全局最高最低价计算成交量分布的bin,确保三个Regime的分布在同一价格轴上对齐,方便对比
  • 颜色统一区分:每个Regime从背景成交量分布、K线主体到POC线都用专属颜色,视觉上清晰区分不同阶段
  • 叠加式背景:用透明度控制不同Regime的成交量分布背景,避免相互遮挡,同时保留各阶段的分布信息
  • 整合K线展示:所有5分钟K线按时间顺序排列,影线统一黑色保证清晰度,主体用Regime对应颜色,直观展示不同阶段的价格走势

内容来源于stack exchange

火山引擎 最新活动