【MQL5】OrderSendAsync関数について

MQL5リファレンス
スポンサーリンク
  1. OrderSendAsync関数の働き・役割
  2. OrderSend関数との違い
    1. OrderSend関数
    2. OrderSendAsync関数
  3. OrderSendAsync関数の引数について
    1. request
    2. result
  4. OrderSendAsync関数の戻り値について
  5. OrderSendAsync関数を使う際の注意点
  6. OrderSendAsync関数を使ったサンプルコード
  7. 解説1:グローバル領域での定義
    1. スクリプトの説明
    2. 入力パラメータの定義
    3. 変数の宣言
    4. 詳細な解説
  8. 解説2:OnInit関数
    1. OnInit関数の役割
    2. コードの解説
    3. 詳細な解説
  9. 解説3:OnDeinit関数
    1. OnDeinit関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  10. 解説4:OnTradeTransaction関数
    1. OnTradeTransaction関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  11. 解説5:OnTrade関数
    1. OnTrade関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  12. 解説6:OnChartEvent関数
    1. OnChartEvent関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  13. 解説7:TransactionDescription関数(オリジナル関数)
    1. TransactionDescription関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  14. 解説8:RequestDescription関数(オリジナル関数)
    1. RequestDescription関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  15. 解説9:TradeResultDescription関数(オリジナル関数)
    1. TradeResultDescription関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  16. 解説10:CreateBuySellButtons関数(オリジナル関数)
    1. CreateBuySellButtons関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  17. 解説11:BuyAsync関数(オリジナル関数)
    1. BuyAsync関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ
  18. 解説12:SellAsync関数(オリジナル関数)
    1. SellAsync関数の役割
    2. コードの解説
    3. 詳細な解説
    4. 全体の流れ

OrderSendAsync関数の働き・役割

OrderSendAsync関数は、取引サーバの返答を待たずに非同期的(同時に複数の処理を進めることができる)な取引操作を行うためのリクエストを送信するために使用されます。

この関数は、サーバからの応答を待つ時間の無駄を容認できない取引アルゴリズムの条件下での高頻度取引のために設計されています。高頻度取引とは、非常に短い時間内で多くの取引を行う戦略を指し、迅速な処理が求められます。

OrderSendAsync関数を使用することで、取引のリクエストを即座に送信し、その結果を待たずに次の処理を行うことが可能になります。

OrderSend関数との違い

OrderSend関数OrderSendAsync関数の主な違いは、リクエストの送信方法と応答の待機方法にあります。

OrderSend関数

OrderSend関数は、取引リクエストをサーバに送信し、その結果が返ってくるまで処理を停止します。サーバからの応答を待つ間、プログラムの他の部分は実行されません。

このため、処理の遅延が発生する可能性がありますが、確実に取引が完了したかどうかを確認できます。

OrderSendAsync関数

OrderSendAsync関数は、取引リクエストを非同期的(同時に複数の処理を進めることができる)にサーバに送信し、サーバからの応答を待たずに次の処理を続行します。

これにより、処理の遅延を回避できるため、高頻度取引やリアルタイム性が求められるシステムに適しています。

ただし、リクエストが確実に完了したかどうかを確認するには、別途TradeイベントやOnTradeTransaction関数を使用して取引結果を監視する必要があります。

OrderSendAsync関数の引数について

OrderSendAsync関数引数構成は以下の通りです。

bool OrderSendAsync(
  MqlTradeRequest& request,  // リクエスト構造体
  MqlTradeResult& result     // 返答構造体
);

request

  • 第1引数
  • 種類: MqlTradeRequest構造体型の構造体への参照
  • 説明: クライアントの取引アクションを記述します。この構造体には、取引の詳細(例えば、シンボル、注文タイプ、価格、ボリュームなど)が含まれます。

result

  • 第2引数
  • 種類: MqlTradeResult型の構造体への参照
  • 説明: 成功した場合(true が返される場合)取引操作の結果を表します。この構造体には、取引の結果(例えば、リクエストID、注文チケット、価格、ボリュームなど)が含まれます。

OrderSendAsync関数の戻り値について

OrderSendAsync関数は、リクエストが取引サーバに送信された場合はtrue、それ以外の場合はfalseを返します。リクエストが送信された場合、result変数内でレスポンスコードがTRADE_RETCODE_PLACED(コード 10008 – 注文が出された)を含みます。

正常な実行は送信の事実のみを意味し、リクエストが取引サーバに到達し処理のために受け入れられている保証を与えるものではありません。受信したリクエストを処理する際、取引サーバは、ポジション、注文や約定の状態の変化を通知する応答をクライアント端末に送信し、これがTradeイベント生成につながります。

OrderSendAsync関数を使う際の注意点

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

OrderSendAsync関数非同期的(同時に複数の処理を進めることができる)であるため、関数の実行結果を待っている間にプログラムの動作は止められません。このため、取引結果が確実に処理されたかどうかを確認するためには、TradeイベントやOnTradeTransaction関数を使用して取引結果を追跡する必要があります。

取引リクエストの送信速度が向上する一方で、取引の成功を保証するものではないため、適切なエラーハンドリングを行う必要があります。例えば、リクエストがサーバに届かなかった場合や、取引が失敗した場合に備えてエラー処理を実装しておくことが重要です。

また、OrderSendAsync関数を利用する際には、過度なリクエスト送信を避けるために、送信間隔や取引条件を慎重に設定することが推奨されます。過剰なリクエストはサーバ負荷を増加させ、最悪の場合、取引が拒否される原因となります。

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

以下に、OrderSendAsync関数を使用して取引リクエストを非同期に送信し、取引イベントを処理するサンプルコードを示します。


#property description "OrderSendAsync() 関数を使用して取引リクエストを送信するエキスパートアドバイザー。\r\n"
#property description "OnTrade() および OnTradeTransaction() ハンドラ関数を使用した取引イベントの処理を表示します。\r\n"
#property description "エキスパートアドバイザーのパラメータで、Magic Number(ユニークID)の設定とエキスパートログにメッセージを表示するモードを設定できます。\r\n"
#property description "詳細はデフォルトで全て表示されます。\r\n"

//--- 入力パラメータ
input int MagicNumber=1234567;      // エキスパートアドバイザー ID
input bool DescriptionModeFull=true; // 詳細出力モード
//--- HistorySelect() 呼び出しに使用される変数
datetime history_start;

