Discord botから株価チャートを送信

Python

前回の記事で紹介したpython mplfinanceで描画したグラフをDiscord botから送信するコードを紹介します
Discord botのスラッシュコマンドを使って、Tickerを入力するとそのTickerのローソク足チャートの画像を返すようにしたいと思います

ローソク足チャートを作成する前回の記事はこちらです

Discord bot の作成方法についての記事はこちらです


スラッシュコマンドの特徴

Discord Botのスラッシュコマンド(Slash Commands)は、/(スラッシュ)で始まるコマンドを使って、ボットの機能を呼び出せる仕組みです
従来の!commandのようなプレフィックスコマンドとは異なり、DiscordのUIに統合されているのが特徴です

  1. コマンド補完が可能
    • ユーザーが/を入力すると、利用可能なコマンドが表示される
    • 誤入力を防ぎ、直感的に操作できる
  2. パラメータの指定が簡単
    • コマンドの引数(オプション)を設定できる
  3. 権限設定ができる
    • 特定のロールやユーザーのみが実行可能なコマンドを設定可能
  4. エラーハンドリングが楽
    • Discordがバリデーションを行い、間違った入力を防ぐ
  5. グローバルまたはギルド専用で登録可能
    • グローバル:全サーバーで使用可能(登録に時間がかかる)
    • ギルド専用:特定のサーバーでのみ使用可能(即時反映)

スラッシュコマンドを使って株価ローソク足チャートを取得

必要なライブラリをインストールします

pip install discord.py python-dotenv yfinance mplfinance

以下のコードでDiscord botにスラッシュコマンドで株価ローソク足チャートの画像を送信してもらいます

import discord
from discord import app_commands
import io
import yfinance as yf
import mplfinance as mpf
import os
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN")

# Intent設定
intents = discord.Intents.default()
intents.message_content = True

# Botの設定
bot = discord.Client(intents=intents)
tree = app_commands.CommandTree(bot)

# チャート作成関数
def create_candlestick_chart(ticker):
    try:
        df = yf.download(ticker, period="1y", interval="1d")
        df.columns = df.columns.get_level_values(0)
        df = df[["Open", "High", "Low", "Close", "Volume"]]

        mc = mpf.make_marketcolors(up='red', down='blue', wick='black', volume='gray')
        s = mpf.make_mpf_style(marketcolors=mc)

        buf = io.BytesIO()
        mpf.plot(df, type="candle", style=s, volume=True, mav=(25, 75), figratio=(10, 6),
                 panel_ratios=(3, 1), title=f"{ticker} 1-Year Candlestick Chart", savefig=buf)
        buf.seek(0)
        return buf

    except Exception as e:
        print(f"エラー: {e}")
        return None

# スラッシュコマンドの登録
@tree.command(name="ticker", description="指定した銘柄の株価チャートを取得")
async def ticker(interaction: discord.Interaction, symbol: str):
    await interaction.response.defer()  # 処理中の表示
    buf = create_candlestick_chart(symbol)

    if buf:
        await interaction.followup.send(file=discord.File(buf, filename=f"{symbol}_chart.png"))
    else:
        await interaction.followup.send("⚠️ チャートの生成に失敗しました。ティッカーを確認してください。")

# Botが起動したときにスラッシュコマンドを同期
@bot.event
async def on_ready():
    await tree.sync()
    print(f"Logged in as {bot.user}")

# Botを起動
bot.run(TOKEN)

このコードを実行するとbotが起動するので、Discordのチャットでスラッシュ(/)を入力するとコマンド一覧が表示されるので、Tickerを選択します

7203.Tなどの引数となるTickerの番号を入力します

するとローソク足チャート画像を送信してくれます


コードの解説

スラッシュコマンド部分のコードの解説をします

intents = discord.Intents.default()
intents.message_content = True
  • Intents を設定し、メッセージの内容を取得できるようにしています
bot = discord.Client(intents=intents)
tree = app_commands.CommandTree(bot)
  • bot = discord.Client(intents=intents): discord.Client を作成
  • tree = app_commands.CommandTree(bot): スラッシュコマンド(/command 形式のコマンド)を管理する CommandTree を作成
# チャート作成関数
def create_candlestick_chart(ticker):
    try:
        df = yf.download(ticker, period="1y", interval="1d")
        df.columns = df.columns.get_level_values(0)
        df = df[["Open", "High", "Low", "Close", "Volume"]]

        mc = mpf.make_marketcolors(up='red', down='blue', wick='black', volume='gray')
        s = mpf.make_mpf_style(marketcolors=mc)

        buf = io.BytesIO()
        mpf.plot(df, type="candle", style=s, volume=True, mav=(25, 75), figratio=(10, 6),
                 panel_ratios=(3, 1), title=f"{ticker} 1-Year Candlestick Chart", savefig=buf)
        buf.seek(0)
        return buf

    except Exception as e:
        print(f"エラー: {e}")
        return None

このあたりは前回のmplfinanceでの記事を参考にしてください
今回のコードでは描画したグラフを保存するときに io.BytesIO() を使用してメモリ上に保存しています

io.BytesIO()の使い方については以下の記事で紹介していますので参考にしてください

@tree.command(name="ticker", description="指定した銘柄の株価チャートを取得")
async def ticker(interaction: discord.Interaction, symbol: str):
  • @tree.command を使い、スラッシュコマンド /ticker を定義
  • ユーザーが symbol(ティッカーシンボル)を入力すると、その銘柄のチャートを取得
await interaction.response.defer()  # 処理中の表示
  • 返信に時間がかかるため、「処理中…」のステータスを表示
buf = create_candlestick_chart(symbol)

先ほど作成した create_candlestick_chart 関数を呼び出し、指定した銘柄のチャート画像を取得

    if buf:
        await interaction.followup.send(file=discord.File(buf, filename=f"{symbol}_chart.png"))
    else:
        await interaction.followup.send("⚠️ チャートの生成に失敗しました。ティッカーを確認してください。")
  • buf が None でなければ、画像をDiscordに送信
  • None の場合はエラーメッセージを送信
@bot.event
async def on_ready():
    await tree.sync()
    print(f"Logged in as {bot.user}")
  • on_ready イベントでスラッシュコマンドを同期し、ログインメッセージを表示
bot.run(TOKEN)

TOKEN を使って Bot を起動


以上のコードでDiscord botのスラッシュコマンドを使ってローソク足チャートを送信することができました

さらにカスタマイズとして取得期間の指定なども実装していきたいと思います

コメント