【MQL5】OnTradeTransaction関数について

MQL5リファレンス
スポンサーリンク
  1. OnTradeTransaction関数の働き・役割
  2. MQL5、MT5における注文と取引の違いについて
  3. OnTradeTransaction関数の引数について
    1. 第1引数:trans
    2. 第2引数:request
    3. 第3引数:result
  4. OnTradeTransaction関数の戻り値について
  5. OnTradeTransaction関数を使う際の注意点
  6. OnTradeTransaction関数を使ったサンプルコード
  7. サンプルコード解説1: OnInit関数とOnTick関数
    1. OnInit関数の解説
      1. OnInit関数の役割
      2. PrintFormat関数
      3. TerminalInfoInteger関数
      4. TERMINAL_PING_LAST識別子
        1. PING時間とは?
      5. ミリ秒から秒への変換
      6. INIT_SUCCEEDED
    2. OnTick関数の解説
      1. OnTick関数の役割
  8. サンプルコード解説2: TradeTransaction 関数その1
    1. TradeTransaction 関数の解説
      1. OnTradeTransaction関数の役割
      2. 引数の解説
      3. 静的変数 counter と lasttime
      4. GetTickCount関数
      5. トランザクションの間隔をチェックする処理
  9. サンプルコード解説3: TradeTransaction 関数その2
    1. TradeTransaction 関数の解説(続き)
      1. 時刻とカウンタの更新
      2. トランザクションの詳細情報の取得
  10. サンプルコード解説4: TradeTransaction 関数その3
      1. トランザクションの種類に応じた処理
  11. サンプルコード解説5: TradeTransaction関数その4
    1. TradeTransaction 関数の解説(続き)
      1. 注文チケットと結果コードの出力
      2. 結果コードが0でない場合の処理
    2. 補足説明
      1. MqlTradeResult構造体
      2. GetRetcodeID関数
  12. サンプルコード解説6: GetRetcodeID関数(オリジナル関数)
    1. GetRetcodeID関数の解説
    2. GetRetcodeID関数の役割
    3. 関数の引数
    4. 関数の戻り値
    5. 関数の実装
    6. 具体的なケースの説明
    7. デフォルトケースの説明

OnTradeTransaction関数の働き・役割

OnTradeTransaction関数は、TradeTransactionイベントが発生したときに自動的に呼び出される関数です。
TradeTransactionイベントとは、取引リクエストの実行結果に関連するイベントを指します。この関数は、取引リクエストの実行結果を処理するために使用されます。

具体的には、
注文の追加、更新、削除、
取引の追加、更新、削除

など、取引口座で発生するさまざまなトランザクション(取引の実行プロセス)を処理します。

MQL5、MT5における注文と取引の違いについて

MQL5およびMT5において、注文と取引は異なる概念です。

注文は、取引を実行するための指示です。例えば、特定の価格で買い注文や売り注文を出すことがこれに当たります。注文は、発注された時点ではまだ実行されていないため、マーケットに対して影響を及ぼしません。

取引は、注文が実行された結果としての実際の売買行為です。取引が成立することで、注文が履歴に記録され、ポジションが変更されます。つまり、取引は注文の結果として発生するアクションです。

OnTradeTransaction関数の引数について

void OnTradeTransaction(
    const MqlTradeTransaction& trans, 
    const MqlTradeRequest& request, 
    const MqlTradeResult& result
);

第1引数:trans

第1引数のtransは、MqlTradeTransaction構造体型の変数であり、取引口座で行われた取引に関する情報を含みます。具体的には、以下のフィールドが含まれます。

第2引数:request

第2引数のrequestは、MqlTradeRequest構造体型の変数であり、トランザクション(取引の実行プロセス)に関連する取引リクエストの詳細を含みます。通常、TRADE_TRANSACTION_REQUEST型のトランザクション値のみが含まれます。主なフィールドは以下の通りです。

  • action: 取引アクションの種類(ENUM_TRADE_REQUEST_ACTIONS列挙体)
  • symbol: 取引シンボル
  • volume: 取引数量
  • price: 取引価格
  • type: 注文の種類(ENUM_ORDER_TYPE列挙体)

