MQL5標準ライブラリエクスプローラー(第8回):CFileTxtによるハイブリッド取引ジャーナルの記録
内容
はじめに
連載第8回へようこそ。本連載では、実践的かつ現実的なプロジェクトを通じてMQL5標準ライブラリの習得を進めています。前回実装したインタラクティブな視覚的ポジション管理システム(CCanvasで描画されたチャート上のバブルや、クリック可能なクローズボタンを含む)を基盤として、今回はプロフェッショナルレベルの永続化レイヤーとしてカスタムCSV取引ジャーナルを追加します。
MetaTrader 5は、約定の詳細や結果を正確に記録する優れた標準取引履歴機能を提供しています。EA内部で動作するハイブリッドシステムにおいては、アルゴリズムによる戦略ロジックと裁量的な手動操作を組み合わせることが多く、その場合には独自の分析ニーズに対応した追加のコンテキスト層が必要となります。本カスタムジャーナルでは、すべての記録イベントについて、その意思決定の起点(アルゴリズムによるものか「ALGO」、あるいはインタラクティブUI上の手動クリックによるものか「HUMAN」)を明示的に記録します。
この意図情報を、時間、チケット、シンボル、アクション、実現損益といった標準情報とともに記録することで、移植性が高く構造化されたデータセットを生成し、正確なパフォーマンス帰属分析を可能にします。本プロジェクトは、Files/FileTxt.mqhコンポーネントを用いた詳細な実装例でもあり、信頼性の高いファイル操作、データ整合性の確保、プラットフォーム標準機能と調和するクリーンな統合パターンを示します。
完成したエキスパートアドバイザー(EA)は、移動平均クロスオーバーロジック、動的キャンバス描画、ヒットボックスベースのインタラクション、そして意図を認識したジャーナリング機能を組み合わせています。その結果、単に取引を実行するだけでなく、その意思決定プロセスを記録し、エビデンスに基づく改善を可能にする成熟したハイブリッドツールとなります。
概念と利点
MetaTrader 5に標準搭載されている[口座履歴]タブおよびストラテジーテスターのレポートは堅牢であり、会計・規制対応・一般的なパフォーマンス要約の目的には十分に機能します。また、実行チャネルを正確に区別し、約定およびポジションの完全な時系列記録を提供します。
しかし、アクティブな開発およびハイブリッドシステムのライブ監視においては、反復的な改善に最も関連する問いに焦点を当てた補助的な記録が頻繁に必要となります。ここでの中心的なメタデータは意思決定のソースであり、アルゴリズムによるシグナルか、それともEAのイベントハンドラおよび取引クラスを通じて実行された裁量的な人間のオーバーライドか、という点です。この明示的なタグ付けにより、各コンポーネントの真の寄与を曖昧さなく分離・比較することが可能になります。
カスタムCSVジャーナルには、以下のような具体的な利点があります。
- 明確な意図の帰属:チャート上のクリックによる手動決済は「HUMAN」として記録され、戦略駆動のエントリーは「ALGO」として記録されます。この分離は、インタラクティブなハイブリッド設計においてはネイティブ履歴だけでは信頼性高く実現できません。
- 高いポータビリティ:CSVファイルはExcel、Google Sheets、LibreOffice、または任意のテキストエディタで即座に開くことができます。エクスポート手順やプラットフォーム依存の形式は不要です。
- 分析用の構造化データ:事前定義されたカラムにより、クレンジングや変換なしで即座にフィルタリング、ピボットテーブル、計算が可能です。
- 拡張性:新しいカラム(例:エントリー時のインジケーター値、現在のドローダウン、ボラティリティ指標、カスタムノートなど)の追加は、ログ記録呼び出しの軽微な変更のみで対応できます。
- 信頼性の高い診断:ジャーナルはシステムの意思決定の正確なタイムラインとして機能し、Expertsタブの出力のみに依存する場合よりも、デバッグや事後分析においてイベントの再構築が容易になります。
- クラッシュ耐性のある永続化:Flush()を適切に使用することで、各エントリーが物理的にディスクへ書き込まれ、ターミナルのクラッシュや電源障害時のデータ損失を防ぎます。
- 外部ツールとの連携:CSVはPython(Pandas、Matplotlib)、R、データベースへの直接入力として利用でき、高度な統計分析、エクイティカーブの分離、意思決定パターンの機械学習などを可能にします。
これらの利点は組み合わさることで、意思決定が混合的な集計ではなく、クリーンでソースを識別可能なエビデンスに基づくプロフェッショナルな開発ワークフローを支えます。
標準ライブラリの紹介
CFileTxtを理解する
CFileTxtクラスは、標準ライブラリにおけるテキストファイル操作のための軽量かつ強力なツールです。ファイルハンドルを抽象化しながら、CSV処理に特化した利便性も提供する高レベルなインターフェースを備えています。
本実装で使用する主要なメソッドとパターンは以下の通りです。
- Open():書き込みアクセス、CSVモード、ANSIエンコーディング、共通フォルダへの配置、さらにサイズチェック用の読み取り機能など、複数のフラグを組み合わせてファイルを開きます。
- Size():ファイルが新規かどうか(0バイトかどうか)を即座に判定し、ヘッダーを一度だけ書き込むために使用します。
- WriteString():テキストを効率的に追記します。CSVフラグが設定されている場合、クォートルールを適切に考慮します。
- Flush():信頼性確保の要となる処理であり、重要な書き込み後にデータを即座にディスクへ書き込みます。
- Seek():ポインタを末尾に移動し、追記処理を整合性のある状態でおこないます。
- Close():リソースを解放します(デストラクタ内で自動的に呼び出されます)。
これらのメソッドにより、最小限のコードでプロダクション品質のファイル処理が実現できます。同じクラスは、EA設定ファイルの保存、カスタムレポートのエクスポート、最適化パラメータの永続化、あるいはスクリプト間の簡易ファイルベース通信などにも同様に有用です。
実装
このセクションでは、第7回構築したインタラクティブ取引システムをさらに拡張します。これは独立したスクリプトではなく、既存実装を論理的に発展させたものです。これは単独のスクリプトではなく、これまでの実装の論理的な発展形です。ここでは、Files/FileTxt.mqhのファイルロギング機能を既存のEAに組み込みます。既存の戦略ロジックと可視化ロジックに、新たなデータ記録層を接続していきます。重点は実際に稼働中のEAへこの機能を組み込む具体的な統合プロセスで、既存のビジュアルロジックおよび売買ロジックとファイル出力を結び付け、自己記録型のアプリケーションを完成させる点にあります。
ステップ1:新しいライブラリによるツールセットの拡張
新機能を追加する最初のステップは、必要な標準ライブラリモジュールをインクルードすることです。本プロジェクトはすでにCanvasおよびトレード関連ライブラリを使用しているため、既存のインクルードリストにファイル操作ライブラリを追加するだけで対応できます。
以下がコードです。
//--- 1. INCLUDES (Extending the list from Part 7) #include <Canvas\Canvas.mqh> // For drawing custom graphics (from Part 7) #include <Trade\PositionInfo.mqh> // For reading trade details (from Part 7) #include <Trade\Trade.mqh> // For executing trades (from Part 7) #include <Indicators\Trend.mqh> // For Moving Averages (from Part 7) #include <Files\FileTxt.mqh> // NEW: This adds the CFileTxt class for file operations.
この一行を追加するだけで、テキストファイルの作成・書き込み・管理に必要なすべてのメソッドがプログラムに組み込まれます。CFileTxtクラスは新しいツールとしてワークショップに加わり、既存のCCanvasやCTradeと並んで利用できるようになります。
ステップ2:新しいコンポーネントとしてのCTradeJournalクラスの設計
次に、すべてのロギング処理を管理するための新しいクラスを設計します。このクラスは、メインプログラムに容易に統合できる自己完結型コンポーネントとして設計されます。その目的は、ファイル操作の複雑さをシンプルなインターフェースの背後に隠蔽することです。
以下がコードです。
//--- 3. THE JOURNAL CLASS (A new component we are adding) class CTradeJournal { private: CFileTxt m_file; // This is our handle to the physical file on disk. string m_filename; string m_sep; // Field separator for CSV format. public: // Constructor: Initializes the object's default state. CTradeJournal() : m_sep(",") {} // The initialization function we will call from OnInit(). bool Init(string filename) { m_filename = filename; // We define flags to control how the file is opened. int flags = FILE_WRITE|FILE_CSV|FILE_SHARE_READ; ResetLastError(); // Here, we attempt to open the file. If it fails, we report the error. if(m_file.Open(filename, flags) == INVALID_HANDLE) { Print("Journal Init Failed. Error: ", GetLastError()); return false; } // If the file is new, we write the column headers to define our data structure. if(m_file.Size() == 0) { string header = "Time,Ticket,Symbol,Action,Source,Profit\n"; m_file.WriteString(header); m_file.Flush(); // Immediately save the headers to disk. } // Move to the end of the file so all new logs are appended. m_file.Seek(0, SEEK_END); return true; }
このInitメソッドでは、いくつかのベストプラクティスを実装しています。FILE_SHARE_READを使用することで、ログファイルを書き込み中であっても他のプログラムが内容を閲覧できるようになります。また、GetLastError()の呼び出しによって、ファイルが開けなかった場合の具体的な診断情報を取得でき、これはデバッグにおいて非常に重要です。さらにFlush()メソッドにより、ヘッダーがメモリ上に保持されるだけでなく、ストレージへ物理的に書き込まれることが保証されます。
ステップ3:コアログ記録メソッドの実装
ここから、クラスの中核となるメソッドを構築します。このメソッドは取引システムのあらゆる場所から呼び出され、イベントを記録するために使用されます。その設計は、呼び出し側にとってのシンプルさと、実行時の信頼性を重視しています。
以下がコードです。
// This is the public method our main code will call to save an entry. void Log(ulong ticket, string action, string source, double profit) { // We construct a single, formatted CSV line from the input parameters. string line = StringFormat("%s,%d,%s,%s,%s,%.2f\n", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), ticket, _Symbol, action, source, // The key differentiator: "ALGO" or "HUMAN" profit); // We write the line and then force it to disk. m_file.WriteString(line); m_file.Flush(); // This ensures the data survives a terminal crash. // We also print to the Experts tab for immediate developer feedback. Print("Journal: ", action, " | Ticket: ", ticket, " | Source: ", source); }
Logメソッドは、設計意図がそのままコードとして具現化される部分です。sourceパラメータは、本システムに追加する最も重要なデータであり、ここでアルゴリズムによる自動取引と手動操作を明確に区別するという要件を実現しています。また、すべての書き込み後にFlush()を実行する設計は意図的なトレードオフであり、わずかなパフォーマンス低下を許容する代わりに、データの完全性を絶対的に保証します。これはトレードジャーナルにおいて妥協できない特性です。
ステップ4:既存システムへの新規コンポーネントの統合
ジャーナルクラスの実装が完了したので、次にこれを既存のEAへ統合します。グローバルインスタンスを追加し、他のオブジェクトと同様にOnInit()で初期化します。
以下がコードです。
//--- 4. GLOBAL OBJECTS (Adding to the existing list from Part 7) CCanvas ExtCanvas; // Existing object for visuals CPositionInfo ExtPosition; // Existing object for position data CTrade ExtTrade; // Existing object for trade execution CTradeJournal ExtJournal; // NEW: Our journaling object // Inside our existing OnInit() function: int OnInit() { // ... (Existing code to create indicators and canvas remains unchanged) ... // NEW INITIALIZATION: We start the journaling system. if(!ExtJournal.Init("HybridJournal.csv")) { return INIT_FAILED; // If logging fails, we fail the whole EA load. } return INIT_SUCCEEDED; }
これはクリーンでモジュール化された統合です。ジャーナルは他のサブシステムと対等なコンポーネントとして扱われます。また、その初期化を重要な処理として位置づけ(起動に失敗した場合はOnInit()を失敗させる)、システムが完全に動作するか、あるいは一切動作しないかのいずれかになるようにしています。これにより、取引が実行されているにもかかわらずログが記録されないという状況を回避できます。
ステップ5:取引イベントへのロギング接続
最後の、そして最も重要なステップは、既存の取引ロジックに計測機能(インストルメンテーション)を組み込むことです。ここでは、意味のあるアクションが発生する正確なタイミングでログ記録呼び出しを挿入します。
まず、第7回で実装した既存のアルゴリズムエントリーロジックを修正します。
以下がコードです。
// This is inside our existing CheckStrategy() function. // After a successful trade execution, we now add a logging call. if(ExtTrade.Buy(0.10, _Symbol, ask, sl, tp, "MA_Cross_Buy")) { // NEW LINE: We log this as an algorithmic entry. ExtJournal.Log(ExtTrade.ResultOrder(), "ENTRY_BUY", "ALGO", 0.0);
次に、第7回で説明した既存のOnChartEventハンドラを拡張し、手動決済をログに記録するようにします。
// Inside our existing OnChartEvent() function, where we handle bubble clicks. if(ExtPosition.SelectByTicket(ExtHitboxes[i].ticket)) { double final_profit = ExtPosition.Profit(); // Get profit before closing ExtTrade.PositionClose(ExtHitboxes[i].ticket); // Existing close command // NEW LINE: We log this as a human-triggered closure with the final profit. ExtJournal.Log(ExtHitboxes[i].ticket, "CLOSE_MANUAL", "HUMAN", final_profit); }
これらの追加処理は、本実装の集大成です。変更内容は最小限かつ的確ですが、その効果は非常に大きなものとなります。それぞれの処理において適切なsource文字列を渡すことで、ログファイル内のすべてのエントリーに、その操作の起点が明確に記録されます。これにより、CTradeJournalクラス、そしてその基盤となるCFileTxtライブラリは、ハイブリッド取引システムの2つの異なる動作モードを統一的に記録する仕組みとして機能するようになります。
ここで実施した内容は、反復的なソフトウェア開発の典型的な例です。第7回では視覚的な取引インターフェースを構築し、第8回ではそこへデータ永続化レイヤーを追加しました。ロギングモジュールは単独で存在するものではなく、キャンバス描画、注文実行、ポジション管理といった既存モジュールが正常に動作することで入力を受け取る依存サブシステムです。このように、ライブラリを追加し、専用クラスを設計し、グローバルインスタンスとして生成し、必要なタイミングでそのメソッドを呼び出すという一連の開発プロセスを通じて、トレードシステムに永続的な記録機構を持たせることができました。その結果、本記事の目的である、アルゴリズムによる操作と手動操作を永続的かつ分析可能な形式で明確に区別して記録する仕組みを実現できました。
テストと結果
コードをコンパイルし、EAの準備が整ったら、テストは複数の補完的なフェーズで実施します。これにより、システムの両側面、すなわちアルゴリズム取引とロギングロジック、そしてインタラクティブな人間主導の操作の両方を検証します。この分離は意図的なものであり、システム自体が自動処理と手動操作を区別している設計思想を反映しています。
フェーズ1:ストラテジーテスターによる迅速な検証(アルゴリズムパス)
コアとなるロギング機能を最も速く検証する方法は、MetaTrader 5のストラテジーテスターを使用することです。この環境では、EAが過去の価格データを処理し、移動平均クロスオーバー戦略に基づいて自動的に取引を実行します。ビジュアルモードを有効にすれば価格変動を観察できますが、ロギング検証には必須ではありません。
このフェーズには重要な制約があります。チャート上のバブルを用いた手動決済は標準的なバックテストではテストできません。なぜなら、ビジュアルインターフェースおよびOnChartEvent()ハンドラが動作しないためです。したがって、このフェーズはアルゴリズム実行およびジャーナリングの検証のみに焦点を当てています。
テストを実行するには、複数の移動平均クロスオーバーが発生する期間を選び、ストラテジーテスターでEAを実行します。実行中はストラテジーテスターの[エキスパート]タブを監視してください。戦略によって取引が実行されるたびに、次のようなメッセージが表示されます。
「Journal Entry Saved:ENTRY_BUY by ALGO.」
これらのメッセージは、アルゴリズム取引イベントが正しくキャプチャされ、ジャーナルに記録されていることを示します。
テスト完了後、生成されたCSVファイルを標準のターミナルディレクトリで確認します。
<ターミナルデータパス>\MQL5\Files\HybridJournal.csv
このファイルを開くことで、すべてのアルゴリズム取引が記録され、「ALGO」タグで一貫して分類されていることが確認できます。この方法により、制御された再現可能な環境で多数の取引に対してロギングロジックをストレステストできます。また、手動操作ロジックと切り離してアルゴリズムを検証することが可能になります。

