見出し画像

EAの成績を確認するインジケーター ソースコード付き

EAの成績を一覧で表示するインジケーターです。


ダウンロードリンク


indicatorのフォルダにいれて使ってください。

ソースコード

//+------------------------------------------------------------------+
//|                                              EAの成績一覧表インジケーター.mq4 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#include <WinUser32.mqh>
#import "user32.dll"
  int GetAncestor(int,int);
  int PostMessageA(int, int, int, int);
#import


input datetime StartDate = D'2000.01.01 00:00'; // ユーザーが開始日を入力できるようにします
input datetime EndDate = D'2038.01.18 23:59'; // ユーザーが終了日を入力できるようにします

struct TradeHistory {
   int magicNumber;
   string comment;
   int tradeCount;
   int winCount;
   int lossCount;
   double winRate;
   double totalLossAmount;
   double totalWinAmount;
   double totalProfitLoss;
   double profitFactor;
   double totalPoints;
};

int magicNumbers[]; // マジックナンバーを保存するグローバル配列
TradeHistory tradeHistories[]; // TradeHistory構造体の配列をグローバルスコープに配置


//+------------------------------------------------------------------+
//| Custom function for extracting magic numbers                     |
//+------------------------------------------------------------------+
void ExtractMagicNumbers() {
   int totalOrders = OrdersHistoryTotal(); // 過去の注文の合計数を取得

   for(int i = 0; i < totalOrders; i++) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { // 注文を選択
         datetime orderOpenTime = OrderOpenTime();

         // 注文の開始時間が指定された期間内にあるかどうかを確認
         if(orderOpenTime >= StartDate && orderOpenTime <= EndDate) {
            int magicNumber = OrderMagicNumber(); // マジックナンバーを取得

            // 既に同じマジックナンバーが配列に存在するかどうかを確認
            bool isDuplicate = false;
            for(int j = 0; j < ArraySize(magicNumbers); j++) {
               if(magicNumbers[j] == magicNumber) {
                  isDuplicate = true;
                  break;
               }
            }

            // マジックナンバーが配列にまだ存在しない場合のみ、配列に追加
            if(!isDuplicate) {
               ArrayResize(magicNumbers, ArraySize(magicNumbers) + 1); // 配列のサイズを増やす
               magicNumbers[ArraySize(magicNumbers) - 1] = magicNumber; // マジックナンバーを配列に追加
            }
         }
      }
   }
}

void CalculateTradeHistory() {
   ArrayResize(tradeHistories, ArraySize(magicNumbers)); // 配列のサイズをマジックナンバーの数に合わせて調整

   for(int i = 0; i < ArraySize(magicNumbers); i++) {
      tradeHistories[i].magicNumber = magicNumbers[i]; // マジックナンバーを設定

      for(int j = OrdersHistoryTotal() - 1; j >= 0; j--) {
         if(OrderSelect(j, SELECT_BY_POS, MODE_HISTORY)) {
            datetime orderOpenTime = OrderOpenTime();

            // 注文の開始時間が指定された期間内にあるかどうかを確認
            if(orderOpenTime >= StartDate && orderOpenTime <= EndDate) {
            if(OrderType() < 2){
               if(OrderMagicNumber() == magicNumbers[i]) {
                  tradeHistories[i].comment = OrderComment();
                  tradeHistories[i].tradeCount++;
                  if(OrderProfit() > 0) {
                     tradeHistories[i].winCount++;
                     tradeHistories[i].totalWinAmount += OrderProfit();
                  } else {
                     tradeHistories[i].lossCount++;
                     tradeHistories[i].totalLossAmount += OrderProfit();
                  }
                  tradeHistories[i].totalPoints += OrderProfit();
               }
            }
         }
      }
      }

      // 勝率、トータル損益、プロフィットファクターを計算
      if(tradeHistories[i].tradeCount > 0) {
         tradeHistories[i].winRate = (double)tradeHistories[i].winCount / tradeHistories[i].tradeCount;
         tradeHistories[i].totalProfitLoss = tradeHistories[i].totalWinAmount + tradeHistories[i].totalLossAmount;
         if(tradeHistories[i].totalLossAmount != 0) {
            tradeHistories[i].profitFactor = -tradeHistories[i].totalWinAmount / tradeHistories[i].totalLossAmount;
         }
      }
   }
}

input int input_comment_width = 500;//コメントの幅の設定

input int input_sonota_width = 250;//その他の幅の設定



void CreateObject(string name, string text, int magic_number_list_index, int koumoku_index) {
   ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE,input_sonota_width * koumoku_index);
   if(koumoku_index!=0){
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, input_comment_width + input_sonota_width * koumoku_index);
   }
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30 + magic_number_list_index * 25);
   ObjectSetText(name, text, 12, "MS Gothic", clrWhite);
}

