ドル円FXで全財産10%突っ込んで爆死した話→ATRベースのポジションサイジングをPythonで実装した

AI×自動売買

FXドル円で去年やらかした最大の失敗が、「口座資金の10%を1トレードに突っ込んで爆死した」こと。。。何が問題だったかというと、ボラティリティが急上昇している相場なのにポジションサイズを全く調整せずに入ったんですよね。普段は大丈夫な値幅でも、ボラが高い日は損切り幅が倍以上になることがある→そんな当たり前のことを学んだのが去年の話です。で、子供の夜泣き対応中に「ATRでポジションサイジングを自動化できないか」と思いついて調べた結果が今回の記事です。

ATR(Average True Range)とは何か

ATRは「平均真の値幅」と訳され、相場のボラティリティ(動きやすさ)を数値化する指標です。J.ウェルズ・ワイルダーが1978年に考案したもので、テクニカル指標の中でも「相場の状態を測る」系の指標として広く使われています。

具体的な計算式はこうです:

  • True Range(TR)= max(高値-安値, |高値-前日終値|, |安値-前日終値|)
  • ATR = TRのN日移動平均(通常N=14)

ドル円で言えば、ATRが0.5円なら「1日に平均0.5円動く相場」、ATRが1.5円なら「1日に平均1.5円動く荒れた相場」ということになります。荒れているときほど同じポジションサイズでは損失が大きくなるので、ATRに合わせてポジションを調整するのが「ATRベースのポジションサイジング」です。

ポジションサイジングの考え方

基本的な考え方はこうです:

1トレードのリスク額 ÷ ATR × N = ポジションサイズ

例えば、口座残高が100万円で「1トレードで最大1%(1万円)しか損しない」というルールを決めた場合:

  • ATRが0.5円のとき → 1万円 ÷ 0.5円 = 2万通貨(2ロット)
  • ATRが1.5円のとき → 1万円 ÷ 1.5円 ≈ 0.67万通貨(0.67ロット)

ボラが高いほど自動的にポジションが小さくなる。これが肝心です。僕が去年やらかしたのはATR無視でポジションを張ったため、ボラ高い日に同じ枚数入って爆死したわけです。

Pythonで実装してみる

import yfinance as yf
import pandas as pd
import numpy as np

# ドル円データ取得(yfinanceではUSDJPY=Xで取得可能)
df = yf.download("USDJPY=X", start="2024-01-01", end="2026-06-01", progress=False)
df.columns = df.columns.droplevel(1) if df.columns.nlevels > 1 else df.columns

# ATR計算
def calc_atr(df, period=14):
    high = df["High"]
    low = df["Low"]
    prev_close = df["Close"].shift(1)

    tr1 = high - low
    tr2 = (high - prev_close).abs()
    tr3 = (low - prev_close).abs()

    true_range = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    atr = true_range.rolling(period).mean()
    return atr

df["atr"] = calc_atr(df)

# ポジションサイジング関数
def calc_position_size(account_balance, risk_pct, atr, pip_value=100):
    """
    account_balance: 口座残高(円)
    risk_pct: 1トレードのリスク割合(0.01 = 1%)
    atr: 現在のATR値
    pip_value: 1通貨あたりの円換算(1ドル=150円のとき、1000通貨=150円=1pip≈150円を仮定)
    """
    risk_amount = account_balance * risk_pct  # リスク許容額(円)
    # ATRをストップロスとして使用(ATRの1.5倍をSLに設定)
    stop_loss_pips = atr * 1.5
    # ポジションサイズ(通貨単位)
    position_size = risk_amount / stop_loss_pips
    # 1000通貨単位に丸める
    position_size_lots = int(position_size / 1000) * 1000
    return position_size_lots, stop_loss_pips

# シミュレーション
account_balance = 1_000_000  # 100万円
risk_pct = 0.01  # 1%リスク

# 最新のATR確認
latest_atr = df["atr"].dropna().iloc[-1]
print(f"現在のATR(14日): {latest_atr:.3f} 円")

# ポジションサイズ計算
pos_size, sl_pips = calc_position_size(account_balance, risk_pct, latest_atr)
print(f"推奨ポジションサイズ: {pos_size:,} 通貨")
print(f"ストップロス幅: {sl_pips:.3f} 円")
print(f"最大損失額: {account_balance * risk_pct:,.0f} 円")

# ATRの推移をグラフ化
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.family'] = 'DejaVu Sans'  # 日本語フォントがない環境向け

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)

ax1.plot(df.index, df["Close"], color="#38bdf8", linewidth=1)
ax1.set_title("USDJPY Close Price")
ax1.set_ylabel("JPY")

ax2.plot(df.index, df["atr"], color="#f87171", linewidth=1)
ax2.axhline(y=df["atr"].mean(), color="white", linestyle="--", alpha=0.5, label="Average ATR")
ax2.set_title("ATR (14 days)")
ax2.set_ylabel("ATR")
ax2.legend()

plt.tight_layout()
plt.savefig("usdjpy_atr_chart.png", dpi=150, bbox_inches="tight",
            facecolor="#0d1117", edgecolor="none")
plt.show()
print("グラフを保存しました")

実際に動かして分かったこと

2024年〜2026年のドル円データでATRを計算してみると、2024年後半の円安局面ではATRが1.0円を超える日が続いていました。一方で、相場が落ち着いている時期は0.4〜0.6円程度。この差は2倍以上あるわけで、ATR無視でポジションを張るのがどれだけ危険か改めて実感しました。

また「ATRの1.5倍をストップロスに設定」というルールを使うと、ATRが高い日は自動的にストップが広がり、ポジションサイズが小さくなります。これによって1日で追い証が来るようなリスクをコントロールしやすくなります。

まとめ

「全資金の10%突っ込んで爆死」というトレーダーとして恥ずかしい失敗を教訓に、ATRベースのポジションサイジングを実装してみました。コード自体は30行ほどで書けるので、FXをPythonで管理したい方はぜひ試してみてください。次は実際の自動売買システムにこのポジションサイジングロジックを組み込んで、「相場が荒れた日は自動的に小ポジションにする」仕組みを作ってみたいです。また何か爆死したら正直に報告します(笑)。

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