Pythonでボラティリティを使ったポジションサイジング入門【ドル円FX対応コード付き】

Python実装・コード

ドル円のトレードを始めたころ、毎回「何ロット入ればいいんだろ」って感覚でやってました。子供が生まれてから相場を見る時間がほぼなくなって、それがかえって良かったのかもしれません。適当にロット数を決めていたのが、ちゃんと計算するようになったので笑。今回はATR(Average True Range)を使ったポジションサイジングをPythonで実装する方法を紹介します。

なぜポジションサイジングが大事なのか

正直、最初はエントリータイミングばかり気にしてました。でも資金管理が甘いと、たとえ勝率60%の戦略でも連敗したときに退場してしまいます。ポジションサイジングとは「1回のトレードでどれだけのリスクを取るか」を事前に計算するプロセスです。FXのドル円では特にボラティリティ(価格変動の大きさ)が日によって全然違うので、固定ロットで入り続けるのは危ないと思います。

ATRとは何か

ATR(Average True Range)は、一定期間の価格変動の平均を示すテクニカル指標です。例えば14日ATRが「0.80円」なら、ここ2週間で平均して1日に0.80円動いているということ。このATRをリスク管理の基準として使います。

計算式のイメージ:

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

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

基本的な考え方は「1回のトレードで口座残高の何%を失っても許容できるか」を先に決めること。一般的には1〜2%が推奨されています。僕は子供の教育費を考えると怖いので1%で設定しています笑。

計算式はシンプルです:

ロット数 = (口座残高 × リスク許容率) ÷ (ATR × ストップロス係数 × 1pipの価値)

PythonでATRベースのポジションサイジングを実装

まずyfinanceでドル円のデータを取得してATRを計算します。

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

def calculate_atr(symbol='JPY=X', period='3mo', atr_period=14):
    """ATRを計算する関数"""
    df = yf.download(symbol, period=period, interval='1d', auto_adjust=True)
    
    # True Range計算
    df['H-L'] = df['High'] - df['Low']
    df['H-PC'] = abs(df['High'] - df['Close'].shift(1))
    df['L-PC'] = abs(df['Low'] - df['Close'].shift(1))
    df['TR'] = df[['H-L', 'H-PC', 'L-PC']].max(axis=1)
    
    # ATR(14日移動平均)
    df['ATR'] = df['TR'].rolling(window=atr_period).mean()
    
    latest_atr = df['ATR'].iloc[-1]
    latest_price = df['Close'].iloc[-1]
    
    return latest_atr, latest_price, df

def calculate_position_size(
    account_balance=500000,   # 口座残高(円)
    risk_rate=0.01,           # リスク許容率(1%)
    atr=None,
    stop_loss_atr_multiplier=2.0,  # ATRの何倍でストップを置くか
    lot_unit=10000,           # 1ロット = 1万通貨
):
    """ポジションサイジングを計算する"""
    if atr is None:
        raise ValueError("ATRを指定してください")
    
    # 許容損失額(円)
    max_loss_jpy = account_balance * risk_rate
    
    # ストップロス幅(円換算)
    # ドル円の場合、1pip = 0.01円
    stop_loss_pips = atr * stop_loss_atr_multiplier
    stop_loss_jpy_per_lot = stop_loss_pips * lot_unit * 0.01  # 1ロットあたりの損失
    
    # ロット数計算
    lots = max_loss_jpy / stop_loss_jpy_per_lot
    
    return {
        'account_balance': account_balance,
        'risk_rate': risk_rate,
        'max_loss_jpy': max_loss_jpy,
        'atr': atr,
        'stop_loss_pips': stop_loss_pips,
        'recommended_lots': round(lots, 2),
        'recommended_units': int(lots * lot_unit)
    }

# 実行例
atr, price, df = calculate_atr()
print(f"現在のドル円: {price:.2f}円")
print(f"14日ATR: {atr:.3f}円")

result = calculate_position_size(
    account_balance=500000,
    risk_rate=0.01,
    atr=atr,
    stop_loss_atr_multiplier=2.0
)

print("
--- ポジションサイジング結果 ---")
print(f"口座残高: {result['account_balance']:,}円")
print(f"リスク許容額: {result['max_loss_jpy']:,.0f}円")
print(f"ストップロス幅: {result['stop_loss_pips']:.3f}円 ({result['stop_loss_pips']*100:.1f}pips)")
print(f"推奨ロット数: {result['recommended_lots']}ロット")
print(f"推奨取引量: {result['recommended_units']:,}通貨")

実行結果のイメージ

現在のドル円: 152.34円
14日ATR: 0.823円

--- ポジションサイジング結果 ---
口座残高: 500,000円
リスク許容額: 5,000円
ストップロス幅: 1.646円 (164.6pips)
推奨ロット数: 0.30ロット
推奨取引量: 3,042通貨

さらに改良:ボラティリティに応じて動的に調整

ATRが高い(ボラが荒い)ときは自動的にロット数を減らす仕組みも作れます。

def dynamic_position_sizing(
    account_balance=500000,
    risk_rate=0.01,
    current_atr=None,
    baseline_atr=0.8,  # 基準ATR
    max_lots=1.0,
    min_lots=0.05
):
    """ボラティリティに応じた動的ポジションサイジング"""
    base_result = calculate_position_size(account_balance, risk_rate, current_atr)
    
    # ボラティリティ調整係数
    vol_adjustment = baseline_atr / current_atr
    adjusted_lots = base_result['recommended_lots'] * vol_adjustment
    
    # 上限・下限を設定
    adjusted_lots = min(max(adjusted_lots, min_lots), max_lots)
    
    return {
        **base_result,
        'vol_adjustment': vol_adjustment,
        'adjusted_lots': round(adjusted_lots, 2)
    }

まとめ

ATRベースのポジションサイジングは、市場のボラティリティに合わせて自動的にリスクを調整してくれるので、固定ロットよりずっと安全です。特にドル円は指標発表や要人発言で急激にATRが上がることがあるので、これを入れておくだけで大きな損失を防げます。

個人的には、このコードを毎朝自動実行して「今日のドル円、何ロットまでOK」をSlackに通知する仕組みを作りたいと思っています。子供が起きてくる前の5分でチェックできるくらい自動化したい笑。次回はその通知システムの実装をやってみます。

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