MQL5 ファイル操作 完全ガイド|FileOpen・FileWrite・CSV読み書き・ログ記録の実装

MQL5 ファイル操作関数を完全網羅。FileOpen・FileWrite・FileReadなど、EA開発で使うすべてのファイル関数をコード付きで解説します。CSV取引ログの記録、設定ファイルの読み書き、EA間通信、データエクスポートまで、実践的なパターンを豊富に紹介。MQL4との違いも併記しています。

MQL5 ファイル操作関数 リファレンスカード
目次

MQL5ファイル操作の基礎知識

MQL5のファイル操作は、セキュリティ上の理由からサンドボックス化されています。EAからアクセスできるディレクトリは限定されており、任意のパスへのアクセスはできません。

ファイルアクセスのサンドボックス

ディレクトリパス用途
ローカルMQL5FilesEA固有のデータ(デフォルト)
共通TerminalCommonFiles複数ターミナル間で共有するデータ
// ローカルフォルダのパス
string localPath = TerminalInfoString(TERMINAL_DATA_PATH) +"MQL5Files";
Print("ローカル:", localPath);
// 例: C:UsersuserAppDataRoamingMetaQuotesTerminalXXXXMQL5Files

// 共通フォルダのパス
string commonPath = TerminalInfoString(TERMINAL_COMMONDATA_PATH) +"Files";
Print("共通:", commonPath);
// 例: C:UsersuserAppDataRoamingMetaQuotesTerminalCommonFiles
重要

MQL5のファイル操作では、MQL5Filesフォルダの外にはアクセスできません。"../"でディレクトリを遡ることもブロックされます。テスター(バックテスト)中は専用のサンドボックスが使用されるため、ファイルパスが異なります。

MQL4とMQL5のファイル操作の違い

項目MQL4MQL5
デフォルトパスMQL4FilesMQL5Files
FILE_COMMON対応(ビルド600+)対応
FILE_SHARE_READ対応対応(同時読み取り可能)
FILE_SHARE_WRITE対応対応(同時書き込み可能)
FileWriteArray対応対応
FileReadArray対応対応
FileFindFirst/Next対応対応
FolderCreate対応対応
FolderDelete対応対応
Unicode対応限定的完全対応(FILE_UNICODE)

FileOpen:ファイルを開く

ファイルを開いてハンドルを取得します。すべてのファイル操作の起点となる関数です。

int FileOpen(
   string  file_name,         // ファイル名
   int     open_flags,        // フラグの組み合わせ
   short   delimiter = 't',  // CSV区切り文字(FILE_CSVの場合)
   uint    codepage = CP_ACP  // コードページ
);
// 戻り値: ファイルハンドル(失敗時 INVALID_HANDLE)

ファイルオープンフラグ

フラグ説明
FILE_READ1読み取り用
FILE_WRITE2書き込み用(ファイルが存在しない場合は新規作成)
FILE_BIN4バイナリモード
FILE_CSV8CSVモード(delimiter指定有効)
FILE_TXT16テキストモード(改行区切り)
FILE_ANSI32ANSI文字列(1バイト)
FILE_UNICODE64Unicode文字列(2バイト)
FILE_SHARE_READ128他プロセスとの同時読み取りを許可
FILE_SHARE_WRITE256他プロセスとの同時書き込みを許可
FILE_COMMON4096共通フォルダを使用
// パターン1: CSVファイルの新規作成
int handle = FileOpen("trade_log.csv", FILE_WRITE | FILE_CSV | FILE_ANSI, ',');
if(handle == INVALID_HANDLE)
  {
   Print("ファイルオープン失敗:", GetLastError());
   return;
  }
// ... 書き込み処理 ...
FileClose(handle);

// パターン2: テキストファイルの読み取り
handle = FileOpen("settings.txt", FILE_READ | FILE_TXT | FILE_ANSI);

// パターン3: バイナリファイルの読み書き
handle = FileOpen("data.bin", FILE_READ | FILE_WRITE | FILE_BIN);

// パターン4: 追記モード(FILE_READ | FILE_WRITE + FileSeek)
handle = FileOpen("log.txt", FILE_READ | FILE_WRITE | FILE_TXT | FILE_SHARE_READ);
if(handle != INVALID_HANDLE)
  {
   FileSeek(handle, 0, SEEK_END);  // ファイル末尾に移動
   FileWriteString(handle,"新しいログ行n");
   FileClose(handle);
  }