//+------------------------------------------------------------------+
//| エキスパート初期化に使用される関数                                    |
//+------------------------------------------------------------------+
int OnInit()
{
  //--- 自動売買が許可されているかどうかをチェックする
  if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
  {
    Alert("自動売買が無効です。エキスパートアドバイザーは削除されます。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-1); // エラーコードを返す
  }

  //--- 実際の口座での取引が不可能かをチェックする
  if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
  {
    Alert("エキスパートアドバイザーは実際の口座で取引できません。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-2); // エラーコードを返す
  }

  //--- この口座で取引が可能かどうかをチェックする(例えば、投資家のパスワードを使用しての取引は不可能)
  if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
  {
    Alert("この口座での取引は無効です。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-3); // エラーコードを返す
  }

  //--- 取引履歴を受信するためにエキスパートアドバイザーを起動する時間を記録する
  history_start=TimeCurrent();
  //--- 買い注文と売り注文のボタンを作成する
  CreateBuySellButtons();
  
  return(INIT_SUCCEEDED); // 初期化成功を返す
}

//+------------------------------------------------------------------+
//| エキスパート初期化解除に使用される関数                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  //--- 全てのグラフィックオブジェクトを削除する
  ObjectDelete(0,"Buy");
  ObjectDelete(0,"Sell");
}

//+------------------------------------------------------------------+
//| 取引トランザクションを処理する関数                                 |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                      const MqlTradeRequest &request,
                      const MqlTradeResult &result)
{
  //--- 取引イベントのハンドラ関数名にちなんだメッセージを表示する
  Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
  //--- トランザクションタイプを取得する
  ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
  
  //--- トランザクションがリクエスト処理の結果の場合
  if(type==TRADE_TRANSACTION_REQUEST)
  {
    //--- トランザクションタイプを表示する
    Print(EnumToString(type));
    //--- 処理されたリクエストの詳細を表示する
    Print("------------RequestDescription\r\n", RequestDescription(request,DescriptionModeFull));
    //--- リクエスト結果の詳細を表示する
    Print("------------ ResultDescription\r\n", TradeResultDescription(result,DescriptionModeFull));
  }
  else // 他のトランザクションタイプの場合
  {
    //--- トランザクションの詳細を表示する
    Print("------------ TransactionDescription\r\n", TransactionDescription(trans,DescriptionModeFull));
  }
}

//+------------------------------------------------------------------+
//| 取引イベントを処理する関数                                        |
//+------------------------------------------------------------------+
void OnTrade()
{
  //--- 取引口座の状態を格納する静的変数
  static int prev_positions=0,prev_orders=0,prev_deals=0,prev_history_orders=0;
  //--- 取引履歴をリクエストする
  bool update=HistorySelect(history_start,TimeCurrent());
  PrintFormat("HistorySelect(%s , %s) = %s", TimeToString(history_start),TimeToString(TimeCurrent()),(string)update);
  
  //--- 取引イベントのハンドラ関数名にちなんだメッセージを表示する
  Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
  //--- 処理の瞬間の注文数を表示する
  int curr_positions=PositionsTotal();
  int curr_orders=OrdersTotal();
  int curr_deals=HistoryOrdersTotal();
  int curr_history_orders=HistoryDealsTotal();
  
  //--- 注文、ポジション、及び約定の数、またカッコ内に変更を表示する
  PrintFormat("PositionsTotal() = %d (%+d)", curr_positions,(curr_positions-prev_positions));
  PrintFormat("OrdersTotal() = %d (%+d)", curr_orders,curr_orders-prev_orders);
  PrintFormat("HistoryOrdersTotal() = %d (%+d)", curr_deals,curr_deals-prev_deals);
  PrintFormat("HistoryDealsTotal() = %d (%+d)", curr_history_orders,curr_history_orders-prev_history_orders);
  
  //--- ログをより便利に表示するための区切り文字を挿入する
  Print("");
  //--- 口座の状態を保存する
  prev_positions=curr_positions;
  prev_orders=curr_orders;
  prev_deals=curr_deals;
  prev_history_orders=curr_history_orders;
}

//+------------------------------------------------------------------+
//| チャートイベントを処理する関数                                    |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                const long &lparam,
                const double &dparam,
                const string &sparam)
{
  //--- CHARTEVENT_OBJECT_CLICK イベント(「チャートクリック」)の処理
  if(id==CHARTEVENT_OBJECT_CLICK)
  {
    Print("=> ",__FUNCTION__,": sparam = ",sparam);
    //--- 最小取引量を取得する
    double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
    //--- 「Buy」ボタンが押された場合
    if(sparam=="Buy")
    {
      PrintFormat("Buy %s %G lot",_Symbol,volume_min);
      BuyAsync(volume_min); // 非同期で買い注文を送信する
      //--- ボタンの状態をリセットする
      ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
    }
    //--- 「Sell」ボタンが押された場合
    if(sparam=="Sell")
    {
      PrintFormat("Sell %s %G lot",_Symbol,volume_min);
      SellAsync(volume_min); // 非同期で売り注文を送信する
      //--- ボタンの状態をリセットする
      ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
    }
    //--- チャートを再描画する
    ChartRedraw();
  }
}

