指定した日時が、米国の雇用統計の発表日かを確認するMQL5関数をChatGPTに書いてもらいました

# はじめに
この記事はChatGPT(GPT-4)で、指定した日時が、米国の雇用統計の発表日かを確認するMQL5関数を作成するための、やり取りをコピーしたものです。
コードは主にChatGPTが作成したものですので、堅牢な作りになっていなかったり、非効率だったり等あるかと思いますが、予めご了承ください。

# ChatGPTとのやり取り
ここからは、実際に行ったチャットのコピーです。質問は太字で表記しています。補足説明がある場合は、回答の最後に薄字で表記しています。

__(質問)__
__指定した日時が、米国の雇用統計の発表日かを確認する関数をMQL5で書いてください。__

(ChatGPTの回答)
MQL5で、指定した日時が米国の雇用統計（Non-Farm Payrolls: NFP）の発表日かどうかを確認する関数を以下に示します。

通常、NFPは毎月の第1金曜日に発表されます。この関数は、指定された日付が第1金曜日であるかどうかを確認することで、NFPの発表日かどうかを判断します。
```.cpp
// MQL5のDatetime構造体を使って日時を表現する
#include <Datetime.mqh>

// 指定された日付がNFP発表日であるかどうかを確認する関数
bool isNFPReleaseDate(const datetime &date)
{
   MqlDateTime mqlDate;
   TimeToStruct(date, mqlDate);

   int day = mqlDate.day;      // 日
   int dayOfWeek = mqlDate.day_of_week; // 曜日 (0: 日曜, 1: 月曜, ..., 6: 土曜)
   int weekNumber = (day - 1) / 7 + 1; // 週番号

   // 第1週の金曜日であれば、NFPの発表日
   if (weekNumber == 1 && dayOfWeek == 5)
   {
      return true;
   }

   return false;
}
```
この関数を使って、指定された日付がNFPの発表日かどうかを確認できます。例えば、次のように使います。
```.cpp
void OnStart()
{
   datetime exampleDate = D'2023.04.07'; // 2023年4月7日

   if (isNFPReleaseDate(exampleDate))
   {
      Print("指定された日付はNFPの発表日です。");
   }
   else
   {
      Print("指定された日付はNFPの発表日ではありません。");
   }
}
```
この例では、2023年4月7日がNFPの発表日かどうかを確認しています。

>(補足)
>#Datetime.mqhは存在しないのでコンパイルエラーが出ます。
>また、雇用統計は第1週の金曜日とは限らないため、質問内容を少し変更してみます。


__(質問)__
__米国の雇用統計の発表日は、前月12日を含む週の3週間後の金曜日です。
ヘッダーファイルを使用せずに、指定した日時が、米国の雇用統計の発表日かを確認する関数をMQL5で書いてください。__

(ChatGPTの回答)
前月12日を含む週の3週間後の金曜日を米国の雇用統計（NFP）の発表日として、指定された日時がNFPの発表日かどうかを確認する関数をMQL5で書いてみます。
```.cpp
bool isNFPReleaseDate(datetime date)
{
   MqlDateTime mqlDate;
   TimeToStruct(date, mqlDate);

   int year = mqlDate.year;
   int month = mqlDate.month;
   int day = mqlDate.day;
   int dayOfWeek = mqlDate.day_of_week;

   // 前月に移動
   if (month == 1)
   {
      year -= 1;
      month = 12;
   }
   else
   {
      month -= 1;
   }

   // 前月の12日を取得
   datetime previousMonth12 = StrToTime(IntegerToString(year) + "." + IntegerToString(month) + ".12");

   MqlDateTime previousMonth12MqlDate;
   TimeToStruct(previousMonth12, previousMonth12MqlDate);

   // 前月12日を含む週の金曜日を取得
   datetime previousMonthFriday = previousMonth12 + (5 - previousMonth12MqlDate.day_of_week) * 60 * 60 * 24;

   // 3週間後の金曜日を取得
   datetime nfpReleaseDate = previousMonthFriday + (3 * 7) * 60 * 60 * 24;

   // 与えられた日付がNFP発表日と一致するかチェック
   if (date == nfpReleaseDate)
   {
      return true;
   }

   return false;
}
```
この関数を使って、指定された日付がNFPの発表日かどうかを確認できます。例えば、次のように使います。
```.cpp
void OnStart()
{
   datetime exampleDate = D'2023.04.07'; // 2023年4月7日

   if (isNFPReleaseDate(exampleDate))
   {
      Print("指定された日付はNFPの発表日です。");
   }
   else
   {
      Print("指定された日付はNFPの発表日ではありません。");
   }
}
```
この例では、2023年4月7日がNFPの発表日かどうかを確認しています。

