ドル円のボリンジャーバンドをPythonで実装してLINEに自動アラートを送る方法

自動化・運用

ボリンジャーバンドのバンド外に出たのにトレードに乗り遅れた、という経験が何度もある。子育て中だと相場を見張る時間がない。そこで「バンド逸脱を自動検知してLINEに飛ばす」仕組みを作った。

ボリンジャーバンドとは

移動平均線 ± 標準偏差×係数で引いたバンド。±2σの外に価格が出ると「異常値」と判断する。ドル円のような平均回帰性の高い通貨ペアでは、バンド逸脱後の反転を狙う戦略が比較的機能しやすい(ただし必ず検証すること)。

実装コード

import yfinance as yf
import pandas as pd
import requests
from datetime import datetime

def get_usdjpy(period="3mo") -> pd.DataFrame:
    """ドル円の日足データを取得"""
    df = yf.download("JPY=X", period=period, interval="1d", auto_adjust=True)
    df.columns = [c[0] if isinstance(c, tuple) else c for c in df.columns]
    return df

def calc_bollinger(close: pd.Series, window=20, num_std=2):
    """ボリンジャーバンドを計算"""
    ma = close.rolling(window=window).mean()
    std = close.rolling(window=window).std()
    upper = ma + num_std * std
    lower = ma - num_std * std
    return ma, upper, lower

def check_band_breakout(df: pd.DataFrame) -> str | None:
    """バンド逸脱を検知してメッセージを返す"""
    _, upper, lower = calc_bollinger(df["Close"])
    
    latest_close = df["Close"].iloc[-1]
    latest_upper = upper.iloc[-1]
    latest_lower = lower.iloc[-1]
    
    if latest_close > latest_upper:
        return (f"⚠️ ドル円バンド上抜け!
"
                f"現在値: {latest_close:.2f}円
"
                f"上限バンド: {latest_upper:.2f}円
"
                f"時刻: {datetime.now().strftime('%H:%M')}")
    elif latest_close < latest_lower:
        return (f"✅ ドル円バンド下抜け!(反転機会?)
"
                f"現在値: {latest_close:.2f}円
"
                f"下限バンド: {latest_lower:.2f}円
"
                f"時刻: {datetime.now().strftime('%H:%M')}")
    return None

def send_line_notify(token: str, message: str):
    """LINE Notifyでメッセージを送信"""
    headers = {"Authorization": f"Bearer {token}"}
    data = {"message": f"
{message}"}
    requests.post("https://notify-api.line.me/api/notify",
                  headers=headers, data=data)

# 実行
LINE_TOKEN = "YOUR_LINE_TOKEN"  # LINE Notifyトークン

df = get_usdjpy()
alert = check_band_breakout(df)

if alert:
    send_line_notify(LINE_TOKEN, alert)
    print("LINEに通知送信:", alert)
else:
    print("シグナルなし。現在値:", df["Close"].iloc[-1])

これをcronで15分ごとに実行している。子供が寝かしつけで離れている間に動きがあっても、スマホに通知が来るので見逃さない。

次は時間帯フィルタ(東京時間はスキップ)も追加してみようと思っている。

タイトルとURLをコピーしました