//+------------------------------------------------------------------+
//| トランザクションの記述を文字列として返す関数                       |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans,
                            const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc=EnumToString(trans.type)+"\r\n";
  //--- detailedモードでは詳細を全て追加する
  if(detailed)
  {
    desc+="Symbol: "+trans.symbol+"\r\n";
    desc+="Deal ticket: "+(string)trans.deal+"\r\n";
    desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
    desc+="Order ticket: "+(string)trans.order+"\r\n";
    desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
    desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
    desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
    desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
    desc+="Price: "+StringFormat("%G",

trans.price)+"\r\n";
    desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
    desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
    desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
    desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

//+------------------------------------------------------------------+
//| 取引リクエストのテキスト記述を返す関数                            |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request,
                        const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc=EnumToString(request.action)+"\r\n";
  //--- detailedモードでは、使用可能のデータを全て追加する
  if(detailed)
  {
    desc+="Symbol: "+request.symbol+"\r\n";
    desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
    desc+="Order ticket: "+(string)request.order+"\r\n";
    desc+="Order type: "+EnumToString(request.type)+"\r\n";
    desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
    desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
    desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
    desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
    desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
    desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
    desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
    desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
    desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
    desc+="Comment: "+request.comment+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

//+------------------------------------------------------------------+
//| リクエスト処理結果の記述をテキスト形式で返す関数                   |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result,
                            const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc="Retcode "+(string)result.retcode+"\r\n";
  //--- detailedモードでは、使用可能のデータを全て追加する
  if(detailed)
  {
    desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
    desc+="Order ticket: "+(string)result.order+"\r\n";
    desc+="Deal ticket: "+(string)result.deal+"\r\n";
    desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
    desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
    desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
    desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
    desc+="Comment: "+result.comment+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

//+------------------------------------------------------------------+
//| 売買に必要な 2 つのボタンを作成する関数                           |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
{
  //--- 「Buy」オブジェクトをチェックする
  if(ObjectFind(0,"Buy")>=0)
  {
    //--- 見つかったオブジェクトがボタンでない場合は削除する
    if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
        ObjectDelete(0,"Buy");
  }
  else
    ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // 「Buy」 ボタンを作成する
  //--- 「Buy」 ボタンを設定する
  ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
  ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
  ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);

  //--- 「Sell」オブジェクトの存在をチェックする
  if(ObjectFind(0,"Sell")>=0)
  {
    //--- 見つかったオブジェクトがボタンでない場合は削除する
    if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
        ObjectDelete(0,"Sell");
  }
  else
    ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // 「 Sell 」ボタンを作成する
  //--- 「Sell」 ボタンを設定する
  ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
  ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);

  //--- ボタンをすぐに表示するためにチャートの強制アップデートを実行する
  ChartRedraw();
}

//+------------------------------------------------------------------+
//| OrderSendAsync() 非同期関数を使用して買い注文を送信する関数           |
//+------------------------------------------------------------------+
void BuyAsync(double volume)
{
  //--- リクエストを準備する
  MqlTradeRequest req={};
  req.action      =TRADE_ACTION_DEAL; // アクションタイプ: 取引
  req.symbol      =_Symbol;           // 取引するシンボル
  req.magic       =MagicNumber;       // Magic Number
  req.volume      =volume;            // 取引量
  req.type        =ORDER_TYPE_BUY;    // 注文タイプ: 買い
  req.price       =SymbolInfoDouble(req.symbol,SYMBOL_ASK); // 現在のAsk価格
  req.deviation   =10;                // 許容スリッページ
  req.comment     ="Buy using OrderSendAsync()"; // 注文コメント

  //--- 取引結果を格納する構造体
  MqlTradeResult res={};

  //--- 非同期で注文を送信し、成功したかどうかを確認する
  if(!OrderSendAsync(req,res))
  {
    //--- エラーが発生した場合の処理
    Print(__FUNCTION__, ": error ", GetLastError(), ", retcode = ", res.retcode);
  }
}

//+------------------------------------------------------------------+
//| OrderSendAsync() 非同期関数を使用して売り注文を送信する関数         |
//+------------------------------------------------------------------+
void SellAsync(double volume)
{
  //--- リクエストを準備する
  MqlTradeRequest req={};
  req.action      =TRADE_ACTION_DEAL; // アクションタイプ: 取引
  req.symbol      =_Symbol;           // 取引するシンボル
  req.magic       =MagicNumber;       // Magic Number
  req.volume      =volume;            // 取引量
  req.type        =ORDER_TYPE_SELL;   // 注文タイプ: 売り
  req.price       =SymbolInfoDouble(req.symbol,SYMBOL_BID); // 現在のBid価格
  req.deviation   =10;                // 許容スリッページ
  req.comment     ="Sell using OrderSendAsync()"; // 注文コメント

  //--- 取引結果を格納する構造体
  MqlTradeResult res={};

  //--- 非同期で注文を送信し、成功したかどうかを確認する
  if(!OrderSendAsync(req,res))
  {
    //--- エラーが発生した場合の処理
    Print(__FUNCTION__, ": error ", GetLastError(), ", retcode = ", res.retcode);
  }
}

解説1:グローバル領域での定義

スクリプトの説明

以下のコードは、エキスパートアドバイザーEA)の説明を定義しています。各行で、エキスパートアドバイザーの機能や目的を記述しています。

#property description "OrderSendAsync() 関数を使用して取引リクエストを送信するエキスパートアドバイザー。\r\n"
#property description "OnTrade() および OnTradeTransaction() ハンドラ関数を使用した取引イベントの処理を表示します。\r\n"
#property description "エキスパートアドバイザーのパラメータで、Magic Number(ユニークID)の設定とエキスパートログにメッセージを表示するモードを設定できます。\r\n"
#property description "詳細はデフォルトで全て表示されます。\r\n"

入力パラメータの定義

次に、エキスパートアドバイザーが使用する入力パラメータを定義します。これらのパラメータは、ユーザーがEAを設定する際に使用されます。

input int MagicNumber=1234567;      // エキスパートアドバイザー ID
input bool DescriptionModeFull=true; // 詳細出力モード

変数の宣言

最後に、EA内で使用する変数を宣言します。この変数は、取引履歴を受信するために使用されます。

datetime history_start;

詳細な解説

  • #property description:このディレクティブは、エキスパートアドバイザーの説明を設定します。複数行にわたる説明を記述することで、EAの目的や機能を明確に伝えます。
  • input int MagicNumber=1234567;:この行は、ユーザーがEAに一意(1つしか存在しない)の識別番号(マジックナンバー)を設定できるようにします。マジックナンバーは、複数のEAを区別するために使用されます。
  • input bool DescriptionModeFull=true;:この行は、EAの動作詳細をログに出力するかどうかを設定するためのフラグです。trueに設定すると、全ての詳細がログに出力されます。
  • datetime history_start;:この変数は、取引履歴を取得するために使用されます。EAの起動時刻を記録し、それ以降の取引履歴を選択する際に使用されます。

解説2:OnInit関数

OnInit関数の役割

OnInit関数は、エキスパートアドバイザーEA)の初期化時に自動的に呼び出される関数です。この関数では、EAが正常に動作するための準備作業を行います。具体的には、自動売買の許可状態や取引口座の状態を確認し、必要な設定を行います。

コードの解説

