資金を守る!Pythonで適切な購入株数とリスクを自動計算する方法

Python実装・コード

※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。

「どの銘柄を買うか」は多くの投資家が熱心に研究しますが、「何株買うか」を論理的に計算している人は少数派です。しかし、長期的にトレードで生き残るために最も重要なのは、銘柄選定よりも資金管理(ポジションサイジング)です。

1回のトレードで資金の何パーセントまでリスクを取るのか。損切りラインまでの値幅から逆算して何株購入するのか。この計算を感覚ではなくルールとして定義し、Pythonで自動化することが、システマティックな投資の第一歩となります。

この記事では、資金管理の基本理論から、リスク許容額に基づく購入株数の計算ロジック、そしてyfinanceで取得したリアルな株価データを使った実践的なコードまでを解説します。

資金管理の基本理論

コードを書く前に、ポジションサイジングの理論的な土台を理解しておく必要があります。

なぜ資金管理が最も重要なのか

どれほど勝率の高い売買戦略であっても、1回のトレードに資金を集中させれば、たった1度の損失で退場するリスクがあります。逆に、1回あたりのリスクを小さく抑えれば、連敗しても資金が致命的に減ることはありません。

資金管理の目的は以下の2点に集約されます。

  • 破産確率を限りなくゼロに近づけること
  • 複利の効果を最大化できる資金配分を維持すること

「固定パーセントリスクモデル」とは

最も広く使われている資金管理手法が固定パーセントリスクモデルです。ルールは非常にシンプルです。

1回のトレードで失ってもよい金額を、総資金の一定割合(通常1〜2%)以内に収める。

たとえば、総資金が100万円でリスク許容率を2%に設定した場合、1回のトレードで許容される最大損失額は2万円です。この2万円から逆算して、購入株数を決定します。

計算に必要な4つのパラメータ

ポジションサイズ(購入株数)を計算するには、以下の4つの値が必要です。

パラメータ 説明
総資金(Capital) 投資に使える資金の合計 1,000,000円
リスク許容率(Risk %) 1トレードあたりの最大損失率 2%
エントリー価格(Entry) 購入予定の株価 2,500円
損切り価格(Stop Loss) 損切りを実行する株価 2,375円

ポジションサイズの計算ロジック

理論を数式に落とし込みます。計算の流れは3ステップです。

ステップ1:リスク許容額の算出

まず、1回のトレードで許容できる損失額を計算します。


リスク許容額 = 総資金 × リスク許容率

例:1,000,000円 × 2% = 20,000円

ステップ2:1株あたりのリスク額の算出

次に、エントリー価格と損切り価格の差額を計算します。これが1株あたりのリスク額です。


1株あたりリスク = エントリー価格 − 損切り価格

例:2,500円 − 2,375円 = 125円

ステップ3:購入株数の算出

リスク許容額を1株あたりリスクで割ることで、購入可能な株数が求められます。


購入株数 = リスク許容額 ÷ 1株あたりリスク

例:20,000円 ÷ 125円 = 160株

日本株の場合、売買単位は100株単位が基本です。計算結果が160株であれば、100株に切り下げるのが安全側の判断となります。

計算結果の検証

100株を2,500円で購入した場合の投資額と最大損失額を確認します。

項目 金額
投資額(100株 × 2,500円) 250,000円
最大損失額(100株 × 125円) 12,500円
総資金に対する損失率 1.25%

リスク許容率2%(20,000円)の範囲内に収まっていることが確認できます。

【コピペOK】基本のポジションサイズ計算コード

上記のロジックをPythonで実装します。まずは外部ライブラリを使わないシンプルな計算コードです。

パラメータを手動入力する基本版


import math

# ==============================
# 資金管理パラメータ設定
# ==============================
CAPITAL = 1_000_000       # 総資金(円)
RISK_PERCENT = 2.0        # リスク許容率(%)
ENTRY_PRICE = 2_500       # エントリー価格(円)
STOP_LOSS_PRICE = 2_375   # 損切り価格(円)
LOT_UNIT = 100            # 売買単位(日本株は通常100株)