MqlTradeRequest構造体の詳細については↓の記事をご参照ください。

第3引数:result

第3引数のresultは、取引リクエストの実行結果を参照する引数です。MqlTradeResult構造体型の変数であり、取引リクエストの結果を含みます。主なフィールドは以下の通りです。

  • retcode: 実行結果コード
  • order: 注文ID
  • deal: 取引ID
  • volume: 実行された取引数量
  • price: 実行された取引価格

MqlTradeResult構造体についての詳細は↓の記事をご参照ください。

OnTradeTransaction関数の戻り値について

OnTradeTransaction関数void型であり、戻り値はありません。関数の主な目的は、発生した取引トランザクション(取引の実行プロセス)に基づいて内部の処理を実行することです。

OnTradeTransaction関数を使う際の注意点

OnTradeTransaction関数を使用する際には、いくつかの重要な注意点があります。

  • 非同期処理: OnTradeTransaction関数は、取引サーバからのTradeTransactionイベントが発生するたびに呼び出されます。これにより、関数非同期に複数回呼び出される可能性があるため、スレッドセーフ(複数のスレッドから安全に呼び出すことができる)な処理が求められます。
    ※スレッドとは「プログラム内で並行して実行される複数の処理単位」を指します。
  • トランザクションの種類: trans引数のtypeフィールドは、ENUM_TRADE_TRANSACTION_TYPE列挙体の値を持ちます。このフィールドに基づいて、トランザクションの種類(注文追加、注文更新、取引追加など)を判断し、適切な処理を行う必要があります。
  • 順序の保証: トランザクション(取引の実行プロセス)の順序は保証されません。取引アルゴリズムを開発する際に、トランザクション(取引の実行プロセス)が到着する順番を前提として処理を行うべきではありません。
  • パフォーマンスの考慮: OnTradeTransaction関数内での処理が長時間かかる場合、トランザクションキュー(処理待ちの命令リスト)が1,024要素を超えると新しいトランザクション(取引の実行プロセス)が失われる可能性があります。処理時間を短縮し、迅速に次のトランザクション(取引の実行プロセス)を処理できるように工夫する必要があります。
  • データの一貫性: OnTradeTransaction関数の処理中に、取引口座の状態が変わる可能性があります。例えば、新しい注文が追加されると同時にその注文が実行され、リストから削除されることがあります。プログラムはこれらのイベントをすべて通知されるため、データの一貫性を保つための適切な処理が求められます。

OnTradeTransaction関数を使ったサンプルコード