int OnInit()
{
  //--- 自動売買が許可されているかどうかをチェックする
  if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
  {
    Alert("自動売買が無効です。エキスパートアドバイザーは削除されます。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-1); // エラーコードを返す
  }

  //--- 実際の口座での取引が不可能かをチェックする
  if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
  {
    Alert("エキスパートアドバイザーは実際の口座で取引できません。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-2); // エラーコードを返す
  }

  //--- この口座で取引が可能かどうかをチェックする(例えば、投資家のパスワードを使用しての取引は不可能)
  if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
  {
    Alert("この口座での取引は無効です。");
    ExpertRemove(); // エキスパートアドバイザーを削除する
    return(-3); // エラーコードを返す
  }

  //--- 取引履歴を受信するためにエキスパートアドバイザーを起動する時間を記録する
  history_start=TimeCurrent();

  //--- 買い注文と売り注文のボタンを作成する
  CreateBuySellButtons();

  return(INIT_SUCCEEDED); // 初期化成功を返す
}

詳細な解説

解説3:OnDeinit関数

OnDeinit関数の役割

OnDeinit関数は、エキスパートアドバイザーEA)の終了時に自動的に呼び出される関数です。この関数では、EAの動作中に作成されたオブジェクトやリソースを適切に解放するための処理を行います。EAが停止されるときや、再起動されるときに実行されます。

コードの解説

//+------------------------------------------------------------------+
//| エキスパート初期化解除に使用される関数                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  //--- 全てのグラフィックオブジェクトを削除する
  ObjectDelete(0,"Buy");
  ObjectDelete(0,"Sell");
}

詳細な解説

  • void OnDeinit(const int reason):OnDeinit関数の定義です。EAの終了時に呼び出されます。reasonパラメータは、EAが終了される理由を示す整数値です。例えば、再起動や手動停止などの理由を表します。
  • ObjectDelete(0,”Buy”);:グラフィックオブジェクトとして作成された「Buy」ボタンを削除します。
  • ObjectDelete関数は、指定したオブジェクトをチャートから削除するために使用されます。
  • 最初の引数0 は現在のチャートを指定します。
  • 二つ目の引数"Buy" は削除するオブジェクトの名前を指定します。
  • ObjectDelete(0,”Sell”);:グラフィックオブジェクトとして作成された「Sell」ボタンを削除します。
  • ObjectDelete関数の使い方は「Buy」ボタンと同様で、ここでは「Sell」ボタンを削除します。

全体の流れ

OnDeinit関数は、EAが終了するときに呼び出され、EAの動作中に作成されたグラフィックオブジェクト(「Buy」ボタンと「Sell」ボタン)を削除します。これにより、EAが停止した後に不要なオブジェクトがチャート上に残るのを防ぎます。

解説4:OnTradeTransaction関数

OnTradeTransaction関数の役割

OnTradeTransaction関数は、取引トランザクションが発生した際に呼び出されるイベントハンドラーです。取引トランザクションとは、取引リクエストの処理結果や、取引注文、ポジションの変更などのイベントを指します。この関数では、取引トランザクションの詳細情報を取得し、ログに出力します。

コードの解説

//+------------------------------------------------------------------+
//| 取引トランザクションを処理する関数                                 |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                      const MqlTradeRequest &request,
                      const MqlTradeResult &result)
{
  //--- 取引イベントのハンドラ関数名にちなんだメッセージを表示する
  Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
  //--- トランザクションタイプを取得する
  ENUM_TRADE_TRANSACTION_TYPE type=trans.type;

  //--- トランザクションがリクエスト処理の結果の場合
  if(type==TRADE_TRANSACTION_REQUEST)
  {
    //--- トランザクションタイプを表示する
    Print(EnumToString(type));
    //--- 処理されたリクエストの詳細を表示する
    Print("------------RequestDescription\r\n", RequestDescription(request,DescriptionModeFull));
    //--- リクエスト結果の詳細を表示する
    Print("------------ ResultDescription\r\n", TradeResultDescription(result,DescriptionModeFull));
  }
  else // 他のトランザクションタイプの場合
  {
    //--- トランザクションの詳細を表示する
    Print("------------ TransactionDescription\r\n", TransactionDescription(trans,DescriptionModeFull));
  }
}

詳細な解説

  //--- トランザクションタイプを表示する
  Print(EnumToString(type));
  //--- 処理されたリクエストの詳細を表示する
  Print("------------RequestDescription\r\n", RequestDescription(request,DescriptionModeFull));
  //--- リクエスト結果の詳細を表示する
  Print("------------ ResultDescription\r\n", TradeResultDescription(result,DescriptionModeFull));
  • EnumToString(type):列挙型文字列に変換して表示します。
  • RequestDescription(request, DescriptionModeFull):リクエストの詳細を取得して表示します。
  • TradeResultDescription(result, DescriptionModeFull):リクエスト結果の詳細を取得して表示します。
  • else ブロック:
  • 他のトランザクションタイプの場合の処理を行います。
  //--- トランザクションの詳細を表示する
  Print("------------ TransactionDescription\r\n", TransactionDescription(trans,DescriptionModeFull));
  • TransactionDescription(trans, DescriptionModeFull):トランザクションの詳細を取得して表示します。

全体の流れ

OnTradeTransaction関数は、取引トランザクションが発生した際に呼び出され、トランザクションの種類に応じて適切な情報をログに出力します。取引リクエストの処理結果やその他の取引イベントの詳細を取得し、ユーザーに提供します。この関数により、取引の進行状況や結果をリアルタイムで監視することが可能になります。

解説5:OnTrade関数

OnTrade関数の役割

OnTrade関数は、取引イベントが発生した際に自動的に呼び出される関数です。この関数では、取引口座の状態や注文の状況を監視し、ログに出力します。例えば、新しい注文が発生したり、既存のポジションが変更されたりした場合に、この関数が実行されます。

コードの解説

//+------------------------------------------------------------------+
//| 取引イベントを処理する関数                                        |
//+------------------------------------------------------------------+
void OnTrade()
{
  //--- 取引口座の状態を格納する静的変数
  static int prev_positions=0, prev_orders=0, prev_deals=0, prev_history_orders=0;

  //--- 取引履歴をリクエストする
  bool update = HistorySelect(history_start, TimeCurrent());
  PrintFormat("HistorySelect(%s , %s) = %s", TimeToString(history_start), TimeToString(TimeCurrent()), (string)update);

  //--- 取引イベントのハンドラ関数名にちなんだメッセージを表示する
  Print("=> ", __FUNCTION__, " at ", TimeToString(TimeCurrent(), TIME_SECONDS));

  //--- 処理の瞬間の注文数を表示する
  int curr_positions = PositionsTotal();
  int curr_orders = OrdersTotal();
  int curr_deals = HistoryOrdersTotal();
  int curr_history_orders = HistoryDealsTotal();

  //--- 注文、ポジション、及び約定の数、またカッコ内に変更を表示する
  PrintFormat("PositionsTotal() = %d (%+d)", curr_positions, (curr_positions - prev_positions));
  PrintFormat("OrdersTotal() = %d (%+d)", curr_orders, (curr_orders - prev_orders));
  PrintFormat("HistoryOrdersTotal() = %d (%+d)", curr_deals, (curr_deals - prev_deals));
  PrintFormat("HistoryDealsTotal() = %d (%+d)", curr_history_orders, (curr_history_orders - prev_history_orders));

  //--- ログをより便利に表示するための区切り文字を挿入する
  Print("");

  //--- 口座の状態を保存する
  prev_positions = curr_positions;
  prev_orders = curr_orders;
  prev_deals = curr_deals;
  prev_history_orders = curr_history_orders;
}