void DisplayTradeHistory() {
   for(int i = 0; i < ArraySize(tradeHistories); i++) {
      // コメント
      string nameComment = "TradeHistoryComment" + IntegerToString(i);
      CreateObject(nameComment, "Comment: " + tradeHistories[i].comment, i, 0);

      // マジックナンバー
      string nameMagicNumber = "TradeHistoryMagicNumber" + IntegerToString(i);
      CreateObject(nameMagicNumber, "Magic Number: " + IntegerToString(tradeHistories[i].magicNumber), i, 1);

      // トレード回数
      string nameTradeCount = "TradeHistoryTradeCount" + IntegerToString(i);
      CreateObject(nameTradeCount, "Trade Count: " + IntegerToString(tradeHistories[i].tradeCount), i, 2);

      // 勝率
      string nameWinRate = "TradeHistoryWinRate" + IntegerToString(i);
      CreateObject(nameWinRate, "Win Rate: " + DoubleToString(tradeHistories[i].winRate, 2), i, 3);

      // 損益額
      string nameProfitLoss = "TradeHistoryProfitLoss" + IntegerToString(i);
      CreateObject(nameProfitLoss, "損益額: " + DoubleToString(tradeHistories[i].totalProfitLoss, 2), i, 4);

      // プロフィットファクター
      string nameProfitFactor = "TradeHistoryProfitFactor" + IntegerToString(i);
      CreateObject(nameProfitFactor, "Profit Factor: " + DoubleToString(tradeHistories[i].profitFactor, 2), i, 5);
   }
}




//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

input bool input_enable_zenrireki = true;//全履歴にする
input int taiki_jikan = 1;//表示までの待機秒
void OnInit()
  {
  if(input_enable_zenrireki){
     if(!IsDllsAllowed()) {
      Comment("全履歴の切り替えはDLLを許可してください。");
   }else{  
  
  int main = GetAncestor(WindowHandle(Symbol(),Period()),2);
  PostMessageA(main,WM_COMMAND,33058,0);
  }
  }
  EventSetTimer(taiki_jikan);
  }
  
  void OnTimer(){
   ExtractMagicNumbers(); // マジックナンバーの抽出関数を呼び出す
   CalculateTradeHistory(); // 取引履歴の計算関数を呼び出す
   DisplayTradeHistory(); // 取引履歴の表示関数を呼び出す
  EventKillTimer();
  
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

MagicNumberを主キーで表示したい場合


//+------------------------------------------------------------------+
//|                                              EAの成績一覧表インジケーター.mq4 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#include <WinUser32.mqh>
#import "user32.dll"
  int GetAncestor(int,int);
  int PostMessageA(int, int, int, int);
#import


input datetime StartDate = D'2000.01.01 00:00'; // ユーザーが開始日を入力できるようにします
input datetime EndDate = D'2038.01.18 23:59'; // ユーザーが終了日を入力できるようにします

struct TradeHistory {
   int magicNumber;
   string comment;
   int tradeCount;
   int winCount;
   int lossCount;
   double winRate;
   double totalLossAmount;
   double totalWinAmount;
   double totalProfitLoss;
   double profitFactor;
   double totalPoints;
};

int magicNumbers[]; // マジックナンバーを保存するグローバル配列
TradeHistory tradeHistories[]; // TradeHistory構造体の配列をグローバルスコープに配置


//+------------------------------------------------------------------+
//| Custom function for extracting magic numbers                     |
//+------------------------------------------------------------------+
void ExtractMagicNumbers() {
   int totalOrders = OrdersHistoryTotal(); // 過去の注文の合計数を取得

   for(int i = 0; i < totalOrders; i++) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { // 注文を選択
         datetime orderOpenTime = OrderOpenTime();

         // 注文の開始時間が指定された期間内にあるかどうかを確認
         if(orderOpenTime >= StartDate && orderOpenTime <= EndDate) {
            int magicNumber = OrderMagicNumber(); // マジックナンバーを取得

            // 既に同じマジックナンバーが配列に存在するかどうかを確認
            bool isDuplicate = false;
            for(int j = 0; j < ArraySize(magicNumbers); j++) {
               if(magicNumbers[j] == magicNumber) {
                  isDuplicate = true;
                  break;
               }
            }

            // マジックナンバーが配列にまだ存在しない場合のみ、配列に追加
            if(!isDuplicate) {
               ArrayResize(magicNumbers, ArraySize(magicNumbers) + 1); // 配列のサイズを増やす
               magicNumbers[ArraySize(magicNumbers) - 1] = magicNumber; // マジックナンバーを配列に追加
            }
         }
      }
   }
}

