Web Lukes
📄

【Python】損切り・リスク管理の自動化|トレーリングストップの実装

公開日: 2025/12/13更新日: 2025/12/13

「エントリーはできるようになった。でも損切りどうすれば...」

自動売買で最も重要なのはリスク管理です。

どんなに優秀なエントリーロジックでも、損切りが適切でなければ一発退場もありえます。

この記事では、Pythonで損切り・利確を自動化する方法を解説します。

損切りの種類

種類説明メリットデメリット
固定損切りエントリー価格から一定pipsシンプル相場のボラに合わない
トレーリングストップ利益方向に追従利益を伸ばせる設定が難しい
ブレイクイーブン一定利益で損切りを建値に負けをゼロに早期決済されやすい
ATRベースボラティリティに応じて調整相場に適応計算が複雑

1. 固定損切り

最もシンプル。エントリー価格から30pipsなど固定。

GMOコインでの実装

GMOコインの外国為替FX APIでは、注文時に損切り(losscutPrice)を指定できます。

Python
def place_order_with_stoploss(symbol, side, size, stoploss_pips=30):
"""
損切り付き成行注文
Args:
symbol: 通貨ペア
side: "BUY" または "SELL"
size: 注文数量
stoploss_pips: 損切り幅(pips)
"""
# 現在価格を取得
ticker = get_ticker(symbol)
current_price = float(ticker["ask"]) if side == "BUY" else float(ticker["bid"])
# 損切り価格を計算
if side == "BUY":
stoploss_price = current_price - (stoploss_pips * 0.01) # ドル円の場合
else:
stoploss_price = current_price + (stoploss_pips * 0.01)
# 注文
body = {
"symbol": symbol,
"side": side,
"executionType": "MARKET",
"size": str(size),
"timeInForce": "FAK",
"losscutPrice": str(round(stoploss_price, 3)) # 損切り価格
}
result = private_request("POST", "/v1/order", body)
if result["status"] == 0:
print(f"✅ 注文成功: {side} @ {current_price}")
print(f" 損切り: {stoploss_price}")
return result["data"]
else:
print(f"❌ エラー: {result}")
return None

2. トレーリングストップ

価格が有利な方向に動いたら、損切りラインも追従させる。

仕組み

  1. エントリー: 150.00円で買い、損切り149.70円(-30pips)
  2. 価格が150.50円に上昇 → 損切りを150.20円に引き上げ
  3. 価格が151.00円に上昇 → 損切りを150.70円に引き上げ
  4. 価格が150.50円に下落 → 損切りは150.70円のまま(下げない)
  5. 150.70円に到達 → 決済(+70pips利益確定)

実装

Python
class TrailingStopManager:
"""トレーリングストップ管理クラス"""
def __init__(self, trailing_pips=30):
self.trailing_pips = trailing_pips
self.positions = {} # {position_id: {"side": "BUY", "highest": 150.00, "stoploss": 149.70}}
def register_position(self, position_id, side, entry_price):
"""新規ポジションを登録"""
if side == "BUY":
stoploss = entry_price - (self.trailing_pips * 0.01)
self.positions[position_id] = {
"side": side,
"entry": entry_price,
"highest": entry_price,
"stoploss": stoploss
}
else: # SELL
stoploss = entry_price + (self.trailing_pips * 0.01)
self.positions[position_id] = {
"side": side,
"entry": entry_price,
"lowest": entry_price,
"stoploss": stoploss
}
print(f"📝 ポジション登録: {position_id}")
print(f" {side} @ {entry_price}, SL: {stoploss}")
def update(self, position_id, current_price):
"""
価格更新時にトレーリングストップを調整
Returns:
True: 損切りに到達(決済すべき)
False: 継続
"""
if position_id not in self.positions:
return False
pos = self.positions[position_id]
if pos["side"] == "BUY":
# 高値更新したらストップを引き上げ
if current_price > pos["highest"]:
pos["highest"] = current_price
new_stoploss = current_price - (self.trailing_pips * 0.01)
if new_stoploss > pos["stoploss"]:
print(f"📈 トレーリング更新: SL {pos['stoploss']:.3f} → {new_stoploss:.3f}")
pos["stoploss"] = new_stoploss
# 損切りチェック
if current_price <= pos["stoploss"]:
print(f"🔴 損切り到達: {current_price} <= {pos['stoploss']}")
return True
else: # SELL
# 安値更新したらストップを引き下げ
if current_price < pos["lowest"]:
pos["lowest"] = current_price
new_stoploss = current_price + (self.trailing_pips * 0.01)
if new_stoploss < pos["stoploss"]:
print(f"📉 トレーリング更新: SL {pos['stoploss']:.3f} → {new_stoploss:.3f}")
pos["stoploss"] = new_stoploss
# 損切りチェック
if current_price >= pos["stoploss"]:
print(f"🔴 損切り到達: {current_price} >= {pos['stoploss']}")
return True
return False
def remove_position(self, position_id):
"""ポジション削除"""
if position_id in self.positions:
del self.positions[position_id]