//+------------------------------------------------------------------+
//| エキスパート初期化関数                                           |
//+------------------------------------------------------------------+
int OnInit()
{
  // 最後のPING時間をミリ秒単位で取得し、秒に変換して出力
  PrintFormat("LAST PING=%.f ms", TerminalInfoInteger(TERMINAL_PING_LAST)/1000.0);
  return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| エキスパートティック関数                                         |
//+------------------------------------------------------------------+
void OnTick()
{
  // ティックごとに実行されるコードをここに記述
}

//+------------------------------------------------------------------+
//| TradeTransaction 関数                                            |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
  static int counter = 0;   // OnTradeTransaction関数の呼び出し回数をカウント
  static uint lasttime = 0; // 最後にOnTradeTransactionが呼び出された時刻

  uint time = GetTickCount();
  
  // 最後のトランザクションが1秒以上前に実行された場合
  if (time - lasttime > 1000)
  {
    counter = 0; // 新しい取引としてカウンタをリセット
    if (IS_DEBUG_MODE)
      Print(" New trade operation");
  }

  lasttime = time;
  counter++;
  Print(counter, ". ", __FUNCTION__);

  // 取引リクエストの実行結果を出力
  ulong lastOrderID = trans.order;
  ENUM_ORDER_TYPE lastOrderType = trans.order_type;
  ENUM_ORDER_STATE lastOrderState = trans.order_state;
  string trans_symbol = trans.symbol; // トランザクションが実行される取引シンボルの名称
  ENUM_TRADE_TRANSACTION_TYPE trans_type = trans.type; // トランザクションの種類

  switch (trans.type)
  {
    case TRADE_TRANSACTION_POSITION:   // ポジション修正
    {
      ulong pos_ID = trans.position;
      PrintFormat("MqlTradeTransaction: Position #%I64u %s modified: SL=%.5f TP=%.5f",
                  pos_ID, trans_symbol, trans.price_sl, trans.price_tp);
    }
    break;

    case TRADE_TRANSACTION_REQUEST:     // 取引リクエストの送信
      PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
      break;

    case TRADE_TRANSACTION_DEAL_ADD:   // 取引の追加
    {
      ulong lastDealID = trans.deal;
      ENUM_DEAL_TYPE lastDealType = trans.deal_type;
      double lastDealVolume = trans.volume;
      string Exchange_ticket = "";
      if (HistoryDealSelect(lastDealID))
        Exchange_ticket = HistoryDealGetString(lastDealID, DEAL_EXTERNAL_ID);
      if (Exchange_ticket != "")
        Exchange_ticket = StringFormat("(Exchange deal=%s)", Exchange_ticket);

      PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot %s",
                  EnumToString(trans_type), lastDealID, EnumToString(lastDealType), trans_symbol, lastDealVolume, Exchange_ticket);
    }
    break;

    case TRADE_TRANSACTION_HISTORY_ADD: // 履歴への注文の追加
    {
      string Exchange_ticket = "";
      if (lastOrderState == ORDER_STATE_FILLED)
      {
        if (HistoryOrderSelect(lastOrderID))
          Exchange_ticket = HistoryOrderGetString(lastOrderID, ORDER_EXTERNAL_ID);
        if (Exchange_ticket != "")
          Exchange_ticket = StringFormat("(Exchange ticket=%s)", Exchange_ticket);
      }
      PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s %s",
                  EnumToString(trans_type), lastOrderID, EnumToString(lastOrderType), trans_symbol, EnumToString(lastOrderState), Exchange_ticket);
    }
    break;

    default: // 他のトランザクション
    {
      string Exchange_ticket = "";
      if (lastOrderState == ORDER_STATE_PLACED)
      {
        if (OrderSelect(lastOrderID))
          Exchange_ticket = OrderGetString(ORDER_EXTERNAL_ID);
        if (Exchange_ticket != "")
          Exchange_ticket = StringFormat("Exchange ticket=%s", Exchange_ticket);
      }
      PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s",
                  EnumToString(trans_type), lastOrderID, EnumToString(lastOrderType), trans_symbol, EnumToString(lastOrderState), Exchange_ticket);
    }
    break;
  }

  // 注文チケットと結果コードを出力
  ulong orderID_result = result.order;
  string retcode_result = GetRetcodeID(result.retcode);
  if (orderID_result != 0)
    PrintFormat("MqlTradeResult: order #%d retcode=%s ", orderID_result, retcode_result);
}

