English Русский Deutsch
preview
ルーチン作業なしのアルゴリズム取引:MetaTrader 5におけるSQLiteを用いた高速取引分析

ルーチン作業なしのアルゴリズム取引:MetaTrader 5におけるSQLiteを用いた高速取引分析

MetaTrader 5 |
36 1
MetaQuotes
MetaQuotes

アルゴリズム取引におけるフィードバック問題

アルゴリズム取引では、競争力のある戦略を開発するだけでなく、結果を継続的に監視することが不可欠です。フィードバックがなければ、取引システムは制御不能になり得ます。戦略がリアルタイムでどのように振る舞うかを確認するまでは、それは実際のシステムではなく、仮説の集まりを管理しているに過ぎません。

現代の株式市場および外国為替(FX)市場では、取引頻度が急激に増加しています。データは分析する前に古くなってしまいます。そしてデータが古くなるにつれて、それに基づく結論もまた古くなります。さらに、反復的な手作業は、遅延やミスを必然的に生み出します。これは、単に人間が疲れている、注意が散漫になっている、あるいは急いでいるといった理由で発生します。

このような背景において、MetaTrader 5は特に有用です。組み込みのSQLite(ローカルデータベース)サポートは大きな利点です。データベースは単なる保存先ではなく、取引プロセスの不可欠な一部となります。クエリはほぼリアルタイムで実行され、統計は自動的に更新され、取引分析は数時間ではなく数秒で完了します。さらに、分析結果は必要な場所、つまり取引プロセスの外ではなく、ターミナル内で直接利用できます。

本記事では、アルゴリズムトレーダーの「最小実用構成」を扱います。具体的には、取引ジャーナル用データベース構造、安全かつ高速なデータ記録、SQLによる分析クエリ、そしてMetaTrader 5上のインタラクティブダッシュボードで主要統計を表示する方法です。これにより、多くのルーチン作業を排除し、トレーダーは取引システムの改善という創造的な作業に集中できるようになります。


アルゴリズムトレーダーにローカルデータベースが必要な理由

取引戦略の開発およびテストでは、膨大な量のデータが生成されます。最適化結果、取引履歴、インジケーターシグナル、マクロ経済イベントなど、これらはすべて単なる保存だけでなく、構造化と高速アクセスが必要です。ローカルデータベースは、こうした本格的なアルゴリズムトレーダーが直面する課題を解決します。

テストおよび最適化結果の保存

パラメータを総当たりで戦略を最適化すると、数百、場合によっては数千ものパラメータの組み合わせが生成されます。各試行では、評価指標、パラメータ値、結果が生成されます。これらをどのように比較し、どのように戦略の進化を追跡すればよいのでしょうか。データベースを使うことで、最適化の完全な履歴を保存でき、単純な表形式から複雑な相関分析まで、あらゆる条件で分析できるようになります。

自動取引ジャーナル

スプレッドシートで手作業のログを取る代わりに、ターミナル上でEAを実行することで、すべての取引を自動的に記録できます。記録される内容は、シンボル、マジックナンバー、ロット数、価格、時間、結果、コメントなどです。データはリアルタイムでデータベースに保存され、追加の作業なしで即座に分析可能になります。

取引シグナル分析

シグナルの保存と分析により、従来のログでは得られない洞察が可能になります。シグナルの有効性、インジケーター同士の相関、エントリーおよびエグジットの最適条件など、多くのトレーダーが知りたい問いに答えることができます。SQLクエリを使うことで、追加のコードを書かずに強力な分析が可能になります。

SQLiteを使用するためには、以下の3つの関数だけで十分です。

  1. DatabaseOpen:データベースを開く
  2. DatabaseExecute:データベースに対してクエリを実行する
  3. DatabaseClose:データベースを閉じる

これだけでも、アルゴリズムトレーダーが日常的に直面する問題の大半に対応できます。

以下はデータベースのオープンおよびクローズの例です。

