決済のたびに`deal_log_mt4.csv`へ1行ずつ、
書き出すところまでを解説しました。
ただし、書き出しただけでは、
「結局どの通貨ペアで一番稼げているのか」は目で見て数えるしかありません。
この記事では、`StringSplit()`と`StringFind()`を使って、
CSVの1行をカンマ区切りで分解し、
通貨ペアごとの合計損益を自動で集計するスクリプトを解説します。
StringSplit/StringFindの書式
まずは2つの関数の書式を確認します。
StringSplitでカンマ区切りの1行を配列に分解する
公式リファレンス(StringSplit)によると、シグネチャは次の通りです。
int StringSplit( const string string_value, //分解したい文字列 const ushort separator, //区切り文字のコード string &result[] //分解結果を格納する配列 );
戻り値は、分解できた要素の数(`int`)です。
区切り文字には`’,’`のような1文字を指定します。
string fields[]; int count = StringSplit(line, ',', fields);
StringFindで特定の文字列を探す
公式リファレンス(StringFind)によると、シグネチャは次の通りです。
int StringFind( string string_value, //検索対象の文字列 string match_substring, //探したい部分文字列 int start_pos=0 //検索を始める位置 );
見つかった場合は開始位置、見つからなかった場合は`-1`が返ります。
補足: 文字列の先頭に一致するかどうかを調べたいだけなら、
`StringFind(line, “決済時刻”) == 0`のように、
戻り値が`0`かどうかで判定できます。
ヘッダー行のスキップと銘柄の絞り込み
集計を正しく行うために、読み込んだ1行ごとに3つのチェックを行います。
ヘッダー行をStringFindで検出してスキップする
`deal_log_mt4.csv`の1行目には、
「決済時刻,銘柄,方向,ロット,決済損益」という見出し行が入っています。
これを数値として集計しようとするとエラーの原因になるため、
`StringFind()`で先頭が「決済時刻」かどうかを調べ、
一致する行は読み飛ばします。
対象銘柄をStringFindで絞り込む
`TargetSymbol`が指定されている場合は、
`StringSplit()`で取り出した銘柄名(2列目)に対して、
`StringFind()`で部分一致を調べ、含まれていない行は集計から除外します。
列数が足りない行を弾く(壊れたデータへの備え)
注意: ログファイルを手動で編集した直後や、
書き込み中にMT4が強制終了した場合など、
まれに列が欠けた不完全な行が残ることがあります。
`StringSplit()`の戻り値(要素数)が期待する列数(5)未満の行は、
集計対象から外して読み飛ばすようにしてください。
実際に動くコード全体(集計スクリプト)
`deal_log_mt4.csv`を読み込み、
通貨ペアごとの合計損益と決済件数を「エキスパート」タブに出力する、
実際にMetaEditorでコンパイルできるスクリプトです。
//+------------------------------------------------------------------+
//| DealLogSummarizer.mq4 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.00"
#property strict
input string LogFileName = "deal_log_mt4.csv";//読み込むログファイル名
input string TargetSymbol = "";//空なら全銘柄を対象にする
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int handle = FileOpen(LogFileName, FILE_READ|FILE_TXT|FILE_ANSI);
if(handle == INVALID_HANDLE)
{
Print("ログファイルを開けませんでした。エラーコード=", GetLastError());
return;
}
double totalProfit = 0;
int dealCount = 0;
while(!FileIsEnding(handle))
{
string line = FileReadString(handle);
if(StringLen(line) == 0)
continue;
if(StringFind(line, "決済時刻") == 0)
continue;//ヘッダー行はスキップ
string fields[];
int fieldCount = StringSplit(line, ',', fields);
if(fieldCount < 5)
continue;//列数が足りない行はスキップ
string symbol = fields[1];
if(TargetSymbol != "" && StringFind(symbol, TargetSymbol) < 0)
continue;//対象銘柄でなければスキップ
double profit = StringToDouble(fields[4]);
totalProfit += profit;
dealCount++;
}
FileClose(handle);
Print("集計対象=", (TargetSymbol == "" ? "全銘柄" : TargetSymbol),
" 件数=", dealCount,
" 合計損益=", DoubleToString(totalProfit, 2));
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4のMetaEditorで「ファイル」→「新規作成」→「スクリプト」を選ぶ
- 「DealLogSummarizer」という名前で作成し、テンプレートの中身をすべて削除してコード全体を貼り付ける
- F7キーでコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- 先に決済ログを書き込むEAで`deal_log_mt4.csv`を用意しておく
- ナビゲーターの「スクリプト」からチャートへドラッグ&ドロップして実行し、「エキスパート」タブに集計結果が表示されるか確認する
集計結果の見方と限界
このスクリプトが表示する「合計損益」は、
あくまで`OrderProfit()`をそのまま合計した値です。
要点: スワップやコミッションを
別枠で管理しているブローカーの場合、
`OrderProfit()`だけでは実質的な損益と一致しないことがあります。
必要に応じてOrderSwap()や
OrderCommission()もログに追加し、
集計にも含めるよう改造してください。
`TargetSymbol`を空にすれば全銘柄が対象になりますが、
複数の通貨ペアを同時に取引している場合、
銘柄ごとに何度もスクリプトを実行して比較する使い方を想定しています。
よくあるエラー・意図と違う動きになるとき
- 合計損益が常に0になる: `deal_log_mt4.csv`に決済データがまだ1行もない可能性がある。先に決済ログを書き込むEAでポジションを1回決済しておく
- コンパイルエラーになる: `StringSplit()`の第3引数が配列(`string fields[]`のように`[]`付き)になっているか確認する
- 特定銘柄で絞り込んでも0件になる: `TargetSymbol`のスペルが`deal_log_mt4.csv`内の銘柄表記(例: `USDJPY`)と完全に一致しているか確認する。前後に余分な空白が入っていないかも確認する
- `INVALID_HANDLE`でファイルを開けない: `deal_log_mt4.csv`がMT4の「MQL4/Files」フォルダに存在するか確認する
よくある質問
StringSplit/StringFindでよく検索されている疑問を、
3つにまとめて回答します。
区切り文字がカンマ以外の場合はどうすればよいですか?
`StringSplit()`の第2引数(`separator`)に、
タブや`;`など別の文字コードを渡せば、同じ仕組みでそのまま対応できます。
StringFindは大文字・小文字を区別しますか?
区別します。
銘柄名の表記ゆれ(`usdjpy`と`USDJPY`等)が心配な場合は、
`StringToUpper()`で両方を大文字にそろえてから、
比較してください。
配列の添字がずれてエラーになることがあります
`StringSplit()`の戻り値(要素数)を確認せずに、
`fields[4]`のように決め打ちで参照すると、列数が足りない行でエラーになります。
この記事のコードのように、
戻り値が期待する列数未満の行は先にスキップする書き方を徹底してください。
【MQL4】StringSplit/StringFindで決済ログCSVを解析し、通貨ペアごとの合計損益を集計するスクリプトの作り方:まとめ
この記事では、`StringSplit()`と`StringFind()`を使って、
決済ログCSVの1行をカンマ区切りで分解し、
通貨ペアごとの合計損益を集計するスクリプトを解説しました。
ポイントは、ヘッダー行の除外・列数不足の行の除外・
対象銘柄の絞り込みという、
実際にCSVを解析するときに必ず直面する3つの壁を、
あらかじめ防御的に処理しておくことです。
決済ログを書き出す記事と組み合わせれば、
「記録する」から「集計して振り返る」までを、
MT4だけで完結させられます。
コメント