# ==============================
# ポジションサイズ計算
# ==============================
def calc_position_size(capital, risk_pct, entry, stop_loss, lot_unit):
    risk_amount = capital * (risk_pct / 100)
    risk_per_share = entry - stop_loss

    if risk_per_share <= 0:
        print("エラー: 損切り価格がエントリー価格以上になっています。")
        return None

    raw_shares = risk_amount / risk_per_share
    adjusted_shares = math.floor(raw_shares / lot_unit) * lot_unit

    if adjusted_shares == 0:
        print("警告: 計算結果が0株です。資金不足またはリスク幅が大きすぎます。")
        return None

    return {
        "リスク許容額": risk_amount,
        "1株あたりリスク": risk_per_share,
        "計算上の株数": raw_shares,
        "購入株数(単元調整後)": adjusted_shares,
        "投資額": adjusted_shares * entry,
        "最大損失額": adjusted_shares * risk_per_share,
        "実質リスク率": (adjusted_shares * risk_per_share) / capital * 100,
    }

# ==============================
# 実行
# ==============================
if __name__ == "__main__":
    result = calc_position_size(
        CAPITAL, RISK_PERCENT, ENTRY_PRICE, STOP_LOSS_PRICE, LOT_UNIT
    )

    if result:
        print("=== ポジションサイズ計算結果 ===")
        for key, value in result.items():
            if isinstance(value, float):
                print(f"  {key}: {value:,.2f}")
            else:
                print(f"  {key}: {value:,}")

このコードを position_size.py として保存し、python position_size.py で実行してください。

出力結果の例


=== ポジションサイズ計算結果 ===
  リスク許容額: 20,000.00
  1株あたりリスク: 125.00
  計算上の株数: 160.00
  購入株数(単元調整後): 100
  投資額: 250,000
  最大損失額: 12,500.00
  実質リスク率: 1.25

【コピペOK】yfinanceと連携したリアルタイム計算コード

実際の運用では、エントリー価格をリアルタイムの株価から取得し、損切り価格をテクニカル指標(直近安値やATRなど)から自動算出するのが効率的です。

ATR(Average True Range)を使った損切り幅の自動計算

ATRは、一定期間の値動きの平均的な幅を表す指標です。ATRの2倍をエントリー価格から引いた値を損切りラインとして設定する方法が広く使われています。


import yfinance as yf
import pandas as pd
import math

# ==============================
# 設定エリア
# ==============================
SYMBOL = "7203.T"         # 銘柄コード(トヨタ自動車)
CAPITAL = 1_000_000       # 総資金(円)
RISK_PERCENT = 2.0        # リスク許容率(%)
ATR_PERIOD = 14           # ATRの計算期間
ATR_MULTIPLIER = 2.0      # ATR倍率(損切り幅に使用)
LOT_UNIT = 100            # 売買単位

# ==============================
# データ取得とATR計算
# ==============================
def fetch_and_calc_atr(symbol, period="3mo"):
    ticker = yf.Ticker(symbol)
    df = ticker.history(period=period)

    if df.empty:
        print(f"エラー: {symbol} のデータを取得できませんでした。")
        return None, None

    high = df["High"]
    low = df["Low"]
    close = df["Close"]

    tr1 = high - low
    tr2 = abs(high - close.shift(1))
    tr3 = abs(low - close.shift(1))

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

    latest_close = close.iloc[-1]
    latest_atr = atr.iloc[-1]

    return latest_close, latest_atr

# ==============================
# ポジションサイズ計算
# ==============================
def calc_position(capital, risk_pct, entry, atr_value, multiplier, lot_unit):
    stop_loss = entry - (atr_value * multiplier)
    risk_amount = capital * (risk_pct / 100)
    risk_per_share = entry - stop_loss

    if risk_per_share <= 0:
        print("エラー: 損切り幅が0以下です。")
        return None

    raw_shares = risk_amount / risk_per_share
    adjusted_shares = math.floor(raw_shares / lot_unit) * lot_unit

    if adjusted_shares == 0:
        print("警告: 購入株数が0株です。資金を増やすかリスク許容率を見直してください。")
        return None

    return {
        "銘柄": SYMBOL,
        "現在株価": entry,
        "ATR(14日)": atr_value,
        "損切りライン": stop_loss,
        "1株あたりリスク": risk_per_share,
        "リスク許容額": risk_amount,
        "購入株数": adjusted_shares,
        "投資額": adjusted_shares * entry,
        "最大損失額": adjusted_shares * risk_per_share,
        "実質リスク率(%)": (adjusted_shares * risk_per_share) / capital * 100,
    }