使用例

Python
# 初期化
trailing_manager = TrailingStopManager(trailing_pips=30)
# エントリー時
position_id = place_order("USD_JPY", "BUY", 100)
trailing_manager.register_position(position_id, "BUY", 150.00)
# メインループ内で定期的に更新
while True:
current_price = float(get_ticker("USD_JPY")["bid"])
for pos_id in list(trailing_manager.positions.keys()):
if trailing_manager.update(pos_id, current_price):
# 損切り到達 → 決済
close_position(pos_id)
trailing_manager.remove_position(pos_id)
time.sleep(1)

3. ブレイクイーブン(建値決済)

一定の利益が出たら、損切りラインを建値(エントリー価格)に移動。

これで「負けをゼロにする」ことができます。

Python
class BreakevenManager:
"""ブレイクイーブン管理"""
def __init__(self, trigger_pips=20, buffer_pips=2):
"""
Args:
trigger_pips: 何pips利益が出たらブレイクイーブンに移動するか
buffer_pips: 建値からさらに何pipsバッファを持たせるか
"""
self.trigger_pips = trigger_pips
self.buffer_pips = buffer_pips
self.positions = {}
def register_position(self, position_id, side, entry_price, initial_stoploss):
self.positions[position_id] = {
"side": side,
"entry": entry_price,
"stoploss": initial_stoploss,
"breakeven_triggered": False
}
def update(self, position_id, current_price):
"""ブレイクイーブンチェック"""
if position_id not in self.positions:
return False
pos = self.positions[position_id]
# すでにブレイクイーブン済みならスキップ
if pos["breakeven_triggered"]:
# 通常の損切りチェック
if pos["side"] == "BUY" and current_price <= pos["stoploss"]:
return True
if pos["side"] == "SELL" and current_price >= pos["stoploss"]:
return True
return False
# ブレイクイーブントリガーチェック
profit_pips = 0
if pos["side"] == "BUY":
profit_pips = (current_price - pos["entry"]) * 100
else:
profit_pips = (pos["entry"] - current_price) * 100
if profit_pips >= self.trigger_pips:
# ブレイクイーブンに移動
if pos["side"] == "BUY":
pos["stoploss"] = pos["entry"] + (self.buffer_pips * 0.01)
else:
pos["stoploss"] = pos["entry"] - (self.buffer_pips * 0.01)
pos["breakeven_triggered"] = True
print(f"✅ ブレイクイーブン発動! SL → {pos['stoploss']:.3f}")
return False

4. ATRベース損切り

ATR(Average True Range)を使って、相場のボラティリティに応じた損切り幅を設定。

ATRとは?

「平均的な1本のローソク足の値幅」を示す指標。ボラが高いと大きく、低いと小さくなります。

実装

