MetaTraderとGoogleシートがPythonAnywhereで融合:安全なデータフローのガイド
はじめに
MetaTraderを利用するトレーダーにとって、取引データの取得と分析は、ミスを防ぎ、将来より良い判断を下すために欠かせません。MetaTraderにはデータをエクスポートするための組み込み機能があるものの、クラウドサービスへの直接エクスポートには対応していません。チャート、履歴、ログといったデータを自動的にクラウドへ送信できれば、トレーダーの意思決定プロセスを大きく改善することができます。
MetaTraderからGoogleスプレッドシートなどのクラウドソリューションへデータを転送する手段はいくつか存在しますが、無料で使えるものは安全性に不安があり、安全性の高いものは有料であったり利用に制限があるケースもあります。将来の取引に活かすために過去データを分析したいトレーダーにとって、コストを抑えつつ安全にクラウドへエクスポートする方法を見つけるのは、しばしば悩ましい課題です。
さらに、MetaTraderにはクラウドへの自動バックアップ機能がないため、重要な取引履歴や有益な情報を失ってしまうことも珍しくありません。その結果、クラウド上で利用できる可視化ツールや分析ツールを十分に活かせず、利益向上の機会を逃してしまうことがあります。本記事では、MetaTraderからGoogleスプレッドシートへのデータ転送を、追加コストなしで高いセキュリティを保ちながら自動化する方法を紹介します。これにより、手軽に利用できるツールを活用し、将来の取引でより良い結果を得られるようになります。
本記事は、クラウドソリューションやストレージへデータを転送したいトレーダーや開発者に向けたガイドです。Googleのサービスアカウントキーや、PythonAnywhereと呼ばれる安全で無料のWebベースクラウドプラットフォーム上でホスト可能なプロキシサーバーといった、無料かつ安全に利用できるツールをどのように活用するかを解説していきます。
Googleスプレッドシートとサービスアカウントキーが必要な理由
Googleスプレッドシートが重要なのは、クラウドベースで、そこに保存されたデータにいつでもどこからでもアクセスできる非常に価値の高いソリューションであるためです。トレーダーはGoogleスプレッドシートにエクスポートされた取引データや関連情報にいつでもアクセスでき、将来の取引に向けた分析を自由におこなうことができます。また、Googleスプレッドシートのデータ分析ツールを活用したり、GoogleDataStudioやTradingViewなどの他のツールと統合したりすることもできます。他のトレーダーやアシスタントとシート上で共同作業し、それぞれの分析や見解を共有することも可能です。
私は、MetaTraderからGoogleスプレッドシートへのデータ転送にGoogleのApps Script機能を使用する、無料でダウンロードして使えるInfo Exporter MT5ユーティリティユーティリティアプリケーションをMQL5マーケットに公開しました。
Apps Scriptは無料で簡単に使えますが、公開アクセス可能なURLが生成され、そのURLを知っている人なら誰でもスクリプトに対して読み書きをおこない、シートデータにアクセスできてしまうため、十分に安全とは言えません。他にも、Workload Identity連携やGoogle Sheets APIなどのさまざまな方法がありますが、それらは使い方が複雑だったり、有料だったり、無料枠が限られていたりします。
サービスアカウントキーは、より安全かつ無料で、設定に必要な知識も比較的少なくて済みます。
Googleアカウントのサービスキーを設定してアプリケーションで使用する方法の詳細については、動画「Access Google Sheets using service account key in proxy server」をご覧ください。
PythonAnywhereでプロキシサーバーを使用する理由
MetaTraderにはGoogleスプレッドシートおよびそのAPIとの直接的な統合がありません。そのため、プロキシサーバーはデータをGoogleスプレッドシートに転送するための最適な選択肢となります。pythonanywhereのようなクラウドベースのソリューションを使用することで、可用性、スケーラビリティ、セキュリティ、信頼性を得ることができます。可用性とは、私たちのマシンがオフラインでもサービスが利用可能であることです。スケーラビリティとは、有効なスプレッドシートIDを提供する限り、リンクを持つ誰もが利用できることを意味します。セキュリティ面では、サービスが優れたエンジニアによって十分にテストされ、され、管理されている点が挙げられます。信頼性とは、無料版であってもそのサービスに常に頼ることができるということです。
PythonAnywhereは、この種のアプリケーション向けにシンプルなプロキシサーバーを作成できる、妥当な無料ティアパッケージを提供しています。無料版のプロキシサーバーURLは3か月間有効ですが、各3か月の期限が切れる前に延長すれば継続して利用することができます。