//+------------------------------------------------------------------+
//| 実行結果コードをテキストに変換する関数                           |
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
{
  switch (retcode)
  {
    case 10004: return "TRADE_RETCODE_REQUOTE"; break;
    case 10006: return "TRADE_RETCODE_REJECT"; break;
    case 10007: return "TRADE_RETCODE_CANCEL"; break;
    case 10008: return "TRADE_RETCODE_PLACED"; break;
    case 10009: return "TRADE_RETCODE_DONE"; break;
    case 10010: return "TRADE_RETCODE_DONE_PARTIAL"; break;
    case 10011: return "TRADE_RETCODE_ERROR"; break;
    case 10012: return "TRADE_RETCODE_TIMEOUT"; break;
    case 10013: return "TRADE_RETCODE_INVALID"; break;
    case 10014: return "TRADE_RETCODE_INVALID_VOLUME"; break;
    case 10015: return "TRADE_RETCODE_INVALID_PRICE"; break;
    case 10016: return "TRADE_RETCODE_INVALID_STOPS"; break;
    case 10017: return "TRADE_RETCODE_TRADE_DISABLED"; break;
    case 10018: return "TRADE_RETCODE_MARKET_CLOSED"; break;
    case 10019: return "TRADE_RETCODE_NO_MONEY"; break;
    case 10020: return "TRADE_RETCODE_PRICE_CHANGED"; break;
    case 10021: return "TRADE_RETCODE_PRICE_OFF"; break;
    case 10022: return "TRADE_RETCODE_INVALID_EXPIRATION"; break;
    case 10023: return "TRADE_RETCODE_ORDER_CHANGED"; break;
    case 10024: return "TRADE_RETCODE_TOO_MANY_REQUESTS"; break;
    case 10025: return "TRADE_RETCODE_NO_CHANGES"; break;
    case 10026: return "TRADE_RETCODE_SERVER_DISABLES_AT"; break;
    case 10027: return "TRADE_RETCODE_CLIENT_DISABLES_AT"; break;
    case 10028: return "TRADE_RETCODE_LOCKED"; break;
    case 10029: return "TRADE_RETCODE_FROZEN"; break;
    case 10030: return "TRADE_RETCODE_INVALID_FILL"; break;
    case 10031: return "TRADE_RETCODE_CONNECTION"; break;
    case 10032: return "TRADE_RETCODE_ONLY_REAL"; break;
    case 10033: return "TRADE_RETCODE_LIMIT_ORDERS"; break;
    case 10034: return "TRADE_RETCODE_LIMIT_VOLUME"; break;
    case 10035: return "TRADE_RETCODE_INVALID_ORDER"; break;
    case 10036: return "TRADE_RETCODE_POSITION_CLOSED"; break;
    default:
      return "TRADE_RETCODE_UNKNOWN=" + IntegerToString(retcode);
      break;
  }
}

サンプルコード解説1: OnInit関数とOnTick関数

OnInit関数の解説

//+------------------------------------------------------------------+
//| エキスパート初期化関数                                           |
//+------------------------------------------------------------------+
int OnInit()
{
  // 最後のPING時間をミリ秒単位で取得し、秒に変換して出力
  PrintFormat("LAST PING=%.f ms", TerminalInfoInteger(TERMINAL_PING_LAST)/1000.0);
  return(INIT_SUCCEEDED);
}

OnInit関数の役割

OnInit関数は、エキスパートアドバイザEA)が初期化されるときに最初に呼び出される関数です。この関数は、EAの初期設定や初期値の取得、ログの出力などを行うために使用されます。

PrintFormat関数

PrintFormat関数は、指定されたフォーマットに従って文字列を作成し、エキスパートログ(コンソール)に出力します。この関数は、デバッグ情報や重要なメッセージをユーザーに通知するために使用されます。

TerminalInfoInteger関数

TerminalInfoInteger関数は、指定された端末プロパティの整数値を取得します。この関数は、端末に関するさまざまな情報を取得するために使用されます。ここでは、TERMINAL_PING_LASTという識別子を使って最後のPING時間を取得しています。

TERMINAL_PING_LAST識別子

TERMINAL_PING_LASTは、サーバーへの最後のPING時間を表す識別子です。

PING時間とは?

PING時間とは、クライアント端末からサーバーまでの往復時間を測定したものです。これにより、通信の遅延を確認することができます。

PINGは、”Packet InterNet Groper” の略です。これは、ネットワーク上で特定のコンピュータやサーバーに信号を送り、その応答を確認するためのコマンド(命令)の名前です。

ミリ秒から秒への変換

取得したPING時間はミリ秒単位で表されるため、1000で割ることで秒単位に変換しています。これは、ユーザーがより理解しやすい形で時間を表示するためです。

INIT_SUCCEEDED

INIT_SUCCEEDEDは、初期化が成功したことを示す定数です。OnInit関数はこの定数を返すことで、EAの初期化が正常に完了したことを示します。

