コンテンツにスキップ

【移植#47】生のHSTを読まずに履歴を一括CSV化 — 3通貨×500本をCopyRatesで書き出す

EURUSD・USDJPY・GBPUSDの確定済みM1足をCSVへ一括出力し、行数・時系列・OHLCを検証したMT5画面

この記事の3行まとめ

  • 古いHSTバイナリを直接解析せず、MT5のCopyRates()から確定足を取得します
  • 初期設定では3通貨×500本を別々のCSVへ出力し、古い足から新しい足へ並べます
  • 実機では全1,500行を元のレートと再照合し、時刻・OHLC・出来高・スプレッドの一致を確認しました

今回の原典は「HSTをCSVへ一括変換するPerlツール」

投稿日順で次に当たる2010年2月5日の記事は、MT4の履歴ファイルをCSVへ変換するPerlツールを紹介していました。

元記事「hstファイルをcsvに一括変換するPerlツール。」を読む

原典のツールは、ファイルまたはフォルダーをドラッグ&ドロップで受け取り、対象となるHSTファイルをまとめてCSVへ変換するものでした。フォルダーのサブ階層までは探索しない、単純な一括処理です。

当時の説明では、HSTファイルを次の固定長バイナリとして扱っていました。

  • 先頭148バイト: ヘッダー
  • 以降44バイトずつ: 日時、OHLC、出来高を含むレコード

この方法は、変換対象の形式とレコード配置が分かっている場合には高速です。一方、端末やファイル形式の世代が変わると、固定したバイト数や型の並びも見直さなければなりません。

今回は「複数の履歴をまとめてCSV化する」という目的だけを引き継ぎ、現在のMT5が提供する時系列APIから書き出します。


HSTを解析せず、端末に履歴を問い合わせる

配布インジケーターは、CopyRates()MqlRates配列を取得します。

MQL
MqlRates rates[];
const int copied =
   CopyRates(symbol, InpTimeframe, 1, InpBarsPerFile, rates);

開始位置を1にしているのは、形成中の0番バーを除外するためです。エクスポートの途中で高値や終値が変わらない、確定済みの足だけを対象にします。

MqlRatesには次の情報がまとまっています。

フィールド CSV列
time DateTime
open Open
high High
low Low
close Close
tick_volume TickVolume
spread Spread
real_volume RealVolume

生のHSTファイルを開かないため、ヘッダーのバイト数、レコード長、エンディアン、数値型の配置をエクスポーター側で決め打ちしません。

ただし、CopyRates()が成功するには、指定した銘柄と時間足の履歴が端末側で利用できる必要があります。未取得の履歴はダウンロードや構築が始まり、最初の呼び出しでは必要本数が返らないことがあります。

そのため、配布版は1秒タイマーで再試行し、全銘柄を必要本数取得できた時点で処理を完了します。完了後はタイマーを停止し、同じCSVを繰り返し上書きしません。


銘柄を選択してから一括処理する

初期設定の対象は次の3通貨です。

Text Only
EURUSD,USDJPY,GBPUSD

カンマで分割した後、空欄と重複を拒否し、各銘柄をSymbolSelect()で気配値表示へ追加してから履歴を取得します。

処理は対象銘柄ごとに次の順で進みます。

  1. 銘柄を選択する
  2. 確定済みの500本を取得する
  3. 時刻の昇順とOHLCの整合性を確認する
  4. 銘柄ごとのCSVへ500行を書き出す
  5. 全銘柄が成功したらCOMPLETEにする

1銘柄でも取得、検査、書込みに失敗すると完了扱いになりません。成功した件数だけを見て「だいたい終わった」と判定しない設計です。


CSVは古い足から新しい足へ並べる

CopyRates()で配列へコピーされたデータは、物理メモリ上では最も古い要素が先頭に置かれます。配布版はその順序を保ったまま、0番から末尾まで書き出します。

出力例は次のとおりです。

Text Only
Date,Time,Open,High,Low,Close,TickVolume,Spread,RealVolume
2026.07.23,23:52,1.17789,1.17795,1.17786,1.17791,18,0,0
2026.07.23,23:53,1.17791,1.17796,1.17788,1.17794,24,0,0

日付と時刻を分離しているため、表計算ソフトでも列として扱いやすくなります。価格の小数桁は銘柄のSYMBOL_DIGITSに合わせます。

FileWrite()を使い、1行目に9列のヘッダー、その後に指定本数のデータ行を書きます。改行はMQL5のファイル関数に任せています。

出力先はMT5のファイルサンドボックス内です。初期設定では、端末固有のファイル領域に次の3ファイルが作られます。

Text Only
MQL47_Export\EURUSD_M1.csv
MQL47_Export\USDJPY_M1.csv
MQL47_Export\GBPUSD_M1.csv

任意の絶対パスへ直接書く方式ではありません。MQL5のFileOpen()が許可する領域に限定することで、出力場所の境界を明確にしています。


書き出す前に時系列とOHLCを検査する

CSVが作成できても、並びや値が壊れていれば変換成功とはいえません。配布版は各銘柄について、書込み前に次を確認します。

時系列

MQL
if(index > 0 && rates[index].time <= rates[index - 1].time)
   monotonic = false;

隣り合う日時が同一、または逆行していれば失敗です。CSV内の重複時刻や逆順を、そのまま後工程へ渡しません。

OHLC

各足について、少なくとも次の関係を満たすことを確認します。

Text Only
High >= max(Open, Close)
Low  <= min(Open, Close)
High >= Low

さらに日時と各価格が正の値であることも確認します。

この検査は相場データの完全性を保証するものではありませんが、列ずれ、型の読み違い、明らかなOHLC破損を早い段階で見つける助けになります。