// パターン5: 共通フォルダ(複数ターミナル間共有)
handle = FileOpen("shared_data.csv",
                      FILE_WRITE | FILE_CSV | FILE_COMMON | FILE_SHARE_READ, ',');

ファイルを開いたら必ずFileClose()で閉じてください。閉じ忘れるとファイルがロックされ、他のEAや手動でのアクセスができなくなります。特にOnTick()内で毎ティックファイルを開く場合は注意が必要です。

FileClose:ファイルを閉じる

void FileClose(
   int  file_handle  // ファイルハンドル
);

// 安全なファイル操作パターン
void SafeFileWrite(string filename, string content)
  {
   int handle = FileOpen(filename, FILE_WRITE | FILE_TXT | FILE_ANSI);
   if(handle == INVALID_HANDLE)
     {
      Print("ファイルオープン失敗:", filename," Error:", GetLastError());
      return;
     }

   FileWriteString(handle, content);
   FileClose(handle);
  }

FileWrite:CSV行の書き込み

CSVモードで開いたファイルに、区切り文字で区切られた1行を書き込みます。

uint FileWrite(
   int  file_handle,  // ファイルハンドル
   ...                // 書き込むデータ(可変長・型混在OK)
);
// 戻り値: 書き込んだバイト数(0はエラー)

// CSVトレードログの作成
void WriteTradeLog(ulong ticket, string action, double price, double lot, double profit)
  {
   int handle = FileOpen("trade_log.csv",
                         FILE_READ | FILE_WRITE | FILE_CSV | FILE_ANSI, ',');
   if(handle == INVALID_HANDLE) return;

   // ファイルが空の場合、ヘッダーを書き込む
   if(FileSize(handle) == 0)
     {
      FileWrite(handle,"DateTime","Ticket","Action","Symbol","Price","Lot","Profit","Balance");
     }

   FileSeek(handle, 0, SEEK_END);
   FileWrite(handle,
      TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS),
      ticket, action, _Symbol,
      DoubleToString(price, _Digits),
      DoubleToString(lot, 2),
      DoubleToString(profit, 2),
      DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2)
   );
   FileClose(handle);
  }

FileWriteString:テキスト書き込み

uint FileWriteString(
   int     file_handle,    // ファイルハンドル
   string  text_string,    // 書き込む文字列
   int     length = -1     // 書き込む文字数(-1=全部)
);

// テキストログの書き込み
void AppendLog(string message)
  {
   int handle = FileOpen("ea_log.txt",
                         FILE_READ | FILE_WRITE | FILE_TXT |
                         FILE_ANSI | FILE_SHARE_READ);
   if(handle == INVALID_HANDLE) return;

   FileSeek(handle, 0, SEEK_END);
   string line = StringFormat("[%s] %sn",
                              TimeToString(TimeCurrent(), TIME_SECONDS),
                              message);
   FileWriteString(handle, line);
   FileClose(handle);
  }

FileWriteInteger / FileWriteDouble:数値の書き込み

uint FileWriteInteger(
   int  file_handle,               // ファイルハンドル
   int  value,                     // 書き込む整数値
   int  size = INT_VALUE           // バイトサイズ(CHAR_VALUE=1, SHORT_VALUE=2, INT_VALUE=4)
);

uint FileWriteDouble(
   int     file_handle,
   double  value
);

// バイナリ形式でデータを保存(高速・コンパクト)
void SaveBinaryData(double &prices[], int count)
  {
   int handle = FileOpen("price_data.bin", FILE_WRITE | FILE_BIN);
   if(handle == INVALID_HANDLE) return;

   // まず要素数を書き込む
   FileWriteInteger(handle, count);

   // 価格データを書き込む
   for(int i = 0; i < count; i++)
      FileWriteDouble(handle, prices[i]);

   FileClose(handle);
  }

// バイナリデータの読み込み
bool LoadBinaryData(double &prices[])
  {
   int handle = FileOpen("price_data.bin", FILE_READ | FILE_BIN);
   if(handle == INVALID_HANDLE) return false;

   int count = FileReadInteger(handle);
   ArrayResize(prices, count);

   for(int i = 0; i < count; i++)
      prices[i] = FileReadDouble(handle);

   FileClose(handle);
   return true;
  }