OnTick関数の解説

//+------------------------------------------------------------------+
//| エキスパートティック関数                                         |
//+------------------------------------------------------------------+
void OnTick()
{
  // ティックごとに実行されるコードをここに記述
}

OnTick関数の役割

OnTick関数は、チャート上で新しいティック(価格の変動)が発生するたびに呼び出される関数です。この関数内に記述されたコードは、ティックごとに実行されます。取引のロジックやインジケータの計算など、ティック単位での処理を行う場合に使用されます。

サンプルコード解説2: TradeTransaction 関数その1

TradeTransaction 関数の解説

//+------------------------------------------------------------------+
//| TradeTransaction 関数                                            |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
  static int counter = 0;   // OnTradeTransaction関数の呼び出し回数をカウント
  static uint lasttime = 0; // 最後にOnTradeTransactionが呼び出された時刻

  uint time = GetTickCount();

  // 最後のトランザクションが1秒以上前に実行された場合
  if (time - lasttime > 1000)
  {
    counter = 0; // 新しい取引としてカウンタをリセット
    if (IS_DEBUG_MODE)
      Print(" New trade operation");
  }

OnTradeTransaction関数の役割

OnTradeTransaction関数は、TradeTransactionイベントが発生したときに自動的に呼び出されます。TradeTransactionイベントは、取引リクエストの実行結果に関連するイベントで、注文の追加、更新、削除、取引の追加、更新、削除などの取引トランザクション(取引の実行プロセス)が含まれます。
この関数は、そのイベントに対して必要な処理を行います。

引数の解説

静的変数 counter と lasttime

GetTickCount関数

GetTickCount関数は、システムが起動してから経過した時間をミリ秒(1/1000秒)単位で取得します。この関数を使用して、トランザクション(取引の実行プロセス)が最後に実行された時刻を記録します。

トランザクションの間隔をチェックする処理

  • if (time – lasttime > 1000): 現在の時刻と最後のトランザクションの時刻の差が1000ミリ秒(1秒)以上である場合、新しい取引としてカウンタをリセットします。
  • counter = 0: カウンタをリセットして、新しい取引が始まったことを示します。
  • if (IS_DEBUG_MODE) Print(” New trade operation”);: デバッグモードの場合、新しい取引操作のメッセージをエキスパートログ(コンソール)に出力します。

この部分のコードは、トランザクション(取引の実行プロセス)の発生間隔をチェックし、1秒以上の間隔があった場合にカウンタをリセットし、新しい取引が始まったことを示す処理を行っています。

サンプルコード解説3: TradeTransaction 関数その2

TradeTransaction 関数の解説(続き)

  lasttime = time;
  counter++;
  Print(counter, ". ", __FUNCTION__);

  // 取引リクエストの実行結果を出力
  ulong lastOrderID = trans.order;
  ENUM_ORDER_TYPE lastOrderType = trans.order_type;
  ENUM_ORDER_STATE lastOrderState = trans.order_state;
  string trans_symbol = trans.symbol; // トランザクションが実行される取引シンボルの名称
  ENUM_TRADE_TRANSACTION_TYPE trans_type = trans.type; // トランザクションの種類

時刻とカウンタの更新

  • lasttime = time: 現在の時刻をlasttimeに記録し、次回の呼び出し時に使用します。
  • counter++: 呼び出し回数カウンタをインクリメントします。これにより、関数が何回呼び出されたかを追跡します。
  • Print(counter, “. “, __FUNCTION__);: カウンタの値と関数名をエキスパートログ(コンソール)に出力します。これにより、関数の呼び出し回数を確認することができます。

