You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib绘制Binance K线图仅显示竖线,无蜡烛实体与影线求助

问题描述

我通过Binance API获取了BTCUSDT的1日(1d)周期K线数据,使用Matplotlib绘制图表时,图表可正常显示但仅呈现黑色竖线,无法展示包含开盘价(Open)、最高价(High)、最低价(Low)、收盘价(Close)信息的红绿蜡烛实体及影线。现寻求帮助以实现正常蜡烛图的展示。

原代码如下:

import requests
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np

# Binance API endpoint for Kline data
url = 'https://api.binance.com/api/v3/klines'

# Parameters for the API request
symbol = 'BTCUSDT'
interval = '1d'
limit = 200  # Number of Klines to retrieve (max: 1000)

# Prepare the request parameters
params = {
    'symbol': symbol,
    'interval': interval,
    'limit': limit
}

# Send the GET request to the Binance API
response = requests.get(url, params=params)
data = response.json()

# Extracting the relevant data from the API response
timestamps = [entry[0] / 1000 for entry in data]
opens = [float(entry[1]) for entry in data]
highs = [float(entry[2]) for entry in data]
lows = [float(entry[3]) for entry in data]
closes = [float(entry[4]) for entry in data]

# Convert timestamps to readable dates
dates = [mdates.epoch2num(timestamp) for timestamp in timestamps]

# Plotting the candlestick chart
fig, ax = plt.subplots()
ax.xaxis_date()
candlestick_data = list(zip(dates, opens, highs, lows, closes))
ax.vlines(dates, lows, highs, color='black', linewidth=2)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

# Calculate the moving averages
moving_average_7 = np.convolve(closes, np.ones(7) / 7, mode='valid')
moving_average_20 = np.convolve(closes, np.ones(20) / 20, mode='valid')
moving_average_50 = np.convolve(closes, np.ones(50) / 50, mode='valid')

# Determine the corresponding dates for the moving averages
moving_average_dates_7 = dates[7 - 1:]  # Subtract 1 to align the dates with moving average values
moving_average_dates_20 = dates[20 - 1:]  # Subtract 1 to align the dates with moving average values
moving_average_dates_50 = dates[50 - 1:]  # Subtract 1 to align the dates with moving average values

# Plotting the moving averages
ax.plot(moving_average_dates_7, moving_average_7, color='red', linewidth=1, label='7-day Moving Average')
ax.plot(moving_average_dates_20, moving_average_20, color='blue', linewidth=1, label='20-day Moving Average')
ax.plot(moving_average_dates_50, moving_average_50, color='orange', linewidth=1, label='50-day Moving Average')

# Calculate Bollinger Bands
period = 20  # Bollinger Bands period
std_dev = np.std(closes[-period:])  # Standard deviation for the period
middle_band = np.convolve(closes, np.ones(period) / period, mode='valid')  # Middle band is the moving average
upper_band = middle_band + 2 * std_dev  # Upper band is 2 standard deviations above the middle band
lower_band = middle_band - 2 * std_dev  # Lower band is 2 standard deviations below the middle band

# Plotting the Bollinger Bands
ax.plot(dates[period - 1:], upper_band, color='purple', linestyle='--', linewidth=1, label='Upper Band')
ax.plot(dates[period - 1:], lower_band, color='purple', linestyle='--', linewidth=1, label='Lower Band')

# Add the last values of the indicators to the right axis
ax.text(1.02, 0.7, f'Last Price: {closes[-1]:.2f}', transform=ax.transAxes, color='black')
ax.text(1.02, 0.6, f'MA7: {moving_average_7[-1]:.2f}', transform=ax.transAxes, color='red')
ax.text(1.02, 0.5, f'MA20: {moving_average_20[-1]:.2f}', transform=ax.transAxes, color='blue')
ax.text(1.02, 0.4, f'MA50: {moving_average_50[-1]:.2f}', transform=ax.transAxes, color='orange')

plt.xticks(rotation=45)
plt.title(f'Kline Chart for {symbol} - {interval}')
plt.xlabel('Date')
plt.ylabel('Price (USDT)')
plt.legend()
plt.grid(True)
plt.show()

问题原因

你的代码仅调用ax.vlines()绘制了高低价的竖线(蜡烛影线),完全未处理开盘价与收盘价组成的蜡烛实体,也未根据涨跌(收盘价和开盘价的大小关系)设置不同颜色,因此只会显示黑色竖线。此外原代码中布林带的计算存在错误:仅取了最后20个收盘价的固定标准差,而非滚动计算每个周期的标准差,导致布林带呈现平行直线,不符合实际逻辑。

解决方案

方案1:手动绘制蜡烛实体(无需额外库)

在原有代码基础上,添加蜡烛实体绘制逻辑,同时修复布林带计算:

修改后的完整代码:

import requests
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np

# Binance API endpoint for Kline data
url = 'https://api.binance.com/api/v3/klines'

# Parameters for the API request
symbol = 'BTCUSDT'
interval = '1d'
limit = 200  # Number of Klines to retrieve (max: 1000)

# Prepare the request parameters
params = {
    'symbol': symbol,
    'interval': interval,
    'limit': limit
}

# Send the GET request to the Binance API
response = requests.get(url, params=params)
data = response.json()

# Extracting the relevant data from the API response
timestamps = [entry[0] / 1000 for entry in data]
opens = [float(entry[1]) for entry in data]
highs = [float(entry[2]) for entry in data]
lows = [float(entry[3]) for entry in data]
closes = [float(entry[4]) for entry in data]

# Convert timestamps to readable dates
dates = [mdates.epoch2num(timestamp) for timestamp in timestamps]