詳細な解説

  • void OnTrade():OnTrade関数の定義です。取引イベントが発生した際に呼び出されます。
  • static int prev_positions=0, prev_orders=0, prev_deals=0, prev_history_orders=0;:
  • 取引口座の状態を格納する静的変数を定義します。静的変数関数の呼び出し間で値が保存されます。
  • bool update = HistorySelect(history_start, TimeCurrent());:
  • 取引履歴を選択します。HistorySelect関数は、指定した期間の取引履歴を取得します。
  • history_startはEAの起動時間、TimeCurrent()は現在の時間を示します。
  • PrintFormat(“HistorySelect(%s , %s) = %s”, TimeToString(history_start), TimeToString(TimeCurrent()), (string)update);
  • HistorySelect関数の呼び出し結果をフォーマットしてログに出力します。
  • Print(“=> “, __FUNCTION__, ” at “, TimeToString(TimeCurrent(), TIME_SECONDS));:
  • 現在の関数名と現在時刻をログに出力します。__FUNCTION__関数名を示します。
  • int curr_positions = PositionsTotal();:
  • 現在のポジション数を取得します。
  • int curr_orders = OrdersTotal();:
  • 現在の注文数を取得します。
  • int curr_deals = HistoryOrdersTotal();:
  • 現在の履歴注文数を取得します。
  • int curr_history_orders = HistoryDealsTotal();:
  • 現在の履歴約定数を取得します。
  • PrintFormat(“PositionsTotal() = %d (%+d)”, curr_positions, (curr_positions – prev_positions));:
  • 現在のポジション数と前回からの変化をログに出力します。
  • PrintFormat(“OrdersTotal() = %d (%+d)”, curr_orders, (curr_orders – prev_orders));:
  • 現在の注文数と前回からの変化をログに出力します。
  • PrintFormat(“HistoryOrdersTotal() = %d (%+d)”, curr_deals, (curr_deals – prev_deals));:
  • 現在の履歴注文数と前回からの変化をログに出力します。
  • PrintFormat(“HistoryDealsTotal() = %d (%+d)”, curr_history_orders, (curr_history_orders – prev_history_orders));:
  • 現在の履歴約定数と前回からの変化をログに出力します。
  • Print(“”);:
  • ログをより見やすくするための空行を挿入します。
  • prev_positions = curr_positions;:
  • 現在のポジション数を静的変数に保存します。
  • prev_orders = curr_orders;:
  • 現在の注文数を静的変数に保存します。
  • prev_deals = curr_deals;:
  • 現在の履歴注文数を静的変数に保存します。
  • prev_history_orders = curr_history_orders;:
  • 現在の履歴約定数を静的変数に保存します。

全体の流れ

OnTrade関数は、取引イベントが発生した際に呼び出され、現在の取引口座の状態や注文状況をログに出力します。これにより、取引イベントの詳細をリアルタイムで監視し、記録することができます。OnTrade関数はまた、前回の状態と比較して変化を表示するため、取引の進行状況を追跡するのに役立ちます。

解説6:OnChartEvent関数

OnChartEvent関数の役割

OnChartEvent関数は、チャート上で発生するイベントを処理するためのイベントハンドラーです。この関数は、チャート上でのユーザー操作(例えば、オブジェクトのクリック、キーの押下など)に応じて自動的に呼び出されます。イベントの種類に応じて、適切な処理を行います。

コードの解説

void OnChartEvent(const int id,
                const long &lparam,
                const double &dparam,
                const string &sparam)
{
  //--- CHARTEVENT_OBJECT_CLICK イベント(「チャートクリック」)の処理
  if(id==CHARTEVENT_OBJECT_CLICK)
  {
    Print("=> ",__FUNCTION__,": sparam = ",sparam);
    //--- 最小取引量を取得する
    double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
    //--- 「Buy」ボタンが押された場合
    if(sparam=="Buy")
    {
      PrintFormat("Buy %s %G lot",_Symbol,volume_min);
      BuyAsync(volume_min); // 非同期で買い注文を送信する
      //--- ボタンの状態をリセットする
      ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
    }
    //--- 「Sell」ボタンが押された場合
    if(sparam=="Sell")
    {
      PrintFormat("Sell %s %G lot",_Symbol,volume_min);
      SellAsync(volume_min); // 非同期で売り注文を送信する
      //--- ボタンの状態をリセットする
      ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
    }
    //--- チャートを再描画する
    ChartRedraw();
  }
}

詳細な解説

  • void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam):
  • OnChartEvent関数の定義です。チャート上で発生するイベントを処理します。
  • id:イベントの種類を示す整数値。
  • lparam:イベントに関連する追加情報を格納する長整数値。
  • dparam:イベントに関連する追加情報を格納する倍精度浮動小数点数。
  • sparam:イベントに関連する追加情報を格納する文字列
  • if(id==CHARTEVENT_OBJECT_CLICK):
  • イベントがオブジェクトのクリックであるかどうかを確認します。CHARTEVENT_OBJECT_CLICKは、オブジェクトがクリックされたことを示す定数です。
 Print("=> ",__FUNCTION__,": sparam = ",sparam);
  • 現在の関数名とイベントの追加情報(オブジェクトの名前)をログに出力します。__FUNCTION__関数名を示します。
  double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
  • 最小取引量を取得します。SymbolInfoDouble関数は、指定したシンボルの情報を取得するために使用されます。ここでは、現在のシンボル(_Symbol)の最小取引量(SYMBOL_VOLUME_MIN)を取得しています。
  if(sparam=="Buy")
  {
    PrintFormat("Buy %s %G lot",_Symbol,volume_min);
    BuyAsync(volume_min); // 非同期で買い注文を送信する
    //--- ボタンの状態をリセットする
    ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
  }
  • sparamが”Buy”の場合、つまり”Buy”ボタンが押された場合の処理です。
    • PrintFormatで、”Buy”ボタンが押されたことをログに出力します。
    • BuyAsync関数を呼び出し、非同期で買い注文を送信します。
    • ObjectSetInteger関数で、”Buy”ボタンの状態をリセットします。
  if(sparam=="Sell")
  {
    PrintFormat("Sell %s %G lot",_Symbol,volume_min);
    SellAsync(volume_min); // 非同期で売り注文を送信する
    //--- ボタンの状態をリセットする
    ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
  }
  • sparamが”Sell”の場合、つまり”Sell”ボタンが押された場合の処理です。
    • PrintFormatで、”Sell”ボタンが押されたことをログに出力します。
    • SellAsync関数を呼び出し、非同期で売り注文を送信します。
    • ObjectSetInteger関数で、”Sell”ボタンの状態をリセットします。
  ChartRedraw();
  • ChartRedraw関数を呼び出して、チャートを再描画します。これにより、ボタンの状態変更などが即座に反映されます。