トランザクションの詳細情報の取得

  • ulong lastOrderID = trans.order;: 最後の注文IDを取得します。これはトランザクションに関連する注文のIDです。
  • ENUM_ORDER_TYPE lastOrderType = trans.order_type;: 最後の注文タイプを取得します。注文タイプは、買い注文や売り注文などを示します。
  • ENUM_ORDER_STATE lastOrderState = trans.order_state;: 最後の注文状態を取得します。注文状態は、注文が有効、部分約定、全約定、キャンセルなどの状態を示します。
  • string trans_symbol = trans.symbol;: トランザクションが実行される取引シンボルの名称を取得します。これは、取引対象の金融商品(例:通貨ペアや株式)のシンボルです。
  • ENUM_TRADE_TRANSACTION_TYPE trans_type = trans.type;: トランザクションの種類を取得します。トランザクションの種類は、ENUM_TRADE_TRANSACTION_TYPE列挙体に定義されており、新規注文の追加、注文の更新、取引の追加などのイベントタイプを示します。

この部分のコードでは、トランザクションの詳細情報を取得し、それをエキスパートログに出力する準備をしています。これにより、各トランザクションの内容を正確に把握し、後続の処理で使用することができます。

サンプルコード解説4: TradeTransaction 関数その3

switch (trans.type)
  {
    case TRADE_TRANSACTION_POSITION:   // ポジション修正
    {
      ulong pos_ID = trans.position;
      PrintFormat("MqlTradeTransaction: Position #%I64u %s modified: SL=%.5f TP=%.5f",
                  pos_ID, trans_symbol, trans.price_sl, trans.price_tp);
    }
    break;

    case TRADE_TRANSACTION_REQUEST:     // 取引リクエストの送信
      PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
      break;

    case TRADE_TRANSACTION_DEAL_ADD:   // 取引の追加
    {
      ulong lastDealID = trans.deal;
      ENUM_DEAL_TYPE lastDealType = trans.deal_type;
      double lastDealVolume = trans.volume;
      string Exchange_ticket = "";
      if (HistoryDealSelect(lastDealID))
        Exchange_ticket = HistoryDealGetString(lastDealID, DEAL_EXTERNAL_ID);
      if (Exchange_ticket != "")
        Exchange_ticket = StringFormat("(Exchange deal=%s)", Exchange_ticket);

      PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot %s",
                  EnumToString(trans_type), lastDealID, EnumToString(lastDealType), trans_symbol, lastDealVolume, Exchange_ticket);
    }
    break;

    case TRADE_TRANSACTION_HISTORY_ADD: // 履歴への注文の追加
    {
      string Exchange_ticket = "";
      if (lastOrderState == ORDER_STATE_FILLED)
      {
        if (HistoryOrderSelect(lastOrderID))
          Exchange_ticket = HistoryOrderGetString(lastOrderID, ORDER_EXTERNAL_ID);
        if (Exchange_ticket != "")
          Exchange_ticket = StringFormat("(Exchange ticket=%s)", Exchange_ticket);
      }
      PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s %s",
                  EnumToString(trans_type), lastOrderID, EnumToString(lastOrderType), trans_symbol, EnumToString(lastOrderState), Exchange_ticket);
    }
    break;

    default: // 他のトランザクション
    {
      string Exchange_ticket = "";
      if (lastOrderState == ORDER_STATE_PLACED)
      {
        if (OrderSelect(lastOrderID))
          Exchange_ticket = OrderGetString(ORDER_EXTERNAL_ID);
        if (Exchange_ticket != "")
          Exchange_ticket = StringFormat("Exchange ticket=%s", Exchange_ticket);
      }
      PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s",
                  EnumToString(trans_type), lastOrderID, EnumToString(lastOrderType), trans_symbol, EnumToString(lastOrderState), Exchange_ticket);
    }
    break;
  }

トランザクションの種類に応じた処理

