MQL5の取引関数を体系的にまとめました。OrderSendの構造体からCTradeクラス、ポジション管理、待機注文、SL/TP変更、トレーリングストップ、ロット計算、マジックナンバー、部分決済、取引履歴、OnTradeTransactionまで、EA開発に必要な取引処理のすべてをコード付きで解説します。
MQL5の取引モデル(MQL4との根本的な違い)
MQL4とMQL5では取引の仕組みが根本的に異なります。MQL4は「注文=ポジション」でしたが、MQL5は「注文→約定→ポジション」の3段階モデルです。
| 概念 | MQL4 | MQL5 |
|---|---|---|
| 発注 | OrderSend()で直接注文 | OrderSend()でリクエスト送信 |
| 結果 | チケット番号が返る | MqlTradeResult構造体で受け取る |
| ポジション管理 | OrderSelect(ticket) | PositionSelectByTicket(ticket) |
| 決済 | OrderClose(ticket) | 反対売買で決済(CTrade.PositionClose) |
| ヘッジング | 標準対応 | 口座設定による(ネッティング/ヘッジ) |
| OrderSendの引数 | 約10個の引数を直接渡す | MqlTradeRequest構造体にセットして渡す |
MQL5にはOrderClose()やOrderModify()は存在しません。MQL4のコードをそのまま使うとコンパイルエラーになります。
MQL5の取引は、すべてOrderSend()関数にMqlTradeRequest構造体を渡して行います。成行注文も、指値注文も、SL/TP変更も、決済もすべてこの1つの関数で処理します。
OrderSend(MqlTradeRequest / MqlTradeResult 詳解)
MQL5の取引はすべてOrderSend()を通じて行います。2つの構造体を使います。
MqlTradeRequest — 注文リクエスト
取引サーバーに送る注文内容を格納する構造体です。actionフィールドの値によって、他に必要なフィールドが変わります。
| フィールド | 型 | 説明 |
|---|---|---|
| action | ENUM_TRADE_REQUEST_ACTIONS | 取引操作の種類(TRADE_ACTION_DEAL / PENDING / SLTP / MODIFY / REMOVE) |
| magic | ulong | EA識別用マジックナンバー |
| order | ulong | 注文チケット(変更・削除時) |
| symbol | string | 通貨ペア |
| volume | double | ロット数 |
| price | double | 価格 |
| stoplimit | double | ストップリミット注文の指値 |
| sl | double | ストップロス |
| tp | double | テイクプロフィット |
| deviation | ulong | 許容スリッページ(ポイント) |
| type | ENUM_ORDER_TYPE | 注文タイプ(BUY / SELL / BUY_LIMIT等) |
| type_filling | ENUM_ORDER_TYPE_FILLING | 充填タイプ(FOK / IOC / RETURN) |
| type_time | ENUM_ORDER_TYPE_TIME | 有効期限タイプ(GTC / DAY / SPECIFIED等) |
| expiration | datetime | 有効期限日時 |
| comment | string | コメント |
| position | ulong | ポジションチケット(決済・変更時) |
| position_by | ulong | 反対ポジションのチケット(CLOSE_BY時) |
MqlTradeResult — 注文結果
| フィールド | 型 | 説明 |
|---|---|---|
| retcode | uint | リターンコード(10009=成功) |
| deal | ulong | 約定チケット |
| order | ulong | 注文チケット |
| volume | double | 約定ロット数 |
| price | double | 約定価格 |
| bid | double | 現在のBid |
| ask | double | 現在のAsk |
| comment | string | サーバーからのコメント |
| request_id | uint | リクエストID |
成行買い注文の基本コード
void BuyMarket(double lot, int slPoints, int tpPoints)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lot;
request.type = ORDER_TYPE_BUY;
request.price = ask;
request.sl = NormalizeDouble(ask - slPoints * _Point, _Digits);
request.tp = NormalizeDouble(ask + tpPoints * _Point, _Digits);
request.deviation = 10;
request.type_filling = ORDER_FILLING_FOK;
request.magic = 12345;
request.comment = "Buy Order";
if(!OrderSend(request, result))
{
Print("OrderSend失敗: ", GetLastError());
return;
}
if(result.retcode == TRADE_RETCODE_DONE)
Print("買い注文成功: ticket=", result.order, " price=", result.price);
else
Print("買い注文失敗: retcode=", result.retcode, " ", result.comment);
}MqlTradeRequest request = {}; のように必ずゼロ初期化してください。初期化しないとゴミデータが入り、予期しないエラーの原因になります。
CTradeクラス(Buy / Sell / BuyStop / SellLimit等)
CTradeはMQL5標準ライブラリに含まれるクラスで、OrderSend()の複雑な構造体操作をラップしてくれます。実務のEA開発ではCTradeを使うのが一般的です。
#include <Trade\Trade.mqh>
CTrade trade;
int OnInit()
{
trade.SetExpertMagicNumber(12345); // マジックナンバー設定
trade.SetDeviationInPoints(10); // 許容スリッページ
trade.SetTypeFilling(ORDER_FILLING_FOK); // 充填タイプ
return INIT_SUCCEEDED;
}成行注文
// 成行買い(SL/TPなし)
trade.Buy(0.1, _Symbol);
// 成行買い(SL/TP付き)
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = NormalizeDouble(ask - 500 * _Point, _Digits);
double tp = NormalizeDouble(ask + 1000 * _Point, _Digits);
trade.Buy(0.1, _Symbol, ask, sl, tp, "Buy with SL/TP");
// 成行売り
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
sl = NormalizeDouble(bid + 500 * _Point, _Digits);
tp = NormalizeDouble(bid - 1000 * _Point, _Digits);
trade.Sell(0.1, _Symbol, bid, sl, tp, "Sell with SL/TP");
// 結果の確認
if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
Print("注文成功: ", trade.ResultOrder());
else
Print("注文失敗: ", trade.ResultRetcode(), " ", trade.ResultComment());ポジション決済
// チケット番号で決済
trade.PositionClose(ticket);
// 通貨ペア指定で決済(その銘柄の全ポジション)
trade.PositionClose(_Symbol);
// 決済スリッページを指定
trade.PositionClose(ticket, 20); // 20ポイントまで許容注文タイプ(成行・指値・逆指値・ストップリミット)
MQL5では6種類の注文タイプが使えます。MQL4の4種類から、ストップリミット注文が追加されています。
| 定数 | 種類 | 説明 |
|---|---|---|
| ORDER_TYPE_BUY | 成行買い | 現在のAsk価格で即時買い |
| ORDER_TYPE_SELL | 成行売り | 現在のBid価格で即時売り |
| ORDER_TYPE_BUY_LIMIT | 買い指値 | 現在価格より低い価格で買い待ち |
| ORDER_TYPE_SELL_LIMIT | 売り指値 | 現在価格より高い価格で売り待ち |
| ORDER_TYPE_BUY_STOP | 買い逆指値 | 現在価格より高い価格で買い待ち(ブレイクアウト) |
| ORDER_TYPE_SELL_STOP | 売り逆指値 | 現在価格より低い価格で売り待ち(ブレイクアウト) |
| ORDER_TYPE_BUY_STOP_LIMIT | 買いストップリミット | 指定価格に達したら買い指値注文を発行 |
| ORDER_TYPE_SELL_STOP_LIMIT | 売りストップリミット | 指定価格に達したら売り指値注文を発行 |
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// 買い指値: 現在価格より100pips下で待つ
double buyLimitPrice = NormalizeDouble(ask - 1000 * _Point, _Digits);
trade.BuyLimit(0.1, buyLimitPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "BuyLimit");
// 売り指値: 現在価格より100pips上で待つ
double sellLimitPrice = NormalizeDouble(bid + 1000 * _Point, _Digits);
trade.SellLimit(0.1, sellLimitPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "SellLimit");
// 買い逆指値: 現在価格より50pips上で待つ(ブレイクアウト狙い)
double buyStopPrice = NormalizeDouble(ask + 500 * _Point, _Digits);
trade.BuyStop(0.1, buyStopPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "BuyStop");
// 売り逆指値: 現在価格より50pips下で待つ(ブレイクアウト狙い)
double sellStopPrice = NormalizeDouble(bid - 500 * _Point, _Digits);
trade.SellStop(0.1, sellStopPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "SellStop");ポジション管理(Select / GetDouble / GetInteger / Total)
MQL5ではポジション情報の取得に専用のPosition関数群を使います。MQL4のOrderSelect()でポジション情報を取る方法とは完全に異なります。
全ポジションのループ
void PrintAllPositions()
{
int total = PositionsTotal();
Print("ポジション数: ", total);
for(int i = 0; i < total; i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// PositionGetTicket()で選択状態になるので、そのまま情報を取得できる
string symbol = PositionGetString(POSITION_SYMBOL);
long type = PositionGetInteger(POSITION_TYPE); // 0=BUY, 1=SELL
double volume = PositionGetDouble(POSITION_VOLUME);
double openPr = PositionGetDouble(POSITION_PRICE_OPEN);
double sl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
double profit = PositionGetDouble(POSITION_PROFIT);
long magic = PositionGetInteger(POSITION_MAGIC);
PrintFormat("#%I64u %s %s %.2f lot Open=%.5f SL=%.5f TP=%.5f PL=%.2f Magic=%I64d",
ticket, symbol,
(type == POSITION_TYPE_BUY) ? "BUY" : "SELL",
volume, openPr, sl, tp, profit, magic);
}
}特定のポジションを選択
// 方法1: インデックスで選択(PositionGetTicketが選択も兼ねる)
ulong ticket = PositionGetTicket(0); // 0番目のポジションを選択
// 方法2: チケット番号で選択
if(PositionSelectByTicket(12345))
{
double profit = PositionGetDouble(POSITION_PROFIT);
}
// 方法3: 通貨ペアで選択(ネッティング口座向け)
if(PositionSelect(_Symbol))
{
double volume = PositionGetDouble(POSITION_VOLUME);
}PositionSelect(symbol)はネッティング口座では問題なく動きますが、ヘッジング口座では同じ通貨ペアに複数ポジションがあると最初の1つしか選択できません。ヘッジング口座ではPositionGetTicket()でループしてください。
自分のEAのポジションだけを取得
int CountMyPositions(long magicNumber, string symbol = "")
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetInteger(POSITION_MAGIC) != magicNumber)
continue;
if(symbol != "" && PositionGetString(POSITION_SYMBOL) != symbol)
continue;
count++;
}
return count;
}待機注文の管理(OrderGet / OrdersTotal / OrderSelect)
MQL5では「ポジション」と「待機注文(Pending Order)」は別のデータです。ポジションはPositionsTotal()、待機注文はOrdersTotal()で取得します。
// 待機注文の一覧表示
void PrintPendingOrders()
{
int total = OrdersTotal();
Print("待機注文数: ", total);
for(int i = 0; i < total; i++)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0) continue;
string symbol = OrderGetString(ORDER_SYMBOL);
long type = OrderGetInteger(ORDER_TYPE);
double volume = OrderGetDouble(ORDER_VOLUME_CURRENT);
double price = OrderGetDouble(ORDER_PRICE_OPEN);
PrintFormat("#%I64u %s type=%d vol=%.2f price=%.5f",
ticket, symbol, type, volume, price);
}
}
// 特定マジックナンバーの待機注文をすべて削除
void DeleteAllPendingOrders(long magicNumber)
{
for(int i = OrdersTotal() - 1; i >= 0; i--) // 逆順ループ
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0) continue;
if(OrderGetInteger(ORDER_MAGIC) == magicNumber)
trade.OrderDelete(ticket);
}
}待機注文を削除するループは逆順(i–)で回してください。順方向で回すと、削除のたびにインデックスがずれて注文がスキップされます。
SL/TPの設定と変更
既存ポジションのSL/TPを変更するにはTRADE_ACTION_SLTPを使います。CTradeクラスならPositionModify()一発です。
// CTradeでSL/TP変更
bool ModifySLTP(ulong ticket, double newSL, double newTP)
{
newSL = NormalizeDouble(newSL, _Digits);
newTP = NormalizeDouble(newTP, _Digits);
if(!trade.PositionModify(ticket, newSL, newTP))
{
Print("SL/TP変更失敗: ", trade.ResultRetcode(), " ", trade.ResultComment());
return false;
}
return true;
}
// OrderSend直接でSL/TP変更
void ModifySLTP_Direct(ulong ticket, double newSL, double newTP)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.symbol = _Symbol;
request.sl = NormalizeDouble(newSL, _Digits);
request.tp = NormalizeDouble(newTP, _Digits);
if(!OrderSend(request, result))
Print("SL/TP変更失敗: ", GetLastError());
else if(result.retcode != TRADE_RETCODE_DONE)
Print("SL/TP変更失敗: ", result.retcode);
}トレーリングストップの実装
トレーリングストップは、価格が有利な方向に動いたときにSLを追従させる仕組みです。MT5の標準機能にもありますが、EAに組み込むことで細かい制御ができます。
void TrailingStop(int trailPoints, int trailStepPoints, long magicNumber)
{
double trailDistance = trailPoints * _Point;
double stepDistance = trailStepPoints * _Point;
for(int i = 0; i < PositionsTotal(); i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetInteger(POSITION_MAGIC) != magicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
long posType = PositionGetInteger(POSITION_TYPE);
double openPr = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
if(posType == POSITION_TYPE_BUY)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// 価格がトレール開始距離以上に有利に動いている場合のみ
if(bid - openPr < trailDistance) continue;
double newSL = NormalizeDouble(bid - trailDistance, _Digits);
// 新しいSLが現在のSLよりstep以上有利な場合のみ移動
if(newSL > currentSL + stepDistance)
trade.PositionModify(ticket, newSL, tp);
}
else if(posType == POSITION_TYPE_SELL)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(openPr - ask < trailDistance) continue;
double newSL = NormalizeDouble(ask + trailDistance, _Digits);
if(currentSL == 0 || newSL < currentSL - stepDistance)
trade.PositionModify(ticket, newSL, tp);
}
}
}
// OnTick()から呼び出す例
void OnTick()
{
TrailingStop(300, 50, 12345); // 30pipsのトレール、5pipsステップ
}- trailPoints: 現在価格からSLまでの距離。相場がこの距離以上動いたらトレール開始
- trailStepPoints: SLを移動する最小幅。細かすぎるとサーバーリクエストが多くなる
- 売りポジションの
currentSL == 0チェックは、SL未設定時の対策
ロット計算(リスクベース自動計算)
固定ロットではなく、口座残高の一定割合をリスクとしてロットを自動計算する方法です。プロのEAでは標準的に使われています。
// 口座残高の riskPercent% をリスクとしてロットを計算
// slPoints: SLまでの距離(ポイント単位)
double CalcLotByRisk(string symbol, double riskPercent, int slPoints)
{
if(slPoints <= 0) return 0.0;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskMoney = balance * riskPercent / 100.0;
// 1ロット1ポイント動いたときの損益(ティック値)
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
if(tickValue == 0 || tickSize == 0) return 0.0;
double pointValue = tickValue / tickSize * _Point;
double lot = riskMoney / (slPoints * pointValue);
// ブローカーのロット制約に合わせる
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
lot = MathMax(minLot, lot);
lot = MathMin(maxLot, lot);
lot = MathFloor(lot / lotStep) * lotStep;
return NormalizeDouble(lot, 2);
}
// 使用例: 残高の2%リスク、SL 500ポイント(50pips)
double lot = CalcLotByRisk(_Symbol, 2.0, 500);
trade.Buy(lot, _Symbol);クロス円(EURJPY等)と非クロス円(EURUSD等)ではTICK_VALUEが大きく異なります。必ずSymbolInfoDouble()から取得し、ハードコーディングしないでください。
マジックナンバー(複数EA管理)
マジックナンバーは、どのEAがどのポジション/注文を出したかを識別するための数値です。1つのMT5に複数のEAを動かす場合、これがないと他のEAのポジションを誤って決済してしまいます。
input long MagicNumber = 20240101; // EA固有のマジックナンバー
int OnInit()
{
trade.SetExpertMagicNumber(MagicNumber);
return INIT_SUCCEEDED;
}
// ポジション操作時は必ずマジックナンバーでフィルタ
void CloseAllMyPositions()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
trade.PositionClose(ticket);
}
}- マジックナンバーは
inputで宣言し、ユーザーが変更可能にする - 同じEAを複数チャートで動かす場合、異なるマジックナンバーを設定する
- 手動注文のマジックナンバーは0。EAのマジックナンバーを0にすると手動注文と区別できない
部分決済
ポジションの一部だけを決済する方法です。例えば1.0ロットのうち0.5ロットだけ利確し、残りはトレールで伸ばす、といった使い方ができます。
// ポジションの半分を決済する
bool PartialClose(ulong ticket, double closeLot)
{
if(!PositionSelectByTicket(ticket))
{
Print("ポジションが見つかりません: ", ticket);
return false;
}
string symbol = PositionGetString(POSITION_SYMBOL);
long type = PositionGetInteger(POSITION_TYPE);
double volume = PositionGetDouble(POSITION_VOLUME);
// 決済ロットをロットステップに合わせる
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
closeLot = MathFloor(closeLot / lotStep) * lotStep;
closeLot = MathMin(closeLot, volume); // 保有数量を超えない
if(closeLot <= 0) return false;
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = symbol;
request.volume = closeLot;
request.deviation = 10;
request.type_filling = ORDER_FILLING_FOK;
// 反対売買で決済
if(type == POSITION_TYPE_BUY)
{
request.type = ORDER_TYPE_SELL;
request.price = SymbolInfoDouble(symbol, SYMBOL_BID);
}
else
{
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(symbol, SYMBOL_ASK);
}
if(!OrderSend(request, result))
{
Print("部分決済失敗: ", GetLastError());
return false;
}
if(result.retcode == TRADE_RETCODE_DONE)
{
Print("部分決済成功: ", closeLot, " lot closed");
return true;
}
Print("部分決済失敗: ", result.retcode, " ", result.comment);
return false;
}
// 使用例: ポジションの半分を決済
if(PositionSelectByTicket(ticket))
{
double halfLot = PositionGetDouble(POSITION_VOLUME) / 2.0;
PartialClose(ticket, halfLot);
}取引履歴(HistorySelect / HistoryDealGet)
過去の取引履歴を取得するには、まずHistorySelect()で期間を指定してから、HistoryDealsTotal()とHistoryDealGetTicket()でループします。
// 今日の取引履歴を取得
void PrintTodayDeals(long magicNumber)
{
MqlDateTime today;
TimeCurrent(today);
today.hour = 0;
today.min = 0;
today.sec = 0;
datetime startOfDay = StructToTime(today);
// 履歴をロード
if(!HistorySelect(startOfDay, TimeCurrent()))
{
Print("履歴取得失敗");
return;
}
int totalDeals = HistoryDealsTotal();
double totalProfit = 0;
int tradeCount = 0;
for(int i = 0; i < totalDeals; i++)
{
ulong dealTicket = HistoryDealGetTicket(i);
if(dealTicket == 0) continue;
// マジックナンバーでフィルタ
if(HistoryDealGetInteger(dealTicket, DEAL_MAGIC) != magicNumber) continue;
long dealEntry = HistoryDealGetInteger(dealTicket, DEAL_ENTRY);
// DEAL_ENTRY_OUT = 決済約定のみカウント
if(dealEntry != DEAL_ENTRY_OUT) continue;
double profit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
double commission = HistoryDealGetDouble(dealTicket, DEAL_COMMISSION);
double swap = HistoryDealGetDouble(dealTicket, DEAL_SWAP);
totalProfit += profit + commission + swap;
tradeCount++;
PrintFormat("Deal #%I64u PL=%.2f Commission=%.2f Swap=%.2f",
dealTicket, profit, commission, swap);
}
PrintFormat("本日の取引: %d回 合計損益: %.2f", tradeCount, totalProfit);
}HistorySelect()を呼ばないと履歴データが空の状態です。HistoryDealsTotal()やHistoryDealGetTicket()を使う前に必ず呼んでください。
直近の約定情報を取得
// 直近の決済約定の損益を取得
double GetLastClosedProfit(long magicNumber)
{
HistorySelect(0, TimeCurrent());
for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
{
ulong ticket = HistoryDealGetTicket(i);
if(ticket == 0) continue;
if(HistoryDealGetInteger(ticket, DEAL_MAGIC) != magicNumber) continue;
if(HistoryDealGetInteger(ticket, DEAL_ENTRY) != DEAL_ENTRY_OUT) continue;
return HistoryDealGetDouble(ticket, DEAL_PROFIT)
+ HistoryDealGetDouble(ticket, DEAL_COMMISSION)
+ HistoryDealGetDouble(ticket, DEAL_SWAP);
}
return 0;
}OnTradeTransaction(取引イベント処理)
OnTradeTransaction()は取引に変化があったときに自動的に呼ばれるイベントハンドラです。ポジションが約定した瞬間、SL/TPが変更された瞬間などをリアルタイムで検知できます。
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
// 約定が完了したタイミングを検知
if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
{
ulong dealTicket = trans.deal;
// 履歴から約定情報を取得
if(HistoryDealSelect(dealTicket))
{
long entry = HistoryDealGetInteger(dealTicket, DEAL_ENTRY);
if(entry == DEAL_ENTRY_IN)
{
Print("新規ポジション約定: deal=", dealTicket,
" price=", HistoryDealGetDouble(dealTicket, DEAL_PRICE));
}
else if(entry == DEAL_ENTRY_OUT)
{
double profit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
Print("決済約定: deal=", dealTicket, " 損益=", profit);
}
}
}
}OnTradeTransaction()の主な用途:
- 新規ポジション約定後に自動でSL/TPを設定
- 決済後に次の注文を自動で発行
- 部分決済の検知
- 取引結果のログ記録
OnTradeTransaction()内での新規発注は注意が必要です。1回の取引で複数回呼ばれることがあるため、重複発注を防ぐロジックを入れてください。
TRADE_TRANSACTION_TYPE一覧
| 定数 | 意味 |
|---|---|
| TRADE_TRANSACTION_ORDER_ADD | 注文がサーバーに追加された |
| TRADE_TRANSACTION_ORDER_UPDATE | 注文が更新された |
| TRADE_TRANSACTION_ORDER_DELETE | 注文が削除された |
| TRADE_TRANSACTION_DEAL_ADD | 約定が履歴に追加された |
| TRADE_TRANSACTION_DEAL_UPDATE | 約定が更新された |
| TRADE_TRANSACTION_DEAL_DELETE | 約定が削除された |
| TRADE_TRANSACTION_HISTORY_ADD | 注文が履歴に追加された |
| TRADE_TRANSACTION_HISTORY_UPDATE | 履歴の注文が更新された |
| TRADE_TRANSACTION_HISTORY_DELETE | 履歴の注文が削除された |
| TRADE_TRANSACTION_POSITION | ポジションが変更された(SL/TP等) |
| TRADE_TRANSACTION_REQUEST | 取引リクエストが処理された |
プロが開発したEAをお探しの方は → シストレ.COM EA一覧