12バッファとCSV再読込みで独立検証した

画面上のCOMPLETEだけを合格条件にせず、配布インジケーターは12本の診断バッファを公開します。

  1. 全体が完了したか
  2. 要求ファイル数
  3. 出力成功数
  4. 失敗数
  5. 合計データ行数
  6. 1ファイルの行数
  7. 時刻が昇順か
  8. OHLC条件を満たすか
  9. 試行回数
  10. 最後のエラーコード
  11. 全銘柄で最も古い日時
  12. 全銘柄で最も新しい日時

検証EAは12バッファを読み取った後、作成された3つのCSVをインジケーターとは別経路で開き直しました。

各CSVについてヘッダー9列、データ500行、日時の重複なし、厳密な昇順、OHLC条件を確認しています。さらに、CSVの最終時刻を基準にCopyRates()から同じ500本を再取得し、日時、OHLC、ティック出来高、スプレッド、実出来高を全行で照合しました。

実行条件

項目
MT5 Build 5836
表示チャート EURUSD・H1
出力対象 EURUSD・USDJPY・GBPUSD
出力時間足 M1
本数 500本×3ファイル
対象バー 確定足
文字コード UTF-8
区切り文字 カンマ

検証結果

確認項目 結果
配布インジケーターのコンパイル 0エラー・0警告
独立検証EAのコンパイル 0エラー・0警告
出力ファイル 3 / 3
データ行 1,500
各ファイルの行数 500
日時の重複 なし
日時の並び 古い足→新しい足
OHLC条件 全行PASS
元レートとの全項目照合 全行PASS
診断バッファ 12本一致
パネルオブジェクト 12
実画面キャプチャー 成功
売買注文 なし

検証時に作成したCSVは照合後に削除し、テスト用データを端末へ残していません。


ダウンロードと使い方

47_History_Batch_CSV_Exporter_v1_00.mq5 をダウンロード

MT5のIndicatorsへ保存してコンパイルし、任意のチャートへ適用してください。初回処理が完了すると、チャート左上のパネルにCOMPLETEと出力件数が表示されます。

入力パラメーターは次のとおりです。

パラメーター 初期値 役割
InpSymbols EURUSD,USDJPY,GBPUSD カンマ区切りの対象銘柄
InpTimeframe PERIOD_M1 出力する時間足
InpBarsPerFile 500 1銘柄あたりの確定足数
InpOutputFolder MQL47_Export ファイル領域内の出力フォルダー
InpMaxSymbols 10 受け付ける銘柄数の上限
InpShowPanel true 診断パネルを表示

ブローカーが銘柄名へ接尾辞を付けている場合は、実際の名称に合わせてください。たとえばEURUSD.aを利用する口座では、入力もEURUSD.aに変更します。

同名ファイルが存在する場合は上書きされます。必要なCSVは、次の実行前に別名で保存してください。


使えないこと・注意点

  • このインジケーターはHSTファイルを直接読み込む変換ツールではありません。
  • フォルダーを再帰探索せず、InpSymbolsで指定した銘柄だけを処理します。
  • CSVはティックデータではなく、指定時間足のバー情報です。
  • 形成中の0番バーを除外するため、最新ティックまでの途中経過は含みません。
  • 日時は取得したバーの開始時刻です。タイムゾーンは利用するブローカーのサーバー時刻に依存します。
  • 週末、休場、取引停止などがあるため、隣接行の時刻が常に時間足と同じ間隔になるとは限りません。
  • 必要な履歴が端末へ用意されるまで、処理が再試行されることがあります。
  • InpBarsPerFileは10〜100,000本に制限しています。大量出力ではメモリ使用量とファイルサイズが増えます。
  • 初期設定では最大10銘柄です。上限は変更できますが、入力値として50銘柄を超える設定は拒否します。
  • 銘柄名からファイル名に使えない文字は_へ置換します。
  • 同じ安全なファイル名へ変換される特殊な銘柄名を複数指定する運用は避けてください。
  • 出力成功後は自動更新しません。新しい確定足を追加する常時同期ツールではありません。
  • CSVの値は端末が受け取った履歴です。配信元そのものの正確性までは保証しません。
  • 表示とファイル出力だけを行い、注文、変更、取消、ポジション管理は行いません。

ロジック評価の結論

原典のPerlツールは、複数のHSTファイルを一括で扱える実用的な変換器でした。ただし、履歴ファイルの内部構造を148バイトのヘッダーと44バイトのレコードとして直接解釈する設計は、その形式を知っていることが前提です。

今回の移植では、ファイル形式を解析する責任を手放し、端末が公開しているMqlRatesを受け取る方式へ変えました。対象はファイル一覧ではなく銘柄一覧になりましたが、「複数の履歴を表計算や分析で扱えるCSVへまとめて出す」という目的は保っています。

さらに、確定足だけを対象にし、書込み前の時系列・OHLC検査と、書込み後の全行再照合を加えました。CSVが存在するだけで成功とせず、中身が元の履歴と一致するところまで確認しています。

古いバイナリ形式を読む必要が本当にあるなら、その仕様を版ごとに固定し、テストデータで解析結果を検証しなければなりません。しかし、現在の端末から現在の履歴を取り出す目的なら、まず公式APIを使う方が境界が明確です。

「ファイルを読めたか」ではなく、「必要な履歴を、期待した順序と列で、欠損なく書けたか」を合格条件にする。それが、今回の一括変換から引き継げる教訓です。


前後の記事

前: 【移植#46】DDEをやめて共有ファイルへ — Excel→MT5の文字列受信を安全にする

次: 【移植#48】アイコン改造をやめて端末識別バッジへ — 複数MT5を色と別名で見分ける

— SPONSORED —