int db = DatabaseOpen("trading.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(db == INVALID_HANDLE)
 {
  Print("Error opening Database: ", GetLastError());
  return;
 }
// ... working with the database ...
DatabaseClose(db);     // close the database

重要な点として、SQLiteはMetaTrader 5システムに「標準搭載」されており、いわば「すぐに使える状態」で提供されています。また、ターミナルのコアと直接連携して動作します。一方で、Excelやその他のスプレッドシートは外部プログラムであり、MQL5のEAはOLEオートメーションといった旧式の手法、あるいは外部CSVファイルを通じてアクセスする必要があります。MetaTrader 5におけるSQLiteとの比較では、その差は顕著であり、速度、利便性、信頼性のすべてにおいてSQLiteが圧倒的に優れています。


テーブル構成:取引ジャーナルのアーキテクチャ

データベース設計は、「何を保存する必要があるのか」という問いから始まります。取引ジャーナルの場合、その答えは明確で、取引履歴、シグナル、イベントです。しかし、なぜ単一の「大規模で汎用的なテーブル」ではなく、3つのテーブルに分けるのでしょうか。DEALS、SIGNALS、EVENTSへの分割は単なる好みではなく必然です。各エンティティは個別に保存され、必要に応じてクエリ内で関連付けられます。例えば、「信頼度80%以上のシグナル後のすべての取引」を取得したい場合でも、SQLiteならターミナルを離れることなく、簡潔かつ効率的に処理できます。

DEALSテーブル(取引履歴)

このテーブルには、各取引に関する完全な情報が格納されます。内容はID、チケット番号、銘柄、「マジックナンバー」(戦略ID)、ロット数、オープン価格、クローズ価格、時間、損益結果、および任意のコメントなどです。これは取引ジャーナルの中核であり、あらゆる分析の基盤となります。

SIGNALSテーブル(シグナル履歴)

このテーブルには、インジケーターや取引システムからのシグナルが保存されます。内容は銘柄、時間足、売買シグナルの種類(買い/売り)、シグナル発生時の価格、発生時刻、追加パラメータなどです。これにより、シグナルの品質や実際の取引結果との相関を分析することが可能になります。これは、自身の戦略が機能しているかを理解する上で重要な要素です。

EVENTSテーブル(ニュースコンテキスト)

このテーブルには、重要な経済イベントに関する情報が格納されます。イベント名、通貨、重要度、予測値、実績値、発表時刻などが含まれます。これにより、取引結果とニュース背景との関連性を分析できます。市場は孤立して存在しているわけではないためです。

下図はER図(実体関連図)であり、データベース構造およびテーブル間の関係を視覚的に示したものです。

実体関連図

図1:取引ジャーナルテーブルのER図

以下はテーブル作成コードです。

   //  Deal history table - DEALS:
   string createDeals = "CREATE TABLE IF NOT EXISTS DEALS ("
                       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                       "deal_ticket INTEGER UNIQUE, "
                       "order_ticket INTEGER, "
                       "symbol TEXT NOT NULL, "
                       "type INTEGER, "                // 0=BUY, 1=SELL
                       "direction INTEGER, "           // 0=IN, 1=OUT, 2=IN/OUT
                       "volume REAL, "
                       "price_open REAL, "
                       "price_close REAL, "
                       "profit REAL, "
                       "swap REAL, "
                       "commission REAL, "
                       "sl REAL, "
                       "tp REAL, "
                       "magic INTEGER, "
                       "comment TEXT, "
                       "time INTEGER, "                // Unix timestamp
                       "time_msc INTEGER, "
                       "reason INTEGER"
                       ");";
   
   //  Trading signals table - SIGNALS:
   string createSignals = "CREATE TABLE IF NOT EXISTS SIGNALS ("
                         "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                         "symbol TEXT NOT NULL, "
                         "signal_type TEXT, "          // 'BUY', 'SELL', 'CLOSE'
                         "price REAL, "
                         "stop_loss REAL, "
                         "take_profit REAL, "
                         "strength REAL, "             // 0.0 - 1.0
                         "source TEXT, "               // Strategy name
                         "notes TEXT, "
                         "time INTEGER"
                         ");";
   
   //  Events table - EVENTS:
   string createEvents = "CREATE TABLE IF NOT EXISTS EVENTS ("
                        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        "event_type TEXT, "            // 'NEWS', 'ERROR', 'NOTE', etc.
                        "symbol TEXT, "
                        "description TEXT, "
                        "importance INTEGER, "         // 1=Low, 2=Medium, 3=High
                        "time INTEGER,"
                        "actual REAL, "
                        "previous REAL, "
                        "forecast REAL "
                        ");";
   
   //  Indices to speed up search queries:
   string createIndexes[] = 
    {
      "CREATE INDEX IF NOT EXISTS idx_deals_symbol ON DEALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_deals_magic ON DEALS(magic);",
      "CREATE INDEX IF NOT EXISTS idx_deals_time ON DEALS(time);",
      "CREATE INDEX IF NOT EXISTS idx_signals_symbol ON SIGNALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_signals_time ON SIGNALS(time);"
    };
   
   //  Create tables in the database:
   if(!DatabaseExecute(database, createDeals))
    {
      Print("Error creating DEALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createSignals))
    {
      Print("Error creating SIGNALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createEvents))
    {
      Print("Error creating EVENTS table: ", GetLastError());
      return(false);
    }
   
   //  Create indices:
   for(int i = 0; i < ArraySize(createIndexes); i++)
    {
      DatabaseExecute(database, createIndexes[i]);
    }

インデックスに注目してください:idx_deals_symbol、idx_deals_magic、idx_deals_time、idx_signals_symbol、idx_signals_timeです。これらは、DEALSテーブルにおけるsymbol、magic、time、そしてSIGNALSテーブルにおけるsymbol、timeといった主要フィールドのクエリを高速化します。インデックスはパフォーマンス向上のための重要な要素であり、あらゆる分析クエリのたびにその効果が発揮されます。


データ挿入とトランザクション:スピードが重要

MQL5では、テーブルへのデータ挿入方法として、SQLクエリを直接実行する方法と、プリペアドステートメントを使用する方法の2種類があります。どちらを選ぶべきでしょうか。結論としては、セキュリティとパフォーマンスの両面からプリペアドステートメントが推奨されます。

DatabaseExecuteによる直接挿入:

string sql = StringFormat(
                         "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                         "VALUES (%d, '%s', %d, %.2f, %.5f, %I64d, %.2f)",
                         ticket, symbol, magic, volume, price, TimeCurrent(), profit);
DatabaseExecute(db, sql);

DatabasePrepareを介したパラメータ化クエリ:

//  Create a parameterized query:
int request = DatabasePrepare(db,
                             "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                             "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)");

//  Set the value of the first query parameter - in the DatabaseBind function, the indexing of fields in the entry starts from zero:
DatabaseBind(request, 0, ticket);
DatabaseTransactionBegin(db);

//  Set the values of the remaining parameters before adding the entry:
DatabaseBind(request, 1, symbol);
DatabaseBind(request, 2, magic);
DatabaseBind(request, 3, volume);
DatabaseBind(request, 4, price);
DatabaseBind(request, 5, TimeCurrent());
DatabaseBind(request, 6, profit);

//  Execute a request for inserting the entry:
DatabaseRead(request);
DatabaseFinalize(request);
DatabaseTransactionCommit(db);

トランザクションの使用は「選択肢」ではなく「必須事項」です。大量の挿入および更新処理において、トランザクションはパフォーマンスを数百倍から数千倍向上させます。その理由は、トランザクションを使わない場合、各操作が個別にディスクへコミットされるためです。一方でトランザクションを使用すると、すべての操作がまとめられ、1つのブロックとして書き込まれます。

テスト結果は非常に良好です。MQL5におけるSQLiteのパフォーマンスは、ネイティブC++コード(LLVM 9.0)と同等レベルです。ほとんどのテストでは差は5%未満であり、シナリオによってはMQL5がC++を上回る場合もあります。下図は、トランザクションなしでの1000レコード挿入と、トランザクションありでの25000レコード挿入を比較したものです。1レコードあたり3500倍以上の差が確認されています。

取引比較

図2:挿入速度比較(トランザクションなし・あり)

以下は、大量挿入におけるトランザクション使用例です。

DatabaseTransactionBegin(db);
for(int i = 0; i < ArraySize(deals); i++)
 {
  InsertDeal(db, deals[i]);  // inserting the next trade - an element of the array of deals[] structures
 }
DatabaseTransactionCommit(db);

すべてのテストはMQL5フォーラムセクション 「SQLite in MQL5: new features and performance testing 」で確認できます。


SQLクエリ:プログラミング不要の分析

SQLの最大の利点の1つは、単一のクエリで複雑な分析結果を取得できることです。MetaTrader 5ではこの機能が直接利用可能です。ループも条件分岐も時間変数も不要で、クエリ1つで十分です。いくつか典型的なシナリオを見ていきます。

取引銘柄に関する統計

どの銘柄が利益を生み、どの銘柄が静かに資金を減らしているのでしょうか。この問いとそれに対応するSQLクエリは、すべてのトレーダーの基本ツールとなるべきものです。このクエリは、銘柄ごとの取引回数、総利益、平均利益を表示します。

string sql = "SELECT symbol, COUNT(*) as deals, "
             "SUM(profit) as total_profit, "
             "AVG(profit) as avg_profit "
             "FROM DEALS GROUP BY symbol "
             "ORDER BY total_profit DESC";
DatabasePrint(db, sql);

クエリ要素の解説

クエリ要素 詳細
SELECT symbol 銘柄名の列を選択
COUNT(*) 銘柄ごとの取引回数をカウント
SUM(profit) 銘柄ごとの利益合計
GROUP BY symbol 銘柄ごとにグループ化
ORDER BY total_profit DESC 総利益の降順でソート

戦略別分析(マジックナンバー)

マジックナンバーは、各取引に付与されるEA固有のIDです。複数の戦略を同一口座で運用している場合、このクエリにより、どの戦略が最も効率的かを確認できます。この例では、CASE式を使用して利益取引数を計算しています。

string sql = "SELECT magic, COUNT(*) as trades, "
             "SUM(CASE WHEN profit > 0 THEN 1 ELSE 0 END) as wins, "
             "SUM(profit) as net_profit "
             "FROM DEALS GROUP BY magic";
DatabasePrint(db, sql);

クエリ要素の解説

クエリ要素 詳細
SELECT magic マジックナンバー(戦略ID)を選択
COUNT(*) 選択した戦略における取引総数
CASE WHEN profit > 0 利益がプラスかどうかの条件
THEN 1 ELSE 0 END 勝ちトレードを1、負けを0として計算
SUM(wins) 勝ちトレード数の合計

勝ちトレード数(wins)を総取引数(trades)で割ることで、勝率を算出できます。これは戦略評価における重要な指標です。勝率が高いにもかかわらず総利益がマイナスの場合、それはリスク管理の問題を示しています。つまり、負けトレードの損失が勝ちトレードの利益を上回っている可能性があります。

時間帯別取引分布

戦略はいつ最も機能するのでしょうか。欧州市場の時間帯でしょうか、それとも米国市場でしょうか。あるいは、値動きの少ない時間帯でしょうか。strftime関数を使用することで、取引開始時間から「時間(00〜23)」を抽出できます。これにより、最も収益性の高い時間帯とそうでない時間帯を特定できます。

string sql = "SELECT strftime('%H', time, 'unixepoch') as hour, "
             "COUNT(*) as trades, SUM(profit) as profit "
             "FROM DEALS GROUP BY hour";
DatabasePrint(db, sql);

重要:MQL5およびSQLiteでは、時間はUnixタイムスタンプ(1970-01-01からの秒数)として保存されます。そのためunixepoch修飾子が使用されています。同様に、曜日(strftime('%w', ...))、月(strftime('%m', ...))、あるいはそれらの組み合わせによる分析も可能です。

クエリ要素の解説

クエリ要素 詳細
strftime('%H', ...) 取引開始時間から「時(00〜23)」を抽出
time 取引開始時間(Unixタイムスタンプ)
GROUP BY hour 時間ごとにグループ化


統計ダッシュボード:ターミナル内での可視化

単なる数値データも重要ですが、視覚的な分かりやすさはさらに重要です。データベースはターミナル内のグラフィカルダッシュボードと簡単に統合でき、データを直感的な情報へ変換できます。インタラクティブな統計ダッシュボードはリアルタイムで動作し、トレーダーに必要な情報を即座に表示します。

以下のダッシュボードでは、一定期間の総合結果(SUMMARY)、銘柄別結果(BY SYMBOL)、および最も収益性の高い時間帯(BEST HOURS)を表示します。データを構造体に読み込むにはDatabaseReadBind関数を使用します。

統計パネル

図3:ターミナルのインタラクティブな統計ダッシュボード

struct DealStats
 {
  string symbol;
  int count;
  double total_profit;
  double avg_profit;
 };

int request = DatabasePrepare(db,
                             "SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, "
                             "AVG(profit) as avg_profit FROM DEALS GROUP BY symbol");
DealStats stats;
while(DatabaseReadBind(request, stats))
 {
  //  Output to the table on the dashboard:
  AddRowToTable(stats);
 }
DatabaseFinalize(request);

DatabaseReadBind関数は、構造体のフィールド名とSQLクエリの列名を自動的に対応付けます。そのため、クエリの列名に一致するフィールドを持つ構造体を定義するだけで利用可能です。

ダッシュボード操作

[Refresh]ボタンは統計情報を完全再計算して更新します。[Export]ボタンは、データベーステーブルから計算済みデータをCSV形式で出力します。対象は全体の損益、取引履歴、イベント、シグナルなどです。以下はエクスポート例です。

(#),symbol,trades,total_profit,avg_profit,wins,losses
1,XAGUSD,196,322.25,1.64,14,181
2,AUDUSD,196,-12.0,-0.06,82,99
3,EURUSD,58,-38.5,-0.66,23,35
4,GBPUSD,57,-43.2,-0.75,17,40

ホットキーによる操作

  • 「A」または「a」:分析更新
  • 「E」または「e」:CSVファイルへエクスポート
  • 「R」または「r」:取引履歴の読み込み
  • 「P」または「p」:ダッシュボード表示のオン/フ

EA設定項目

  • データベースファイル名:データベースファイル名(デフォルト:「TradingJournal.db」)
  • 自動履歴インポート:取引履歴の自動読み込み(デフォルト:true)
  • 履歴期間(日数):履歴の取得範囲(デフォルト:30日)
  • エクスポートパス:CSV出力先(デフォルト:「MQL5/ファイル」)
  • CSVエクスポート:CSV形式での出力(デフォルト:true)
  • ダッシュボード表示:チャート上に統計ダッシュボードを表示(デフォルト:true)


MetaEditor:データベースツール

MetaTrader 5に付属するMetaEditorには、SQLiteを扱うための組み込みツールが用意されています。これには、テーブルの開閉や編集、SQLクエリの実行、変更のロールバックなどの機能が含まれます。SQLiteデータベースはユーザーのPC上に単一ファイルとして保存されるため、MetaEditorのナビゲーターからいつでもアクセスでき、テーブル構造や内容の確認、デバッグ用クエリの実行が可能です。

これは、データベースを利用するMQL5アプリケーションのデバッグにおいて特に便利です。実際にリアルタイムでデータの状態を確認しながら、EAのロジックを調整することができます。

この仕組みは、この記事で紹介しているテストEA「TradingJournalSQLite-EA」によって作成されたサンプルデータベースを使うことで簡単に確認できます。データベースを開き、テーブルを選択し、SQLクエリを実行して閉じるという一連の流れを見ていきます。ここでは、言葉で説明するよりも実際に見た方が理解しやすいため、順を追って説明します。

1. まず最も基本的な操作として、データベースを開き、目的のテーブルを選択します。

    開く/選択/閉じる

    図4: テーブルを開く/選択する/閉じる

    DEALSテーブルは、名前を左クリックでダブルクリックすることで選択できます。これはナビゲーター上で以下のSQLクエリを実行するのと同等です。

    SELECT * FROM 'DEALS';
    2. 時刻形式を設定します。

      時間形式

      図5:時間形式

      3. 本質的な問い:どの銘柄がどれだけ利益を上げているのか。結果を瞬時に確認できます。
        SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

        長いクエリが苦手な場合は、以下のようにも記述できます。

        SELECT symbol,
        COUNT(*) as count,
        SUM(profit) as total_profit,
        AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;
        

        PnL

        図6:どの銘柄がどれだけ利益を上げているのか

        4. 収入の降順で並べ替えます。
          SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol
          ORDER BY total_profit DESC;
          

          PnL注文

          図7:利益の降順表示


          5. 総利益の確認
            SELECT  SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit FROM DEALS;

            純利益

            図8:総損益

            さらに複雑なクエリのデバッグ

            SELECT   COUNT(*) as total_deals, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END) as closed_trades, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_wins, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_losses, 
                            ROUND(100.0 * SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) / 
                            NULLIF(SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END), 0), 2) as overall_win_rate, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN swap ELSE 0 END) as total_swap,
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN commission ELSE 0 END) as total_commission, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE 0 END) as net_result, 
                            ROUND(AVG(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE NULL END), 2) as avg_profit_per_trade, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) as gross_profit, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) as gross_loss, 
                            CASE WHEN SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) > 0 
                            THEN ROUND(SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) / 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END), 2) 
                            ELSE 0 END as profit_factor, 
                            COUNT(DISTINCT symbol) as symbols_traded, 
                            COUNT(DISTINCT magic) as strategies_used 
                            FROM DEALS;
            

            複雑なリクエスト

            図9:複雑なSQLクエリ

            このSQLクエリは、この記事に付属するテストEA「TradingJournalSQLite-EA」からそのまま変更なしで使用されています。


            結論:MetaTrader 5内に構築される取引・分析システム

            取引ジャーナルはもはや、外部へエクスポートし、サードパーティ製のツールで開き、手動で整形する必要のある静的なファイルではありません。MetaTrader 5では、それはリアルタイムで更新され続ける、正確かつ信頼性の高い取引・分析システムの一部となっています。これはネイティブに実現されており、SQLiteがMetaTrader 5ターミナルのコアレベルに統合されているためです。

            これにより、MetaTrader 5を自己完結型の取引・分析システムとして利用でき、SQLクエリの持つ全ての能力を活用しながら、新しいアイデアに応じて拡張・修正することが可能になります。これによってトレーダーは以下のようなメリットを得られます。

              • データは自動的に保存され、生成直後から分析可能になります。
              • 分析用SQLクエリは、EAコードを複雑化させることなく迅速かつ柔軟に変更できます。
              • 分析ダッシュボードは、実際に取引をおこなうターミナルのチャート上で直接利用できます。
              • 新しいアイデア、評価指標、分析ビューに対しても、サードパーティアプリを使うことなく容易に拡張できます。

              このため、MetaTrader 5における内蔵SQLiteサポートは単なる便利なデータ保存機能ではなく、取引と分析が単一の環境、単一の言語、ネイティブSQLサポートのもとで統合される、本格的な取引インフラの基盤となります。


              SQLiteをMQL5で学ぶための推奨リソース

              記事に添付されているファイルの一覧:

              ファイル名 詳細
              TradingJournalSQLite-EA.mq5 取引統計ダッシュボードを生成するテストEAのコード

              MetaQuotes Ltdによってロシア語から翻訳されました。
              元の記事: https://www.mql5.com/ru/articles/22009

              添付されたファイル |
              最後のコメント | ディスカッションに移動 (1)
              Gerard William G J B M Dinh Sy
              Gerard William G J B M Dinh Sy | 5 5月 2026 において 12:35
              ありがとう
              OpenCLを用いたMQL5におけるCPUからGPUへの実践的移行パス OpenCLを用いたMQL5におけるCPUからGPUへの実践的移行パス
              MQL5でCPUからGPUへの移行方法を実用的に構築する方法を解説します。本記事では、コンテキストの初期化、バッファ構造の設計、大規模バッチ処理、カーネルの起動、データ転送の最小化に焦点を当てます。また、典型的なエラーとその解決方法についても取り上げます。ローソク足パターンの例を通じて、このアプローチの実用的な効果も示します。
              MetaTrader 5でL1トレンドフィルタリングを適用する MetaTrader 5でL1トレンドフィルタリングを適用する
              MetaTrader 5におけるL1トレンドフィルタリングの実践的な応用について、その数理的基礎とMQL5プログラムでの使用方法の両面から解説しています。L1フィルタは、価格ノイズを低減しつつ市場構造の本質を保持する、区分線形トレンドの抽出を可能にします。本研究では、パラメータスケーリング、トレンド推定の挙動、および本手法のアルゴリズム取引戦略への統合について分析しています。実験結果は、L1トレンドフィルタリングがシグナルの安定性、取引タイミング、ならびにトレードシステム全体のロバスト性を向上させることを示しています。
              Python-MetaTrader 5ストラテジーテスター(第1回):取引シミュレーター Python-MetaTrader 5ストラテジーテスター(第1回):取引シミュレーター
              MetaTrader5のPythonモジュールは、Pythonを使ってMetaTrader5アプリで取引を発注するための便利な手段を提供しています。しかし、このモジュールには大きな問題があります。それは、MetaTrader5アプリに存在するストラテジーテスター機能が備わっていないことです。本連載では、Python環境で取引戦略をバックテストするためのフレームワークを構築していきます。
              Python + MetaTrader 5:データ、機能、プロトタイプのための高速研究フレームワーク Python + MetaTrader 5:データ、機能、プロトタイプのための高速研究フレームワーク
              本記事では、PythonとMetaTrader 5の統合によって、研究の柔軟性と取引実行を単一のワークフローに統合できることを示しています。Pythonはデータ分析、特徴量選択、モデル学習に使用され、MetaTrader 5はテストおよび取引自動化に使用されます。このアプローチにより、ソリューションを実運用へ移行するプロセスが簡素化され、再現性が向上し、トレードシステムの開発がより迅速かつ構造化されます。