# ==============================
# メイン処理
# ==============================
if __name__ == "__main__":
    print(f"--- {SYMBOL} のポジションサイズを計算 ---n")

    latest_close, latest_atr = fetch_and_calc_atr(SYMBOL)

    if latest_close is None:
        print("処理を中断します。")
    else:
        result = calc_position(
            CAPITAL, RISK_PERCENT, latest_close,
            latest_atr, ATR_MULTIPLIER, LOT_UNIT
        )

        if result:
            print("=== 計算結果 ===")
            for key, value in result.items():
                if isinstance(value, str):
                    print(f"  {key}: {value}")
                elif isinstance(value, float):
                    print(f"  {key}: {value:,.2f}")
                else:
                    print(f"  {key}: {value:,}")

コードの実行方法

以下のコマンドで必要なライブラリをインストールした上で実行してください。


pip install yfinance pandas
python position_size.py

出力結果の読み方

出力の各項目が示す意味は以下のとおりです。

出力項目 意味
現在株価 yfinanceから取得した直近の終値
ATR(14日) 直近14日間の平均的な値動き幅
損切りライン 現在株価 − ATR × 2.0 で算出
購入株数 リスク許容額から逆算し、100株単位に切り下げた値
実質リスク率 実際の最大損失額が総資金に占める割合

リスク許容率の設定ガイドライン

リスク許容率を何パーセントに設定するかは、投資スタイルとリスク耐性によって異なります。

推奨設定の目安

投資スタイル 推奨リスク許容率 備考
保守的(初心者向け) 0.5〜1.0% 連敗耐性が高く、精神的負担が小さい
標準的(中級者向け) 1.0〜2.0% 資金効率と安全性のバランスが良い
積極的(上級者向け) 2.0〜3.0% 高い期待値の戦略を持つ場合に限定

連敗シミュレーション

リスク許容率2%で10連敗した場合の資金推移を確認します。


100万円 → 98万円 → 96.04万円 → ... → 約81.7万円(10連敗後)

資金の約18%が失われますが、致命的な水準ではありません。一方、リスク許容率10%で10連敗した場合は約34.9万円まで減少し、回復が極めて困難になります。

リスク許容率は最大でも3%以内に設定することを推奨します。「もっと大きく賭けたい」という衝動こそが、資金管理の最大の敵です。

よくあるエラーと対処法

購入株数が0株になってしまう

以下のいずれかが原因です。

  • 総資金に対して株価が高すぎる: 値がさ株(1株数万円以上)ではリスク許容額内に100株分が収まらない場合がある
  • 損切り幅が広すぎる: ATR倍率が大きすぎると1株あたりリスクが増大し、購入可能株数が減少する

対処法としては、ATR倍率を1.5に下げる、またはより株価の低い銘柄を選定することが有効です。

損切り価格がエントリー価格を上回るエラー

ショート(空売り)のロジックを組んでいない場合、損切り価格はエントリー価格より低い値である必要があります。コード内のバリデーション(risk_per_share <= 0 のチェック)がこのエラーを検出します。

空売り対応が必要な場合は、エントリー価格と損切り価格の差の絶対値を使用するようにコードを修正してください。

yfinanceのデータ取得でNoneが返る

ネットワーク接続の問題、または銘柄コードの誤りが主な原因です。日本株の場合、銘柄コードの末尾に.T(東証)を付ける必要があります。

  • トヨタ自動車:7203.T
  • ソニーグループ:6758.T
  • 任天堂:7974.T

まとめ

資金管理とポジションサイジングの要点を整理します。

  • 1回のトレードで許容する最大損失を総資金の1〜2%以内に設定する
  • 購入株数は「リスク許容額 ÷ 1株あたりリスク」で逆算する
  • 日本株の場合は100株単位に切り下げて調整する
  • ATRを活用すれば、損切り幅を相場のボラティリティに応じて自動調整できる
  • yfinanceとの連携により、リアルな株価データに基づく計算が可能になる

「何株買うか」を感覚ではなくルールとして定義することが、長期的に資金を守るための最も確実な方法です。今回のコードをベースに、自身の投資ルールに合わせたパラメータ調整を行い、デモ環境での検証から始めてください。

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