・約6分で読めます

FX自動売買のスプレッドがボット収益に与える影響と対策【2026年版】


PRDMM FXスプレッド業界最狭水準。口座開設数国内トップクラス。最短即日で取引開始。
DMM FX 無料口座開設 →

FX自動売買Botを開発していると「バックテストでは勝てていたのに、本番では全然勝てない」という壁にぶつかることがあります。その原因の一つがスプレッドの扱いです。この記事では、スプレッドがBot収益に与える具体的な影響と、それを考慮した実装方法をPythonコードを交えて解説します。


スプレッドとは何か、なぜBot収益に直結するのか

FX取引では、買値(Ask)と売値(Bid)の間に必ず差があります。この差が「スプレッド」です。たとえばドル円のBidが148.000円、Askが148.003円であれば、スプレッドは0.3銭(3pips × 0.1)ということになります。

手動トレードでは「少し広いな」と感じる程度のスプレッドでも、自動売買Botは1日に何十〜何百回とエントリーするため、その積み重ねが収益を大きく左右します。

スプレッドが収益に与える影響の試算

たとえばドル円で0.3銭のスプレッドがある場合、1回のトレードで1ロット(10万通貨)を売買すると、単純計算でエントリー時点から300円のコストが発生します。

1日30回エントリーするBotであれば、1日あたり9,000円のコストです。月20営業日換算で18万円のコストになります。利益が出るためには、このコストを超えるリターンを得続けなければなりません。

スキャルピング系のBotほどこの影響が顕著です。1回あたりの利幅が小さい戦略では、スプレッドが少し広がるだけで収益がマイナスに転じるケースが多くあります。


通貨ペア別のスプレッド比較と選択の考え方

FX自動売買を始める前に、どの通貨ペアを取引するかの選択はスプレッドの観点からも重要です。一般的に、流動性が高い通貨ペアほどスプレッドが狭い傾向があります。

以下は主要通貨ペアのスプレッドの一般的な水準を比較した目安です(各社・市場状況により変動します)。

通貨ペア 通常スプレッドの目安 流動性 スキャルピング適性
USD/JPY(ドル円) 0.2〜0.5銭 高い
EUR/USD(ユーロドル) 0.3〜0.6pips 高い
EUR/JPY(ユーロ円) 0.5〜1.0銭 中程度
GBP/JPY(ポンド円) 1.0〜2.0銭 中程度
AUD/JPY(豪ドル円) 0.7〜1.5銭 中程度
USD/TRY(ドルトルコリラ) 数十pips〜 低い ×

ドル円やユーロドルは流動性が高くスプレッドが安定しているため、スキャルピング系Botの取引コストを抑えやすい通貨ペアといえます。一方、新興国通貨を含む通貨ペアはスプレッドが大きく、Botには不向きなケースが多いです。

GMOコインのスプレッド水準について

仮想通貨FXを手がけるGMOコインでも、FX関連の取引サービスを展開しています。GMOコインのFXサービスでは、ビットコインFXなどにおいてスプレッドの水準が公式サイトに掲載されており、取引コストの透明性を確認できます。

FX自動売買で利用するブローカーを選ぶ際は、公式サイトのスプレッド情報を実際に確認し、自分のBotの取引頻度・利幅と照らし合わせることが重要です。固定スプレッドか変動スプレッドかによっても戦略の設計が変わってきます。


スプレッドを考慮したバックテストの実装方法(Python)

多くの初心者が陥るのが「スプレッドを無視したバックテスト」です。バックテストで使うOHLC(始値・高値・安値・終値)データは中間値(Midレート)のため、そのまま使うと実際の取引コストが反映されません。

バックテストにスプレッドを組み込む基本的な考え方

エントリー時にスプレッド分のコストを加算することで、より実態に近いバックテストが実現できます。

# スプレッドを考慮したバックテストの基本実装例

SPREAD_PIPS = 0.3  # ドル円のスプレッド(銭)
LOT_SIZE = 10000   # 1ロット = 1万通貨

def calculate_entry_cost(spread_pips: float, lot_size: int) -> float:
    """
    エントリー時のスプレッドコストを計算する
    spread_pips: スプレッド(銭単位)
    lot_size: 取引数量
    """
    spread_in_yen = spread_pips * 0.01  # 銭 → 円換算
    return spread_in_yen * lot_size

def backtest_with_spread(signals: list, prices: list, spread_pips: float, lot_size: int):
    """
    スプレッドを考慮したバックテスト
    signals: 売買シグナルのリスト(1=買い, -1=売り, 0=何もしない)
    prices: 終値のリスト(Midレート)
    """
    entry_cost = calculate_entry_cost(spread_pips, lot_size)
    total_pnl = 0
    position = 0
    entry_price = 0

    for i, (signal, price) in enumerate(zip(signals, prices)):
        if signal == 1 and position == 0:  # 新規買いエントリー
            entry_price = price + (spread_pips * 0.01)  # Ask相当
            position = 1
        elif signal == -1 and position == 1:  # 決済
            exit_price = price  # Bid相当(Midそのまま)
            pnl = (exit_price - entry_price) * lot_size
            total_pnl += pnl
            position = 0

    return total_pnl

# 使用例
# 買いエントリー時にはスプレッド分を加算してAsk相当の価格でエントリー
# 売りエントリー時にはBid相当(Mid)でエントリー

このように、買いエントリーの際にMidレートにスプレッドを加算してAsk相当の価格を求めるのが基本的な手法です。

変動スプレッドを考慮した高度なバックテスト