図1:ストラテジーテスターでのクイックテスト
フェーズ2:ライブテストまたはビジュアルテスト(統合システム)
アルゴリズムパスの検証が完了したら、ライブチャートまたはビジュアルテスト環境で統合システム全体をテストします。
まず、Part8_HybridJournal.mq5ファイルをMetaEditorでコンパイルし、EURUSDなどの実用的な時間足(M5またはH1)チャートにEAを適用します。ライブ環境またはビジュアルテストで実行し、最適化専用モードではないことを確認してください。
EAをチャートに適用した直後に[エキスパート]タブを確認します。キャンバスが作成され、ジャーナルファイルが初期化またはオープンされたことを示すメッセージが表示されるはずです。ファイルアクセスエラーが発生する場合は、ターミナルにMQL5\Filesディレクトリへの書き込み権限があるか確認してください。正常な初期化は、CTradeJournalオブジェクトのInit()ルーチンが正常に実行され、CSVファイルが書き込み準備完了状態になったことを意味します。
次に、移動平均クロスオーバーが発生するまで戦略を実行します。短期移動平均線が長期移動平均線を上抜けると、EAは自動的にBuy注文を実行します。成功は3つのシグナルで確認できます。新しいポジションが[取引]タブに表示され、エントリーポイントにチケット番号と損益情報を含むビジュアルバブルが描画され、[エキスパート]タブに「ENTRY_BUY action by ALGO」というメッセージが出力されます。
これにより、アルゴリズム実行パスとロギングシステムがライブ環境でも完全に統合されていることが確認できます。
次に手動操作パスを検証します。取引バブル上の赤い「X」ボタンを見つけてクリックします。ポジションは即座に決済され、バブルはチャートから消え、[エキスパート]タブには「CLOSE_MANUAL action by HUMAN」というメッセージが表示されます。
この一連の流れにより、イベントがユーザー操作によって発生し、OnChartEvent()ハンドラを通過し、ポジションおよびトレードインターフェースを経由して、ジャーナルに正しく「HUMAN」タグ付きで記録されたことが確認できます。最終的な損益はクローズ前に取得されるため、履歴データの正確性が保証されます。
フェーズ3:ジャーナルの検証とインサイト抽出
正しい動作の最終的な証拠は以下のCSVファイルにあります。
<ターミナルデータパス>\MQL5\Files\HybridJournal.csv