この部分のコードは、トランザクションの種類に応じて適切な処理を行うために使用されます。trans.typeフィールドの値に基づいて、異なるケースが実行されます。

  • TRADE_TRANSACTION_POSITION: ポジションの修正を処理します。
  • pos_IDは、ポジションIDを取得します。
  • PrintFormat関数でポジションの修正内容をエキスパートログに出力します。具体的には、ポジションID、シンボル、ストップロス(SL)、テイクプロフィット(TP)の値を表示します。
  • TRADE_TRANSACTION_REQUEST: 取引リクエストの送信を処理します。
  • PrintFormat関数で取引リクエストの送信メッセージをエキスパートログに出力します。
  • TRADE_TRANSACTION_DEAL_ADD: 新しい取引の追加を処理します。
  • lastDealIDは、取引IDを取得します。
  • lastDealTypeは、取引の種類を取得します。
  • lastDealVolumeは、取引量を取得します。
  • Exchange_ticketは、チケット情報を保持する文字列です。HistoryDealSelect関数で取引IDを選択し、HistoryDealGetString関数でチケット情報を取得します。
  • PrintFormat関数で取引の詳細をエキスパートログに出力します。取引ID、取引種類、シンボル、取引量、およびチケット情報を表示します。
  • TRADE_TRANSACTION_HISTORY_ADD: 履歴への注文の追加を処理します。
  • Exchange_ticketはチケット情報を保持する文字列です。注文が実行された場合、HistoryOrderSelect関数で注文IDを選択し、HistoryOrderGetString関数でチケット情報を取得します。
  • PrintFormat関数数で履歴への注文追加の詳細をエキスパートログに出力します。トランザクションの種類、注文ID、注文種類、シンボル、注文状態、およびチケット情報を表示します。
  • default: 他のすべてのトランザクションを処理します。
  • Exchange_ticketはチケット情報を保持する文字列です。注文が配置された場合、OrderSelect関数で注文IDを選択し、OrderGetString関数でチケット情報を取得します。
  • PrintFormat関数でその他のトランザクションの詳細をエキスパートログに出力します。トランザクションの種類、注文ID、注文種類、シンボル、注文状態、およびチケット情報を表示します。

このコードは、トランザクションの種類に応じて適切な処理を行い、各トランザクションの詳細をエキスパートログに出力することで、取引の状態を正確に把握できるようにしています。

サンプルコード解説5: TradeTransaction関数その4

TradeTransaction 関数の解説(続き)

  // 注文チケットと結果コードを出力
  ulong orderID_result = result.order;
  string retcode_result = GetRetcodeID(result.retcode);
  if (orderID_result != 0)
    PrintFormat("MqlTradeResult: order #%d retcode=%s ", orderID_result, retcode_result);
}

注文チケットと結果コードの出力

  • ulong orderID_result = result.order;: 取引リクエストの実行結果として返された注文IDを取得します。これはMqlTradeResult構造体orderフィールドから取得されます。
  • string retcode_result = GetRetcodeID(result.retcode);: 取引リクエストの実行結果コードを取得し、それを文字列に変換します。この変換は、GetRetcodeID関数を使用して行われます。