>(補足)
>いくつかエラーが出ます。
```エラー修正.cpp
// エラー①:MqlDateTime monthからmonに
int month = mqlDate.month; // 修正前
int month = mqlDate.mon; // 修正後

// エラー②:関数名 StrToTimeからStringToTimeに
datetime previousMonth12 = StrToTime(IntegerToString(year) + "." + IntegerToString(month) + ".12"); // 修正前
datetime previousMonth12 = StringToTime(IntegerToString(year) + "." + IntegerToString(month) + ".12"); // 修正後
```
　
__(質問)__
__この関数の動作確認をしたいので、OnStart関数の中で任意の開始日から終了日まで、1日毎ずらしてNFPの発表日かどうかを確認するように書いてください。__

(ChatGPTの回答)
OnStart関数を変更して、任意の開始日から終了日まで1日ずつずらして、各日がNFPの発表日かどうかを確認するように書きます。
```.cpp
void OnStart()
{
   // 開始日と終了日を設定
   datetime startDate = D'2023.01.01'; // 2023年1月1日
   datetime endDate = D'2023.12.31'; // 2023年12月31日

   // 開始日から終了日まで1日ずつずらしてNFP発表日を確認
   for (datetime currentDate = startDate; currentDate <= endDate; currentDate += 60 * 60 * 24)
   {
      if (isNFPReleaseDate(currentDate))
      {
         MqlDateTime mqlDate;
         TimeToStruct(currentDate, mqlDate);
         string formattedDate = StringFormat("%04d-%02d-%02d", mqlDate.year, mqlDate.mon, mqlDate.day);
         Print("NFPの発表日: ", formattedDate);
      }
   }
}
```
このコードは、2023年1月1日から2023年12月31日までの間で、NFPの発表日をすべて表示します。startDateとendDateを変更することで、確認する期間を変更できます。

>(補足)
>このコードを使用して2022年の雇用統計の発表日を出力した結果がこちらです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/88f3c6c6-06cf-e277-33e0-14bc1a6cb95e.png)
>この結果が正しいか、Investing.comで確認してみます。
https://jp.investing.com/economic-calendar/nonfarm-payrolls-227
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/41a09e78-b896-e31b-c755-dee7b6e6c9a6.png)
>日付は一致しています。正常に動作しているようですね。

# 最後に
ChatGPTで目的の関数を作成し、続けて動作確認用のコードも作りました。人が書けばもっと良いコーディングになるかもしれません。
自分しか使わないプログラムであれば、うまく利用してプログラミング作業の効率アップにつなげることができるのではないかと思いました。

最後に完成したMQL5ソースコード(スクリプト)をもう一度書いておきます。
```.cpp
// ChatGPTによる指定した日時が、米国の雇用統計の発表日かを確認する関数
bool isNFPReleaseDate(datetime date)
{
   MqlDateTime mqlDate;
   TimeToStruct(date, mqlDate);

   int year = mqlDate.year;
   int month = mqlDate.mon;
   int day = mqlDate.day;
   int dayOfWeek = mqlDate.day_of_week;

   // 前月に移動
   if (month == 1)
   {
      year -= 1;
      month = 12;
   }
   else
   {
      month -= 1;
   }

   // 前月の12日を取得
   datetime previousMonth12 = StringToTime(IntegerToString(year) + "." + IntegerToString(month) + ".12");

   MqlDateTime previousMonth12MqlDate;
   TimeToStruct(previousMonth12, previousMonth12MqlDate);

   // 前月12日を含む週の金曜日を取得
   datetime previousMonthFriday = previousMonth12 + (5 - previousMonth12MqlDate.day_of_week) * 60 * 60 * 24;

   // 3週間後の金曜日を取得
   datetime nfpReleaseDate = previousMonthFriday + (3 * 7) * 60 * 60 * 24;

   // 与えられた日付がNFP発表日と一致するかチェック
   if (date == nfpReleaseDate)
   {
      return true;
   }

   return false;
}

// ここからは、ChatGPTによる動作確認用コード
void OnStart()
{
   // 開始日と終了日を設定
   datetime startDate = D'2022.01.01'; // 2023年1月1日
   datetime endDate = D'2022.12.31'; // 2023年12月31日

   // 開始日から終了日まで1日ずつずらしてNFP発表日を確認
   for (datetime currentDate = startDate; currentDate <= endDate; currentDate += 60 * 60 * 24)
   {
      if (isNFPReleaseDate(currentDate))
      {
         MqlDateTime mqlDate;
         TimeToStruct(currentDate, mqlDate);
         string formattedDate = StringFormat("%04d-%02d-%02d", mqlDate.year, mqlDate.mon, mqlDate.day);
         Print("NFPの発表日: ", formattedDate);
      }
   }
}
```