図2:ターミナルフォルダのナビゲーション
このファイルをスプレッドシートで開くと、時間、チケット、シンボル、アクション、ソース、利益を含む構造化された記録が確認できます。アルゴリズム取引は「ALGO」、手動決済は「HUMAN」として明確に分類されているはずです。各行は即座にディスクへ書き込まれるため、予期せぬシャットダウンが発生しても永続性が保たれます。
この時点で、ジャーナルは単なる検証ツールではなくなります。簡単なフィルタリングによってアルゴリズムと手動のパフォーマンスを個別に分析し、取引回数、総利益、平均リターンなどの指標を算出できます。さらに高度な分析として、CSVをPythonに取り込み(PandasやMatplotlib)、Rやデータベースへ統合することで、エクイティカーブの分離、リスク指標の算出、手動介入の行動分析なども可能になります。
これらを総合すると、このテストプロセスは完全かつ体系的なワークフローを示しています。ストラテジーテスターはアルゴリズムロギングの高速で再現可能な検証を提供し、ライブまたはビジュアルテストはインタラクションと統合の検証をおこないます。その結果として得られるのは、ブラックボックス的な挙動を排除し、証拠に基づく洞察を提供する透明性の高い監査可能なシステムです。

図3:ライブテストで生成されたHybridJournal.csvの内容スニペット
図3はライブテスト後に生成されたCSVファイルの一部を示しています。ご覧の通り、テスト目的で多くのトレードが手動で決済されており、これはライブ市場条件下では自動的な出口条件が成立するまで時間がかかるためです。
結論
本記事では、実行と分析の間に存在していた重要なギャップを見事に橋渡しすることに成功しました。これまでの実装に監査・検証に適したジャーナリングシステムを追加することで、単なる取引ツールを「説明責任を持つシステム」へと変換し、すべての意思決定がその発生源に対して明確に帰属されるようにしました。この区別は極めて重要であり、システム性能を選択的に分析するための重要なデータを取得することを可能にします。
技術的観点から見ると、本プロジェクトはCFileTxtライブラリヘッダーコンポーネントを活用することで、最小限の労力でプロフェッショナルレベルの永続化を実現できることを示しています。標準ライブラリを利用することで、低レベルなファイルハンドル管理の複雑さや脆弱性を回避し、その代わりにアプリケーションロジックそのものに集中することができます。その結果として得られるハイブリッド型EAは堅牢でインタラクティブかつ自己記録型となり、構造化されたデータを生成することで規律ある分析と長期的な開発を支援します。また本成果は、集中ログ管理やExcel対応CSV出力といった機能が機関投資家向けプラットフォームに限定されたものではなく、ライブラリを正しく利用すればリテール開発者でも十分に実現可能であるという重要な事実を示しています。
本成果の価値は、この単一のEAにとどまりません。ここで導入された設計パターンは意図的に再利用可能なものとして設計されています。CTradeJournalクラスは自己完結型モジュールであり、将来のプロジェクトに容易に統合することで即座にフォレンジック的な可視性を付与できます。今後は、このジャーナルを拡張して追加フィールドを組み込んだり、別の出力フォーマットを試したり、あるいは他の標準ライブラリコンポーネントを用いたデータベースベースのストレージ統合など、より深い発展も可能です。いずれの拡張も、今回確立した「明確性」と「説明責任」という基盤の上に成り立っています。
添付ファイル
| ソースファイル名 | 種別 | バージョン | 説明 |
|---|---|---|---|
| Part8_HybridJournal | EA | 1.00 | Canvasインタラクションと意思決定ソースを識別できるCSVジャーナリングを統合した完全なハイブリッドEA |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/21045
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
プライスアクション分析ツールキットの開発(第59回):幾何学的非対称性を用いたフラクタル保ち合いからの高精度ブレイクアウトの識別
Python-MetaTrader 5ストラテジーテスター(第5回):複数銘柄および複数時間足ストラテジーテスター
MQL5取引ツールのアクセシビリティ課題を克服する(第1回):MQL5インジケータに状況対応型音声アラートを追加する方法
MQL5標準ライブラリエクスプローラー(第7回):CCanvasによるインタラクティブなポジションラベル表示
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索