FileWriteArray / FileReadArray:配列の一括保存・読み込み

配列をまるごとファイルに保存・読み込みします。構造体配列にも対応しており、大量のデータを効率的に扱えます。

uint FileWriteArray(
   int          file_handle,        // ファイルハンドル
   const void&  array[],            // 書き込む配列
   int          start = 0,          // 開始位置
   int          count = WHOLE_ARRAY // 要素数
);

uint FileReadArray(
   int    file_handle,
   void&  array[],
   int    start = 0,
   int    count = WHOLE_ARRAY
);

// MqlRates(ローソク足データ)の保存と読み込み
void SaveRatesToFile(string filename)
  {
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   int copied = CopyRates(_Symbol, PERIOD_H1, 0, 1000, rates);
   if(copied <= 0) return;

   int handle = FileOpen(filename, FILE_WRITE | FILE_BIN);
   if(handle == INVALID_HANDLE) return;

   FileWriteInteger(handle, copied);  // 要素数
   FileWriteArray(handle, rates, 0, copied);
   FileClose(handle);

   Print(copied,"本のバーデータを保存しました");
  }

bool LoadRatesFromFile(string filename, MqlRates &rates[])
  {
   int handle = FileOpen(filename, FILE_READ | FILE_BIN);
   if(handle == INVALID_HANDLE) return false;

   int count = FileReadInteger(handle);
   ArrayResize(rates, count);
   FileReadArray(handle, rates, 0, count);
   FileClose(handle);

   Print(count,"本のバーデータを読み込みました");
   return true;
  }

// カスタム構造体の保存
struct TradeRecord
  {
   datetime          time;
   string            symbol;  // 注意: string型は保存不可
   double            price;
   double            lot;
   double            profit;
  };
// ※ string型を含む構造体はFileWriteArrayで保存できません。
// バイナリ保存する場合はchar配列に置き換えるか、CSVで保存してください。
重要

FileWriteArray()string型を含む構造体は保存できません。文字列データを含む場合はCSV形式で保存するか、文字列を固定長のchar配列に変換してから保存してください。

FileReadString:テキスト読み込み

string FileReadString(
   int  file_handle,   // ファイルハンドル
   int  length = -1    // 読み取り文字数(-1=区切りまで)
);

// テキストファイルの全行読み込み
void ReadAllLines(string filename)
  {
   int handle = FileOpen(filename, FILE_READ | FILE_TXT | FILE_ANSI);
   if(handle == INVALID_HANDLE)
     {
      Print("ファイルが見つかりません:", filename);
      return;
     }

   int lineNum = 0;
   while(!FileIsEnding(handle))
     {
      string line = FileReadString(handle);
      lineNum++;
      Print(lineNum,":", line);
     }
   FileClose(handle);
  }

// CSVファイルの読み込み(フィールドごと)
void ReadCsvFile(string filename)
  {
   int handle = FileOpen(filename, FILE_READ | FILE_CSV | FILE_ANSI, ',');
   if(handle == INVALID_HANDLE) return;

   while(!FileIsEnding(handle))
     {
      string field1 = FileReadString(handle);  // 最初のフィールド
      string field2 = FileReadString(handle);  // 2番目のフィールド
      double field3 = FileReadNumber(handle);  // 3番目(数値)

      if(StringLen(field1) > 0)
         Print(field1," |", field2," |", field3);
     }
   FileClose(handle);
  }

FileIsExist / FileDelete:ファイルの存在確認と削除

bool FileIsExist(
   const string  file_name,         // ファイル名
   int           common_flag = 0    // FILE_COMMONで共通フォルダ指定
);

bool FileDelete(
   const string  file_name,
   int           common_flag = 0
);

// 使用例: 設定ファイルの存在確認
if(FileIsExist("ea_settings.txt"))
   Print("設定ファイルが見つかりました");
else
   Print("設定ファイルが見つかりません。デフォルト値を使用します。");