実際の市場ではスプレッドは一定ではなく、時間帯や市場の状況によって変動します。より精度の高いバックテストを行うには、時間帯別のスプレッドモデルを組み込むことも一つのアプローチです。

たとえば東京時間・ロンドン時間・NY時間でスプレッドを変えてシミュレーションする、あるいはブローカーから取得したTick dataを使ってより実態に近いスプレッドを使用するといった方法があります。


スプレッドが広い時間帯を回避するロジックの実装

スプレッドは時間帯によって大きく変動します。 特に以下のような時間帯はスプレッドが広がりやすい傾向があります。

  • 東京時間の早朝(7〜8時台): 市場参加者が少なく流動性が低い
  • クロス時間帯(市場の切り替わり): ロンドン市場終了〜NY市場の重複解消後
  • 重要経済指標の発表前後: 数分間スプレッドが急拡大することがある
  • 週明け月曜早朝: ギャップが生じやすい

これらの時間帯を自動的に回避するロジックをBotに組み込むことで、不必要なコストを削減できます。

時間帯(JST) スプレッドの傾向 トレード適性
9:00〜12:00(東京時間) 比較的安定
15:00〜18:00(欧州オープン前後) やや広がる時間あり
17:00〜21:00(ロンドン時間) 流動性高く安定
22:00〜翌1:00(NY時間) 流動性高く安定
翌3:00〜8:00(深夜〜早朝) 広がりやすい △〜×

Pythonで時間帯フィルタを実装する

from datetime import datetime, time
import pytz

# 日本時間(JST)での時間帯フィルタ
JST = pytz.timezone('Asia/Tokyo')

# 経済指標発表スケジュール(実際は外部APIから取得するのが望ましい)
HIGH_IMPACT_EVENTS = [
    {"time": "21:30", "description": "米雇用統計", "avoid_minutes": 30},
    {"time": "22:30", "description": "FOMC政策金利", "avoid_minutes": 60},
]

def is_valid_trading_time(current_time: datetime, spread_threshold_pips: float = 0.5) -> bool:
    """
    現在時刻がトレード適切な時間帯かどうかを判定する
    Returns: True=トレード可 / False=スキップ
    """
    jst_time = current_time.astimezone(JST).time()

    # 深夜〜早朝(3:00〜8:00 JST)は回避
    if time(3, 0) <= jst_time < time(8, 0):
        return False

    # 週明け月曜早朝(8:00まで)も回避
    weekday = current_time.astimezone(JST).weekday()
    if weekday == 0 and jst_time < time(9, 0):  # 0=月曜
        return False

    return True

def should_skip_due_to_spread(current_spread: float, threshold: float = 0.8) -> bool:
    """
    現在のスプレッドが閾値を超えていればトレードをスキップする
    current_spread: 現在のスプレッド(銭)
    threshold: 許容する最大スプレッド(銭)
    """
    return current_spread > threshold

このように「スプレッドが一定の閾値を超えたらエントリーしない」ロジックを組み込むことが、安定したBot運用の基礎になります。重要経済指標の発表前後は特にスプレッドが急拡大するリスクがあるため、外部の経済カレンダーAPIと連携して自動的に回避する実装も検討に値します。

スプレッドの閾値はどう決めるか

閾値の設定は戦略によって異なります。

一般的な考え方としては、「1回の取引で期待できる利幅の20〜30%以内に収まるスプレッドまでを許容する」という基準があります。たとえば1回あたり2銭の利幅を期待するBotであれば、スプレッドの閾値を0.5〜0.6銭程度に設定するのが一つの目安です。

バックテスト時に複数のスプレッド閾値でシミュレーションを行い、収益・取引回数・勝率のバランスを見ながら調整するアプローチが現実的です。

関連記事


スプレッドを味方につけるBot開発の次のステップ

スプレッドを正しく理解し、Botに組み込むことは「勝てるBot」を作るための基礎です。ここで紹介した内容を踏まえた次のアクションをまとめます。

1. 利用するブローカーのスプレッドを事前に確認する

バックテストを始める前に、実際に取引するブローカーのスプレッド情報を公式サイトで確認しましょう。固定スプレッドか変動スプレッドか、そして想定する通貨ペアのスプレッド水準が自分の戦略に合うかを検討してください。

2. バックテストにスプレッドを必ず組み込む

本記事で紹介したPythonコードを参考に、MidレートのOHLCデータを使う場合はエントリー時にスプレッドを加算する処理を追加しましょう。スプレッドを無視したバックテストと、スプレッドを考慮したバックテストの結果を比較するだけで、自分の戦略の真の実力が見えてきます。

3. 時間帯フィルタと閾値フィルタを段階的に実装する

まずはシンプルな「時間帯フィルタ」から始め、安定して動作するようになったら「リアルタイムスプレッドの閾値フィルタ」へと発展させていくのがおすすめです。一度に複雑な実装を目指すと、バグの原因が特定しにくくなります。

4. フォワードテストで実際のスプレッドと乖離がないか確認する

バックテストで良好な結果が出たとしても、フォワードテスト(デモ口座やごく少量での本番テスト)を通じて実際のスプレッドとの乖離を確認することが不可欠です。特に流動性が低い時間帯や、市場のボラティリティが高い局面でのスプレッド拡大は、バックテストだけでは再現しにくい部分があります。

スプレッドは「見えにくいコスト」だからこそ、Botの設計段階から意識的に組み込む習慣をつけることが、長期的に安定したシステムトレードに繋がります。

DMM FX無料口座開設