Python
import pandas_ta as ta
def calculate_atr_stoploss(df, atr_period=14, atr_multiplier=2.0):
"""
ATRベースの損切り幅を計算
Args:
df: ローソク足データ(high, low, close必須)
atr_period: ATR期間
atr_multiplier: ATRの何倍を損切り幅にするか
Returns:
損切り幅(価格単位)
"""
# ATRを計算
df["atr"] = ta.atr(df["high"], df["low"], df["close"], length=atr_period)
current_atr = df["atr"].iloc[-1]
stoploss_distance = current_atr * atr_multiplier
print(f"ATR({atr_period}): {current_atr:.4f}")
print(f"損切り幅: {stoploss_distance:.4f} ({atr_multiplier}倍)")
return stoploss_distance
def place_order_with_atr_stoploss(symbol, side, size, df, atr_multiplier=2.0):
"""ATRベースの損切り付き注文"""
# ATRから損切り幅を計算
stoploss_distance = calculate_atr_stoploss(df, atr_multiplier=atr_multiplier)
# 現在価格
ticker = get_ticker(symbol)
current_price = float(ticker["ask"]) if side == "BUY" else float(ticker["bid"])
# 損切り価格
if side == "BUY":
stoploss_price = current_price - stoploss_distance
else:
stoploss_price = current_price + stoploss_distance
print(f"エントリー: {current_price}")
print(f"損切り: {stoploss_price} (ATR x {atr_multiplier})")
# 注文実行
# ...

ATRの利点

  • ボラティリティが高い時:損切り幅が広がる → ノイズで狩られにくい
  • ボラティリティが低い時:損切り幅が狭まる → リスクを限定

5. 複合リスク管理

実際のボットでは、複数のリスク管理を組み合わせます。

Python
class RiskManager:
"""統合リスク管理クラス"""
def __init__(
self,
max_daily_loss_pct=5.0, # 1日の最大損失率
max_positions=3, # 同時ポジション数
trailing_pips=30, # トレーリングストップ
breakeven_trigger_pips=20 # ブレイクイーブントリガー
):
self.max_daily_loss_pct = max_daily_loss_pct
self.max_positions = max_positions
self.trailing_pips = trailing_pips
self.breakeven_trigger_pips = breakeven_trigger_pips
self.daily_pnl = 0.0
self.initial_balance = None
self.positions = {}
def can_open_position(self):
"""新規ポジションを開けるかチェック"""
# 最大ポジション数チェック
if len(self.positions) >= self.max_positions:
print("⚠️ 最大ポジション数に達しています")
return False
# 日次損失チェック
if self.initial_balance:
loss_pct = (self.daily_pnl / self.initial_balance) * 100
if loss_pct <= -self.max_daily_loss_pct:
print(f"⚠️ 日次損失上限 ({self.max_daily_loss_pct}%) に達しました")
return False
return True
def update_daily_pnl(self, pnl):
"""日次損益を更新"""
self.daily_pnl += pnl
print(f"📊 日次損益: {self.daily_pnl:+.2f}")
def reset_daily(self, current_balance):
"""日次リセット(毎日実行)"""
self.daily_pnl = 0.0
self.initial_balance = current_balance
print(f"🔄 日次リセット: 開始残高 {current_balance}")

リスク管理のベストプラクティス

1. 1トレードあたりのリスクを限定

Python
def calculate_position_size(balance, risk_pct, stoploss_pips):
"""
リスクベースのポジションサイズ計算
Args:
balance: 口座残高
risk_pct: 1トレードでリスクにさらす割合(例: 2%)
stoploss_pips: 損切り幅
Returns:
適切なポジションサイズ
"""
risk_amount = balance * (risk_pct / 100)
pip_value = 100 # ドル円1万通貨の1pip = 100円(概算)
lot_size = risk_amount / (stoploss_pips * pip_value)
return round(lot_size, 2)
# 例: 100万円口座、2%リスク、30pips損切り
size = calculate_position_size(1000000, 2.0, 30)
# → 0.67ロット(6,700通貨)