// 古いログファイルの削除
void CleanOldLogs(int daysToKeep)
  {
   string filename;
   long searchHandle = FileFindFirst("ea_log_*.txt", filename);
   if(searchHandle == INVALID_HANDLE) return;

   do
     {
      // ファイル名から日付を解析して古いものを削除
      // (簡略化した例)
      if(FileIsExist(filename))
        {
         int handle = FileOpen(filename, FILE_READ | FILE_BIN);
         if(handle != INVALID_HANDLE)
           {
            // ファイルの更新日時チェックは直接取得できないため
            // ファイル名に日付を含める方式が推奨
            FileClose(handle);
           }
        }
     }
   while(FileFindNext(searchHandle, filename));
   FileFindClose(searchHandle);
  }

FileFindFirst / FileFindNext / FileFindClose:ファイルの検索

long FileFindFirst(
   const string  file_filter,   // 検索パターン(ワイルドカード対応)
   string&       returned_filename,
   int           common_flag = 0
);

bool FileFindNext(
   long     search_handle,
   string&  returned_filename
);

void FileFindClose(
   long  search_handle
);

// MQL5Files 内のCSVファイル一覧を取得
void ListCsvFiles()
  {
   string filename;
   long handle = FileFindFirst("*.csv", filename);
   if(handle == INVALID_HANDLE)
     {
      Print("CSVファイルが見つかりません");
      return;
     }

   Print("=== CSVファイル一覧 ===");
   int count = 0;
   do
     {
      count++;
      Print(count,":", filename);
     }
   while(FileFindNext(handle, filename));

   FileFindClose(handle);
   Print("合計:", count,"ファイル");
  }

// サブフォルダ内の検索
void ListFilesInFolder(string folder)
  {
   string filename;
   long handle = FileFindFirst(folder +"*.*", filename);
   if(handle == INVALID_HANDLE) return;

   do
     {
      Print(folder,"", filename);
     }
   while(FileFindNext(handle, filename));

   FileFindClose(handle);
  }

FolderCreate / FolderDelete:フォルダ操作

bool FolderCreate(
   string  folder_name,        // フォルダ名
   int     common_flag = 0     // FILE_COMMONで共通フォルダ
);

bool FolderDelete(
   string  folder_name,
   int     common_flag = 0
);

// EA用のサブフォルダを作成
string eaFolder ="MyEA_v2";
// FolderCreateは既存フォルダでも問題なく動作する
   FolderCreate(eaFolder);

// 日付別のログフォルダ
MqlDateTime dt;
TimeCurrent(dt);
string dateFolder = StringFormat("logs%04d%02d%02d", dt.year, dt.mon, dt.day);
FolderCreate(dateFolder);

// フォルダ内にファイルを作成
int handle = FileOpen(dateFolder +"trade_log.csv",
                      FILE_WRITE | FILE_CSV | FILE_ANSI, ',');
if(handle != INVALID_HANDLE)
  {
   FileWrite(handle,"Time","Action","Price");
   FileClose(handle);
  }

FileSeek / FileTell / FileSize:ファイルポインタ操作

bool FileSeek(
   int   file_handle,  // ファイルハンドル
   long  offset,       // オフセット(バイト数)
   int   origin        // 基準位置: SEEK_SET(先頭), SEEK_CUR(現在位置), SEEK_END(末尾)
);

ulong FileTell(
   int  file_handle    // 現在位置を取得
);

ulong FileSize(
   int  file_handle    // ファイルサイズを取得
);

// 追記パターン
void AppendToFile(string filename, string text)
  {
   int handle = FileOpen(filename, FILE_READ | FILE_WRITE | FILE_TXT | FILE_ANSI);
   if(handle == INVALID_HANDLE)
     {
      // ファイルが存在しない場合は新規作成
      handle = FileOpen(filename, FILE_WRITE | FILE_TXT | FILE_ANSI);
      if(handle == INVALID_HANDLE) return;
     }
   else
      FileSeek(handle, 0, SEEK_END);  // 末尾に移動

   FileWriteString(handle, text +"n");
   FileClose(handle);
  }

// ファイルサイズの確認
void CheckFileSize(string filename)
  {
   int handle = FileOpen(filename, FILE_READ | FILE_BIN);
   if(handle == INVALID_HANDLE) return;

   ulong size = FileSize(handle);
   FileClose(handle);

   if(size > 10 * 1024 * 1024)  // 10MB超
      Print("警告: ファイルサイズが大きいです:", size / 1024,"KB");
  }