無料サービスとして、プロキシサーバーでAPIサービスとして使用されるアクセス可能なURLが提供されます。このURLは、Googleスプレッドシートへのアクセスや、シートからの読み取り、情報用の静的ページの表示など、その他必要な機能に使用されます。また、コンソールにアクセスでき、必要なライブラリのインストールや、ファイル操作やネットワーク関連の作業(ログファイルの編集など)をおこなうためにターミナルコマンドを実行できます。
さらに、APIサービスで情報の保存やキャッシュに使用できるMySQLデータベースにもアクセスできます。また、指定した時刻に繰り返し実行されるcronジョブを作成できるスケジューリング機能も利用できるため、手動で実行する必要がなくなります。ファイルの作成、編集、削除ツール、エラーログの表示、サイトのセキュリティ設定、仮想環境の作成などが可能なWebインターフェースにもアクセスできます。
この記事で使用されているものと同一のプロキシサーバーを作成するために、PythonAnywhereでのプロキシサーバーの作成、編集、ホスト方法について必要な情報をすべてカバーする動画を作成しました。
データフロー図
この転送プロセスにおけるデータフローの概念はシンプルで理解しやすいものです。MetaTraderはデータソースとして機能し、収益性の高い取引判断のための慎重な分析に必要なデータがそこに存在し、それらがクラウドベースのPythonAnywhereプラットフォームでホストされるプロキシサーバーへ転送されます。プロキシサーバーは、Google認証パッケージとGoogleアカウントのサービスキーから作成された認証情報を使用して、受け取ったデータを認可されたGoogleスプレッドシートに書き込みます。このプロセスは次の図でより明確になります。

これは、MetaTraderからGoogleスプレッドシートへデータを転送するための、無料で安全な方法の1つです。プロキシサーバーからは、ローカルでホストされている場合でも、pythonanywhereのようなテスト済みで安全なクラウドプラットフォームでホストされている場合でも、認可されたシートのみにアクセスがおこなわれます。
サービスアカウントキーを作成するプロセス
Googleクラウドコンソールには、無料で非常に便利な豊富な機能が多数あります。その中の1つがGoogleサービスアカウントです。サービスアカウントは、以下のように[IAM & Admin]セクションにあります。

サービスアカウントの管理に進む前に、新規プロジェクトを作成するか、既存のプロジェクトを選択してください。サービスアカウントページは以下のようになっており、[Create service account]ボタンが最上部に表示されています。

[Create service account]セクションで必要な情報を入力すると、後述のシート共有手順で使用するサービスアカウント用メールアドレスが生成されます。[Key ID]フィールドは空の状態ですが、作成済みサービスアカウントの詳細ページに移動することで作成可能です。

[Add key]ボタンをクリックすると、キーを作成し、jsonまたはp12形式で認証情報をダウンロードするオプションが表示されます。json形式を選択すると、プロキシサーバーで認証に使用するファイルが自動的にダウンロードされます。
次のステップは、以下に示す[APIs & Services]でプロジェクトのGoogle Sheets APIを有効化することです。ここでGoogle Sheets APIを見つけ、有効にしてください。