void CalculateTradeHistory() {
   ArrayResize(tradeHistories, ArraySize(magicNumbers)); // 配列のサイズをマジックナンバーの数に合わせて調整

   for(int i = 0; i < ArraySize(magicNumbers); i++) {
      tradeHistories[i].magicNumber = magicNumbers[i]; // マジックナンバーを設定

      for(int j = OrdersHistoryTotal() - 1; j >= 0; j--) {
         if(OrderSelect(j, SELECT_BY_POS, MODE_HISTORY)) {
            datetime orderOpenTime = OrderOpenTime();

            // 注文の開始時間が指定された期間内にあるかどうかを確認
            if(orderOpenTime >= StartDate && orderOpenTime <= EndDate) {
            if(OrderType() < 2){
               if(OrderMagicNumber() == magicNumbers[i]) {
                  tradeHistories[i].comment = OrderComment();
                  tradeHistories[i].tradeCount++;
                  if(OrderProfit() > 0) {
                     tradeHistories[i].winCount++;
                     tradeHistories[i].totalWinAmount += OrderProfit();
                  } else {
                     tradeHistories[i].lossCount++;
                     tradeHistories[i].totalLossAmount += OrderProfit();
                  }
                  tradeHistories[i].totalPoints += OrderProfit();
               }
            }
         }
      }
      }

      // 勝率、トータル損益、プロフィットファクターを計算
      if(tradeHistories[i].tradeCount > 0) {
         tradeHistories[i].winRate = (double)tradeHistories[i].winCount / tradeHistories[i].tradeCount;
         tradeHistories[i].totalProfitLoss = tradeHistories[i].totalWinAmount + tradeHistories[i].totalLossAmount;
         if(tradeHistories[i].totalLossAmount != 0) {
            tradeHistories[i].profitFactor = -tradeHistories[i].totalWinAmount / tradeHistories[i].totalLossAmount;
         }
      }
   }
}



input int input_sonota_width = 250;//行幅の設定



void CreateObject(string name, string text, int magic_number_list_index, int koumoku_index) {
   ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE,input_sonota_width * koumoku_index);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30 + magic_number_list_index * 25);
   ObjectSetText(name, text, 12, "MS Gothic", clrWhite);
}

void DisplayTradeHistory() {
   for(int i = 0; i < ArraySize(tradeHistories); i++) {


      // マジックナンバー
      string nameMagicNumber = "TradeHistoryMagicNumber" + IntegerToString(i);
      CreateObject(nameMagicNumber, "Magic Number: " + IntegerToString(tradeHistories[i].magicNumber), i, 0);

      // トレード回数
      string nameTradeCount = "TradeHistoryTradeCount" + IntegerToString(i);
      CreateObject(nameTradeCount, "Trade Count: " + IntegerToString(tradeHistories[i].tradeCount), i, 1);

      // 勝率
      string nameWinRate = "TradeHistoryWinRate" + IntegerToString(i);
      CreateObject(nameWinRate, "Win Rate: " + DoubleToString(tradeHistories[i].winRate, 2), i, 2);

      // 損益額
      string nameProfitLoss = "TradeHistoryProfitLoss" + IntegerToString(i);
      CreateObject(nameProfitLoss, "損益額: " + DoubleToString(tradeHistories[i].totalProfitLoss, 2), i, 3);

      // プロフィットファクター
      string nameProfitFactor = "TradeHistoryProfitFactor" + IntegerToString(i);
      CreateObject(nameProfitFactor, "Profit Factor: " + DoubleToString(tradeHistories[i].profitFactor, 2), i, 4);
      // コメント
      string nameComment = "TradeHistoryComment" + IntegerToString(i);
      CreateObject(nameComment, "Comment: " + tradeHistories[i].comment, i, 5);
   }
}




//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

input bool input_enable_zenrireki = true;//全履歴にする
input int taiki_jikan = 1;//表示までの待機秒
void OnInit()
  {
  if(input_enable_zenrireki){
     if(!IsDllsAllowed()) {
      Comment("全履歴の切り替えはDLLを許可してください。");
   }else{  
  
  int main = GetAncestor(WindowHandle(Symbol(),Period()),2);
  PostMessageA(main,WM_COMMAND,33058,0);
  }
  }
  EventSetTimer(taiki_jikan);
  }
  
  void OnTimer(){
   ExtractMagicNumbers(); // マジックナンバーの抽出関数を呼び出す
   CalculateTradeHistory(); // 取引履歴の計算関数を呼び出す
   DisplayTradeHistory(); // 取引履歴の表示関数を呼び出す
  EventKillTimer();
  
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

ここから先は

0字
このマガジンで読み放題です。

EA開発者のためのサンプルコード集

この記事が気に入ったらサポートをしてみませんか?