FileFlush:バッファのフラッシュ

void FileFlush(
   int  file_handle  // ファイルハンドル
);

// リアルタイムログでの使用
// FileClose()せずに、書き込んだデータをディスクに確実に保存
int logHandle = INVALID_HANDLE;

int OnInit()
  {
   logHandle = FileOpen("realtime_log.txt",
                        FILE_WRITE | FILE_TXT | FILE_SHARE_READ | FILE_ANSI);
   return logHandle != INVALID_HANDLE ? INIT_SUCCEEDED : INIT_FAILED;
  }

void OnTick()
  {
   if(logHandle == INVALID_HANDLE) return;

   string line = StringFormat("%s Bid=%.5f Ask=%.5fn",
                              TimeToString(TimeCurrent(), TIME_SECONDS),
                              SymbolInfoDouble(_Symbol, SYMBOL_BID),
                              SymbolInfoDouble(_Symbol, SYMBOL_ASK));
   FileWriteString(logHandle, line);
   FileFlush(logHandle);  // 即座にディスクに書き込む
  }

void OnDeinit(const int reason)
  {
   if(logHandle != INVALID_HANDLE)
      FileClose(logHandle);
  }

FileFlush()は、ファイルを閉じずにバッファの内容をディスクに書き出します。リアルタイムのログ記録で、外部プログラムからログを監視したい場合に使用します。ただし、毎ティック呼び出すとパフォーマンスに影響するため、特定のイベント時のみ使用することを推奨します。

FileIsEnding / FileIsLineEnding:ファイル終端の検出

bool FileIsEnding(int file_handle);      // ファイルの終端に達したか
bool FileIsLineEnding(int file_handle);  // 行の終端に達したか

// テキストファイルの全行読み込み
int handle = FileOpen("data.txt", FILE_READ | FILE_TXT | FILE_ANSI);
if(handle != INVALID_HANDLE)
  {
   while(!FileIsEnding(handle))
     {
      string line = FileReadString(handle);
      Print(line);
     }
   FileClose(handle);
  }

// CSVの行ごとの処理
int handle = FileOpen("data.csv", FILE_READ | FILE_CSV | FILE_ANSI, ',');
if(handle != INVALID_HANDLE)
  {
   while(!FileIsEnding(handle))
     {
      // 1行分のフィールドを読み込み
      string fields[];
      int fieldCount = 0;

      while(!FileIsLineEnding(handle) && !FileIsEnding(handle))
        {
         fieldCount++;
         ArrayResize(fields, fieldCount);
         fields[fieldCount-1] = FileReadString(handle);
        }

      // fieldsに1行分のデータが入っている
      if(fieldCount > 0)
         Print("列数:", fieldCount," 先頭:", fields[0]);
     }
   FileClose(handle);
  }

実践パターン:EA開発でのファイル活用

パターン1:CSV取引ログシステム

class CTradeLogger
  {
private:
   string            m_filename;
   bool              m_headerWritten;

public:
                     CTradeLogger(string eaName)
     {
      MqlDateTime dt;
      TimeCurrent(dt);
      m_filename = StringFormat("%s%s_%04d%02d%02d.csv",
                                eaName, _Symbol, dt.year, dt.mon, dt.day);
      m_headerWritten = FileIsExist(m_filename);

      // フォルダ作成
      FolderCreate(eaName);
     }

   void              LogEntry(ulong ticket, string direction, double price,
                              double lot, double sl, double tp)
     {
      int handle = FileOpen(m_filename,
                            FILE_READ | FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ',');
      if(handle == INVALID_HANDLE) return;

      if(!m_headerWritten)
        {
         FileWrite(handle,"DateTime","Ticket","Type","Symbol","Price","Lot","SL","TP","Spread","Comment");
         m_headerWritten = true;
        }

      FileSeek(handle, 0, SEEK_END);
      FileWrite(handle,
         TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS),
         ticket, direction, _Symbol,
         DoubleToString(price, _Digits),
         DoubleToString(lot, 2),
         DoubleToString(sl, _Digits),
         DoubleToString(tp, _Digits),
         (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD),"Entry"
      );
      FileClose(handle);
     }

   void              LogExit(ulong ticket, double closePrice, double profit)
     {
      int handle = FileOpen(m_filename,
                            FILE_READ | FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ',');
      if(handle == INVALID_HANDLE) return;

      FileSeek(handle, 0, SEEK_END);
      FileWrite(handle,
         TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS),
         ticket,"Close", _Symbol,
         DoubleToString(closePrice, _Digits),"","","",
         (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD),
         StringFormat("Exit P/L=%.2f", profit)
      );
      FileClose(handle);
     }
  };