結果コードが0でない場合の処理

  • if (orderID_result != 0): orderID_resultが0でない場合、つまり有効な注文IDが存在する場合に以下の処理を行います。
  • PrintFormat(“MqlTradeResult: order #%d retcode=%s “, orderID_result, retcode_result);: 注文IDと結果コードをエキスパートログに出力します。注文IDと結果コードを整形して表示することで、取引の結果を確認することができます。

補足説明

MqlTradeResult構造体

  • MqlTradeResult構造体は、取引リクエストの実行結果を含むデータ構造です。主に以下のフィールドを持っています。
  • order: 実行された注文のID
  • retcode: 実行結果コード

GetRetcodeID関数

  • GetRetcodeID関数は、取引リクエストの実行結果コードを人間が読みやすい文字列に変換します。この関数は、数値で表された結果コードを対応するテキスト表現に変換するために使用されます。

サンプルコード解説6: GetRetcodeID関数(オリジナル関数)

GetRetcodeID関数の解説

//+------------------------------------------------------------------+
//| 実行結果コードをテキストに変換する関数                           |
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
{
  switch (retcode)
  {
    case 10004: return "TRADE_RETCODE_REQUOTE"; break;
    case 10006: return "TRADE_RETCODE_REJECT"; break;
    case 10007: return "TRADE_RETCODE_CANCEL"; break;
    case 10008: return "TRADE_RETCODE_PLACED"; break;
    case 10009: return "TRADE_RETCODE_DONE"; break;
    case 10010: return "TRADE_RETCODE_DONE_PARTIAL"; break;
    case 10011: return "TRADE_RETCODE_ERROR"; break;
    case 10012: return "TRADE_RETCODE_TIMEOUT"; break;
    case 10013: return "TRADE_RETCODE_INVALID"; break;
    case 10014: return "TRADE_RETCODE_INVALID_VOLUME"; break;
    case 10015: return "TRADE_RETCODE_INVALID_PRICE"; break;
    case 10016: return "TRADE_RETCODE_INVALID_STOPS"; break;
    case 10017: return "TRADE_RETCODE_TRADE_DISABLED"; break;
    case 10018: return "TRADE_RETCODE_MARKET_CLOSED"; break;
    case 10019: return "TRADE_RETCODE_NO_MONEY"; break;
    case 10020: return "TRADE_RETCODE_PRICE_CHANGED"; break;
    case 10021: return "TRADE_RETCODE_PRICE_OFF"; break;
    case 10022: return "TRADE_RETCODE_INVALID_EXPIRATION"; break;
    case 10023: return "TRADE_RETCODE_ORDER_CHANGED"; break;
    case 10024: return "TRADE_RETCODE_TOO_MANY_REQUESTS"; break;
    case 10025: return "TRADE_RETCODE_NO_CHANGES"; break;
    case 10026: return "TRADE_RETCODE_SERVER_DISABLES_AT"; break;
    case 10027: return "TRADE_RETCODE_CLIENT_DISABLES_AT"; break;
    case 10028: return "TRADE_RETCODE_LOCKED"; break;
    case 10029: return "TRADE_RETCODE_FROZEN"; break;
    case 10030: return "TRADE_RETCODE_INVALID_FILL"; break;
    case 10031: return "TRADE_RETCODE_CONNECTION"; break;
    case 10032: return "TRADE_RETCODE_ONLY_REAL"; break;
    case 10033: return "TRADE_RETCODE_LIMIT_ORDERS"; break;
    case 10034: return "TRADE_RETCODE_LIMIT_VOLUME"; break;
    case 10035: return "TRADE_RETCODE_INVALID_ORDER"; break;
    case 10036: return "TRADE_RETCODE_POSITION_CLOSED"; break;
    default:
      return "TRADE_RETCODE_UNKNOWN=" + IntegerToString(retcode);
      break;
  }
}

GetRetcodeID関数の役割

GetRetcodeID関数は、取引リクエストの実行結果コードを人間が読みやすい文字列に変換するための関数です。取引結果コードは通常数値で表されますが、この関数を使用することで、対応するテキスト表現を取得しやすくなります。

関数の引数

  • int retcode: 取引リクエストの実行結果コード。このコードは、取引の結果を数値で表したものです。

関数の戻り値

関数の実装

  • switch文を使用して、結果コードに対応する文字列を返します。各ケースは、特定の結果コードに対応しています。
  • 各ケースの構文は次の通りです:
  case 結果コード: return "対応する文字列"; break;
  • デフォルトのケースでは、未知の結果コードを処理し、”TRADE_RETCODE_UNKNOWN=”というプレフィックス(前につける記号)と結果コードを文字列に変換したものを返します。

具体的なケースの説明

以下は、いくつかのケースの具体的な説明です:

リターンコードの詳細は↓の記事をご参照ください。

デフォルトケースの説明

  • default: 上記のどのケースにも該当しない場合、このブロックが実行されます。未知の結果コードとして処理され、”TRADE_RETCODE_UNKNOWN=”と結果コードが文字列に変換されたものを返します。

この関数は、取引の結果を簡単に理解できる形式で表示するために使用されます。これにより、取引リクエストの結果を迅速に判断し、適切な対応を取ることができます。

タイトルとURLをコピーしました