上記の「Googleスプレッドシートとサービスアカウントキーが必要な理由」セクションに、このプロセスの詳細な動画へのリンクがあります。
プロキシサーバープログラム
上記の「PythonAnywhereでプロキシサーバーを使用する理由」セクションで共有した動画をご覧になった方は、これから説明する内容をより理解しやすいはずです。ここでは、Google認証パッケージの関数とサービスアカウントキーの認証情報を使用して、Googleスプレッドシートを更新する簡単なFlaskアプリケーションを作成します。
まず、プログラムに必要なライブラリをインポートします。
from flask import Flask, request, jsonify from google.oauth2 import service_account from googleapiclient.discovery import build
これらのライブラリがシステムや仮想環境にない場合は、pipを使用してインストールする必要があります。動画でもその手順を解説しています。
次に、Flaskフレームワークをオブジェクト化します。これにより、後でプログラム内でAPIエンドポイント(GET、POST、PUT、DELETE)やルーターなどを作成できるようになります。次の行でそれをおこないます。
app = Flask(__name__)
次のステップでは、サービスアカウントキー作成時にダウンロードした認証情報JSONファイルの場所を指定します。さらにスコープを定義することで、Googleスプレッドシートなど必要な項目のみにアクセス権を限定できます。認証情報とスコープを基に、GoogleAPIクライアントを初期化する際に使用される認証情報オブジェクトが作成されます。
SERVICE_ACCOUNT_FILE = 'service_account.json' SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES )
続いて、「update-sheet」というPOST APIを定義します。
@app.route('/update-sheet', methods=['POST'])
def update_sheet(): POST APIは通常、データをサーバーに送信するために使用され、クライアントから送信されるデータの情報を含むヘッダーも渡すことができます。これにより、サーバーはデータを簡単に抽出できます。
data = request.json sheet_id = data['sheet_id'] data_range = data['range'] values = data['values']
上記のコードでは、requestはFlaskのオブジェクトで、クライアントがPOSTリクエストで送信した情報(JSONデータを含む)を保持しています。上記のコードでは、スプレッドシートID、シート範囲、そしてシートに書き込む値を抽出しています。
次に、上記で作成した認証情報オブジェクトを渡して、GoogleクライアントAPIパッケージを初期化します。
service = build('sheets', 'v4', credentials=credentials)
このサービスオブジェクトは、上記で抽出したsheet_idによって識別されるスプレッドシートを更新するために使用されます。
result = service.spreadsheets().values().update(spreadsheetId=sheet_id, range=data_range, valueInputOption='RAW', body={'values': values}).execute()
上記のコードは、指定された範囲に渡された値を使ってスプレッドシートを更新するよう、Google APIクライアントサービスに指示します。追加のAppend APIを含む完全なコードも添付されており、シート名の存在を確認し、存在しない場合は作成する処理や、追加のAppend APIも確認できます。必要に応じて、Deleteなどの他のAPIエンドポイントを追加することも可能です。
MetaTraderプログラム
実際のMQ5プログラムには、ターミナル情報、口座情報、取引履歴、注文履歴のエクスポート機能と、ユーザーが転送する情報を選択できる入力セクションが含まれています。ここでは、口座情報に関するコードのみを説明します。以下は、AccountInfo.mqhヘッダーファイルを使用して口座データを抽出し、そのデータをStringToCharArray関数で使用できるよう文字列配列にフォーマットし、WebRequestネットワーク関数で必要なchar配列を作成する関数です。
#include <Trade\AccountInfo.mqh> string GetAccountInfo() { CAccountInfo accountInfo; string account_info = "[\"symbol\", \"name\", \"currency\", \"company\", \"balance\", \"credit\", " + "\"profit\", \"equity\", \"margin\", \"login\", \"trade_mode\", \"leverage\", \"limit_orders\", \"margin_mode\"]"; StringAdd(account_info, StringFormat( ", [\"%s\", \"%s\", \"%s\", \"%s\", \"%f\", \"%f\", \"%f\", \"%f\", \"%f\", \"%d\", \"%d\", \"%d\", \"%d\", \"%d\"]", Symbol(), accountInfo.Name(), accountInfo.Currency(), accountInfo.Company(), accountInfo.Balance(), accountInfo.Credit(), accountInfo.Profit(), accountInfo.Equity(), accountInfo.Margin(), accountInfo.Login(), accountInfo.TradeMode(), accountInfo.Leverage(), accountInfo.LimitOrders(), accountInfo.MarginMode() )); return account_info; }
上記の関数は、口座情報のデータのみを準備します。添付の完全なコードProxyExport.mq5には、ターミナル情報、取引履歴、注文履歴のデータを準備するための3つの追加関数が含まれています。データを準備した後、それらは次のWriteToGoogleSheet関数に送信され、そこで追加の文字列操作がおこなわれ、SheetExporter関数が呼び出されます。
void WriteToGoogleSheet(string terminalInfos, string historicalDeals, string historicalOrders, string accountInfos) { if(terminalInfos != NULL) { StringReplace(terminalInfos, "\\", "/"); SheetExporter(terminalInfoName, terminalInfos); } if(historicalDeals != NULL) { SheetExporter(historyDealsName, historicalDeals); } if(historicalOrders != NULL) { SheetExporter(historyOrdersName, historicalOrders); } if(accountInfos != NULL) { SheetExporter(accountInfoName, accountInfos); } } void SheetExporter(string sheetName, string data) { string headers = "Content-Type: application/json\r\n"; char postData[], result[]; string responseHeaders; string jsonDataWithSheetName = StringFormat("{\"spreadSheetId\": \"%s\", \"sheetName\": \"%s\", \"data\": [%s]}", spreadSheetId, sheetName, data); // Convert to char array StringToCharArray(jsonDataWithSheetName, postData, 0, StringLen(jsonDataWithSheetName), CP_UTF8); // Send POST request int res = WebRequest("POST", proxyServerUrl, headers, 5000, postData, result, responseHeaders); // Check response if(res != 200) { Alert("Account Infos not exported to Google Sheets returned error ", res, " and get last error is ", GetLastError()); } }
SheetExporter関数は、プロキシサーバーに送信されるJSON文字列のデータに加えて、spreadSheetIdとsheetNameを追加します。覚えておくべきこととして、プロキシサーバーのURLを[WebRequestを許可するURLリスト]フィールドに入力する必要があります。この欄は[ツール]>[オプション]メニュー下にあります。また、同じプロキシサーバーのURLを、以下の入力フィールドにも貼り付ける必要があります。

データフローのデモ
上記の「サービスアカウントキーを作成するプロセス」セクションで説明した手順に従い、サービスアカウントキーを作成し、MetaTraderのデータをエクスポートしたいスプレッドシートをプロキシサーバーで認証するために必要なJSONファイルをダウンロードします。その後、自分でプロキシサーバーを構築するか、PythonAnywhereなど自分が使いやすいプラットフォームを使用して、service_accounts_proxy.pyコードを実行し、更新APIをホストします。コードは必要に応じて自由に修正可能です。
最後のステップは、ProxyExport.mq5コードをコンパイルし、チャート上でEX5を実行することです。どのデータをエクスポートするかの選択肢や、APIやスプレッドシートIDを入力するフィールドが表示されます。これらが設定されていないと、エクスポートは動作しません。
以下のGIFでは、サービスアカウントキーの認証情報作成、サービスアカウント用にGoogleスプレッドシートを有効化、そしてGoogleスプレッドシートをサービスアカウントのメールアドレスと共有する手順をすべて網羅して説明しようとしています。

以下のGIFでは、PythonAnywhereで必要な手順や操作をすべてまとめて示そうとしています。

以下のGIFでは、エクスポートを動作させるためにMetaEditorとMetaTraderでおこなう必要があるすべての手順をまとめて示そうとしています。さらに、MetaTraderの情報がGoogleスプレッドシートに自動転送される様子を、以下のGIFでライブでキャプチャしています。

Googleスプレッドシートを使った取引分析
以下の取引履歴データをGoogleスプレッドシートにエクスポートしました。ここでは9行のみを掲載しています。

Pipsの値は、「(Exit Price - Entry Price) × multiplier」で計算されます。ここで、multiplierはJPY通貨ペアの場合100、それ以外の場合は10000です。Profitの値は「Pips × Lot Size × 10」で計算されます。Cumulative Profitは、(前回の累積利益 + 今回の利益)で計算されます。
上記シートの名前は、私のコードの作り方に従ってHistory_Dealsとなっています。必要に応じて名前は変更可能です。その後、別のシートを作成し、matricesと名前を付け、以下のようにラベルと数式を設定できます。
| ラベル | 公式 |
|---|---|
| Total Trades | =COUNTA(History_Deals!A2:A) |
| Winning Trades | =COUNTIF(History_Deals!K2:K,">0") |
| Losing Trades | =COUNTIF(History_Deals!K2:K,"<0") |
| Win Rate % | =FIXED(B2/A2 * 100, 2) |
| Loss Rate % | =FIXED(C2/A2 * 100, 2) |
| Average Win | =FIXED(AVERAGEIF(History_Deals!K2:K,">0"), 2) |
| Average Loss | =FIXED(AVERAGEIF(History_Deals!K2:K,"<0"), 2) |
| Risk-Reward Ratio | =FIXED(F2/ABS(G2), 2) |
| Expectancy | =FIXED((D2/100*F2)-(E2/100*G2), 2) |
| Total Profit | =SUM(History_Deals!K2:K) |
| Profit Factor | =SUMIF(History_Deals!K2:K,">0")/ABS(SUMIF(History_Deals!K2:K,"<0")) |
| Max Drawdown | =MIN(History_Deals!L2:L)-MAX(FILTER(History_Deals!L2:L,History_Deals!L2:L<MIN(History_Deals!L2:L))) |
上記テーブルで使用されている指標を簡単に説明します。
- Total Trades:成功裏に完了した取引の総数です。総取引数が多いほど、統計が信頼でき正確であることを示します。
- Winning Trades:利益でクローズした取引の数です。この数値は正しい判断の回数を示します。
- Losing Trades:損失でクローズした取引の数です。この数値は誤った判断の回数を示します。
- Win Rate %およびLoss Rate %:それぞれ利益でクローズした割合と損失でクローズした割合です。重要な点として、勝率が高いからといって必ずしも利益が出るわけではありません。トレーダーは、勝率が30〜40%であっても、適切なリスクリワードで利益を上げることが可能です。
- Average WinおよびAverage Loss:正解したときにいくら勝つか、間違ったときにいくら負けるかを示す数値です。戦略上、平均損失額は常に低く抑えるようにしています。
- Risk-Reward Ratio:平均勝ち額を平均負け額で割った比率です。トレーダーの目標は常に1以上にすることです。黄金律としては1.5〜2:1の範囲が望ましいとされています。
- Expectancy:1取引あたりの平均利益です。たとえば、この値が20であれば、100取引で2000の利益が見込めます。
- Total Profit:すべての利益と損失の合計です。
- Profit Factor:全体的な収益性を示す数値です。トレーダーは常に1.5以上を目標にするべきです。
- Max Drawdown:累積利益のピークからの最大下落です。トレーダーは常にこれを可能な限り小さくすることを目指します。
すべての数式を適用すると、以下のようなテーブルが得られます。
| Total Trades | Winning Trades | Losing Trades | Win Rate % | Loss Rate % | Average Win | Average Loss | Risk-Reward Ratio | Expectancy | Total Profit | Profit Factor | Max Drawdown |
| 9 | 7 | 2 | 77.78 | 22.22 | 285.71 | -400.00 | 0.71 | 311.11 | 1200 | 2.5 | 200 |
取引の健全性や一貫性は、累積利益を折れ線グラフとしてプロットすることで確認できます。手順としては、[挿入]>[チャート]>[折れ線グラフ]を選び、縦軸に累積利益、横軸に決済日を指定します。

勝ちトレードと負けトレードの割合は、以下のように円グラフで比較することもできます。

通貨ペアごとのパフォーマンスは、以下のように縦棒グラフで確認できます。

このように、Googleスプレッドシートでは多様な分析が可能です。
結論
このソリューションを活用することで、トレーダーはMetaTraderのデータをGoogleスプレッドシートへ簡単かつ安全に転送し、Googleスプレッドシートの可視化ツールを効果的に利用できるようになります。本ソリューションは、ジャーナル作成や追加分析のためにMetaTraderのデータをエクスポートする手段として、無料で利用できる仕組みを組み合わせて構築されています。本記事では、自前でプロキシサーバーを構築する方法に加え、PythonAnywhereのようなクラウドベースのプラットフォームを利用する方法も紹介しました。クラウドベースのソリューションは、安全性が高くスケーラブルです。また MetaTraderのプログラムをモジュール化することで、柔軟な構成が可能となり、たとえばストラテジーテスター用のログ収集など、新しい機能を容易に追加できるようになります。
まとめると、本記事で紹介した手法は、トレーダーや開発者がMetaTraderのデータを効率的にクラウドへ転送し、さらなる分析に役立て、より良い取引判断につなげるための有用な選択肢となるはずです。
なお、プロキシサーバーとMetaTraderスクリプトのソースコードも含めています。
| ファイル名 | 説明 |
|---|---|
| service_accounts_proxy.py | 更新および追加APIを備えたシンプルなFlaskアプリケーション |
| ProxyExport.mq5 | エクスポートするデータの選択肢を備えたMetaTraderアプリケーション |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/19175
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
MQL5での取引戦略の自動化(第29回):プライスアクションに基づくガートレーハーモニックパターンシステムの作成
初心者からエキスパートへ:Reporting EAで詳細な取引レポートをマスターする
プライスアクション分析ツールキットの開発(第38回):ティックバッファVWAPと短期不均衡エンジン
取引システムの構築(第3回):現実的な利益目標のための最小リスクレベルの決定
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
新しい記事をご覧ください:MetaTrader Meets Google Sheets with Pythonanywhere:安全なデータフローへのガイド。
著者ラメッシュ・マハルジャン
MQLで同じ機能を実行できるのに、なぜPythonを使うのですか?
Pythonサーバーで使ったようなgoogleのライブラリをMQLで使うことはできますか?もし可能なら、MQLでどのようにできるかリンクを教えてください。新しい方法に感謝します。