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

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

目次

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

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

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

ディレクトリパス用途
ローカルMQL5\Files\EA固有のデータ(デフォルト)
共通Terminal\Common\Files\複数ターミナル間で共有するデータ
// ローカルフォルダのパス
string localPath = TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Files\\";
Print("ローカル: ", localPath);
// 例: C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\XXXX\MQL5\Files\

// 共通フォルダのパス
string commonPath = TerminalInfoString(TERMINAL_COMMONDATA_PATH) + "\\Files\\";
Print("共通: ", commonPath);
// 例: C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\Common\Files\
重要

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

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

項目MQL4MQL5
デフォルトパスMQL4\Files\MQL5\Files\
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] %s\n",
                              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
);

// MQL5\Files\ 内の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=%.5f\n",
                              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 Generated\n");
      FileWriteString(handle, StringFormat("# %s\n\n",
                      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一覧

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

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

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