全体の流れ

OnChartEvent関数は、チャート上で発生するイベント(特にオブジェクトのクリックイベント)を処理します。”Buy”ボタンまたは”Sell”ボタンがクリックされた場合に、対応する非同期の取引注文を送信し、ボタンの状態をリセットします。また、各イベント処理の際にログ出力を行い、チャートの再描画を行うことで、ユーザーインターフェースの更新を即座に反映させます。

解説7:TransactionDescription関数(オリジナル関数)

TransactionDescription関数の役割

TransactionDescription関数は、取引トランザクションの詳細情報を文字列として返すための関数です。トランザクションの種類や、関連するシンボル、注文情報などを整形して一つの文字列として返します。この関数は、トランザクションの内容をログに記録する際に便利です。

コードの解説

//+------------------------------------------------------------------+
//| トランザクションの記述を文字列として返す関数                       |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans,
                            const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc=EnumToString(trans.type)+"\r\n";
  //--- detailedモードでは詳細を全て追加する
  if(detailed)
  {
    desc+="Symbol: "+trans.symbol+"\r\n";
    desc+="Deal ticket: "+(string)trans.deal+"\r\n";
    desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
    desc+="Order ticket: "+(string)trans.order+"\r\n";
    desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
    desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
    desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
    desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
    desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
    desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
    desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
    desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
    desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

詳細な解説

  desc+="Symbol: "+trans.symbol+"\r\n";
  desc+="Deal ticket: "+(string)trans.deal+"\r\n";
  • 取引チケット番号を追加します。
  desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
  • 取引の種類を文字列に変換して追加します。
  desc+="Order ticket: "+(string)trans.order+"\r\n";
  • 注文チケット番号を追加します。
  desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
  • 注文の種類を文字列に変換して追加します。
  desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
  • 注文の状態を文字列に変換して追加します。
  desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
  • 注文の時間タイプを文字列に変換して追加します。
  desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
  • 注文の有効期限を文字列に変換して追加します。
  desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
  • 価格を文字列に変換して追加します。
  desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
  • トリガー価格を文字列に変換して追加します。
  desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
  • ストップロス価格を文字列に変換して追加します。
  desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
  • テイクプロフィット価格を文字列に変換して追加します。
  desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";

全体の流れ

TransactionDescription関数は、取引トランザクションの詳細情報を整形して文字列として返します。detailed パラメータが true の場合、トランザクションのすべての詳細情報を含めて返します。この関数を使用することで、取引トランザクションの内容を簡単に確認したり、ログに記録したりすることができます。

解説8:RequestDescription関数(オリジナル関数)

RequestDescription関数の役割

RequestDescription関数は、取引リクエストの詳細情報を文字列として返すための関数です。取引リクエストの種類や、関連するシンボル、注文情報などを整形して一つの文字列として返します。この関数は、取引リクエストの内容をログに記録する際に便利です。

コードの解説

//+------------------------------------------------------------------+
//| 取引リクエストのテキスト記述を返す関数                            |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request,
                        const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc=EnumToString(request.action)+"\r\n";
  //--- detailedモードでは、使用可能のデータを全て追加する
  if(detailed)
  {
    desc+="Symbol: "+request.symbol+"\r\n";
    desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
    desc+="Order ticket: "+(string)request.order+"\r\r\n";
    desc+="Order type: "+EnumToString(request.type)+"\r\n";
    desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
    desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
    desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
    desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
    desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
    desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
    desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
    desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
    desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
    desc+="Comment: "+request.comment+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

詳細な解説

  • string RequestDescription(const MqlTradeRequest &request, const bool detailed=true):
  • RequestDescription関数の定義です。取引リクエストの詳細を文字列として返します。
  • request:取引リクエストの詳細を含む MqlTradeRequest 型の構造体
  • detailed:詳細モードを示すブール値。trueの場合、詳細情報を含めて返します。
  • string desc=EnumToString(request.action)+”\r\n”;:
  • リクエストのアクションタイプを文字列に変換して desc 文字列に追加します。EnumToString は、列挙型文字列に変換します。
  • if(detailed):
  • detailed パラメータが true の場合、詳細情報を追加します。
  desc+="Symbol: "+request.symbol+"\r\n";
  • リクエストに関連するシンボルを追加します。
  desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
 desc+="Order ticket: "+(string)request.order+"\r\n";
  • 注文チケット番号を追加します。
  desc+="Order type: "+EnumToString(request.type)+"\r\n";
  • 注文の種類を文字列に変換して追加します。
 desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
  desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
  • 注文の時間タイプを文字列に変換して追加します。
  desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
  • 注文の有効期限を文字列に変換して追加します。
  desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
  • 価格を文字列に変換して追加します。
  desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
  desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
  • ストップロス価格を文字列に変換して追加します。
  desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
  • テイクプロフィット価格を文字列に変換して追加します。
  desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
  • ストップリミット価格を文字列に変換して追加します。
  desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
  • 取引量を文字列に変換して追加します。
  desc+="Comment: "+request.comment+"\r\n";
  • 注文のコメントを追加します。
  • return desc;:
  • 準備した文字列を返します。

全体の流れ

RequestDescription関数は、取引リクエストの詳細情報を整形して文字列として返します。detailed パラメータが true の場合、リクエストのすべての詳細情報を含めて返します。この関数を使用することで、取引リクエストの内容を簡単に確認したり、ログに記録したりすることができます。

解説9:TradeResultDescription関数(オリジナル関数)

TradeResultDescription関数の役割

TradeResultDescription関数は、取引リクエストの処理結果の詳細情報を文字列として返すための関数です。取引リクエストの結果に関連する情報を整形して一つの文字列として返します。この関数は、取引結果の内容をログに記録する際に便利です。

コードの解説

//+------------------------------------------------------------------+
//| リクエスト処理結果の記述をテキスト形式で返す関数                   |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result,
                            const bool detailed=true)
{
  //--- 関数が返す文字列を準備する
  string desc="Retcode "+(string)result.retcode+"\r\n";
  //--- detailedモードでは、使用可能のデータを全て追加する
  if(detailed)
  {
    desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
    desc+="Order ticket: "+(string)result.order+"\r\n";
    desc+="Deal ticket: "+(string)result.deal+"\r\n";
    desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
    desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
    desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
    desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
    desc+="Comment: "+result.comment+"\r\n";
  }
  //--- 受信された文字列を返す
  return desc;
}

詳細な解説

  • string TradeResultDescription(const MqlTradeResult &result, const bool detailed=true):
  • TradeResultDescription関数の定義です。取引リクエストの処理結果の詳細を文字列として返します。
  • result:取引リクエストの結果を含む MqlTradeResult 型の構造体
  • detailed:詳細モードを示すブール値。trueの場合、詳細情報を含めて返します。
  • string desc=”Retcode “+(string)result.retcode+”\r\n”;:
  • リターンコード文字列に変換して desc 文字列に追加します。result.retcode は取引リクエストの結果を示すコードです。
  • if(detailed):
  • detailed パラメータが true の場合、詳細情報を追加します。
  desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
  • リクエストIDを文字列に変換して追加します。
  desc+="Order ticket: "+(string)result.order+"\r\n";
  • 注文チケット番号を追加します。
 desc+="Deal ticket: "+(string)result.deal+"\r\n";
  • 取引チケット番号を追加します。
  desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
  • 取引量を文字列に変換して追加します。
  desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
  • 価格を文字列に変換して追加します。
  desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
  • Ask価格を文字列に変換して追加します。
  desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
  • Bid価格を文字列に変換して追加します。
  desc+="Comment: "+result.comment+"\r\n";
  • 注文のコメントを追加します。
  • return desc;:
  • 準備した文字列を返します。

全体の流れ

TradeResultDescription関数は、取引リクエストの処理結果の詳細情報を整形して文字列として返します。detailed パラメータが true の場合、リクエスト結果のすべての詳細情報を含めて返します。この関数を使用することで、取引リクエストの結果を簡単に確認したり、ログに記録したりすることができます。

解説10:CreateBuySellButtons関数(オリジナル関数)

CreateBuySellButtons関数の役割

CreateBuySellButtons関数は、チャート上に「Buy」ボタンと「Sell」ボタンの2つのグラフィックオブジェクトを作成し、設定するための関数です。このボタンはユーザーがクリックすることで、対応する取引を実行するトリガーとなります。

コードの解説

//+------------------------------------------------------------------+
//| 売買に必要な 2 つのボタンを作成する関数                           |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
{
  //--- 「Buy」オブジェクトをチェックする
  if(ObjectFind(0,"Buy")>=0)
  {
    //--- 見つかったオブジェクトがボタンでない場合は削除する
    if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
        ObjectDelete(0,"Buy");
  }
  else
    ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // 「Buy」 ボタンを作成する
  //--- 「Buy」 ボタンを設定する
  ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
  ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
  ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);

  //--- 「Sell」オブジェクトの存在をチェックする
  if(ObjectFind(0,"Sell")>=0)
  {
    //--- 見つかったオブジェクトがボタンでない場合は削除する
    if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
        ObjectDelete(0,"Sell");
  }
  else
    ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // 「 Sell 」ボタンを作成する
  //--- 「Sell」 ボタンを設定する
  ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
  ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);

  //--- ボタンをすぐに表示するためにチャートの強制アップデートを実行する
  ChartRedraw();
}

