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のファイル操作の違い
| 項目 | MQL4 | MQL5 |
|---|---|---|
| デフォルトパス | 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_READ | 1 | 読み取り用 |
| FILE_WRITE | 2 | 書き込み用(ファイルが存在しない場合は新規作成) |
| FILE_BIN | 4 | バイナリモード |
| FILE_CSV | 8 | CSVモード(delimiter指定有効) |
| FILE_TXT | 16 | テキストモード(改行区切り) |
| FILE_ANSI | 32 | ANSI文字列(1バイト) |
| FILE_UNICODE | 64 | Unicode文字列(2バイト) |
| FILE_SHARE_READ | 128 | 他プロセスとの同時読み取りを許可 |
| FILE_SHARE_WRITE | 256 | 他プロセスとの同時書き込みを許可 |
| FILE_COMMON | 4096 | 共通フォルダを使用 |
// パターン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);
}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 | ファイルを閉じる | 全モード |
| FileWrite | CSV行の書き込み | 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一覧





