
プライスアクション分析ツールキットの開発(第9回):External Flow
はじめに
金融市場は非常に複雑であり、トレーダーやアナリストにとって、データを正確に処理し解釈することはしばしば大きな課題となります。こうした課題に対処するため、市場分析を簡素化するさまざまなライブラリが開発されており、それぞれが特定の目的に沿ってデータを扱うよう設計されています。MQL5ライブラリは主に取引戦略やインジケーターの作成に使用されますが、Pythonのデータ分析ツールなどの外部ライブラリは、さらに高度で深い分析を実現するための追加的なリソースを提供します。
これまでの記事では、価格アクションやデータ分析に焦点を当て、主にMQL5のエキスパートアドバイザー(EA)によって処理される計算や指標を通じてシグナルを生成する方法を探ってきました。ただし、これらの記事はすべてMQL5ベースの分析にとどまっていました。今回の記事では、そうした枠を超えて、より高度なデータ分析のために設計された外部ライブラリの統合を取り上げます。Pythonのpandasライブラリを活用することで、トレーダーにとって新たな可能性が広がり、さまざまなニーズに対応した幅広い分析手法が実現できます。
この手法はMQL5の代替ではなく、その中核的な役割を果たします。MQL5のEAは、外部ライブラリやサーバーとの連携を可能にするブリッジとして機能し、より強力で柔軟な分析フレームワークを構築するための要となります。この記事は、高度な分析を本格的に活用するための第一歩に過ぎません。今後の連載では、さらに包括的な知見と実践的な手法をご紹介していく予定です。
それでは、どのようにこの課題に取り組んでいくかを見ていきましょう。
戦略の概要
このシステムの主な目的は、PythonのPandasライブラリを活用し、そのデータ解釈機能を使って売買シグナルを生成することです。このセクションでは、システムがどのようにコアロジックを実行しているのかを詳しく見ていきます。全体のやり取りは、MQL5のEAとPythonの間でおこなわれ、シグナルが最終的にチャートに表示されるまでの間に、いくつかの処理ステップが挟まれます。以下の手順を追って、システムの仕組みを理解していきましょう。
1. MQL5 EAからPythonへ
- MQL5 EAは、過去10日分の前日高値、安値、始値、終値、出来高のデータを収集します。
- データをPythonサーバーに送信します。
- データをCSV文字列にフォーマットし、HTTP POSTリクエストとしてPythonサーバーに送信します。
2. Pythonの処理
- Pythonは受信したデータを受け取り、Pandasなどのライブラリを使って処理します。
- その後、データを分析し、売買シグナル、平均価格、平均出来高を算出し、説明文を生成します。
3. PythonからEAへ
- Pythonは、生成したシグナル、平均価格、平均出来高、説明文をHTTPレスポンスとしてMQL5 EAに返送します。
4. MQL5 EAの処理
- MQL5 EAはレスポンスを受信し、それを解析してシグナル、平均価格、平均出来高、説明を抽出します。
- 現在のシグナルと異なる場合は、チャート上の表示を更新し、新しいシグナルを表示します。
システムの全体像をより明確に把握するために、以下の図もご参照ください。
図1:ロジックチャート
Pythonについて
Pythonは、そのシンプルさと幅広い用途で知られる汎用プログラミング言語です。データ分析、機械学習、Web開発、自動化など、さまざまな分野で広く利用されています。本システムにおいては、特にPandasのようなライブラリを通じて高度なデータ分析をおこなうためにPythonが重要な役割を果たします。さらに、PythonはMQL5とそのライブラリ間のやり取りを可能にするサーバーの構築にも使用されます。Pythonを使って複雑な市場データを処理することで、システムは過去のマーケットデータに基づいた売買シグナルを生成し、それをMQL5 EAに渡すことで、リアルタイムの取引判断をサポートします。
ここでは、Pythonのインストールからスクリプトの作成、実行までの手順を順を追って解説します。
- Pythonインストーラーをダウンロードする(Python の公式サイトにアクセスする)
- インストーラーを実行する
重要:[Add Python to PATH]にチェックを入れてから[Install Now]をクリックしてください。これにより、コマンドラインからPythonを簡単に実行できるようになります。
- インストールを完了する
インストーラーがインストールを開始します。完了するまで待ち、完了後は[Close]をクリックします。
- インストールを確認する
Windowsキー + Rを押し、「cmd」と入力してEnterを押します。コマンドプロンプトが開いたら、python --versionと入力してEnterを押します。Pythonが正しくインストールされていれば、バージョン情報(例:Python 3.x.x)が表示されます。
pythonのインストールに成功したら、次はflaskとpandasをインストールします。 Flaskは、PythonでWebアプリケーションを構築するための軽量なWebフレームワークで、シンプルで柔軟な設計が特徴です。 本システムでは、Flaskを使って簡易Webサーバーを構築し、MQL5 EAとPythonのデータ分析ライブラリ間の通信を可能にします。EAはFlaskにHTTPリクエストでデータを送信し、FlaskはそのデータをPandasで処理し、生成されたシグナルをEAへ返します。
コマンドプロンプトでFlaskとPandasをインストールするには、以下の手順に従ってください。
コマンドプロンプトを開く
- Windows + Rキーを押し、cmdと入力し、Enterキーを押します。
pip (Python Package Installer)がインストールされていることを確認する
- まず、pip(Pythonのパッケージマネージャー)がインストールされているかどうかを確認します。
pip --version
- バージョン情報が表示されればpipはインストール済みです。インストールされていない場合は、以下の手順に従ってインストールできます。通常、pipはPythonと一緒に自動的にインストールされますが、もしインストールされていない場合は、get-pip.pyをダウンロードし、次のコマンドで実行してください。
Flaskをインストールする
- Flaskをインストールするには、コマンドプロンプトで以下のコマンドを実行します。
pip install Flask
- インストールが完了するまで待ちます。Flaskがインストールされ、使用可能になります。
Pandasをインストールする
- Pandasをインストールするには、以下のコマンドを実行します。
pip install pandas
- 同様に、インストールが完了するまで待ちます。
インストールを確認する
- 両方のパッケージをインストールした後、以下のコマンドを使ってインストールが正しくおこなわれたかを確認できます。
python -c "import flask; print(flask.__version__)" python -c "import pandas; print(pandas.__version__)"
- これにより、FlaskとPandasのインストール済みバージョンが表示され、正常にインストールされていることが確認できます。
Pythonのインストールと必要なパッケージの準備が整ったら、スクリプトの作成に進みます。個人的には、スクリプト作成にはNotepad++を使うのが好みです。この作業を始めるには、Notepad++を開き、新しいファイルを開始し、[言語]メニューからPythonを選択して言語を設定してください。スクリプトを記述したら、わかりやすい場所に保存します。保存する際は、ファイル名の拡張子が「.py」になっていることを確認してください。これにより、ファイルがPythonスクリプトとして正しく認識されます。
Pythonスクリプト
import pandas as pd import flask from flask import request, jsonify app = flask.Flask(__name__) app.config["DEBUG"] = True @app.route('/analyze', methods=['POST']) def analyze_csv(): try: # Read CSV data from the POST request csv_data = request.data.decode('utf-8') # Write the CSV data to a file (optional, for debugging) with open('received_data.csv', 'w') as file: file.write(csv_data) # Load the CSV data into a DataFrame from io import StringIO data = StringIO(csv_data) df = pd.read_csv(data) # Ensure the CSV has the correct columns required_columns = ['date', 'prev_high', 'prev_low', 'prev_open', 'prev_close', 'prev_volume'] for column in required_columns: if column not in df.columns: return jsonify({"error": f"Missing column: {column}"}), 400 # Print the received metrics for debugging print("Received metrics:") print(df) # Perform analysis (Example: Calculate average price and volume) df['average_price'] = (df['prev_high'] + df['prev_low'] + df['prev_open'] + df['prev_close']) / 4 average_price = df['average_price'].mean() # Average of all the average prices average_volume = df['prev_volume'].mean() # Average volume # Print the computed averages print(f"Average Price: {average_price}") print(f"Average Volume: {average_volume}") # Create a trading signal based on a simple rule last_close = df['prev_close'].iloc[-1] if last_close > average_price: signal = "BUY" signal_explanation = f"The last close price ({last_close}) is higher than the average price ({average_price})." else: signal = "SELL" signal_explanation = f"The last close price ({last_close}) is lower than the average price ({average_price})." # Print the signal and explanation print(f"Generated Signal: {signal}") print(f"Signal Explanation: {signal_explanation}") # Return the signal as JSON return jsonify({ "signal": signal, "average_price": average_price, "average_volume": average_volume, "signal_explanation": signal_explanation }) except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == '__main__': app.run(host='189.7.6.8', port=5877)
スクリプトを実行するには、コンピュータでコマンドプロンプトを開きます。
以下のコマンドを実行します。
cd C:\Users\pathway to your python script folder
次に、以下のコマンドを実行します。
python filename.py
スクリプトを実行する際は、自分がそのスクリプトに付けた正確なファイル名を使用してください。スクリプトが実行されると、指定したポートが待機状態(リスニング)になっていることが表示されます。
Running on http://189.7.6.8:5877
主な関数
初期化(OnInit)
この関数は、EAがMetaTraderプラットフォーム上で初期化されたときに実行されます。EAが必要とするリソースや設定を準備するために使用されます。このケースでは、Pythonサーバーとの連携を開始する準備が整ったことを示すメッセージをログに出力するだけの役割を果たします。
int OnInit() { Print("Expert initialized. Ready to send data to Python."); return(INIT_SUCCEEDED); }
戻り値INIT_SUCCEEDEDは、初期化が成功したことを示します。
初期化解除(OnDeinit)
この関数は、EAが削除されたときや、MetaTraderプラットフォームが終了されたときに呼び出されます。通常は、リソースの解放や開いているファイルのクローズなど、クリーンアップ処理に使用されます。この場合は、EAが非アクティブとなり、初期化解除されたことを示すメッセージをログに出力するだけの処理をおこないます。
void OnDeinit(const int reason) { Print("Expert deinitialized."); }
OnTick(中核的な機能)
これは、市場の状況が変化するたび(新しいティックが到来するたび)に実行される、EAのメイン関数です。
void OnTick() { // Check if enough time has passed since the last signal update if(TimeCurrent() - lastSignalTime < signalInterval) { return; // Skip if it's too soon to update } // Collect data and prepare CSV for Python string csvData = "date,prev_high,prev_low,prev_open,prev_close,prev_volume\n"; // Get the previous trend data for the last `trendDays` for(int i = 1; i <= 10; i++) // You can adjust the trendDays here { datetime prevDate = iTime(Symbol(), PERIOD_D1, i); double prevHigh = iHigh(Symbol(), PERIOD_D1, i); double prevLow = iLow(Symbol(), PERIOD_D1, i); double prevOpen = iOpen(Symbol(), PERIOD_D1, i); double prevClose = iClose(Symbol(), PERIOD_D1, i); long prevVolume = iVolume(Symbol(), PERIOD_D1, i); csvData += StringFormat("%s,%.5f,%.5f,%.5f,%.5f,%ld\n", TimeToString(prevDate, TIME_DATE | TIME_MINUTES), prevHigh, prevLow, prevOpen, prevClose, prevVolume); } // Save data to CSV file string fileName = StringFormat("%s_analytics.csv", Symbol()); int fileHandle = FileOpen(fileName, FILE_WRITE | FILE_CSV | FILE_ANSI); if(fileHandle != INVALID_HANDLE) { FileWriteString(fileHandle, csvData); FileClose(fileHandle); Print("CSV file created: ", fileName); } }
この関数では、以下の処理も実行されます。
- シグナル間隔の確認:EAはまず、TimeCurrent関数を使って前回のシグナル更新から十分な時間が経過しているかを確認します。条件を満たしていない場合は、処理をスキップします。
- データ収集:EAは過去10日分(またはループ内の値を変更すればそれ以上)の市場データを収集します。これには、前日の高値、安値、始値、終値、および出来高が含まれます。
- データの整形:収集したデータを、Pythonサーバーに送信しやすいようにCSV形式に整形します。
- CSVファイルの保存:整形されたデータは「<symbol>_analytics.csv」という名前のCSVファイルとしてディスクに保存されます。ファイルの作成および書き込みが成功すると、ログに成功メッセージが出力されます。
PythonサーバーへのHTTPリクエスト(WebRequest)
string headers = "Content-Type: application/json\r\n"; char result[]; string resultHeaders; int responseCode = WebRequest( "POST", // HTTP method pythonUrl, // URL headers, // Custom headers timeout, // Timeout in milliseconds data, // Data to send result, // Response content resultHeaders // Response headers ); if(responseCode == 200) { string response = CharArrayToString(result); Print("Received response: ", response); } else { Print("Error: HTTP request failed with code ", responseCode); }
CSV形式でデータを整形した後、EAはこのデータをHTTP POSTを使用してPythonサーバーに送信します。
- ヘッダー:Content-Typeヘッダーにはapplication/jsonが設定されており、送信するデータがJSON形式であることをサーバーに知らせます。
- WebRequest:WebRequest関数は、HTTP POSTリクエストをPythonサーバーに送信するために使用されます。この関数は以下の2つの値を返します。
1) responseCode:HTTPレスポンスコード(たとえば、成功の場合は200)
2) result:サーバーからのレスポンス本文(通常は分析結果が含まれます)
図2:WebRequestフローチャート
- リクエストが成功した場合(responseCode == 200)、レスポンス内容はchar配列からstringに変換され、成功メッセージがログに表示されます。一方で、リクエストが失敗した場合には、エラーメッセージが表示され、通信が正常におこなわれなかったことが通知されます。
レスポンスの解析と表示
if(responseCode == 200) { string signal = ""; string avgPrice = ""; string avgVolume = ""; string explanation = ""; // Extract signal, avgPrice, avgVolume, and explanation from the response int signalStart = StringFind(response, "\"signal\":"); int signalEnd = StringFind(response, "\"average_price\":"); int explanationStart = StringFind(response, "\"signal_explanation\":"); int avgPriceStart = StringFind(response, "\"average_price\":"); int avgVolumeStart = StringFind(response, "\"average_volume\":"); if(signalStart != -1 && signalEnd != -1) { signal = StringSubstr(response, signalStart + 10, signalEnd - signalStart - 12); } if(explanationStart != -1) { explanation = StringSubstr(response, explanationStart + 23, StringFind(response, "\"", explanationStart + 23) - (explanationStart + 23)); } if(avgPriceStart != -1) { avgPrice = StringSubstr(response, avgPriceStart + 16, StringFind(response, "\"", avgPriceStart + 16) - (avgPriceStart + 16)); } if(avgVolumeStart != -1) { avgVolume = StringSubstr(response, avgVolumeStart + 18, StringFind(response, "\"", avgVolumeStart + 18) - (avgVolumeStart + 18)); } // Update the chart if the signal has changed if(signal != lastSignal) { lastSignal = signal; lastSignalTime = TimeCurrent(); // Update last signal time string receivedSummary = "Signal: " + signal + "\n" + "Avg Price: " + avgPrice + "\n" + "Avg Volume: " + avgVolume + "\n" + "Explanation: " + explanation; Print("Received metrics and signal: ", receivedSummary); Comment(receivedSummary); // Display it on the chart } }
Pythonサーバーからのレスポンスを受信した後、EAはそのレスポンスを解析し、以下のようなキーデータを抽出します。
- Signal:売買シグナル(例:「買い」または「売り」)
- Avg Price:分析から得られた平均価格
- Avg Volume:平均取引量
- Explanation:なぜそのシグナルが生成されたのかに関する説明文
これらの値は、StringFindおよびStringSubstr関数を使用してレスポンス文字列から抽出されます。
新しいシグナルが前回のシグナルと異なる場合(signal != lastSignal)、EAは以下の操作をおこないます。
1) lastSignal変数とlastSignalTime変数を更新します。
2) Comment()関数を使用して、チャート上に新しいシグナル・平均価格・出来高・説明文を表示します。
シグナルの更新と表示
この処理は前述のステップに統合されており、シグナルが変化した際にチャート上の表示を更新します。
if(signal != lastSignal) { lastSignal = signal; lastSignalTime = TimeCurrent(); // Update last signal time string receivedSummary = "Signal: " + signal + "\n" + "Avg Price: " + avgPrice + "\n" + "Avg Volume: " + avgVolume + "\n" + "Explanation: " + explanation; Print("Received metrics and signal: ", receivedSummary); Comment(receivedSummary); // Display it on the chart }
シグナルが変更された場合(つまり、前回のシグナルと異なる場合)、EAは以下の処理を実行します。
- lastSignal変数とlastSignalTime変数を更新します。
- シグナル、平均価格、平均出来高、および説明を含む要約文字列を作成します。
- この要約をチャート上にコメントとして表示し、ログにも出力します。
CharArrayToString(ユーティリティ関数)
string CharArrayToString(char &arr[]) { string result = ""; for(int i = 0; i < ArraySize(arr); i++) { result += StringFormat("%c", arr[i]); } return(result); }
このユーティリティ関数は、HTTPレスポンスで受け取ったchar配列を文字列に変換するために使用されます。char配列の各要素を順にループで処理し、それぞれの文字を結果の文字列に追加していきます。
これらの各ステップは、次のプロセスの特定の部分を処理するために設計されています。データの収集、Pythonサーバーへの送信、分析結果の受信、そして取引シグナルをチャートに反映させることです。この方法により、EAは自律的に動作し、関連する市場データを収集し、Pythonによる分析に基づいて判断を下すことができます。
結果
最初のステップは、Pythonスクリプトが起動し、必要なサーバーでアクティブにリスニングしていることを確認することです。スクリプトのセットアップおよび実行に関する詳細な手順は、前述のPythonのセクションをご参照ください。アクティブにリスニングしている場合、以下のように表示されます。Running on http://189.7.6.8:5877
なお、上記のAPIおよびホストは実際に使用されているものではなく、教育目的で生成されたものです。次に、MQL5 EAの起動に進みます。MQL5とPythonサーバー間の接続が正常に確立されると、チャートの[エキスパート]タブにログメッセージが表示されます。また、コマンドプロンプトで動作中のPythonスクリプトは受信したメトリクスを表示します。
コマンドプロンプトには次の内容が表示されます。
189.7.6.8 - - [21/Jan/2025 10:53:44] "POST /analyze HTTP/1.1" 200 - Received metrics: date prev_high prev_low prev_open prev_close prev_volume 0 2025.01.20 00:00 868.761 811.734 826.389 863.078 83086.0 1 2025.01.19 00:00 856.104 763.531 785.527 826.394 82805.0 2 2025.01.18 00:00 807.400 752.820 795.523 785.531 82942.0 3 2025.01.17 00:00 886.055 790.732 868.390 795.546 83004.0 4 2025.01.16 00:00 941.334 864.202 932.870 868.393 83326.0 5 2025.01.15 00:00 943.354 870.546 890.620 932.876 83447.0 6 2025.01.14 00:00 902.248 848.496 875.473 890.622 83164.0 7 2025.01.13 00:00 941.634 838.520 932.868 875.473 82516.0 8 2025.01.12 00:00 951.350 868.223 896.455 932.883 83377.0 9 2025.01.11 00:00 920.043 857.814 879.103 896.466 83287.0 10 NaN NaN NaN NaN NaN NaN
上記の情報は、pandasによる分析とシグナル生成に使用されます。10日目のデータが「NaN」と表示されているのは、当該日の取引が未完了のためであり、分析は主に過去の日付から得られた値に基づいています。しかし、10日目の現在の価格水準も不完全ながら取り込まれています。以下に、コマンドプロンプト(CMD)でpandasが表示するログおよび分析結果の例を示します。
Average Price: 865.884525 Average Volume: 83095.4 Generated Signal: SELL Signal Explanation: The last close price (nan) is lower than the average price (865.884525).
MetaTrader 5は以下を表示します。
まずは[エキスパート]タブでログを確認しましょう。結果は以下をご参照ください。
2025.01.21 10:50:28.106 External Flow (Boom 300 Index,D1) CSV file created: Boom 300 Index_analytics.csv 2025.01.21 10:50:28.161 External Flow (Boom 300 Index,D1) Received response: { 2025.01.21 10:50:28.161 External Flow (Boom 300 Index,D1) "average_price": 865.884525, 2025.01.21 10:50:28.161 External Flow (Boom 300 Index,D1) "average_volume": 83095.4, 2025.01.21 10:50:28.161 External Flow (Boom 300 Index,D1) "signal": "SELL", 2025.01.21 10:50:28.161 External Flow (Boom 300 Index,D1) "signal_explanation": "The last close price (nan) is lower than the average price (865.884525)."
結果はチャート上にも表示され、入力パラメータで指定されたタイムアウト設定に基づいて、処理が繰り返されます。
図3:表示結果
以下は、生成されたシグナルと追加分析に基づいて行った利益の出た取引の図です。取引は見やすさを考慮し、M1(1分足)チャート上に表示しています。
図4:約定済みの取引
結論
本プロジェクトにおいて、pandasなどの外部ライブラリを活用した高度な分析の実装手順を示すことで、プライスアクションや市場分析のためのより高度なツール開発に向けた堅固な基盤を築けたと考えています。すべてのトレーダーの皆様には、本稿を市場の動向を予測・理解するための総合的なガイドとして活用いただきたいと思います。ただし、最適な取引執行のためには、ご自身が熟知されている他の戦略も併せてご活用ください。今後も専門性の高い市場分析ツールの開発に尽力していきます。ぜひご意見・ご感想をお寄せください。
日付 | ツール名 | 詳細 | バージョン | アップデート | 備考 |
---|---|---|---|---|---|
01/10/24 | ChartProjector | 前日のプライスアクションをゴースト効果でオーバーレイするスクリプト | 1.0 | 初回リリース | Lynnchris Tool Chestの最初のツール |
18/11/24 | Analytical Comment | 前日の情報を表形式で提供し、市場の将来の方向性を予測する | 1.0 | 初回リリース | Lynnchris Tool Chestの2番目のツール |
27/11/24 | Analytics Master | 2時間ごとに市場指標を定期的に更新 | 1.01 | v.2 | Lynnchris Tool Chestの3番目のツール |
02/12/24 | Analytics Forecaster | Telegram統合により、2時間ごとに市場指標を定期的に更新 | 1.1 | v.3 | ツール番号4 |
09/12/24 | Volatility Navigator | ボリンジャーバンド、RSI、ATR指標を使用して市場の状況を分析するEA | 1.0 | 初回リリース | ツール番号5 |
19/12/24 | Mean Reversion Signal Reaper | 平均回帰戦略を用いて市場を分析し、シグナルを提供する | 1.0 | 初回リリース | ツール番号6 |
9/01/2025 | Signal Pulse | 多時間枠分析ツール | 1.0 | 初回リリース | ツール番号7 |
17/01/2025 | Metrics Board | 分析用のボタン付きパネル | 1.0 | 初回リリース | ツール番号8 |
21/01/2025 | External Flow | 外部ライブラリによる分析 | 1.0 | 初回リリース | ツール番号9 |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16967





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索