MQL5注文・ポジション・履歴管理完全ガイド|OrderSend・Position・Deal・Historyの基本
MQL5でEAを開発する時、注文を出す処理だけでなく、注文後のポジション確認、約定履歴、決済履歴、Magic Number、チケット番号、Order・Deal・Position・Historyの違いを理解しておくことが重要です。
EAがOrderSendやCTradeで注文を送った後、MT5内部では「注文」「約定」「ポジション」「履歴」が別の情報として扱われます。注文要求を送ったこと、注文が受け付けられたこと、約定したこと、現在ポジションとして残っていること、決済後に履歴へ移ったことは、それぞれ確認する場所が異なります。
この記事では、MQL5で注文・ポジション・履歴を管理する時に確認したい基本を整理します。Order、Deal、Position、History、OrderSend、CTrade、PositionSelect、PositionSelectByTicket、HistorySelect、HistoryOrderGet、HistoryDealGet、Magic Number、order ticket、deal ticket、position id、OnTradeTransaction、Hedging / Netting、ログ設計、バックテスト時の確認までを実務目線でまとめます。
なお、この記事はMT5 / MQL5のEA開発、注文管理、ポジション管理、履歴確認、ログ確認を目的とした技術記事です。特定の売買判断、利益、勝率、損失回避、推奨ロット、推奨銘柄を案内するものではありません。
- この記事で確認すること
- MQL5の注文管理で混同しやすい4つの要素
- OrderSend後に確認すること
- MqlTradeRequestとMqlTradeResultを分けて見る
- CTrade利用時も結果確認は必要
- CTradeで注文・決済・変更を実装する
- Positionとは何か
- PositionSelectとPositionSelectByTicket
- Magic Numberで自EAの対象だけを抽出する
- Dealとは何か
- HistorySelectで履歴を確認する
- HistoryOrdersとHistoryDealsを分けて見る
- order ticket・deal ticket・position ticket・position id の違い
- OnTradeTransactionで取引イベントを追う
- Hedging口座とNetting口座の違いに注意する
- 決済後に履歴を確認する
- 注文・ポジション・履歴のログ設計
- バックテストで履歴管理を確認する
- CTradeの口座条件・イベント・検証を確認する
- よくある不具合と確認ポイント
- 開発依頼前に整理する情報
- 注文・ポジション・履歴管理の実務チェック表
- よくある質問
- 関連する確認ページ
- あわせて確認したいページ
- まとめ
- お問い合わせはEAFC公式LINEへ
- 利用条件・相談窓口
この記事で確認すること
- Order・Deal・Position・Historyの違い
- OrderSend後に確認するretcode、order、deal、comment
- CTrade利用時のResultRetcode確認
- PositionSelectとPositionSelectByTicketの使い分け
- HistorySelectで注文履歴・約定履歴を確認する考え方
- order ticket、deal ticket、position ticket、position id の違い
- Magic Numberで自EAの対象だけを抽出する方法
- Hedging口座とNetting口座の違い
- 決済後に履歴を追跡する方法
- OnTradeTransactionで注文・約定イベントを確認する方法
- 注文・約定・ポジション・履歴のログ設計
- バックテストで履歴確認する時の注意点
- 開発依頼前に整理する情報
MQL5の注文管理で混同しやすい4つの要素
MQL5の注文管理では、Order、Deal、Position、Historyを分けて考える必要があります。MT4に慣れている場合や、EAを初めて作る場合は、この違いで混乱しやすくなります。
注文要求を送った時点ではOrderが中心になります。実際に売買が成立するとDealが発生します。約定によって現在保有している建玉がPositionとして扱われます。決済済みの注文や約定はHistoryから確認します。
EA開発では、「注文を送った」「約定した」「ポジションが残っている」「履歴へ移った」を同じものとして扱わないことが重要です。たとえば、OrderSendの戻り値がtrueに見えても、実際の約定やポジション状態は別途確認する必要があります。
| 要素 | 意味 | 確認する場面 |
|---|---|---|
| Order | 注文です。成行、指値、逆指値などの注文要求や未約定注文を扱います。 | 注文を送ったか、未約定注文が残っているか、注文番号を確認する時。 |
| Deal | 約定です。実際に売買が成立した記録です。 | どの価格で約定したか、どのロットが成立したか、決済損益を確認する時。 |
| Position | 現在保有中のポジションです。 | 現在の建玉、ロット、建値、SL/TP、損益、対象チケットを確認する時。 |
| History | 過去の注文や約定の履歴です。 | 決済済み取引、過去注文、約定履歴、検証結果を確認する時。 |
OrderSend後に確認すること
MQL5のOrderSend()がtrueを返しても、売買処理そのものが完了したことを意味しません。まずMqlTradeResult.retcodeを確認し、必要に応じてOnTradeTransactionで後続のorder・deal・position変化を追います。
OrderSendを使った場合、MqlTradeRequestで注文要求を作り、MqlTradeResultで注文送信結果を受け取ります。ここで確認すべきなのは、OrderSendの戻り値だけではありません。result.retcode、result.order、result.deal、result.comment、GetLastErrorを確認します。
OrderSendを呼び出したとしても、注文が約定したとは限りません。注文が拒否された、価格が不正、SL/TP距離が不正、証拠金不足、取引不可、ロット不正、約定方式が合わないなど、さまざまな理由で失敗することがあります。
注文処理のログでは、「何を注文しようとしたか」と「注文結果がどうだったか」を分けて残します。注文方向、ロット、価格、SL/TP、Magic Number、retcode、order ticket、deal ticket、commentを確認できるようにしておくと、バックテストや不具合調査で原因を追いやすくなります。
bool SendBuyOrder(double lots)
{
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lots;
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.magic = 123456;
ResetLastError();
bool ok = OrderSend(request, result);
PrintFormat("ORDER_SEND ok=%s retcode=%d order=%I64u deal=%I64u last_error=%d comment=%s",
ok ? "true" : "false",
result.retcode,
result.order,
result.deal,
GetLastError(),
result.comment);
return ok;
}この例では、OrderSendの戻り値、retcode、order、deal、GetLastError、commentをログに出しています。実務では、これに加えて、注文前チェックのログ、ロット、価格、SL/TP、Magic Number、銘柄、時間足、発注理由も必要に応じて記録します。
MqlTradeRequestとMqlTradeResultを分けて見る
OrderSendを読む時は、MqlTradeRequestとMqlTradeResultを分けて確認します。MqlTradeRequestは、EAが送ろうとした注文要求です。MqlTradeResultは、送信後に返ってきた結果です。
注文できない時に、request側が間違っているのか、result側で拒否されているのかを分けないと、原因を追いにくくなります。たとえば、volumeが銘柄仕様に合っていない、SL/TPが近すぎる、priceの扱いがBUY / SELLで逆になっている、type_fillingが合っていない、といった問題はrequest側で確認します。
| 区分 | 主な項目 | 確認ポイント |
|---|---|---|
| MqlTradeRequest | action、symbol、volume、type、price、sl、tp、magic、comment。 | EAがどの注文を送ろうとしたか確認します。 |
| MqlTradeResult | retcode、order、deal、volume、price、bid、ask、comment。 | 注文送信後に何が返ったか確認します。 |
| GetLastError | MQL関数側のエラー情報。 | retcodeとは別に確認します。 |
| Expertsログ | EA側のログ。 | シグナル、発注前チェック、注文結果を確認します。 |
| Journalログ | MT5側のログ。 | 取引許可、接続、プラットフォーム側の状態を確認します。 |
CTrade利用時も結果確認は必要
CTradeを使う場合、Buy、Sell、PositionClose、PositionModifyなどのメソッドで注文や決済を行えます。ただし、CTradeを使っても結果確認は必要です。BuyやSellの戻り値だけで判断せず、ResultRetcode、ResultRetcodeDescription、ResultOrder、ResultDeal、GetLastErrorを確認します。
CTradeは注文処理を読みやすく整理できますが、発注前チェックや対象ポジション確認を自動で十分に行ってくれるわけではありません。EA側で、スプレッド、ロット、証拠金、SL/TP距離、Magic Number、最大ポジション数を確認してください。
#include <Trade/Trade.mqh>
CTrade trade;
bool TrySell(double lots)
{
ResetLastError();
bool ok = trade.Sell(lots, _Symbol);
PrintFormat("CTRADE_SELL ok=%s retcode=%d desc=%s order=%I64u deal=%I64u last_error=%d",
ok ? "true" : "false",
trade.ResultRetcode(),
trade.ResultRetcodeDescription(),
trade.ResultOrder(),
trade.ResultDeal(),
GetLastError());
return ok;
}CTradeで注文した後は、ResultRetcodeだけでなく、ResultOrderとResultDealも確認すると、注文と約定の追跡がしやすくなります。決済や変更でも同様に、PositionCloseやPositionModifyの戻り値だけで判断しないようにします。
CTradeで注文・決済・変更を実装する
以下のコード例は、個別の処理と確認項目を読むためのものです。複数の例をそのまま一つのEAへ連結する前提ではありません。初期化、値の取得、状態更新、終了処理をそれぞれの例で区別して確認してください。
CTradeとは
CTradeは、MQL5標準ライブラリに含まれる取引用クラスです。成行注文、指値注文、逆指値注文、決済、注文変更、ポジション変更などを、関数呼び出しで扱いやすくするために用意されています。
MQL5では、MqlTradeRequestとMqlTradeResultを使って注文リクエストを直接組み立てる方法があります。一方、CTradeを使うと、Buy、Sell、PositionClose、PositionModifyのようなメソッドを使って、基本的な注文処理を簡潔に書けます。
ただし、CTradeは発注処理を簡略化するためのクラスであり、EAの設計そのものを代わりに行ってくれるものではありません。注文前の条件確認、ロット計算、証拠金確認、スプレッド確認、SL/TP距離確認、ログ設計はEA側で行います。
| 方法 | 特徴 | 向いている用途 |
|---|---|---|
| CTrade | 標準ライブラリのメソッドで注文処理を書けます。 | 基本的なEA注文処理、保守性重視の実装。 |
| MqlTradeRequest | 注文リクエストを細かく指定できます。 | 詳細制御、特殊注文、低レベル確認。 |
| OrderCheck | 注文前に証拠金や取引条件を確認できます。 | 発注前チェック、invalid stops対策。 |
| OnTradeTransaction | 取引イベントを追跡できます。 | 約定、決済、注文変更のログ確認。 |
CTradeを使う前に設計を分ける
CTradeはexecution、つまり注文実行の責務に置くのが基本です。シグナル判定、フィルター、リスク確認、注文実行をすべてCTrade周辺に混ぜてしまうと、注文しない理由を追いにくくなります。
EA設計では、signal、filter、risk、executionを分けます。signalは買い候補・売り候補を返します。filterはスプレッドや時間帯などの取引環境を確認します。riskはロット、証拠金、StopLevel、SL/TP距離を確認します。executionは、CTradeで注文を送る責務です。
この分離により、CTrade.Buyが呼ばれなかった理由が明確になります。シグナルがなかったのか、フィルターで止まったのか、riskで止まったのか、CTradeのretcodeで失敗したのかを分けてログ確認できます。
#include <Trade/Trade.mqh>
CTrade trade;
void OnTick()
{
if(!IsNewBar(_Symbol, PERIOD_CURRENT))
return;
int signal = EvaluateEntrySignal();
if(signal == 0)
{
Print("ENTRY_SKIP reason=NO_SIGNAL");
return;
}
if(!PassEntryFilters(signal))
return;
if(!CheckEntryRisk(signal))
return;
ExecuteEntryByCTrade(signal);
}この例では、OnTickの中で直接CTrade.BuyやCTrade.Sellを書かず、最後にExecuteEntryByCTradeへ渡しています。CTradeは注文実行部分に限定し、判定やリスク確認とは分けます。
CTradeを使う基本準備
CTradeを使うには、標準ライブラリのTrade.mqhをincludeし、CTrade型のインスタンスを用意します。EA全体で使う場合は、グローバルにCTrade trade; のように宣言しておくことが多いです。
また、EAで注文する場合は、Magic Numberや許容スリッページを明確に設定しておくと管理しやすくなります。Magic Numberは、複数EAや裁量注文と区別するために重要です。
#include <Trade/Trade.mqh>
input long InpMagicNumber = 935001;
input int InpDeviationPoints = 20;
CTrade trade;
int OnInit()
{
trade.SetExpertMagicNumber(InpMagicNumber);
trade.SetDeviationInPoints(InpDeviationPoints);
PrintFormat("INIT_CTRADE magic=%I64d deviation=%d",
InpMagicNumber,
InpDeviationPoints);
return INIT_SUCCEEDED;
}この例では、OnInitでMagic Numberと許容スリッページを設定しています。注文前に毎回設定しても動作しますが、EA全体の初期化時にログへ残しておくと確認しやすくなります。
Buyで買い注文を送る
CTradeのBuyは、買いの成行注文を送るために使います。基本的には、ロット、銘柄、価格、SL、TP、コメントを指定できます。価格を0にすると、通常は現在のAskを使う形で処理されます。
ただし、Buyを呼ぶ前に、取引許可、スプレッド、ロット、証拠金、StopLevel、最大ポジション数などを確認する必要があります。Buyの呼び出しだけを見て「発注処理は完成」と考えるのは危険です。
bool ExecuteBuy(double volume, double sl, double tp)
{
ResetLastError();
bool result = trade.Buy(volume,
_Symbol,
0.0,
sl,
tp,
"EA_BUY");
PrintFormat("CTRADE_BUY result=%s retcode=%d deal=%I64u order=%I64u comment=%s last_error=%d",
result ? "Y" : "N",
trade.ResultRetcode(),
trade.ResultDeal(),
trade.ResultOrder(),
trade.ResultComment(),
GetLastError());
return result;
}この例では、Buyの戻り値だけでなく、ResultRetcode、ResultDeal、ResultOrder、ResultComment、GetLastErrorをログに出しています。注文処理の調査では、戻り値だけでなくretcodeとcommentを確認することが重要です。
Sellで売り注文を送る
CTradeのSellは、売りの成行注文を送るために使います。Buyと同様に、ロット、銘柄、価格、SL、TP、コメントを指定できます。売り注文では、現在のBid側を基準に考えるため、SL/TPの価格方向を間違えないようにします。
買いと売りでSL/TPの位置関係は逆になります。BUYではSLが現在価格より下、TPが上になることが多く、SELLではSLが現在価格より上、TPが下になることが多いです。この方向を誤ると、invalid stopsの原因になります。
bool ExecuteSell(double volume, double sl, double tp)
{
ResetLastError();
bool result = trade.Sell(volume,
_Symbol,
0.0,
sl,
tp,
"EA_SELL");
PrintFormat("CTRADE_SELL result=%s retcode=%d deal=%I64u order=%I64u comment=%s last_error=%d",
result ? "Y" : "N",
trade.ResultRetcode(),
trade.ResultDeal(),
trade.ResultOrder(),
trade.ResultComment(),
GetLastError());
return result;
}BuyとSellは似ていますが、価格方向、SL/TP方向、スプレッド、注文条件を分けて確認します。ログ名もCTRADE_BUY、CTRADE_SELLのように分けておくと、あとから検索しやすくなります。
SL/TP価格を作る時の注意
CTradeでBuyやSellを使う時、SLとTPを指定する場合は、価格方向とStopLevelを確認します。銘柄によってpoint、digits、StopLevel、FreezeLevelが異なるため、固定値だけでSL/TPを作ると注文失敗の原因になります。
特に、XAUUSD、指数、仮想通貨CFDなどでは、通貨ペアと価格桁やpointの感覚が違う場合があります。SL/TPをpips感覚で固定すると、実際の価格距離がブローカー条件に合わないことがあります。
bool BuildStopsForMarketOrder(int signal, double stop_points, double take_points, double &sl, double &tp)
{
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(point <= 0.0 || bid <= 0.0 || ask <= 0.0)
{
Print("STOPS_FAIL reason=BAD_MARKET_PRICE");
return false;
}
if(signal > 0)
{
sl = NormalizeDouble(ask - stop_points * point, digits);
tp = NormalizeDouble(ask + take_points * point, digits);
}
else if(signal < 0)
{
sl = NormalizeDouble(bid + stop_points * point, digits);
tp = NormalizeDouble(bid - take_points * point, digits);
}
else
{
Print("STOPS_FAIL reason=NO_SIGNAL");
return false;
}
PrintFormat("STOPS_BUILT signal=%d sl=%.5f tp=%.5f", signal, sl, tp);
return true;
}この例では、BUYとSELLでSL/TPの方向を分けています。実務では、この後にStopLevelやFreezeLevelを確認し、必要ならOrderCheckで最終確認します。
PositionCloseでポジションを決済する
CTradeのPositionCloseは、保有ポジションを決済するために使います。銘柄指定で決済する方法や、チケットを指定して決済する方法があります。Hedging口座とNetting口座では、ポジションの扱いが異なるため、どのポジションを閉じるのかを明確にします。
単一ポジション前提のEAでは、_Symbolを指定してPositionCloseする設計でも扱いやすい場合があります。一方で、複数ポジション、複数EA、複数Magic Numberを扱う場合は、ポジション選択とMagic Number確認を慎重に行う必要があります。
bool CloseCurrentSymbolPosition()
{
if(!PositionSelect(_Symbol))
{
PrintFormat("POSITION_CLOSE_SKIP reason=NO_POSITION symbol=%s", _Symbol);
return false;
}
ResetLastError();
bool result = trade.PositionClose(_Symbol);
PrintFormat("CTRADE_POSITION_CLOSE result=%s retcode=%d deal=%I64u order=%I64u comment=%s last_error=%d",
result ? "Y" : "N",
trade.ResultRetcode(),
trade.ResultDeal(),
trade.ResultOrder(),
trade.ResultComment(),
GetLastError());
return result;
}この例では、対象銘柄のポジションがある場合だけPositionCloseを呼んでいます。決済できない場合も、ResultRetcodeとResultCommentを残すことで原因確認がしやすくなります。
PositionModifyでSL/TPを変更する
CTradeのPositionModifyは、保有ポジションのSL/TPを変更するために使います。トレーリングストップ、建値移動、利益確保、損切り位置変更などで使われます。
SL/TP変更では、FreezeLevelやStopLevelに注意が必要です。価格に近すぎる変更は拒否される場合があります。また、変更処理を毎ティックで実行するとログが増え、無駄な変更リクエストが増えるため、必要な時だけ実行する設計にします。
bool ModifyPositionStops(double new_sl, double new_tp)
{
if(!PositionSelect(_Symbol))
{
PrintFormat("POSITION_MODIFY_SKIP reason=NO_POSITION symbol=%s", _Symbol);
return false;
}
ResetLastError();
bool result = trade.PositionModify(_Symbol, new_sl, new_tp);
PrintFormat("CTRADE_POSITION_MODIFY result=%s retcode=%d sl=%.5f tp=%.5f comment=%s last_error=%d",
result ? "Y" : "N",
trade.ResultRetcode(),
new_sl,
new_tp,
trade.ResultComment(),
GetLastError());
return result;
}PositionModifyは便利ですが、価格距離や変更頻度を確認しないと失敗しやすい処理です。トレーリングや建値移動を入れる場合は、現在SLとの差、最小変更幅、変更済みフラグを管理すると安定しやすくなります。
SetExpertMagicNumberでEAを識別する
Magic Numberは、EAが出した注文やポジションを識別するための番号です。複数EAを同じ口座で動かす場合や、裁量注文とEA注文を分ける場合に重要です。
CTradeでは、SetExpertMagicNumberでMagic Numberを設定できます。これを設定しておくと、CTradeから送る注文にMagic Numberを付けられます。ただし、保有ポジションを確認する時は、PositionGetInteger(POSITION_MAGIC)などでMagic Numberを確認する必要があります。
input long InpMagicNumber = 935001;
int OnInit()
{
trade.SetExpertMagicNumber(InpMagicNumber);
PrintFormat("MAGIC_SET magic=%I64d", InpMagicNumber);
return INIT_SUCCEEDED;
}Magic Numberは、EAごと、戦略ごと、銘柄グループごとに分けることがあります。後からポジション管理やログ確認をしやすくするため、設計段階でルールを決めておくことが重要です。
SetDeviationInPointsと許容スリッページ
SetDeviationInPointsは、注文時に許容する価格ずれをpoints単位で設定するために使います。相場状況や銘柄によっては、注文リクエスト時の価格と約定価格がずれることがあります。
許容値を小さくしすぎると、注文が通りにくくなる場合があります。大きくしすぎると、想定より不利な価格で約定する可能性があります。銘柄、時間帯、スプレッド、EAの目的に応じて設定します。
input int InpDeviationPoints = 20;
int OnInit()
{
trade.SetDeviationInPoints(InpDeviationPoints);
PrintFormat("DEVIATION_SET points=%d", InpDeviationPoints);
return INIT_SUCCEEDED;
}許容スリッページは、注文成功率と約定価格のバランスに関係します。バックテストだけで判断せず、デモ口座や実チャートで注文結果ログを確認してください。
CTradeで指値・逆指値と注文設定を扱う
CTradeでは、BuyやSellによる成行注文だけでなく、指値・逆指値の予約注文も扱えます。また、銘柄ごとの注文履行方式や、取引処理を同期・非同期のどちらで扱うかも設定できます。
| メソッド | 主な用途 | 確認ポイント |
|---|---|---|
| BuyLimit / SellLimit | 買い指値・売り指値の予約注文を出す | 注文価格、SL/TP、注文有効期限、銘柄仕様を確認します。 |
| BuyStop / SellStop | 買い逆指値・売り逆指値の予約注文を出す | 現在価格との位置関係、stops level、注文有効期限を確認します。 |
| SetTypeFillingBySymbol | 銘柄設定に応じた注文履行方式を設定する | ブローカーや銘柄によって許可されるFilling方式が異なる場合に確認します。 |
| SetAsyncMode | 取引処理の非同期モードを設定する | 非同期モードでは取引サーバーの応答を待たずに処理が進むため、結果確認の流れを別途設計します。 |
| ResultRetcodeDescription | 直近の取引結果コードを文字列で確認する | ResultRetcodeとあわせてログへ残すと、結果を確認しやすくなります。 |
予約注文メソッドが正常終了を返しても、取引サーバー側で注文が成立したことまで保証するものではありません。成行注文と同様に、ResultRetcode、ResultOrder、ResultCommentなどを確認し、注文結果をログへ残してください。
ResultRetcodeを必ず確認する
CTradeの注文メソッドはboolを返しますが、注文結果を確認する時はboolだけで判断しない方が安全です。ResultRetcode、ResultDeal、ResultOrder、ResultCommentを確認することで、注文がどう処理されたかを追いやすくなります。
注文が失敗した場合、retcodeやcommentに原因が出ることがあります。たとえば、取引不可、証拠金不足、無効な価格、無効なSL/TP、マーケットクローズ、リクオート、取引量不正などです。
| 確認項目 | 内容 | 目的 |
|---|---|---|
ResultRetcode() | 注文結果コード。 | 成功・失敗理由の確認。 |
ResultDeal() | 約定deal番号。 | 約定確認。 |
ResultOrder() | 注文番号。 | 注文追跡。 |
ResultComment() | ブローカーやサーバーからのコメント。 | 失敗理由の確認。 |
GetLastError() | MQL側の直近エラー。 | 関数呼び出し失敗の確認。 |
void PrintCTradeResult(string action_name, bool result)
{
PrintFormat("%s result=%s retcode=%d deal=%I64u order=%I64u comment=%s last_error=%d",
action_name,
result ? "Y" : "N",
trade.ResultRetcode(),
trade.ResultDeal(),
trade.ResultOrder(),
trade.ResultComment(),
GetLastError());
}注文処理ごとに同じ形式でログを出すと、Buy、Sell、PositionClose、PositionModifyの結果を比較しやすくなります。
OrderCheckとCTradeの役割分担
CTradeは注文を送るためのクラスですが、発注前の確認をすべて代替するものではありません。証拠金、ロット、StopLevel、SL/TP距離などを事前に確認したい場合は、OrderCheckやSymbolInfoを組み合わせます。
OrderCheckは、注文リクエストが通りそうかを事前に確認するために使います。CTradeで注文する前に、同等のMqlTradeRequestを作ってOrderCheckする設計もあります。特に、証拠金不足やinvalid stopsを減らしたい場合は、OrderCheckを使った発注前チェックが有効です。
実務では、risk責務でロットやSL/TP距離を確認し、必要に応じてOrderCheckを行い、通過したらexecution責務でCTradeを呼び出す構成にすると整理しやすくなります。
| 処理 | 役割 | 配置する責務 |
|---|---|---|
| SymbolInfo | 銘柄仕様を取得します。 | risk / init。 |
| OrderCalcMargin | 必要証拠金を概算します。 | risk。 |
| OrderCheck | 注文前にリクエストを確認します。 | risk。 |
| CTrade.Buy / Sell | 注文を送信します。 | execution。 |
| ResultRetcode | 注文結果を確認します。 | execution / log。 |
| OnTradeTransaction | 取引イベントを追跡します。 | log / notification。 |
Positionとは何か
Positionは、現在保有している建玉を表します。EAが現在のポジションを確認する時は、PositionSelect、PositionSelectByTicket、PositionGetInteger、PositionGetDouble、PositionGetStringなどを使います。
現在ポジションを確認する時は、単に「ポジションがあるか」だけでなく、銘柄、Magic Number、方向、チケット、ロット、建値、SL/TP、損益を確認します。複数EAや手動ポジションが混在する環境では、Magic Numberと銘柄で対象を絞ることが重要です。
特に、EAが注文しない、重複発注する、誤って決済する、手動ポジションまで触る、といった問題は、Positionの対象範囲が曖昧な時に起きやすくなります。ポジション管理では、必ず「このEAが管理すべき対象か」を確認してください。
| 確認項目 | 見る内容 | 注意点 |
|---|---|---|
| POSITION_TICKET | ポジションのチケット番号。 | 決済や変更対象の特定に使います。 |
| POSITION_SYMBOL | 対象銘柄。 | 複数銘柄EAでは必ず確認します。 |
| POSITION_MAGIC | Magic Number。 | 自EAのポジションだけを抽出します。 |
| POSITION_TYPE | BUY / SELL方向。 | 決済条件や反対売買判定に使います。 |
| POSITION_VOLUME | 保有ロット。 | 部分決済や最大保有数確認に使います。 |
| POSITION_PRICE_OPEN | 建値。 | 建値移動、損益計算、トレーリングに使います。 |
| POSITION_SL / POSITION_TP | 設定中のSL / TP。 | 変更処理や安全確認に使います。 |
| POSITION_PROFIT | 現在損益。 | 決済条件や状態表示に使います。 |
PositionSelectとPositionSelectByTicket
PositionSelectは、指定した銘柄の現在ポジションを選択する時に使います。PositionSelectByTicketは、チケット番号を指定してポジションを選択する時に使います。EAの構造によって、どちらを使うべきかが変わります。
単一銘柄・単一ポジション前提のEAではPositionSelectで足りる場合があります。一方、複数ポジション、複数銘柄、Hedging口座、個別チケット決済を扱うEAでは、PositionSelectByTicketで対象を明確にする方が安全です。
PositionSelectで取得できたとしても、そのポジションが自EAの対象とは限りません。取得後にPOSITION_MAGICとPOSITION_SYMBOLを確認し、対象外であれば処理しないようにします。
void PrintCurrentPosition(string symbol)
{
if(!PositionSelect(symbol))
{
PrintFormat("POSITION_NONE symbol=%s", symbol);
return;
}
ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
long magic = PositionGetInteger(POSITION_MAGIC);
long type = PositionGetInteger(POSITION_TYPE);
double volume = PositionGetDouble(POSITION_VOLUME);
double profit = PositionGetDouble(POSITION_PROFIT);
PrintFormat("POSITION_FOUND symbol=%s ticket=%I64u magic=%d type=%d volume=%.2f profit=%.2f",
symbol,
ticket,
magic,
type,
volume,
profit);
}この例では、指定銘柄のポジションを選択し、チケット、Magic Number、方向、ロット、損益をログに出しています。実際のEAでは、このポジションが自EAの対象かどうかをMagic Numberで確認してください。
Magic Numberで自EAの対象だけを抽出する
Magic Numberは、EAごとの注文やポジションを識別するために使います。複数EA、複数チャート、手動ポジションが混在する場合、Magic Numberを確認しないと、他EAのポジションを数えたり、決済したりする可能性があります。
EAで最大ポジション数を確認する場合、PositionsTotalだけを見るのではなく、対象銘柄とMagic Numberに一致するポジションだけを数える必要があります。PositionsTotalは口座全体のポジション数として扱われるため、自EAの保有数とは一致しないことがあります。
int CountMyPositions(string symbol, ulong magic)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
if(!PositionSelectByTicket(ticket))
continue;
string pos_symbol = PositionGetString(POSITION_SYMBOL);
long pos_magic = PositionGetInteger(POSITION_MAGIC);
if(pos_symbol == symbol && (ulong)pos_magic == magic)
count++;
}
PrintFormat("POSITION_SCOPE symbol=%s magic=%I64u count=%d",
symbol,
magic,
count);
return count;
}このように、ポジション数を確認する時は、対象範囲をログに残すと安全です。特に、複数EA、コピーEA、半裁量EA、裁量補助パネルでは、対象外ポジションを誤って扱わないことが重要です。
Dealとは何か
Dealは、実際に約定した記録です。注文を送っただけではDealが発生しない場合があります。成行注文が約定した時、指値注文が約定した時、決済が成立した時などにDealとして履歴に残ります。
EAの履歴確認では、Dealの方向、約定価格、ロット、損益、手数料、スワップ、Magic Number、コメントなどを確認します。注文が成功したかどうかだけでなく、どの価格で約定し、どの履歴として残ったかを見ることが重要です。
決済後にポジションが消えていても、Deal履歴を確認しなければ、どの価格で決済されたのか、手数料やスワップを含めた損益がどうだったのか、EAによる決済なのか手動決済なのかを追いにくくなります。
| 確認項目 | 内容 | 使いどころ |
|---|---|---|
| DEAL_TICKET | Dealのチケット番号。 | 約定履歴の識別に使います。 |
| DEAL_ORDER | 関連する注文番号。 | 注文と約定の対応確認に使います。 |
| DEAL_POSITION_ID | 関連するポジションID。 | ポジション単位の追跡に使います。 |
| DEAL_SYMBOL | 対象銘柄。 | 複数銘柄の履歴確認に使います。 |
| DEAL_MAGIC | Magic Number。 | 自EAの約定だけを抽出します。 |
| DEAL_TYPE | BUY / SELLなどの約定種別。 | エントリー・決済の方向確認に使います。 |
| DEAL_ENTRY | エントリーか決済かなどの区分。 | IN / OUT / INOUTの確認に使います。 |
| DEAL_VOLUME | 約定ロット。 | 部分決済や分割約定の確認に使います。 |
| DEAL_PRICE | 約定価格。 | 想定価格との差を確認する時に使います。 |
| DEAL_PROFIT | 約定損益。 | 決済結果の確認に使います。 |
HistorySelectで履歴を確認する
HistorySelectは、指定した期間の履歴を選択するために使います。過去の注文や約定を確認するには、まずHistorySelectで期間を指定し、その後、HistoryOrdersTotalやHistoryDealsTotalで件数を確認します。
履歴確認では、期間指定が重要です。期間が狭すぎると対象履歴が取れず、広すぎると不要な履歴まで含まれて確認しにくくなります。バックテストや不具合調査では、発生時刻の前後を含めて期間指定するのが基本です。
また、HistorySelectで履歴を選択した後は、注文履歴と約定履歴を分けて確認します。注文履歴はHistoryOrderGet系、約定履歴はHistoryDealGet系で確認します。OrderとDealを混同すると、注文は存在するが約定していない状態や、約定は存在するが現在ポジションはない状態を誤って判断することがあります。
void PrintRecentDeals(datetime from_time, datetime to_time, ulong magic)
{
if(!HistorySelect(from_time, to_time))
{
PrintFormat("HISTORY_SELECT_FAIL from=%s to=%s last_error=%d",
TimeToString(from_time),
TimeToString(to_time),
GetLastError());
return;
}
int total = HistoryDealsTotal();
PrintFormat("HISTORY_DEALS total=%d from=%s to=%s",
total,
TimeToString(from_time),
TimeToString(to_time));
for(int i = 0; i < total; i++)
{
ulong deal_ticket = HistoryDealGetTicket(i);
if(deal_ticket == 0)
continue;
long deal_magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
if((ulong)deal_magic != magic)
continue;
string symbol = HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
double volume = HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
double profit = HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
long type = HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
PrintFormat("DEAL_FOUND ticket=%I64u symbol=%s magic=%I64d type=%d volume=%.2f profit=%.2f",
deal_ticket,
symbol,
deal_magic,
type,
volume,
profit);
}
}この例では、指定期間のDeal履歴から、Magic Numberが一致する約定だけをログに出しています。実務では、銘柄、position id、deal entry、deal reason、手数料、スワップなども必要に応じて確認します。
HistoryOrdersとHistoryDealsを分けて見る
履歴確認では、HistoryOrdersとHistoryDealsを分けて見ます。注文履歴は、過去に出された注文の情報を確認するために使います。約定履歴は、実際に成立した売買の情報を確認するために使います。
たとえば、指値注文を出したが約定せずにキャンセルされた場合、注文履歴には残ってもDealとしては残らないことがあります。逆に、成行注文が約定した場合は、OrderとDealの両方を追う必要があります。
| 履歴種別 | 主な確認関数 | 見る内容 |
|---|---|---|
| 注文履歴 | HistoryOrdersTotal、HistoryOrderGetTicket、HistoryOrderGetInteger、HistoryOrderGetDouble、HistoryOrderGetString。 | 過去注文、注文種別、注文状態、価格、ロット、Magic Number。 |
| 約定履歴 | HistoryDealsTotal、HistoryDealGetTicket、HistoryDealGetInteger、HistoryDealGetDouble、HistoryDealGetString。 | 約定、約定価格、約定ロット、損益、手数料、スワップ、Magic Number。 |
| 現在ポジション | PositionsTotal、PositionGetTicket、PositionSelectByTicket、PositionGetInteger。 | 現在保有中のポジション、ロット、建値、SL/TP、損益。 |
| 取引イベント | OnTradeTransaction。 | 注文追加、約定、履歴追加、ポジション変化など。 |
order ticket・deal ticket・position ticket・position id の違い
MQL5では、order ticket、deal ticket、position ticket、position id を混同しないことが重要です。注文番号、約定番号、ポジションの識別番号、ポジション単位のIDは役割が異なります。ログでこれらを分けて残しておくと、注文後の追跡がしやすくなります。
不具合調査では、「注文番号はあるがDealがない」「Dealはあるが現在Positionがない」「PositionはないがHistoryには残っている」といった状態を分けて確認します。ログにorder、deal、positionを同じ名前で出してしまうと、後から混乱しやすくなります。
| 項目 | 意味 | 使いどころ |
|---|---|---|
| order ticket | 注文の識別番号です。 | 注文要求や未約定注文を追う時に使います。 |
| deal ticket | 約定の識別番号です。 | 実際の売買成立記録を追う時に使います。 |
| position ticket | 現在ポジションの識別番号です。 | 決済や変更対象を指定する時に使います。 |
| position id | ポジション単位で履歴を追うための識別情報です。 | 注文・約定・ポジションの関連確認に使います。 |
| Magic Number | EA識別用の番号です。 | 自EA対象の注文・約定・ポジションを抽出します。 |
OnTradeTransactionで取引イベントを追う
OnTradeTransactionは、注文、約定、ポジション変化などの取引イベントを受け取るためのイベント関数です。注文処理後に何が起きたかをリアルタイムに追いたい場合に役立ちます。
OrderSendやCTradeの結果ログだけでは、注文後のイベントを十分に追えないことがあります。OnTradeTransactionを使うと、注文追加、約定、履歴追加、ポジション変化などのイベントをログ化できます。
ただし、OnTradeTransactionのログは多くなりやすいため、常時すべてを詳細出力するとExpertsログが読みにくくなります。開発時、検証時、異常時でログ粒度を切り替える設計が現実的です。
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
PrintFormat("TRADE_TRANSACTION type=%d order=%I64u deal=%I64u position=%I64u symbol=%s retcode=%d",
trans.type,
trans.order,
trans.deal,
trans.position,
trans.symbol,
result.retcode);
}OnTradeTransactionを使う場合は、trans.type、trans.order、trans.deal、trans.position、trans.symbol、result.retcodeを確認します。必要に応じて、注文追加、約定追加、履歴追加などのイベント種別ごとにログを分けてください。
Hedging口座とNetting口座の違いに注意する
MT5では、口座タイプによってポジションの扱いが異なる場合があります。Hedging口座では同一銘柄に複数ポジションを持てることがあり、Netting口座では同一銘柄のポジションが集約されることがあります。
EAでポジション管理を行う場合、口座タイプの違いを考慮しないと、ポジション数、決済対象、反対売買、履歴確認で想定と違う動きになることがあります。複数ポジションや部分決済を扱うEAでは、特に注意してください。
開発依頼や検証時には、対象口座がHedgingなのかNettingなのかを確認しておくと、仕様の食い違いを減らせます。特に、ナンピン、グリッド、分割決済、両建て、コピーEAでは、口座タイプの違いが重要になります。
| 口座タイプ | 特徴 | EA側の注意点 |
|---|---|---|
| Hedging | 同一銘柄で複数ポジションを持てる場合があります。 | チケット単位、Magic Number単位で管理します。 |
| Netting | 同一銘柄のポジションが集約される場合があります。 | 反対売買やポジション更新の扱いを確認します。 |
| 複数EA運用 | 同じ銘柄で複数EAが動く場合があります。 | Magic Numberと対象銘柄で範囲を絞ります。 |
| 手動ポジション混在 | EA外で建てたポジションが混ざる場合があります。 | EA対象外ポジションを誤決済しないようにします。 |
| コピーEA | コピー元・コピー先で口座タイプが異なる場合があります。 | チケット対応、ロット同期、決済同期の仕様を明確にします。 |
決済後に履歴を確認する
EAで決済処理を行った後は、現在ポジションがなくなったかを見るだけでなく、履歴にどのように残ったかを確認します。決済Deal、損益、手数料、スワップ、決済理由、コメント、Magic Numberを確認すると、後から検証しやすくなります。
特に、部分決済、トレーリング、建値決済、時間決済、一括決済を行うEAでは、決済理由をログと履歴で対応させることが重要です。履歴に残った結果だけでは、EAがどの理由で決済したのか分からない場合があります。
決済後の確認では、決済Dealが発生しているか、Positionが消えているか、Historyに損益が反映されているか、手数料やスワップが想定どおりかを確認します。バックテストレポートとログを照合する時にも、この整理が役立ちます。
| 確認項目 | 内容 | 理由 |
|---|---|---|
| 決済Deal | 決済として発生した約定。 | 決済が成立したか確認します。 |
| 決済理由ログ | TP、SL、トレーリング、時間決済、手動決済など。 | EA内部の決済理由を追うため。 |
| 損益 | DEAL_PROFIT、手数料、スワップ。 | レポートとの照合に使います。 |
| position id | 対象ポジションとの対応。 | エントリーと決済を結び付けるため。 |
| Magic Number | 自EAの履歴かどうか。 | 他EAや手動取引を除外するため。 |
| コメント | 注文・決済コメント。 | 補助的な識別に使います。 |
| 決済後Position | 現在ポジションが残っているか。 | 部分決済か全決済かを確認するため。 |
注文・ポジション・履歴のログ設計
注文・ポジション・履歴管理では、ログ設計が重要です。EAが注文を出したか、約定したか、ポジションを持っているか、決済されたか、履歴に残ったかを追えるようにします。
ログ名を統一しておくと、Expertsログ内で検索しやすくなります。ORDER、DEAL、POSITION、HISTORY、CLOSE、MODIFY、TRANSACTIONなど、処理の種類ごとに接頭辞を分けると原因追跡がしやすくなります。
また、通常運用ではログを出しすぎないようにし、検証時や不具合発生時に詳細ログをONにできる構成にすると扱いやすくなります。取引履歴の追跡では、order ticket、deal ticket、position id、Magic Numberを同じログ行に含めると照合しやすくなります。
| ログ名 | 残す内容 | 目的 |
|---|---|---|
ORDER_SEND | 注文方向、ロット、価格、retcode、order、deal。 | 注文送信結果を確認します。 |
CTRADE_BUY | CTradeのBuy結果、ResultRetcode、order、deal。 | CTrade利用時の発注結果を確認します。 |
CTRADE_CLOSE | 決済対象チケット、ResultRetcode、deal。 | 決済処理の結果を確認します。 |
POSITION_FOUND | ticket、symbol、magic、type、volume、profit。 | 現在ポジションを確認します。 |
POSITION_SCOPE | 対象銘柄、Magic Number、保有数。 | 自EA対象範囲を確認します。 |
DEAL_FOUND | deal ticket、symbol、magic、volume、profit。 | 約定履歴を確認します。 |
HISTORY_SELECT | 検索期間、件数、失敗時のGetLastError。 | 履歴取得範囲を確認します。 |
TRADE_TRANSACTION | 注文・約定イベントの種類、order、deal、position。 | 取引イベントを追跡します。 |
バックテストで履歴管理を確認する
バックテストでは、最終損益だけでなく、注文履歴、約定履歴、ポジション管理、決済理由を確認します。EAが想定どおりに注文しているか、決済しているか、Magic Numberの対象範囲が正しいかを確認してください。
バックテストで履歴を確認する時は、銘柄、時間足、期間、スプレッド、モデル、初期証拠金、setファイル、Expertsログ、Testerログを保存します。注文・決済履歴だけを見ても、EA内部の見送り理由や決済理由が分からない場合があるため、ログもセットで確認します。
バックテスト結果は将来の結果を保証するものではありません。ここでは、EAの注文・決済・履歴管理が想定どおりに動いているか、再現条件を整理できるか、ログで原因を追えるかを確認する材料として扱います。
- EA名とバージョンを記録する
- 使用したsetファイルを保存する
- 銘柄、時間足、期間、スプレッドを記録する
- 注文履歴と約定履歴を確認する
- 現在ポジションと決済履歴を分けて確認する
- 決済理由をExpertsログで確認する
- Magic Numberで自EAの履歴だけを抽出できるか確認する
- Position、Deal、Historyの対応を確認する
- order ticket、deal ticket、position idをログに残す
- バックテスト結果を将来成績保証として扱わない
CTradeの口座条件・イベント・検証を確認する
以下のコード例は、個別の処理と確認項目を読むためのものです。複数の例をそのまま一つのEAへ連結する前提ではありません。初期化、値の取得、状態更新、終了処理をそれぞれの例で区別して確認してください。
Hedging口座とNetting口座の違いに注意する
MQL5では、口座方式によってポジション管理の考え方が変わります。Hedging口座では同一銘柄に複数ポジションを持てる場合があります。Netting口座では同一銘柄のポジションが統合される形になります。
CTradeでPositionCloseやPositionModifyを使う時、Hedging口座とNetting口座で「どのポジションを対象にするか」の考え方が変わります。複数ポジションを持つEAでは、ticket、symbol、Magic Numberを確認して処理する必要があります。
単純にPositionClose(_Symbol)だけで決済する設計は、EAの仕様によっては十分ではありません。複数EAや複数Magic Numberを運用する場合は、対象ポジションを絞り込む関数を用意してください。
bool IsMyPositionSelected()
{
if(!PositionSelect(_Symbol))
return false;
long magic = (long)PositionGetInteger(POSITION_MAGIC);
if(magic != InpMagicNumber)
{
PrintFormat("POSITION_SKIP reason=MAGIC_MISMATCH position_magic=%I64d ea_magic=%I64d",
magic,
InpMagicNumber);
return false;
}
return true;
}この例では、選択したポジションのMagic Numberを確認しています。実際のHedging口座では、ポジション一覧をループしてticket単位で確認する設計が必要になる場合があります。
CTradeとOnTradeTransactionを組み合わせる
CTradeで注文を送った後、実際にどのような取引イベントが発生したかを追跡するには、OnTradeTransactionが役立ちます。CTradeの戻り値とResultRetcodeで注文送信結果を確認し、OnTradeTransactionで注文、約定、決済、変更イベントを追跡します。
注文処理のログと取引イベントのログを両方残すことで、OrderSendは成功したが約定がどう処理されたのか、決済イベントが発生したのか、通知対象にすべきイベントは何かを確認しやすくなります。
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
PrintFormat("TRADE_TX type=%d order=%I64u deal=%I64u symbol=%s volume=%.2f price=%.5f retcode=%d",
trans.type,
trans.order,
trans.deal,
trans.symbol,
trans.volume,
trans.price,
result.retcode);
}OnTradeTransactionはイベントごとに呼ばれるため、ログの出しすぎには注意してください。通知へ接続する場合は、OnTradeTransactionで通知候補を作り、OnTimerで送信キューを処理する構成が扱いやすいです。
CTradeを使った注文処理のログ設計
CTradeを使うEAでは、注文前、注文時、注文後のログを分けると確認しやすくなります。注文しない理由と注文失敗の理由を混同しないことが重要です。
| ログ名 | 残す内容 | 目的 |
|---|---|---|
SIGNAL_BUY | シグナル条件値。 | 買い候補の確認。 |
FILTER_BLOCK | スプレッド、時間帯、最大ポジションなど。 | 見送り理由の確認。 |
RISK_BLOCK | ロット、証拠金、StopLevelなど。 | 発注前停止の確認。 |
CTRADE_BUY | Buy結果、retcode、deal、order。 | 買い注文結果の確認。 |
CTRADE_SELL | Sell結果、retcode、deal、order。 | 売り注文結果の確認。 |
CTRADE_POSITION_CLOSE | 決済結果、retcode、comment。 | 決済結果の確認。 |
CTRADE_POSITION_MODIFY | SL/TP変更結果。 | ポジション変更の確認。 |
TRADE_TX | 注文・約定・決済イベント。 | 取引イベント追跡。 |
ログは、あとから検索しやすい固定名にします。CTradeの結果だけでなく、CTradeを呼ぶ前に止まった理由も残すことで、EAの挙動を正確に追いやすくなります。
バックテストで確認すること
CTradeを使ったEAをバックテストする時は、損益だけでなく、注文処理のログを確認します。BuyやSellが呼ばれた回数、ResultRetcode、注文失敗理由、決済理由、PositionModifyの失敗回数などを確認します。
バックテストでは、シグナルが出ているのに注文が少ない場合、filterで止まっているのか、riskで止まっているのか、CTradeの注文結果で失敗しているのかをログで分けて確認します。
また、バックテストと実チャートでは、スプレッド、約定、スリッページ、取引時間、ブローカー条件が異なる場合があります。CTradeのretcodeとcommentは、実チャート確認でも重要です。
- OnInitでMagic Numberとdeviationをログに出す
- Buy / Sellを呼ぶ前にfilterとriskを確認する
- ロット、証拠金、SL/TP距離を確認する
- CTradeの戻り値だけでなくResultRetcodeを確認する
- ResultDeal、ResultOrder、ResultCommentをログに残す
- PositionCloseの対象ポジションを確認する
- PositionModifyではStopLevelとFreezeLevelを確認する
- OnTradeTransactionで取引イベントを追跡する
- バックテスト結果を将来成績保証として扱わない
よくある不具合と確認ポイント
CTradeを使ったEAでよくある不具合は、注文しない、決済しない、SL/TP変更が失敗する、別EAのポジションを閉じる、Magic Numberで識別できない、retcodeを確認していない、といったものです。
| 症状 | 確認する場所 | 主な原因候補 |
|---|---|---|
| Buy / Sellが呼ばれない | SIGNAL、FILTER、RISKログ。 | シグナル不成立、スプレッド、時間帯、証拠金不足。 |
| Buy / Sellが失敗する | ResultRetcode、ResultComment。 | 取引不可、価格不正、ロット不正、invalid stops。 |
| SL/TPが入らない | StopLevel、FreezeLevel、価格方向。 | 距離不足、BUY/SELL方向ミス。 |
| PositionCloseできない | PositionSelect、Magic Number、retcode。 | 対象ポジションなし、口座方式、Magic不一致。 |
| 別EAのポジションを処理する | POSITION_MAGIC。 | Magic Number確認不足。 |
| 注文結果が追えない | ResultDeal、ResultOrder、OnTradeTransaction。 | 注文ログ不足、取引イベント未記録。 |
| バックテストと実チャートで違う | スプレッド、deviation、約定、取引時間。 | ブローカー条件や実環境差。 |
開発依頼前に整理する注文仕様
CTradeを使ったEAの開発や改修を依頼する場合は、売買条件だけでなく、注文仕様を整理してください。どの条件でBuyするのか、Sellするのか、どのロットで注文するのか、SL/TPをどう置くのか、決済条件は何か、Magic Numberはどう分けるのかを明確にします。
「CTradeで注文するEAを作りたい」だけでは、発注前チェック、口座方式、ロット計算、決済、ログ、通知、複数EA運用の仕様が不足します。注文処理はEAの中核なので、仕様段階で確認項目を分けることが重要です。
| 整理する情報 | 内容 | 理由 |
|---|---|---|
| 注文方向 | BUY、SELL、両方。 | Buy / Sell処理の設計に必要です。 |
| ロット | 固定ロット、残高連動、複利、段階式。 | risk処理に必要です。 |
| SL/TP | 固定points、ATR連動、なし、後付け。 | StopLevel確認に必要です。 |
| 決済条件 | 反対シグナル、時間決済、トレーリング、全決済。 | exit処理に必要です。 |
| Magic Number | EAごと、戦略ごと、銘柄ごと。 | ポジション識別に必要です。 |
| 口座方式 | Hedging、Netting。 | ポジション管理に影響します。 |
| 発注前チェック | OrderCheck、証拠金、StopLevel、スプレッド。 | 注文失敗を減らすため。 |
| ログ | ResultRetcode、ResultComment、TRADE_TX。 | 不具合調査に必要です。 |
| 通知 | 注文時、約定時、決済時。 | notification処理に必要です。 |
| 送らない情報 | 口座番号、パスワード、APIキー、Webhook URL。 | 機密情報保護のため。 |
実務チェック表
- CTradeをexecution責務として分離している
- OnTick内に注文処理を直接詰め込みすぎていない
- Buy / Sell前にfilterとriskを確認している
- Magic Numberを設定している
- PositionClose前に対象ポジションを確認している
- Hedging / Netting口座の違いを考慮している
- SL/TPの価格方向をBUY / SELLで分けている
- StopLevelとFreezeLevelを確認している
- ResultRetcodeとResultCommentをログに出している
- OnTradeTransactionで取引イベントを追跡している
- 口座番号や認証情報をログに出していない
よくある不具合と確認ポイント
注文・ポジション・履歴管理では、EAが注文しない、決済されない、履歴が取得できない、Magic Numberで絞れない、バックテストと通常チャートで結果が違う、といった問題が起きることがあります。
このような時は、注文処理だけを疑うのではなく、発注前チェック、OrderSend / CTrade結果、現在ポジション、履歴取得期間、Magic Number、口座タイプ、ログ粒度を順番に確認します。
| 症状 | 確認する場所 | 主な原因候補 |
|---|---|---|
| 注文したはずなのにポジションがない | OrderSend / CTradeログ、retcode、Deal履歴。 | 注文失敗、約定していない、即時決済、履歴確認漏れ。 |
| DealはあるがPositionがない | HistoryDeals、現在ポジション。 | 決済済み、Netting口座で相殺、短時間でクローズ。 |
| Positionはあるが自EAのものではない | POSITION_MAGIC、POSITION_SYMBOL。 | 他EA、手動ポジション、Magic Number未設定。 |
| 履歴が取得できない | HistorySelectの期間、GetLastError。 | 期間指定ミス、サーバー時間のずれ、履歴未選択。 |
| 決済対象を間違える | ticket、symbol、magic、type。 | 対象範囲の絞り込み不足。 |
| バックテストと通常チャートで違う | set、スプレッド、口座タイプ、ログ。 | 検証条件差、約定条件差、外部環境差。 |
| OnTradeTransactionログが多すぎる | ログ粒度、イベント種別。 | すべての取引イベントを常時出力している。 |
開発依頼前に整理する情報
注文・ポジション・履歴管理の不具合を相談する場合は、対象EA、setファイル、注文履歴、Expertsログ、Journalログ、バックテスト条件、発生時刻を整理してください。単に「決済されない」「履歴が取れない」だけでは、原因を確認しにくくなります。
特に、注文後の追跡では、order ticket、deal ticket、position id、Magic Number、決済理由、発生時刻が重要です。履歴確認のためには、HistorySelectで指定すべき期間も分かるようにしておく必要があります。
| 整理する情報 | 内容 | 理由 |
|---|---|---|
| EA名・バージョン | 対象ファイル名、更新日、バージョン。 | 確認対象を特定するため。 |
| setファイル | input設定一式。 | 同じ条件を再現するため。 |
| 注文履歴 | 注文番号、約定番号、ポジションID。 | Order・Deal・Positionを照合するため。 |
| Expertsログ | EA内部の注文・決済・履歴ログ。 | EA側の判断を確認するため。 |
| Journalログ | MT5側の取引・環境ログ。 | プラットフォーム側の状態を確認するため。 |
| バックテスト条件 | 銘柄、時間足、期間、スプレッド、モデル。 | 検証条件を再現するため。 |
| 発生時刻 | 問題が起きたサーバー時間・ローカル時間。 | 履歴検索期間を指定するため。 |
| 口座タイプ | HedgingまたはNetting。 | ポジション管理仕様に影響するため。 |
| 送らない情報 | 口座番号、パスワード、APIキー、Webhook URL。 | 機密情報を保護するため。 |
注文・ポジション・履歴管理の実務チェック表
- Order、Deal、Position、Historyの違いを確認した
- OrderSend後にretcode、order、deal、commentを確認している
- CTrade利用時にResultRetcodeを確認している
- PositionSelectまたはPositionSelectByTicketで対象を確認している
- Magic Numberで自EAの対象だけを抽出している
- PositionsTotalだけで保有数を判断していない
- HistorySelectの期間指定を確認している
- HistoryOrderGet系とHistoryDealGet系を分けて確認している
- HistoryDealGetTicketでDeal履歴を確認している
- order ticket、deal ticket、position ticket、position idを混同していない
- OnTradeTransactionで取引イベントを必要に応じて追跡している
- Hedging口座とNetting口座の違いを考慮している
- 決済理由をログと履歴で照合できる
- バックテスト条件とsetファイルを保存している
- 口座情報や認証情報をログへ出していない
よくある質問
MQL5のOrderとPositionは何が違いますか?
Orderは注文を表し、Positionは現在保有している建玉を表します。注文が送られても、必ず現在ポジションになるとは限りません。注文、約定、ポジション、履歴を分けて確認してください。
Dealとは何ですか?
Dealは実際に約定した記録です。注文が成立した時や決済が成立した時にDealとして履歴に残ります。約定価格、ロット、損益、Magic Numberなどを確認できます。
PositionSelectだけでポジション管理できますか?
単一銘柄・単一ポジション前提なら確認できる場合があります。ただし、複数ポジションやHedging口座では、PositionSelectByTicketやMagic Numberによる絞り込みが重要です。
HistorySelectで履歴が取れない時は何を確認しますか?
指定期間、サーバー時間、履歴の種類、HistorySelectの戻り値、GetLastErrorを確認してください。期間が狭すぎると対象履歴が含まれないことがあります。
Magic Numberは履歴確認にも必要ですか?
必要です。複数EAや手動ポジションが混在する場合、Magic Numberを見ないと自EAの注文・約定・ポジションだけを抽出できません。履歴確認でもMagic Numberを使って対象を絞ると安全です。
OnTradeTransactionは必ず使うべきですか?
必須ではありませんが、注文・約定・ポジション変化をリアルタイムに追いたい場合に役立ちます。ログが多くなりやすいため、開発時・検証時・異常時で粒度を分けるとよいです。
Hedging口座とNetting口座でEAの作り方は変わりますか?
変わる場合があります。Hedging口座では同一銘柄に複数ポジションを持てることがあり、Netting口座では同一銘柄のポジションが集約される場合があります。複数ポジション、分割決済、両建て、コピーEAでは特に注意が必要です。
CTradeを使えばOrderSendは不要ですか?
基本的な注文処理ではCTradeで十分な場合があります。ただし、MqlTradeRequestを細かく制御したい場合や、OrderCheck用のリクエストを明示的に作りたい場合は、MqlTradeRequestやOrderSendを直接扱う設計もあります。
CTradeの戻り値だけ見れば注文結果は分かりますか?
戻り値だけで判断しない方が安全です。ResultRetcode、ResultDeal、ResultOrder、ResultComment、GetLastErrorを確認してください。さらに、約定や決済イベントはOnTradeTransactionでも追跡すると確認しやすくなります。
Magic Numberは必ず必要ですか?
複数EA運用や裁量注文との区別を考えるなら、Magic Numberを設定する方が安全です。CTradeではSetExpertMagicNumberで設定できます。ポジション管理時にもPOSITION_MAGICを確認してください。
PositionClose(_Symbol)だけで決済してもよいですか?
EAの仕様によります。単一銘柄・単一ポジション前提なら扱いやすい場合がありますが、複数EA、複数Magic Number、Hedging口座では、ticketやMagic Numberで対象を絞る設計が必要になることがあります。
CTradeでもOrderCheckは使うべきですか?
証拠金、ロット、StopLevel、SL/TP距離を事前に確認したい場合は、OrderCheckを使うと検証しやすくなります。CTradeは注文実行、OrderCheckは発注前チェックとして役割を分けると整理しやすいです。
CTradeのログは何を残すべきですか?
Buy / Sell / PositionClose / PositionModifyの結果、ResultRetcode、ResultDeal、ResultOrder、ResultComment、GetLastErrorを残すと確認しやすくなります。注文前に止まった理由も、FILTER_BLOCKやRISK_BLOCKとして分けて残してください。
関連する確認ページ
確認したい内容に応じて、次のページを参照してください。本文中ですでに案内したページは、ここでは重ねて掲載していません。
あわせて確認したいページ
今回の確認内容に関連する補足ページです。必要な項目だけ確認してください。
| 確認目的 | 関連ページ |
|---|---|
| 読後の任意の手続き・一覧入口。本文解決や購入の必須前提にしない | MT4/MT5 技術講座 |
| 「MQL5 注文 ポジション 履歴 管理」の読後に「MQL5注文関数・取引構造体辞典」を補足確認 | MQL5注文関数・取引構造体辞典 |
| 「MQL5 注文 ポジション 履歴 管理」の読後に「MQL5ポジション・注文・約定・履歴用語辞典」を補足確認 | MQL5ポジション・注文・約定・履歴用語辞典 |
| 「MQL5 注文 ポジション 履歴 管理」の読後に「MQL5 OnTradeTransactionで約定を追跡する方法」を補足確認 | MQL5 OnTradeTransactionで約定を追跡する方法 |
| 「MQL5 注文 ポジション 履歴 管理」の読後に「MQL5 Hedging / Netting口座の違い」を補足確認 | MQL5 Hedging / Netting口座の違い |
まとめ
MQL5でEAの注文処理を作る時は、Order、Deal、Position、Historyを分けて理解することが重要です。注文を送ったこと、約定したこと、現在ポジションがあること、履歴に残ったことは、それぞれ確認する場所が異なります。
OrderSendやCTradeを使った後は、retcode、order ticket、deal ticket、position ticket、position id、Magic Number、commentをログに残してください。PositionSelectやHistorySelectを使う時も、対象銘柄、Magic Number、期間指定を確認することで、自EAの注文・約定・ポジションだけを抽出しやすくなります。
バックテストや不具合調査では、注文履歴だけでなく、Expertsログ、Journalログ、setファイル、検証条件、決済理由をあわせて確認してください。注文・約定・ポジション・履歴を分けて追跡できるようにしておくと、EA開発や改修時の原因確認が進めやすくなります。
お問い合わせはEAFC公式LINEへ
EAFCサイト内の記事、商品、導入前確認、設定確認、ログ確認、開発依頼前のご相談など、各種お問い合わせはEAFC公式LINEより受け付けています。
※投資助言、売買指示、利益保証、推奨ロット、推奨銘柄の案内は行っておりません。
口座番号、認証情報、Webhook URL、GAS URL、APIキーなどの機密情報は送信しないでください。
利用条件・相談窓口
| 確認内容 | 案内ページ |
|---|---|
| 不具合報告の方法 | 不具合報告・サポート依頼 |
| MT5 開発依頼・作成代行|EA・インジケーター新規開発・MT4/MT5既存改修 | 開発・改修の相談ページ |
| EA・MT5・MQL5 技術辞典|用語・関数・設定を目的別に探す | EA・MT5・MQL5 技術辞典|用語・関数・設定を目的別に探す |