パターン2:設定ファイルの読み書き

class CSettings
  {
private:
   string            m_filename;
   string            m_keys[];
   string            m_values[];
   int               m_count;

public:
                     CSettings(string filename) : m_filename(filename), m_count(0) {}

   // 設定ファイルの読み込み(key=value形式)
   bool              Load()
     {
      if(!FileIsExist(m_filename)) return false;

      int handle = FileOpen(m_filename, FILE_READ | FILE_TXT | FILE_ANSI);
      if(handle == INVALID_HANDLE) return false;

      m_count = 0;
      while(!FileIsEnding(handle))
        {
         string line = FileReadString(handle);
         StringTrimLeft(line);
         StringTrimRight(line);

         // コメント行とブランク行をスキップ
         if(StringLen(line) == 0 || StringGetCharacter(line, 0) == '#')
            continue;

         // key=value の解析
         int eqPos = StringFind(line,"=");
         if(eqPos <= 0) continue;

         m_count++;
         ArrayResize(m_keys, m_count);
         ArrayResize(m_values, m_count);
         m_keys[m_count-1] = StringSubstr(line, 0, eqPos);
         m_values[m_count-1] = StringSubstr(line, eqPos + 1);
         StringTrimLeft(m_keys[m_count-1]);
         StringTrimRight(m_keys[m_count-1]);
         StringTrimLeft(m_values[m_count-1]);
         StringTrimRight(m_values[m_count-1]);
        }
      FileClose(handle);
      Print(m_count,"件の設定を読み込みました");
      return true;
     }

   // 値の取得
   string            GetString(string key, string defaultVal ="")
     {
      for(int i = 0; i < m_count; i++)
         if(m_keys[i] == key) return m_values[i];
      return defaultVal;
     }

   int               GetInt(string key, int defaultVal = 0)
     { return (int)StringToInteger(GetString(key, IntegerToString(defaultVal))); }

   double            GetDouble(string key, double defaultVal = 0)
     { return StringToDouble(GetString(key, DoubleToString(defaultVal, 8))); }

   bool              GetBool(string key, bool defaultVal = false)
     { return GetString(key, defaultVal ?"true" :"false") =="true"; }

   // 設定ファイルの保存
   bool              Save()
     {
      int handle = FileOpen(m_filename, FILE_WRITE | FILE_TXT | FILE_ANSI);
      if(handle == INVALID_HANDLE) return false;

      FileWriteString(handle,"# EA Settings - Auto Generatedn");
      FileWriteString(handle, StringFormat("# %snn",
                      TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS)));

      for(int i = 0; i < m_count; i++)
         FileWriteString(handle, m_keys[i] +"=" + m_values[i] +"n");

      FileClose(handle);
      return true;
     }
  };

// 使用例
CSettings settings("myea_config.txt");
int OnInit()
  {
   if(settings.Load())
     {
      double lotSize = settings.GetDouble("lot_size", 0.01);
      int slPips = settings.GetInt("sl_pips", 50);
      bool useTrailing = settings.GetBool("use_trailing", false);
     }
   return INIT_SUCCEEDED;
  }

パターン3:EA間通信(ファイルベース)

// 共通フォルダを使ったEA間通信
// 送信側EA
void SendSignal(string signalName, int direction, double price)
  {
   string filename ="signals" + signalName +".sig";
   int handle = FileOpen(filename,
                         FILE_WRITE | FILE_TXT | FILE_COMMON | FILE_SHARE_READ);
   if(handle == INVALID_HANDLE) return;

   string data = StringFormat("%d|%.5f|%s|%s",
                              direction, price, _Symbol,
                              TimeToString(TimeCurrent()));
   FileWriteString(handle, data);
   FileClose(handle);
  }

// 受信側EA
struct SignalData
  {
   int    direction;
   double price;
   string symbol;
   string time;
  };