2. 相関のある通貨ペアに注意

ドル円とユーロ円を同時にロングすると、実質的にドル安リスクが2倍。

3. 週末・重要指標前のポジション

週末や重要指標(FOMC、雇用統計)前はポジションを閉じるか縮小。

まとめ

損切り手法用途
固定損切りシンプル、初心者向け
トレーリングストップ利益を伸ばしたい時
ブレイクイーブン負けを減らしたい時
ATRベースボラに適応したい時

最も重要なこと:損切りを設定しないトレードは絶対にしない。

エントリーより損切りの方が大事です。どんなに勝率が高くても、1回の大損で全てを失う可能性があります。


🎉 おめでとうございます!

これで10記事シリーズ完走です!

  • MQL4/MT4でEAを作る方法
  • Pythonでボットを作る方法
  • クラウドで24時間稼働させる方法
  • リスク管理の自動化

ここまで学んだあなたは、もう「業者のツールを選ぶだけ」の人ではありません。

自分でシステムを作れる人です。

これからも、自分だけの戦略を形にしていきましょう。応援しています! 🚀

🎁おすすめツール・サービス

FX自動売買VPSなら50%OFF

キャンペーンで月1,790円〜。MT4/MT5プリインストール済み、自動復旧機能付き。14日間無料お試し。

シンクラウドデスクトップ for FX
ゴトー日EAを探しているならソースコード付

4年で資金4.7倍のバックテスト実績。ソースコード付きで自由にカスタマイズ可能。

ゴトー日EA Ultimate版(3,980円)

※上記リンクにはプロモーション(広告)が含まれています

🔮
MEMBERSHIP

量子相場謀略|ホソノP

ブログでは書けない本音のトレード戦略とEA開発の裏側を公開。 データに基づいた検証で、再現性のある手法だけをお届けします。

✓EAソースコード公開
✓バックテスト生データ共有
✓リアルタイム相場分析
✓メンバー限定記事
メンバーシップに参加する※ noteアカウントで簡単登録

📚あわせて読みたい

📄

【Python FXボット入門】MT4を使わない自動売買の始め方

Pythonで直接FX取引する自動売買ボットの作り方。MT4に依存しない、自由度の高いシステム開発の第一歩。GMOコインやOANDAのAPIを使った実践的な入門ガイド。

FX自動売買2025/12/13
📄

【Python】移動平均線クロスボットを作る|pandasでテクニカル分析

Pythonとpandasを使って移動平均線クロス戦略のFXボットを作ります。ローソク足データの取得から、MA計算、クロス検出、自動売買まで完全解説。

FX自動売買2025/12/13
📄

【Python】RSI逆張りボットを作る|pandas-taでテクニカル指標計算

Pythonとpandas-taを使ってRSI逆張り戦略のFXボットを作ります。RSIが30以下で買い、70以上で売り。テクニカル指標の計算が1行で完結!

FX自動売買2025/12/13
📄

【検証】ゴトー日ショートにSL/TPは必要か?100パターン検証で判明した最適設定

ゴトー日9:55ショートに最適なSL/TPを100パターン(SL/TP各5〜50pips)で検証。SL20・TP45で+133pips改善、SL25・TP5で勝率72%超え!ただし56%の設定は逆効果という衝撃の結果も。

FX自動売買2026/1/19
📄

🔬【検証】ゴトー日にトレーリングストップは有効か?30パターン徹底検証した結果

「利確は伸ばせ、損切りはトレーリングストップで追従」という定説をゴトー日で検証。発動タイミング3種類×トレール幅10種類=30パターンを総当たり。結果は意外な展開に...

FX自動売買2025/12/18
📄

【完全ガイド】FXボットを24時間稼働させる方法|VPS vs クラウド

FX自動売買ボットを24時間止めずに動かす方法を解説。従来のVPSからGoogle Cloud Functions、AWSまで、用途に合わせた最適な選択肢を紹介します。

FX自動売買2025/12/13