# Plotting the candlestick chart
fig, ax = plt.subplots(figsize=(12, 6))
ax.xaxis_date()
candlestick_data = list(zip(dates, opens, highs, lows, closes))

# 绘制影线(高低价竖线)
ax.vlines(dates, lows, highs, color='black', linewidth=1)

# 绘制蜡烛实体
candle_width = 0.4  # 调整蜡烛宽度适配日线周期
for date, open_p, high_p, low_p, close_p in candlestick_data:
    # 根据涨跌设置颜色
    if close_p >= open_p:
        color = '#00ff00'  # 上涨用绿色
        bottom_price = open_p
        top_price = close_p
    else:
        color = '#ff0000'  # 下跌用红色
        bottom_price = close_p
        top_price = open_p
    # 添加矩形实体
    ax.add_patch(plt.Rectangle(
        (date - candle_width/2, bottom_price), 
        candle_width, 
        top_price - bottom_price, 
        color=color
    ))

ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

# Calculate the moving averages
moving_average_7 = np.convolve(closes, np.ones(7) / 7, mode='valid')
moving_average_20 = np.convolve(closes, np.ones(20) / 20, mode='valid')
moving_average_50 = np.convolve(closes, np.ones(50) / 50, mode='valid')

# Determine the corresponding dates for the moving averages
moving_average_dates_7 = dates[7 - 1:]
moving_average_dates_20 = dates[20 - 1:]
moving_average_dates_50 = dates[50 - 1:]

# Plotting the moving averages
ax.plot(moving_average_dates_7, moving_average_7, color='red', linewidth=1, label='7-day Moving Average')
ax.plot(moving_average_dates_20, moving_average_20, color='blue', linewidth=1, label='20-day Moving Average')
ax.plot(moving_average_dates_50, moving_average_50, color='orange', linewidth=1, label='50-day Moving Average')

# Calculate Bollinger Bands(修复滚动标准差计算)
period = 20
# 用滚动窗口计算标准差
rolling_std = []
for i in range(len(closes) - period + 1):
    window = closes[i:i+period]
    rolling_std.append(np.std(window))
rolling_std = np.array(rolling_std)

middle_band = np.convolve(closes, np.ones(period) / period, mode='valid')
upper_band = middle_band + 2 * rolling_std
lower_band = middle_band - 2 * rolling_std

# Plotting the Bollinger Bands
ax.plot(dates[period - 1:], upper_band, color='purple', linestyle='--', linewidth=1, label='Upper Band')
ax.plot(dates[period - 1:], lower_band, color='purple', linestyle='--', linewidth=1, label='Lower Band')

# Add the last values of the indicators to the right axis
ax.text(1.02, 0.7, f'Last Price: {closes[-1]:.2f}', transform=ax.transAxes, color='black')
ax.text(1.02, 0.6, f'MA7: {moving_average_7[-1]:.2f}', transform=ax.transAxes, color='red')
ax.text(1.02, 0.5, f'MA20: {moving_average_20[-1]:.2f}', transform=ax.transAxes, color='blue')
ax.text(1.02, 0.4, f'MA50: {moving_average_50[-1]:.2f}', transform=ax.transAxes, color='orange')

plt.xticks(rotation=45)
plt.title(f'Kline Chart for {symbol} - {interval}')
plt.xlabel('Date')
plt.ylabel('Price (USDT)')
plt.legend()
plt.grid(True)
plt.tight_layout()  # 自动调整布局,防止日期被截断
plt.show()

方案2:使用mplfinance库(推荐,更简洁专业)

mplfinance是专门为金融K线图设计的库,无需手动绘制蜡烛,还能一键添加均线、布林带等指标。

步骤:

  1. 安装库:pip install mplfinance pandas
  2. 修改代码如下:
import requests
import pandas as pd
import mplfinance as mpf

# Binance API endpoint for Kline data
url = 'https://api.binance.com/api/v3/klines'

# Parameters for the API request
symbol = 'BTCUSDT'
interval = '1d'
limit = 200

# Prepare the request parameters
params = {
    'symbol': symbol,
    'interval': interval,
    'limit': limit
}

# 获取数据并整理成DataFrame
response = requests.get(url, params=params)
data = response.json()
df = pd.DataFrame(data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_asset_volume', 'number_of_trades', 'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore'])

# 转换数据类型和时间格式
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df = df.astype({'open': float, 'high': float, 'low': float, 'close': float})
df.set_index('timestamp', inplace=True)

# 设置指标:均线和布林带
apds = [
    mpf.make_addplot(df['close'].rolling(7).mean(), color='red', label='7-day MA'),
    mpf.make_addplot(df['close'].rolling(20).mean(), color='blue', label='20-day MA'),
    mpf.make_addplot(df['close'].rolling(50).mean(), color='orange', label='50-day MA'),
    mpf.make_addplot(df['close'].rolling(20).mean() + 2*df['close'].rolling(20).std(), color='purple', linestyle='--', label='Upper Band'),
    mpf.make_addplot(df['close'].rolling(20).mean() - 2*df['close'].rolling(20).std(), color='purple', linestyle='--', label='Lower Band')
]

# 绘制蜡烛图
mpf.plot(df, 
         type='candle', 
         style='yahoo', 
         addplot=apds, 
         title=f'{symbol} {interval} Kline Chart',
         ylabel='Price (USDT)',
         figratio=(12,6),
         tight_layout=True,
         legend=True)

这个方案代码更简洁,指标计算更准确,且默认自带红绿蜡烛样式。

内容的提问来源于stack exchange,提问作者g_rx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:02:02