bool ReceiveSignal(string signalName, SignalData &signal)
  {
   string filename ="signals" + signalName +".sig";
   if(!FileIsExist(filename, FILE_COMMON)) return false;

   int handle = FileOpen(filename,
                         FILE_READ | FILE_TXT | FILE_COMMON | FILE_SHARE_WRITE);
   if(handle == INVALID_HANDLE) return false;

   string data = FileReadString(handle);
   FileClose(handle);

   // シグナルデータを解析
   string parts[];
   if(StringSplit(data, '|', parts) < 4) return false;

   signal.direction = (int)StringToInteger(parts[0]);
   signal.price     = StringToDouble(parts[1]);
   signal.symbol    = parts[2];
   signal.time      = parts[3];

   // 読み取り後にファイルを削除(1回だけ処理)
   FileDelete(filename, FILE_COMMON);
   return true;
  }

パターン4:パフォーマンスレポートの出力

void GeneratePerformanceReport()
  {
   string filename = StringFormat("report_%s_%s.csv",
                                  _Symbol,
                                  TimeToString(TimeCurrent(), TIME_DATE));
   StringReplace(filename,".","");
   StringReplace(filename,":","");

   int handle = FileOpen(filename, FILE_WRITE | FILE_CSV | FILE_ANSI, ',');
   if(handle == INVALID_HANDLE) return;

   // ヘッダー
   FileWrite(handle,"Ticket","Time","Type","Symbol","Lot","Price","SL","TP","Profit","Swap","Commission");

   // 取引履歴の出力
   HistorySelect(0, TimeCurrent());
   int total = HistoryDealsTotal();
   double totalProfit = 0;
   int winCount = 0, lossCount = 0;

   for(int i = 0; i < total; i++)
     {
      ulong ticket = HistoryDealGetTicket(i);
      if(HistoryDealGetInteger(ticket, DEAL_ENTRY) != DEAL_ENTRY_OUT)
         continue;

      double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
      totalProfit += profit;
      if(profit >= 0) winCount++; else lossCount++;

      FileWrite(handle,
         ticket,
         TimeToString((datetime)HistoryDealGetInteger(ticket, DEAL_TIME)),
         HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_BUY ?"Buy" :"Sell",
         HistoryDealGetString(ticket, DEAL_SYMBOL),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_VOLUME), 2),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_PRICE), _Digits),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_SL), _Digits),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_TP), _Digits),
         DoubleToString(profit, 2),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_SWAP), 2),
         DoubleToString(HistoryDealGetDouble(ticket, DEAL_COMMISSION), 2)
      );
     }

   // サマリー行
   FileWrite(handle,"");
   FileWrite(handle,"Summary");
   FileWrite(handle,"Total Trades", winCount + lossCount);
   FileWrite(handle,"Win", winCount);
   FileWrite(handle,"Loss", lossCount);
   FileWrite(handle,"Win Rate",
             DoubleToString(winCount * 100.0 / MathMax(winCount + lossCount, 1), 1) +"%");
   FileWrite(handle,"Total Profit", DoubleToString(totalProfit, 2));

   FileClose(handle);
   Print("レポートを出力しました:", filename);
  }

ファイル関数一覧リファレンス

関数機能対応モード
FileOpenファイルを開くCSV / TXT / BIN
FileCloseファイルを閉じる全モード
FileWriteCSV行の書き込みCSV
FileWriteString文字列の書き込みTXT / BIN
FileWriteInteger整数の書き込みBIN
FileWriteDouble浮動小数点の書き込みBIN
FileWriteArray配列の一括書き込みBIN
FileReadString文字列の読み込みCSV / TXT / BIN
FileReadInteger整数の読み込みBIN
FileReadDouble浮動小数点の読み込みBIN
FileReadArray配列の一括読み込みBIN
FileIsExistファイルの存在確認-
FileDeleteファイルの削除-
FileFindFirst/Next/Closeファイルの検索-
FolderCreateフォルダの作成-
FolderDeleteフォルダの削除-
FileSeekポインタ移動全モード
FileTell現在位置の取得全モード
FileSizeファイルサイズ全モード
FileFlushバッファのフラッシュ全モード
FileIsEndingファイル終端検出全モード
FileIsLineEnding行終端検出CSV / TXT
  • FILE_SHARE_READを使えば、EA動作中に外部プログラムからログを監視できる
  • FILE_COMMONで複数ターミナル間のデータ共有が可能
  • 追記はFILE_READ | FILE_WRITE + FileSeek(SEEK_END)の組み合わせで実現
  • バイナリ保存はFileWriteArrayが最も高速でコンパクト
  • ファイルを開いたら必ずFileClose()で閉じる(リソースリーク防止)

