チャートを見る時間がゼロ→ドル円MACD+RSI自動アラートをPythonで作った【Gmail通知付き】

Python実装・コード

子供が生まれてチャートを見る時間がゼロに。。。ドル円MACD+RSI自動アラートをPythonで作った話

子供が生まれてから、夜にゆっくりチャートを見る時間がほぼなくなりました。ドル円は毎日動きがあるので、以前は子供が寝たあとにチャートをチェックする習慣があったんですが、それすら最近できていなくて。。。気づいたら大きく動いていた、ということが続いたので、せめてエントリーチャンスを自動で教えてくれるシステムを作ることにしました。今日はMACDとRSIを組み合わせた自動アラートの実装を紹介します。

なぜMACDとRSIを組み合わせるのか

ドル円のFXトレードをやっていると、「トレンドに乗るか、逆張りするか」という判断がいつも悩ましいですよね。MACDはトレンドの方向性を、RSIは買われすぎ・売られすぎを教えてくれる指標なので、この2つを組み合わせると「トレンドが出ていて、かつ過熱感が落ち着いてきたタイミング」を拾えるという発想です。

具体的には:
・MACDがシグナルラインをゴールデンクロス → 上昇トレンドの開始示唆
・RSIが30〜50の範囲 → 売られすぎからの回復局面
この2条件が重なったときにアラートを出す、というシンプルな設計にしました。

まず必要なライブラリのインストール

pip install yfinance pandas-ta

ドル円データの取得とMACD・RSI計算

import yfinance as yf
import pandas as pd
import pandas_ta as ta
from datetime import datetime, timedelta

def get_usdjpy_data(period_days=180):
    ticker = "JPY=X"
    end = datetime.now()
    start = end - timedelta(days=period_days)
    df = yf.download(ticker, start=start.strftime('%Y-%m-%d'),
                     end=end.strftime('%Y-%m-%d'), interval='1d')
    df = df[['Close']].copy()
    df.columns = ['close']
    return df

def add_indicators(df):
    macd_result = ta.macd(df['close'])
    df['macd'] = macd_result['MACD_12_26_9']
    df['macd_signal'] = macd_result['MACDs_12_26_9']
    df['macd_hist'] = macd_result['MACDh_12_26_9']
    df['rsi'] = ta.rsi(df['close'], length=14)
    return df.dropna()

df = get_usdjpy_data()
df = add_indicators(df)
print(df.tail(10))

アラート条件の実装

def check_signals(df):
    signals = []
    for i in range(1, len(df)):
        prev = df.iloc[i-1]
        curr = df.iloc[i]
        date = df.index[i]

        macd_golden_cross = (prev['macd'] <= prev['macd_signal'] and
                             curr['macd'] > curr['macd_signal'])
        macd_dead_cross = (prev['macd'] >= prev['macd_signal'] and
                           curr['macd'] < curr['macd_signal'])
        rsi_oversold_recovery = 30 <= curr['rsi'] <= 55
        rsi_overbought = curr['rsi'] >= 70

        if macd_golden_cross and rsi_oversold_recovery:
            signals.append({
                'date': date, 'type': '買いシグナル',
                'price': curr['close'], 'rsi': round(curr['rsi'], 2),
                'macd': round(curr['macd'], 4)
            })
        if macd_dead_cross and rsi_overbought:
            signals.append({
                'date': date, 'type': '売りシグナル',
                'price': curr['close'], 'rsi': round(curr['rsi'], 2),
                'macd': round(curr['macd'], 4)
            })
    return pd.DataFrame(signals)

signals_df = check_signals(df)
print(signals_df)

Gmailでアラートを送信する

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def send_alert_email(signals_df, gmail_user, gmail_app_password, to_email):
    if signals_df.empty:
        print("本日のシグナルはありません")
        return

    today = pd.Timestamp.now().normalize()
    recent = signals_df[signals_df['date'] >= today - pd.Timedelta(days=1)]
    if recent.empty:
        print("本日の新規シグナルはありません")
        return

    body = "【ドル円アルゴアラート】

"
    for _, row in recent.iterrows():
        body += f"📌 {row['type']}
"
        body += f"   日付: {row['date'].strftime('%Y-%m-%d')}
"
        body += f"   価格: {row['price']:.3f} 円
"
        body += f"   RSI: {row['rsi']}

"

    msg = MIMEMultipart()
    msg['From'] = gmail_user
    msg['To'] = to_email
    msg['Subject'] = f"ドル円アラート - {pd.Timestamp.now().strftime('%Y/%m/%d')}"
    msg.attach(MIMEText(body, 'plain', 'utf-8'))

    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
        server.login(gmail_user, gmail_app_password)
        server.send_message(msg)
    print(f"アラートメールを送信しました({len(recent)}件)")

毎朝自動実行するmain関数

def main():
    print(f"実行日時: {datetime.now()}")
    df = get_usdjpy_data(period_days=90)
    df = add_indicators(df)
    signals_df = check_signals(df)

    import os
    gmail_user = os.environ.get('GMAIL_USER')
    gmail_pass = os.environ.get('GMAIL_APP_PASS')

    if gmail_user and gmail_pass:
        send_alert_email(signals_df, gmail_user, gmail_pass, gmail_user)
    else:
        print("シグナル一覧:")
        print(signals_df.tail(5))

if __name__ == "__main__":
    main()

まとめ:「見る時間がない」ならアラートを作ろう

MACDとRSIの組み合わせアラートを作ってから、チャートを毎日見なくてもエントリーチャンスを逃しにくくなりました。もちろん完璧な精度じゃないですし、FXは相場環境によって有効なシグナルが変わるので過信は禁物ですが、「少なくとも大きな動きを見逃さない」という安心感は得られています。

次のステップとして、時間足を1時間足や4時間足に変えたバージョンも試してみたいと思っています。同じようにチャートを見る時間がなくて困っている方、ぜひこのアラートシステムを参考にしてみてください。

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