詳細な解説

  • void CreateBuySellButtons():
  • CreateBuySellButtons関数の定義です。チャート上に「Buy」ボタンと「Sell」ボタンを作成し、設定します。
  • 「Buy」ボタンの作成と設定:
  • if(ObjectFind(0,”Buy”)>=0):
    • 「Buy」オブジェクトが既に存在するかどうかをチェックします。ObjectFind関数は、指定されたオブジェクトが存在するかどうかを確認します。
    • 0は現在のチャートを指定します。
  • if(ObjectGetInteger(0,”Buy”,OBJPROP_TYPE)!=OBJ_BUTTON):
    • 既存の「Buy」オブジェクトがボタンでない場合は削除します。ObjectGetInteger関数は、オブジェクトのプロパティを取得します。
    • OBJPROP_TYPEは、オブジェクトの種類を示します。
  • ObjectCreate(0,”Buy”,OBJ_BUTTON,0,0,0);:
    • 「Buy」ボタンを作成します。ObjectCreate関数は、新しいオブジェクトを作成します。
    • OBJ_BUTTONはボタンオブジェクトを示します。
  ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
  ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
  ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);
  • ボタンの設定を行います。
  • 「Sell」ボタンの作成と設定:
  • if(ObjectFind(0,”Sell”)>=0):
    • 「Sell」オブジェクトが既に存在するかどうかをチェックします。
  • if(ObjectGetInteger(0,”Sell”,OBJPROP_TYPE)!=OBJ_BUTTON):
    • 既存の「Sell」オブジェクトがボタンでない場合は削除します。
  • ObjectCreatejectCreate(0,”Sell”,OBJ_BUTTON,0,0,0);:
    • 「Sell」ボタンを作成します。
  ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
  ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
  ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
  ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);
  • ボタンの設定を行います。
    • ボタンの位置、距離、サイズ、テキスト、色を設定します。設定内容は「Buy」ボタンと同様です。
  • ChartRedraw();:
  • ChartRedraw関数でチャートの強制アップデートを実行します。これにより、ボタンがすぐに表示されます。

全体の流れ

CreateBuySellButtons関数は、チャート上に「Buy」ボタンと「Sell」ボタンを作成し、設定します。既存のボタンが存在する場合は、その種類を確認し、ボタンでない場合は削除します。新しいボタンを作成し、位置やサイズ、色などの設定を行います。最後に、チャートを強制的に再描画して、ボタンの表示を更新します。これにより、ユーザーは「Buy」および「Sell」ボタンをクリックして取引を実行することができます。

解説11:BuyAsync関数(オリジナル関数)

BuyAsync関数の役割

BuyAsync関数は、指定された取引量で買い注文を非同期に送信するための関数です。この関数を使用することで、サーバーからの応答を待たずに取引リクエストを送信できます。非同期処理により、高速取引が可能となります。

コードの解説