プロが開発したEAをお探しの方は → シストレ.COM EA一覧

MQL5ファイル操作 よくある質問

MQL5のファイル操作の特徴は?

MQL4と同じFileOpen()/FileWrite()/FileClose()に加え、FileFindFirst()/FileFindNext()によるファイル検索、FileIsExist()による存在確認が追加されています。FILE_COMMONフラグで全MT5インスタンス共有フォルダへの保存も可能です。

MQL5でCSVファイルに書き込む方法は?

FileOpen(filename,FILE_CSV|FILE_WRITE|FILE_ANSI,',')でCSVモードで開き、FileWrite(handle,col1,col2)で行を書き込みます。FILE_ANSIまたはFILE_UNICODEのエンコード指定が必要です。

MQL5のファイル保存場所は?

MQL5/Filesフォルダ(データフォルダ内)が標準の保存先です。FILE_COMMONフラグを使うと共通フォルダ(全MT5インスタンス共有)に保存できます。TerminalInfoString(TERMINAL_DATA_PATH)でデータフォルダのパスを取得できます。

MQL5でログファイルを実装する方法は?

FileOpen()でFILE_WRITE|FILE_TXTモードで開き、FileWrite()でログ行を書き込みます。タイムスタンプにはTimeToString(TimeCurrent())を使用します。追記はFILE_READ|FILE_WRITEでシークするか、FILE_WRITEのみで毎回上書きします。

MQL5のファイル操作エラーの対処法は?

GetLastError()でエラーコード確認、FileIsExist()で事前存在チェック、返り値がINVALID_HANDLEの場合はエラー処理を行います。OnDeinit()でFileClose()を必ず呼んでハンドルリークを防ぎます。

MQL5でCSVファイルを読み込む方法は?

FileOpen(filename,FILE_CSV|FILE_READ|FILE_ANSI,',')で開き、FileIsEnding(handle)でEOFを確認しながらFileReadString()で1フィールドずつ読み込みます。FileReadInteger()/FileReadDouble()で型を指定した読み込みも可能です。

まとめ

MQL5リファレンス 関連記事

シストレ.COM編集部|200種類以上のEAをフォワード計測する運営3年の検証メディア。MetaTrader (MT4/MT5) を実運用してきた編集部が監修・執筆しています。

⚠ リスクに関する注意事項

本記事は情報提供を目的としており、特定の金融商品の売買を推奨するものではありません。FX取引はレバレッジ取引の特性上、預託した証拠金以上の損失が生じる可能性があります。取引の際は、ご自身の判断と責任において行ってください。詳しくは特定商取引法に基づく表記をご確認ください。

シストレ.COMで実績のあるEAが使い放題!/
無料会員登録はこちら
FX自動売買でEAを探すなら
シストレ.COM 記事下バナー
実績あるEAが無料
厳格な審査を乗り越えた実績のあるEAが無料で使えます!
自由な口座選び
有料版を購入し柔軟な口座選びが可能!
フォワードテスト公開
全EAのフォワードテスト結果を公開中!
FX初心者も安心
初心者の方も安心して取引を始められます。
多様なEA選択肢
様々な種別のEAをご用意!自分の手法にあった取引が可能です。
信頼のFX会社と提携
人気のFX会社と提携中!様々なFX会社から選べます。
1分で登録完了!EA探すならシストレ.COM!/
無料会員登録はこちら

この記事が気に入ったら
フォローしてね!

お役立ち情報をシェアする
  • URLをコピーしました!

この記事を書いた人

シストレ.COM編集部は、FX自動売買(EA)とテクニカル分析を専門とするインターネットメディア「シストレ.COM」の編集チームです。200本以上のEAのフォワードテスト結果を公開し、実際の運用データに基づいた客観的な情報を発信しています。記事の執筆・監修はMetaTrader(MT4/MT5)での実運用経験を持つスタッフが担当。

目次