- 1 1. MQL5におけるSL・TP設定の基本
- 2 2. MQL5でSL・TPを設定する3つの方法
- 3 3. OrderSendでSL・TPを設定する実装詳細
- 4 4. 「invalid stops」エラーの原因と対処法
- 5 5. pips・point・価格の違いとSL/TP計算の正しい方法
- 6 6. 実務でそのまま使えるSL・TP設定テンプレート(再利用コード)
- 7 7. 初心者向け:最短で動くシンプル実装(最小コード)
- 8 8. SL/TP設計の戦略的考え方(EA設計)
- 9 9. MQL5のSL/TP設定チェックリストと最終整理
- 10 FAQ(よくある質問)
1. MQL5におけるSL・TP設定の基本
このセクションで書く要点
・SL(損切り)とTP(利確)の役割
・MQL5における設定方法の全体像
・なぜ初心者がつまずくのか
1.1 SL(Stop Loss)とTP(Take Profit)とは
SL(Stop Loss)とは、損失を一定の価格で自動的に確定する注文です。
TP(Take Profit)は、利益を一定の価格で確定する注文です。
例えば、以下のようなイメージです。
- BUY(買い)の場合
- SL:現在価格より下に設定(損切り)
- TP:現在価格より上に設定(利確)
- SELL(売り)の場合
- SL:現在価格より上に設定
- TP:現在価格より下に設定
この2つは単なる補助機能ではなく、EA(自動売買)のリスク管理の中核です。
特にSLが未設定の場合、相場が逆行した際に損失が無制限に拡大するリスクがあります。
1.2 なぜSL/TP設定が重要なのか(リスク管理の観点)
MQL5でのSL/TP設定は、単なる「機能」ではなく、期待値とドローダウン(最大損失)を制御するための必須要素です。
主な目的は以下です。
- 損失の上限を固定する(リスク制御)
- 利益確定を自動化する(感情排除)
- EAの再現性を担保する(ルール化)
例えば、SLを設定しないEAは以下の問題を抱えます。
- 想定外のドローダウン増大
- ロット管理と整合しない
- フォワードテストと実運用の乖離
逆に、適切なSL/TPを設定することで
- PF(プロフィットファクター)の安定
- DD(ドローダウン)の抑制
- 戦略の再現性向上
といった効果が得られます。
1.3 MQL5でのSL/TP設定方法の全体像(3パターン)
MQL5では、SL/TPの設定方法は大きく3つに分かれます。
① 注文時に設定(最も基本)
注文を出すタイミングで同時に設定する方法です。
OrderSendのsl/tpを使用- 最もシンプルで推奨される方法
request.sl = price - 100 * _Point;
request.tp = price + 100 * _Point;
② 注文後に設定・変更
既に保有しているポジションに対して設定・変更します。
PositionModifyを使用- 動的な戦略(途中変更)に対応可能
③ トレーリングストップ
価格に追従してSLを動かす方法です。
- 利益を伸ばしつつ損失を抑える
- 固定TPとは別概念
つまずきやすいポイント・注意点
初心者が最もハマるポイントは以下です。
■ BUYとSELLで方向が逆
- BUY:SLは下、TPは上
- SELL:SLは上、TPは下
→ これを間違えると「invalid stops」エラーになります
■ pipsとpointの混同
_Point:最小価格単位- pips:通貨ごとの慣習単位
→ 計算ミスの原因No.1
■ SL/TP未設定で注文
- 後から設定できるが、リスクが高い
→ 原則「注文時設定」が安全
■ ブローカー制約を無視
- 最低ストップ距離(StopLevel)が存在
→ 近すぎるとエラーになる
※これらは環境(ブローカー・通貨ペア)により異なるため、実行前の確認が必要です。
よくある失敗
- SL/TPの方向を逆に設定
- 値幅が小さすぎて注文拒否
- Ask/Bidを考慮していない
- 価格計算を固定値で書いてしまう
2. MQL5でSL・TPを設定する3つの方法
このセクションで書く要点
・注文時・後から変更・トレーリングの違い
・初心者はどれを使うべきか
2.1 注文時にSL/TPを同時設定する(基本)
最も基本かつ推奨される方法は、注文と同時にSL/TPを設定する方法です。
MQL5では MqlTradeRequest 構造体の sl / tp に価格を指定します。
手順(基本フロー)
- 現在価格(Ask / Bid)を取得
- SL / TPの価格を計算
request.sl/request.tpに設定OrderSendを実行
コード例(BUY)
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.1;
request.type = ORDER_TYPE_BUY;
request.price = price;
// SL / TP設定
request.sl = price - 100 * _Point;
request.tp = price + 100 * _Point;
OrderSend(request, result);
ポイント
_Pointは最小価格単位(例:0.00001)- BUY時は「SLは下・TPは上」
- SELL時は逆になる
初心者への結論
→ まずはこの方法だけ使えばOK
最もシンプルでエラーが少なく、実運用にも適しています。
2.2 注文後にSL/TPを変更する(PositionModify)
すでに保有しているポジションに対して、後からSL/TPを設定・変更する方法です。
動的な戦略(条件に応じて変更)で使われます。
手順
- 対象ポジションを選択(PositionSelect)
- 現在のSL/TPを取得
- 新しい値で
PositionModifyを実行
コード例
if(PositionSelect(_Symbol))
{
double new_sl = SymbolInfoDouble(_Symbol, SYMBOL_BID) - 100 * _Point;
double new_tp = SymbolInfoDouble(_Symbol, SYMBOL_BID) + 100 * _Point;
trade.PositionModify(_Symbol, new_sl, new_tp);
}
※ trade は CTrade クラスのインスタンス
注意点
- ポジション未選択だと失敗する
_Symbolではなくチケット指定の方が安全なケースあり- 変更頻度が高すぎると拒否される場合あり(環境依存)
2.3 トレーリングストップとの違い
トレーリングストップは、価格に応じてSLを自動的に引き上げる仕組みです。
TPとは異なり、「利益を伸ばすための動的なSL」です。
比較
| 項目 | 固定SL/TP | トレーリング |
|---|---|---|
| 性質 | 固定 | 動的 |
| 利益確定 | TPで固定 | SLで追従 |
| 実装難易度 | 低 | 中 |
基本ロジック
if(PositionSelect(_Symbol))
{
double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double new_sl = current_price - 50 * _Point;
// 現在のSLより有利な場合のみ更新
if(new_sl > PositionGetDouble(POSITION_SL))
{
trade.PositionModify(_Symbol, new_sl, PositionGetDouble(POSITION_TP));
}
}
つまずきやすいポイント・注意点
■ 注文時に設定しない問題
→ 「後で設定すればいい」と考えがち
→ 実運用では瞬間的な暴落で未設定状態が致命傷になる
■ トレーリングとTPの混同
→ TPは固定、トレーリングはSLの更新
→ 役割が完全に異なる
■ PositionModifyの失敗
- ポジション未選択
- 値が近すぎる(StopLevel違反)
- 同値で更新しようとして無効
よくある失敗
- SL/TPを0のまま注文(未設定)
- BUYなのにSLを上に設定
- トレーリングでSLが下がる(逆方向更新)
- 更新条件を入れていないため無限ループ
初心者向けの結論
- まずは 注文時設定(OrderSend)だけ使う
- 慣れてから PositionModify
- トレーリングは最後
3. OrderSendでSL・TPを設定する実装詳細
このセクションで書く要点
・MqlTradeRequestの構造と必須項目
・SL/TP設定の正しい書き方
・実務でそのまま使えるコード
3.1 MqlTradeRequest構造体の基本
MQL5では、注文は MqlTradeRequest 構造体に情報を詰めて OrderSend に渡します。
この中にSL/TPも含めて指定します。
主な項目
| 項目 | 内容 |
|---|---|
| action | 注文タイプ(成行・指値など) |
| symbol | 通貨ペア |
| volume | ロット数 |
| type | BUY / SELL |
| price | 注文価格 |
| sl | 損切り価格 |
| tp | 利確価格 |
最低限必要な項目
request.action
request.symbol
request.volume
request.type
request.price
SL/TPは任意ですが、実務では必須レベルです。
3.2 SL/TPの正しい設定方法(BUY/SELL別)
SL/TPは「価格」で指定します。
ポイント数ではなく価格値である点が重要です。
BUYの場合
request.sl = price - 100 * _Point;
request.tp = price + 100 * _Point;
SELLの場合
request.sl = price + 100 * _Point;
request.tp = price - 100 * _Point;
なぜこうなるのか
- BUY:価格上昇で利益 → TPは上
- SELL:価格下落で利益 → TPは下
→ 方向を間違えると即エラー(invalid stops)
3.3 実務で使える完全コード例
以下は、エラー対策も含めた実用コードです。
#include <Trade/Trade.mqh>
CTrade trade;
void OpenBuy()
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
// 最低ストップ距離取得
int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
double sl = ask - (stopLevel + 10) * _Point;
double tp = ask + (stopLevel + 10) * _Point;
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.1;
request.type = ORDER_TYPE_BUY;
request.price = ask;
request.sl = NormalizeDouble(sl, _Digits);
request.tp = NormalizeDouble(tp, _Digits);
request.deviation = 10;
if(!OrderSend(request, result))
{
Print("OrderSend failed: ", result.retcode);
}
}
3.4 NormalizeDoubleと桁数の重要性
価格は必ず、通貨ペアの桁数に合わせて丸める必要があります。
NormalizeDouble(price, _Digits);
理由
- 不正な桁数 → 注文拒否
- ブローカー仕様に依存
例
- EURUSD(5桁)→
_Digits = 5 - USDJPY(3桁)→
_Digits = 3
つまずきやすいポイント・注意点
■ SL/TPをポイントで指定してしまう
→ 必ず「価格」で指定する
→ _Point を掛けて変換する
■ stopLevelを無視
→ 最低距離未満は拒否される
→ 環境ごとに異なる
■ Ask/Bidの使い分けミス
- BUY:Ask
- SELL:Bid
→ 逆にすると価格ズレ
■ NormalizeDouble未使用
→ 桁エラーで失敗するケースあり
よくある失敗
- SL/TPを0のまま送信
- 桁数を合わせずにエラー
- stopLevelを考慮せず注文拒否
- priceとSL/TPの整合性が崩れる
実務上のベストプラクティス
- SL/TPは必ず注文時に設定
- stopLevel + αで余裕を持たせる
- NormalizeDoubleで整形
- エラーコードを必ずログ出力
4. 「invalid stops」エラーの原因と対処法
このセクションで書く要点
・invalid stopsの発生条件
・具体的な原因の分類
・再現性のある対処方法
4.1 invalid stopsとは何か
invalid stops は、SL(損切り)またはTP(利確)の設定が不正な場合に発生するエラーです。
MQL5では、OrderSend や PositionModify 実行時に返されます。
主な特徴:
- 注文自体は有効でも、SL/TPのみが不正
- ブローカー側の制約に違反しているケースが多い
- 初心者が最も遭遇しやすいエラー
4.2 主な原因(5パターン)
① SL/TPの方向ミス
最も多い原因です。
- BUYなのにSLが上にある
- SELLなのにTPが上にある
→ 価格の上下関係が逆だと即エラー
② 最低ストップ距離(StopLevel)違反
ブローカーには、SL/TPを現在価格から一定距離以上離す必要がある制約があります。
int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
- 単位:ポイント(point)
- 通貨ペア・ブローカーごとに異なる
→ これ未満だと invalid stops
③ スプレッド未考慮
特にBUY注文で発生しやすい問題です。
- BUYはAskで約定
- SL/TPはBidベースで判定されるケースあり
→ スプレッド分を考慮しないと距離不足になる
④ 価格の桁数ミス
NormalizeDouble(price, _Digits);
- 桁数不一致 → 不正価格扱い
- 特にUSDJPYなどで発生しやすい
⑤ 現在価格に近すぎる
理論上正しくても、以下のケースでNGになります。
- 約定直後にSLを近距離で設定
- 急変動中で価格がずれる
→ 実行タイミング依存のエラー
4.3 対処法(実務テンプレート)
以下は、実務でそのまま使える対策コードです。
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
// 安全マージンを追加
double buffer = (stopLevel + 10) * _Point;
// BUY例
double sl = NormalizeDouble(ask - buffer, _Digits);
double tp = NormalizeDouble(ask + buffer, _Digits);
4.4 実務でのチェックリスト
注文前に以下を確認するだけで、ほぼ防げます。
- SL < price < TP(BUYの場合)
- TP < price < SL(SELLの場合)
- stopLevel以上の距離を確保
- NormalizeDouble済み
- Ask/Bidの整合性OK
つまずきやすいポイント・注意点
■ StopLevelは常に同じではない
→ 時間帯や銘柄で変わる場合あり
→ 毎回取得するのが安全
■ スプレッド拡大時の誤動作
→ 指標発表時などで急拡大
→ SLが無効になるケースあり
■ 成行と指値で挙動が違う
→ pending注文では条件がさらに厳しい
よくある失敗
- stopLevelを0と誤認(実際は内部制約あり)
- SL/TPをギリギリに設定しすぎる
- スプレッドを考慮しない
- デバッグログを見ない
実務上のベストプラクティス
- stopLevel + α(10〜20ポイント)で設定
- NormalizeDoubleを必ず使用
- エラーコード(result.retcode)をログ出力
- 環境差(ブローカー差)を前提に設計
5. pips・point・価格の違いとSL/TP計算の正しい方法
このセクションで書く要点
・pipsとpointの違いを明確化
・SL/TP計算で混乱しやすいポイントの整理
・実務で使える安全な計算方法
5.1 pipsとpointの違い(最重要)
MQL5で最も混乱しやすいのが、pipsとpointの違いです。
用語の定義
- point:最小価格単位(
_Point) - pips:一般的な価格変動単位(通貨ペアごとに異なる)
具体例
| 通貨ペア | _Point | 1 pips |
|---|---|---|
| EURUSD(5桁) | 0.00001 | 0.0001 |
| USDJPY(3桁) | 0.001 | 0.01 |
つまり、
- EURUSD:1 pips = 10 point
- USDJPY:1 pips = 10 point
→ 多くの環境で「1 pips = 10 point」だが、例外もあるため注意
5.2 なぜ混乱が起きるのか
MQL5ではすべて「point基準」で処理されます。
しかし、トレーダーは通常「pips」で考えます。
このズレにより、
- 設定値が10倍ズレる
- SLが近すぎてエラー
- TPが遠すぎて非現実的
といった問題が発生します。
5.3 pipsを使った安全なSL/TP計算
実務では、pips入力 → point変換 → 価格計算の流れが安全です。
例:20pipsのSL/TPを設定
double pips = 20;
// 1 pips = 10 point(一般的な前提)
double pip_value = 10 * _Point;
double sl = ask - pips * pip_value;
double tp = ask + pips * pip_value;
5.4 汎用的なpips計算関数(推奨)
通貨ペアごとの差異を吸収するため、以下のような関数を用意すると安全です。
double GetPipValue()
{
if(_Digits == 3 || _Digits == 5)
return 10 * _Point;
else
return _Point;
}
使用例
double pip = GetPipValue();
double sl = NormalizeDouble(ask - 20 * pip, _Digits);
double tp = NormalizeDouble(ask + 20 * pip, _Digits);
5.5 SELL時の計算(注意)
SELLは方向が逆になります。
double pip = GetPipValue();
double sl = NormalizeDouble(bid + 20 * pip, _Digits);
double tp = NormalizeDouble(bid - 20 * pip, _Digits);
つまずきやすいポイント・注意点
■ pipsをそのまま使う
→ MQL5では通用しない
→ 必ずpoint換算が必要
■ 通貨ペアごとの差を無視
→ JPY系とそれ以外で桁が違う
→ _Digits を必ず確認
■ 固定値で書く
→ 0.0001などのハードコードは危険
→ 銘柄変更で崩壊する
よくある失敗
- 20pipsのつもりが2pipsになる
- SLが近すぎてinvalid stops
- TPが遠すぎて現実的でない
- 通貨ペア変更でロジック崩壊
実務上のベストプラクティス
- pips → point変換関数を必ず用意
_Digitsベースで設計- NormalizeDoubleで整形
- SL/TP計算は共通関数化
6. 実務でそのまま使えるSL・TP設定テンプレート(再利用コード)
このセクションで書く要点
・再利用可能な関数設計
・BUY/SELL両対応のテンプレート
・実運用で壊れにくい実装
6.1 テンプレート設計の考え方
SL/TP設定は毎回個別に書くと、以下の問題が発生します。
- バグ混入(方向ミス・桁ミス)
- 通貨ペア変更で崩壊
- メンテナンス性低下
→ 解決策は、共通関数化(テンプレート化)です。
6.2 汎用SL/TP計算関数
まずは、pipsベースで安全に計算する関数を定義します。
double GetPipValue()
{
if(_Digits == 3 || _Digits == 5)
return 10 * _Point;
else
return _Point;
}
6.3 SL/TP計算テンプレート(BUY/SELL対応)
bool CalculateSLTP(bool isBuy, double price, double sl_pips, double tp_pips, double &sl, double &tp)
{
double pip = GetPipValue();
if(isBuy)
{
sl = price - sl_pips * pip;
tp = price + tp_pips * pip;
}
else
{
sl = price + sl_pips * pip;
tp = price - tp_pips * pip;
}
sl = NormalizeDouble(sl, _Digits);
tp = NormalizeDouble(tp, _Digits);
return true;
}
6.4 StopLevel対応込みテンプレート(実務向け)
さらに安全性を高めるため、最低ストップ距離(StopLevel)を考慮します。
bool AdjustToStopLevel(double price, double &sl, double &tp)
{
int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
double min_distance = (stopLevel + 10) * _Point;
// SL距離チェック
if(MathAbs(price - sl) < min_distance)
{
if(sl < price)
sl = price - min_distance;
else
sl = price + min_distance;
}
// TP距離チェック
if(MathAbs(price - tp) < min_distance)
{
if(tp > price)
tp = price + min_distance;
else
tp = price - min_distance;
}
sl = NormalizeDouble(sl, _Digits);
tp = NormalizeDouble(tp, _Digits);
return true;
}
6.5 実際の注文コード(完全版)
void OpenTrade(bool isBuy)
{
double price = isBuy ?
SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl, tp;
// SL/TP計算
CalculateSLTP(isBuy, price, 20, 40, sl, tp);
// StopLevel調整
AdjustToStopLevel(price, sl, tp);
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.1;
request.type = isBuy ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 10;
if(!OrderSend(request, result))
{
Print("Order failed: ", result.retcode);
}
}
つまずきやすいポイント・注意点
■ SL/TPを関数外で直接書く
→ バグの温床
→ 必ず共通関数にまとめる
■ StopLevel未対応
→ 環境依存で突然エラー
→ 実運用では必須
■ pip変換を省略
→ 通貨ペア変更で崩壊
よくある失敗
- BUY/SELLの条件分岐ミス
- NormalizeDoubleを忘れる
- StopLevelを考慮しない
- 同一コードをコピペして分散管理
実務上のベストプラクティス
- SL/TPは関数化して再利用
- pipsベースで設計
- StopLevel + バッファを必ず入れる
- すべての価格をNormalizeDouble
7. 初心者向け:最短で動くシンプル実装(最小コード)
このセクションで書く要点
・余計な要素を削ぎ落とした最小構成
・まず動かすことを優先した実装
・どこを後で改善すべきか
7.1 最小構成の考え方
初心者はまず、「正しく動く最小コード」から始めるべきです。
最初から汎用化・最適化を行うと、以下の問題が起きます。
- エラー原因が特定できない
- ロジックが複雑化
- 学習コストが上がる
→ まずは「1通貨・固定pips・注文時設定」で十分です。
7.2 最小BUY注文コード(SL/TP付き)
#include <Trade/Trade.mqh>
void OnTick()
{
static bool executed = false;
if(executed) return;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
// 固定値(20pips / 40pips)
double sl = ask - 200 * _Point;
double tp = ask + 400 * _Point;
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.1;
request.type = ORDER_TYPE_BUY;
request.price = ask;
request.sl = NormalizeDouble(sl, _Digits);
request.tp = NormalizeDouble(tp, _Digits);
request.deviation = 10;
OrderSend(request, result);
executed = true;
}
7.3 このコードのポイント
- 1回だけ実行(static変数)
- SL/TPは固定値(まずは理解優先)
- NormalizeDoubleで整形
なぜ200・400なのか
- 5桁環境の場合
- 200 point = 20 pips
- 400 point = 40 pips
→ シンプルに「20pips / 40pips」を表現
7.4 この段階でやらなくていいこと
初心者は以下を無理に入れる必要はありません。
- 汎用関数化
- StopLevel調整
- トレーリングストップ
- 複雑な条件分岐
→ まずは「動くこと」が最優先
つまずきやすいポイント・注意点
■ 何度も注文される
→ OnTick は毎ティック実行
→ staticフラグで制御必須
■ SL/TPが逆方向
→ BUY:SL下・TP上
■ pointとpipsの混同
→ 200 = 20pips(5桁の場合)
■ デモ環境と実環境の違い
→ スプレッド・StopLevelが異なる
よくある失敗
- 無限に注文が発行される
- SL/TP未設定で注文
- 数値の意味を理解せずコピペ
- いきなり複雑なEAを作ろうとする
次にやるべき改善(ステップアップ)
このコードが理解できたら、次にやるべきは以下です。
- pips変換関数の導入
- StopLevel対応
- SELL対応
- PositionModifyの追加
8. SL/TP設計の戦略的考え方(EA設計)
このセクションで書く要点
・SL/TPは単なる設定値ではなく戦略設計そのもの
・期待値、再現性、ドローダウン管理との関係
・固定幅と動的幅の使い分け
8.1 SL/TPは「注文の付属設定」ではなく戦略本体
MQL5でSL(損切り)とTP(利確)を設定する場面では、つい「注文時に必要な値」として扱いがちです。
しかし実務では、SL/TPはエントリー条件と同じか、それ以上に重要な戦略パラメータです。
なぜなら、最終的な損益は以下の組み合わせで決まるからです。
- どこで入るか
- どこで切るか(SL)
- どこで利益確定するか(TP)
- 何ロットで入るか
このうち、SL/TPは損益分布を直接決める要素です。
エントリー精度が同じでも、SL/TP設計が違えば、PF(プロフィットファクター)やDD(ドローダウン)は大きく変わります。
例えば、同じBUYシグナルでも
- SL 10pips / TP 20pips
- SL 30pips / TP 30pips
- SL 50pips / TP 100pips
では、必要勝率も損益の揺れ方もまったく異なります。
8.2 リスクリワード比(RR)を先に決める
SL/TP設計で最初に考えるべきなのは、RR(Risk Reward Ratio:損失に対する利益の比率)です。
例
- SL 20pips / TP 40pips → RR 1:2
- SL 30pips / TP 30pips → RR 1:1
- SL 40pips / TP 20pips → RR 2:1
一般に、RRが高いほど1回の利益は大きくなりますが、利確到達率は下がりやすいです。
逆に、RRが低いほど勝率は上がりやすいものの、1回の負けの重みが増します。
実務上の見方
- 短期メリット
- RRを固定するとバックテスト比較がしやすい
- EAの設計が単純になる
- 長期メリット
- ロット管理と結びつけやすい
- 損益の再現性が上がる
初心者向けの目安
まずは以下のどちらかから始めると整理しやすいです。
- 保守型:1:1〜1:1.5
- 利益伸ばし型:1:2前後
ただし、正解は固定ではありません。
勝率、スプレッド、約定滑り、通貨ペア特性により最適値は変わります。
8.3 固定SL/TPと動的SL/TPの違い
SL/TP設計は大きく分けて2種類あります。
固定幅型
例:常にSL 20pips、TP 40pips
メリット
- 実装が簡単
- バックテスト比較が明確
- 初心者でも管理しやすい
デメリット
- 相場のボラティリティ変化に弱い
- 低ボラ時は遠すぎ、高ボラ時は近すぎることがある
動的型
例:ATR(平均的な値幅)に応じてSL/TPを変える
メリット
- 相場環境に適応しやすい
- 異常な近すぎSLを避けやすい
- 通貨ペアごとの差を吸収しやすい
デメリット
- 実装が複雑
- テスト条件を揃えにくい
- 初学者には原因分析が難しい
実務上の推奨順
- 最初は 固定幅型
- その後、必要に応じて ATR型などの動的型
この順番の方が、どこで成績が変わったのかを追いやすくなります。
8.4 PF・DDへの影響をどう見るか
SL/TPの設計は、見た目の勝率だけでなく、PFとDDの形に直結します。
固定SLが狭すぎる場合
- 小さなノイズで損切りされやすい
- 勝率低下
- 連敗が増えやすい
固定SLが広すぎる場合
- 勝率は見かけ上改善しやすい
- 1回の損失が重くなる
- DDが深くなりやすい
TPが近すぎる場合
- 小さな利益は取りやすい
- コスト(スプレッド・手数料)の影響を受けやすい
- PFが伸びにくい
TPが遠すぎる場合
- 一撃利益は大きい
- 到達率が下がる
- 利益のばらつきが大きくなる
つまり、SL/TPは「安全か危険か」の二択ではなく、損益分布をどう設計するかの問題です。
8.5 初心者が避けるべき設計ミス
■ 勝率だけで判断する
勝率70%でも、負け1回が勝ち3回分なら期待値は悪化します。
■ 通貨ペアを変えても同じ値幅を使う
EURUSDとGBPJPYでは値動き特性が違います。
固定pipsをそのまま流用すると、設計が崩れやすくなります。
■ SLだけ、またはTPだけを最適化する
片側だけ調整すると、全体のバランスを失います。
必ずセットで検証します。
■ バックテストの最良値をそのまま採用する
過度な最適化(過剰適合)により、将来の再現性が落ちることがあります。
8.6 実務でのおすすめ設計手順
SL/TP設計で迷う場合は、次の順で進めると整理しやすいです。
- まず固定SL/TPで試作する
- RRを1:1、1:1.5、1:2程度で比較する
- PF、DD、勝率を同時に見る
- 通貨ペアごとの差を確認する
- 必要ならATR連動に進む
この順なら、再現性を維持しながら改善できます。
つまずきやすいポイント・注意点
- RRが高ければ必ず有利、ではない
- 勝率が高ければ優秀、でもない
- 通貨ペアと時間足で最適値は変わる
- バックテスト最適値は将来も再現するとは限らない
よくある失敗
- 10pips刻みで雑に調整して終わる
- DDを見ずにPFだけで判断する
- 固定SLで負けた後すぐ動的SLへ逃げる
- そもそもリスク許容度を決めていない
9. MQL5のSL/TP設定チェックリストと最終整理
このセクションで書く要点
・実務でミスを防ぐチェック項目
・再現性を担保するための確認ポイント
・本記事の要点を短く整理
9.1 注文前チェックリスト(必須)
実務では、SL/TPの設定ミスは即損失または注文拒否に直結します。
以下のチェックをルーチン化することで、ほぼすべてのトラブルを防げます。
基本チェック
- SLとTPが0ではない
- BUY:SL < price < TP
- SELL:TP < price < SL
_Digitsに合わせて NormalizeDouble済み
距離チェック
- stopLevel以上の距離がある
- buffer(+10〜20point)を確保している
- スプレッドを考慮している
計算チェック
- pips → point変換済み
- 通貨ペアに依存しない設計
- ハードコード値を使っていない
9.2 実行後チェック(デバッグ)
注文が通っても、意図通りの値か確認する習慣が重要です。
ログ出力例
Print("price=", request.price,
" SL=", request.sl,
" TP=", request.tp);
確認ポイント
- 設定値が想定通りか
- 桁数が崩れていないか
- SL/TPの方向が正しいか
9.3 エラー発生時の確認手順
エラー時は感覚で修正せず、順序立てて確認します。
手順
result.retcodeを確認- SL/TPの価格をログ出力
- stopLevelを確認
- Ask/Bidとの位置関係を確認
例
Print("retcode=", result.retcode);
9.4 実務での最重要ルール(再現性重視)
SL/TP設定で最も重要なのは、再現性と一貫性です。
守るべきルール
- 必ず関数化する
- pipsベースで設計する
- NormalizeDoubleを徹底する
- stopLevel + bufferを前提にする
なぜ重要か
- 環境差(ブローカー差)を吸収できる
- バックテストと実運用の乖離を減らす
- バグの局所化ができる
9.5 本記事の要点整理
本記事の内容を、実務視点で簡潔にまとめます。
技術面
- SL/TPは「価格」で設定する
_Pointと_Digitsを正しく扱う- stopLevel違反はエラーの主因
実装面
- 注文時設定(OrderSend)が基本
- PositionModifyで後から変更可能
- 共通関数化でバグを防ぐ
戦略面
- SL/TPはリスク設計そのもの
- RR(リスクリワード)を先に決める
- 固定→動的の順で改善
9.6 最短で安定させるための結論
初心者〜中級者が最短で安定させるには、以下の構成が最適です。
- 固定pips(例:SL20 / TP40)
- 注文時にSL/TP設定
- stopLevel + buffer対応
- NormalizeDouble徹底
この状態でまず安定稼働させ、その後に最適化へ進むのが再現性の高い進め方です。
つまずきやすいポイント・注意点
- 一部だけ修正して全体の整合性が崩れる
- エラーを無視して進める
- 通貨ペア変更で破綻する設計
- バックテスト結果を過信する
よくある失敗
- SL/TP未設定で本番運用
- ログを見ずに原因不明のまま修正
- StopLevel無視でエラー連発
- 設計を固めずに最適化に進む
FAQ(よくある質問)
Q1. SL/TPは必ず設定すべきですか?
A. はい。未設定は損失無制限のリスクがあるため、実務では必須です。
Q2. invalid stopsエラーはどうすれば防げますか?
A. stopLevel以上の距離確保、方向の正しさ、NormalizeDoubleを徹底すればほぼ防げます。
Q3. pipsとpointの違いは何ですか?
A. pointは最小単位、pipsは慣習単位です。MQL5ではpoint基準で計算します。
Q4. 注文後にSL/TPを変更できますか?
A. 可能です。PositionModifyを使用します。
Q5. トレーリングストップとTPの違いは?
A. TPは固定利確、トレーリングはSLを動的に更新する仕組みです。
Q6. 最適なSL/TPはどう決めますか?
A. RR(リスクリワード)とバックテスト結果を基に、PFとDDのバランスで判断します。
Q7. 通貨ペアごとに設定は変えるべきですか?
A. はい。ボラティリティが異なるため、同一設定は非推奨です。