void BuyAsync(double volume)
{
  //--- リクエストを準備する
  MqlTradeRequest req={};
  req.action      =TRADE_ACTION_DEAL; // アクションタイプ: 取引
  req.symbol      =_Symbol;           // 取引するシンボル
  req.magic       =MagicNumber;       // Magic Number
  req.volume      =volume;            // 取引量
  req.type        =ORDER_TYPE_BUY;    // 注文タイプ: 買い
  req.price       =SymbolInfoDouble(req.symbol,SYMBOL_ASK); // 現在のAsk価格
  req.deviation   =10;                // 許容スリッページ
  req.comment     ="Buy using OrderSendAsync()"; // 注文コメント

  //--- 取引結果を格納する構造体
  MqlTradeResult res={};

  //--- 非同期で注文を送信し、成功したかどうかを確認する
  if(!OrderSendAsync(req,res))
  {
    //--- エラーが発生した場合の処理
    Print(__FUNCTION__, ": error ", GetLastError(), ", retcode = ", res.retcode);
  }
}

詳細な解説

  • void BuyAsync(double volume):
  • BuyAsync関数の定義です。volumeパラメータは取引量を指定します。
  • リクエストの準備:
  • MqlTradeRequest req={};:
  • req.action = TRADE_ACTION_DEAL;:
    • リクエストのアクションタイプを取引に設定します。TRADE_ACTION_DEALは即時実行の取引を示します。
  • req.symbol = _Symbol;:
    • 取引するシンボルを設定します。_Symbolは現在のチャートのシンボルを示します。
  • req.magic = MagicNumber;
  • req.volume = volume;
    • 取引量を設定します。関数引数で渡された値が使用されます。
  • req.type = ORDER_TYPE_BUY;:
    • 注文タイプを買い注文に設定します。ORDER_TYPE_BUYは買い注文を示します。
  • req.price = SymbolInfoDouble(req.symbol, SYMBOL_ASK);:
    • 現在のAsk価格を設定します。SymbolInfoDouble関数は指定されたシンボルの価格情報を取得します。
  • req.deviation = 10;
  • req.comment = “Buy using OrderSendAsync();”:
    • 注文にコメントを追加します。
  • 取引結果を格納する構造体の準備:
  • MqlTradeResult res={};:
  • 非同期注文の送信とエラーチェック:
  • if(!OrderSendAsync(req,res)):
    • 非同期で注文を送信し、成功したかどうかを確認します。OrderSendAsync関数非同期で取引リクエストを送信します。
    • 注文が失敗した場合は false を返します。
  • Print(__FUNCTION__, “: error “, GetLastError(), “, retcode = “, res.retcode);:
    • 注文が失敗した場合のエラーメッセージをログに出力します。GetLastError関数は最後のエラーコードを取得します。res.retcodeは取引リクエストの結果コードを示します。

全体の流れ

BuyAsync関数は、指定された取引量で買い注文を非同期に送信します。まず、取引リクエストを準備し、必要なパラメータを設定します。次に、取引結果を格納するための構造体を初期化します。非同期で注文を送信し、成功したかどうかを確認します。注文が失敗した場合は、エラーメッセージをログに出力します。非同期処理により、取引リクエストの送信と同時に他の処理を続行することができます。

解説12:SellAsync関数(オリジナル関数)

SellAsync関数の役割

SellAsync関数は、指定された取引量で売り注文を非同期に送信するための関数です。この関数を使用することで、サーバーからの応答を待たずに取引リクエストを送信できます。非同期処理により、高速取引が可能となります。

コードの解説

void SellAsync(double volume)
{
  //--- リクエストを準備する
  MqlTradeRequest req={};
  req.action      =TRADE_ACTION_DEAL; // アクションタイプ: 取引
  req.symbol      =_Symbol;           // 取引するシンボル
  req.magic       =MagicNumber;       // Magic Number
  req.volume      =volume;            // 取引量
  req.type        =ORDER_TYPE_SELL;   // 注文タイプ: 売り
  req.price       =SymbolInfoDouble(req.symbol,SYMBOL_BID); // 現在のBid価格
  req.deviation   =10;                // 許容スリッページ
  req.comment     ="Sell using OrderSendAsync()"; // 注文コメント

  //--- 取引結果を格納する構造体
  MqlTradeResult res={};

  //--- 非同期で注文を送信し、成功したかどうかを確認する
  if(!OrderSendAsync(req,res))
  {
    //--- エラーが発生した場合の処理
    Print(__FUNCTION__, ": error ", GetLastError(), ", retcode = ", res.retcode);
  }
}

詳細な解説

  • void SellAsync(double volume):
  • SellAsync関数の定義です。volumeパラメータは取引量を指定します。
  • リクエストの準備:
  • MqlTradeRequest req={};:
  • req.action = TRADE_ACTION_DEAL;
    • リクエストのアクションタイプを取引に設定します。TRADE_ACTION_DEALは即時実行の取引を示します。
  • req.symbol = _Symbol;:
    • 取引するシンボルを設定します。_Symbolは現在のチャートのシンボルを示します。
  • req.magic = MagicNumber;
  • req.volume = volume;
    • 取引量を設定します。関数引数で渡された値が使用されます。
  • req.type = ORDER_TYPE_SELL;:
    • 注文タイプを売り注文に設定します。ORDER_TYPE_SELLは売り注文を示します。
  • req.price = SymbolInfoDouble(req.symbol, SYMBOL_BID);:
    • 現在のBid価格を設定します。SymbolInfoDouble関数は指定されたシンボルの価格情報を取得します。
  • req.deviation = 10;
  • req.comment = “Sell using OrderSendAsync();”:
    • 注文にコメントを追加します。
  • 取引結果を格納する構造体の準備:
  • MqlTradeResult res={};:
  • 非同期注文の送信とエラーチェック:
  • if(!OrderSendAsync(req,res)):
    • 非同期で注文を送信し、成功したかどうかを確認します。OrderSendAsync関数非同期で取引リクエストを送信します。
    • 注文が失敗した場合は false を返します。
  • Print(__FUNCTION__, “: error “, GetLastError(), “, retcode = “, res.retcode);:
    • 注文が失敗した場合のエラーメッセージをログに出力します。GetLastError関数は最後のエラーコードを取得します。res.retcodeは取引リクエストの結果コードを示します。

全体の流れ

SellAsync関数は、指定された取引量で売り注文を非同期に送信します。まず、取引リクエストを準備し、必要なパラメータを設定します。次に、取引結果を格納するための構造体を初期化します。非同期で注文を送信し、成功したかどうかを確認します。注文が失敗した場合は、エラーメッセージをログに出力します。非同期処理により、取引リクエストの送信と同時に他の処理を続行することができます。

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