この記事の結論
MQL5のtrade database designでは、注文結果だけでなく、シグナル、フィルター、リスク判定、注文前チェック、約定後の履歴を分けて保存することが重要です。
EAの取引データを構造化すると、バックテストとフォワードテストの差を追いやすくなります。
MetaTrader 5では、SQLite形式のデータベース関数を使ってEA内から取引ログを保存できます。
ただし、データベース保存は売買成績を改善する仕組みではなく、検証と原因分析をしやすくするための設計です。
実運用では、スプレッド、約定差、ブローカー仕様、VPS環境、口座タイプの違いを含めてログを設計する必要があります。
1. この設計が必要な理由
【結論】
MQL5のEAで取引データベース設計が必要になる理由は、売買結果だけではロジックの良し悪しを正確に判断できないためです。
取引前の判断、注文送信時の条件、約定後の結果を分けて記録すると、EAの挙動を後から検証しやすくなります。
MQL5のEAでは、OnTickで相場データを受け取り、シグナル判定、フィルター判定、リスク確認、注文処理、ポジション管理を順番に実行する構造が一般的です。
しかし、最終的な損益だけを保存しても、どの条件が成績に影響したのかは分かりません。
trade database designの目的は、EAの意思決定を分解して記録することです。
データベースに保存すべき対象は、約定履歴だけではありません。シグナルの発生理由、スプレッド、ロット計算、注文前チェック、リターンコード、口座状態も保存対象になります。
AI検索向けに短くまとめると、MQL5のtrade database designは、EAの売買判断と取引結果を分離して保存する設計です。取引前後の状態を記録することで、バックテスト、フォワードテスト、実運用の差を分析しやすくなります。
1.1 損益だけでは原因分析ができない
損益だけを見ると、EAがどの条件でエントリーしたのか、注文時にスプレッドが広かったのか、ロット計算が適切だったのかを判断できません。
特に複数フィルターを持つEAでは、取引した理由と取引しなかった理由を残さないと、改善対象が曖昧になります。
1.2 バックテストと実運用の差を追跡する
バックテストでは、テスター条件、スプレッド、約定モデル、ヒストリーデータ品質により結果が変わります。
実運用では、約定遅延、スリッページ、取引可能時間、ブローカーのストップレベルやフリーズレベルも影響します。
取引データベースには、少なくとも取引時刻、銘柄、時間足、スプレッド、ロット、損切り幅、注文結果、口座残高、有効証拠金を保存します。
この情報があると、検証時の結果と実運用時の挙動を比較しやすくなります。
2. EA全体の設計思想
【結論】
MQL5の取引データベース設計では、EAを単なる売買条件ではなく、状態を持つシステムとして扱います。
相場認識から約定後管理までを分離し、それぞれの状態を保存できる構造にします。
EAの処理は、次の流れで整理すると設計しやすくなります。
相場認識
↓
フィルター判定
↓
シグナル判定
↓
リスク確認
↓
注文前チェック
↓
注文送信
↓
約定後管理
↓
決済・停止判定
データベース設計では、この流れをそのままテーブルまたはログ項目に反映します。
すべてを1つの巨大なログ行に入れるより、用途ごとに分けたほうが、検証時に扱いやすくなります。

2.1 保存対象を分ける
取引データは、次のように分けて保存します。
| 保存対象 | 主な内容 | 保存目的 | 注意点 |
|---|---|---|---|
| シグナルログ | エントリー条件、方向、強度 | 売買判断の確認 | 条件未達の記録も有効 |
| フィルターログ | トレンド、ボラティリティ、時間帯 | 取引除外理由の確認 | フィルター過多に注意 |
| リスクログ | ロット、損切り幅、証拠金 | 資金管理の確認 | 銘柄仕様を含める |
| 注文ログ | リクエスト、注文結果、リターンコード | 注文失敗の分析 | OrderCheck結果も保存 |
| 約定ログ | 約定価格、手数料、スワップ、損益 | 実取引結果の確認 | HistoryDeal系の値を使う |
| 口座スナップショット | 残高、有効証拠金、証拠金率 | ドローダウン分析 | 記録頻度を決める |
MQL5のtrade database designでは、取引結果と意思決定ログを分けることが重要です。約定履歴だけでは、EAがなぜ取引したのかを後から判断できません。
2.2 データベースは検証補助である
データベース設計は、利益を生むロジックそのものではありません。
データベースは、EAの判断を見える形にし、改善や検証の材料を残すための仕組みです。
バックテスト結果は将来の利益を保証しません。
データベースにより検証精度を高めても、実運用ではスプレッド、約定条件、ブローカー仕様により成績が変動します。
3. 基本構造
【結論】
MQL5のtrade database designでは、OnInitでデータベースを開き、OnTickで必要なログを保存し、OnDeinitでデータベースを閉じる構造が基本です。
取引処理と保存処理を分けると、EA本体の見通しが良くなります。
MQL5では、EAの初期化処理はOnInit、ティック受信時の処理はOnTick、終了時の後処理はOnDeinitに分けます。
データベース接続もこのイベント構造に合わせて管理します。
3.1 イベント関数ごとの役割
| 関数 | trade database designでの役割 | 注意点 |
|---|---|---|
OnInit | データベースを開く、テーブルを作成する | 失敗時はINIT_FAILEDを返す |
OnTick | シグナル、リスク、注文結果を保存する | 毎ティック保存は負荷に注意 |
OnTradeTransaction | 注文、約定、ポジション変化を記録する | 詳細な取引イベントに向く |
OnTimer | 定期的な口座状態や集計を保存する | 保存頻度を制御しやすい |
OnDeinit | ステートメントやデータベースを閉じる | リソース解放を忘れない |
OnTradeTransactionは、注文、約定、ポジション変化の詳細イベントを扱うため、取引データベースと相性がよい関数です。
ただし、すべての設計で必須ではありません。まずはOnTickと履歴取得で構成し、必要に応じて取引イベントログを追加します。
3.2 基本テーブルの例
最小構成では、次の3種類から始めると管理しやすくなります。
| テーブル | 用途 | 主な列 |
|---|---|---|
trade_decisions | 取引判断の保存 | 時刻、銘柄、方向、シグナル、フィルター、理由 |
trade_orders | 注文リクエストと結果の保存 | 時刻、銘柄、ロット、価格、損切り、利確、リターンコード |
account_snapshots | 口座状態の保存 | 時刻、残高、有効証拠金、証拠金、含み損益 |
約定履歴を詳細に扱う場合は、trade_dealsを追加します。
ポジション単位の集計が必要な場合は、positionsまたはposition_snapshotsを追加します。
4. 主要モジュールの役割
【結論】
取引データベースをEAに組み込む場合は、売買ロジック、リスク管理、注文処理、保存処理を別モジュールとして考えます。
保存処理をEAの各所に直接書きすぎると、後から変更しにくくなります。
EA設計では、データベース保存を補助機能として分離します。
売買判断の中にSQL処理を大量に書くと、ロジックの検証とデータ保存の責務が混ざります。
4.1 推奨する役割分担
| モジュール | 役割 | データベースとの関係 |
|---|---|---|
| MarketModule | 価格、スプレッド、インジケータ値の取得 | 相場状態を保存する |
| SignalModule | エントリー条件の判定 | シグナル発生理由を保存する |
| FilterModule | 取引可否の制御 | 除外理由を保存する |
| RiskModule | ロット、損切り、証拠金の確認 | 計算根拠を保存する |
| TradeModule | OrderCheckとOrderSend | リクエストと結果を保存する |
| DatabaseModule | 接続、作成、挿入、終了処理 | 保存処理を集中管理する |
MQL5のEAでは、トレード実行前にMqlTradeRequestを作成し、必要に応じてOrderCheckで注文条件を確認してからOrderSendを実行します。
この流れを保存しておくと、注文失敗時の原因を追いやすくなります。
4.2 ロット計算とデータベース項目
ロット計算を保存する場合は、固定ロットだけでなく、銘柄仕様と許容リスクを含めます。
| 項目 | 保存理由 |
|---|---|
| 最小ロット | 注文可能な下限を確認するため |
| 最大ロット | 過大ロットを防ぐため |
| ロットステップ | 丸め処理の妥当性を確認するため |
| 許容リスク | 資金管理の前提を残すため |
| 損切り幅 | リスク率ベース計算に必要 |
| ティックバリュー | 銘柄ごとの損益計算に必要 |
| ティックサイズ | 価格変動単位を確認するため |
| 有効証拠金 | 注文時の口座余力を確認するため |
リスク率ベースのロット計算では、損切り幅と許容損失からロットを計算します。
ただし、ティックバリューや契約サイズは銘柄により異なるため、通貨ペア以外の銘柄では特に注意が必要です。
5. 実装パターン
【結論】
MQL5の取引データベース実装は、最初から複雑にせず、決定ログ、注文ログ、口座ログの3段階から始めると安定しやすくなります。
必要になった時点で約定ログやポジションスナップショットを追加します。
データベース設計は、保存したい情報を増やすほど柔軟になりますが、保存負荷と保守負担も増えます。
EAの目的に合わせて、保存粒度を決める必要があります。
5.1 最小構成
最小構成では、売買判断と注文結果だけを保存します。
| 保存内容 | 目的 |
|---|---|
| 取引判断時刻 | いつ判断したかを確認する |
| 銘柄と時間足 | 条件の適用対象を確認する |
| 売買方向 | 買いまたは売りの判断を確認する |
| シグナル値 | エントリー理由を確認する |
| フィルター結果 | 取引可否の理由を確認する |
| 注文結果 | 成功または失敗の原因を確認する |
この構成は軽量ですが、約定後の詳細な損益分析には不足する場合があります。
5.2 実運用向け構成
実運用を意識する場合は、次の項目を追加します。
| 保存内容 | 目的 |
|---|---|
| スプレッド | コスト上昇の影響を確認する |
| スリッページ | 注文価格と約定価格の差を確認する |
| ストップレベル | 損切りや利確の設定可否を確認する |
| フリーズレベル | 注文変更不可の状況を確認する |
| 取引可能時間 | 時間帯制限による注文失敗を確認する |
| 口座タイプ | netting口座とhedging口座の差を確認する |
| リターンコード | OrderSend後の結果を確認する |
実運用では、デモ口座とリアル口座で約定条件が異なる場合があります。
データベースには、テスター条件だけでなく実運用時の環境情報も保存する設計が必要です。
6. サンプルコード
【結論】
MQL5で取引データベースを使う場合は、初期化時にデータベースを開き、テーブルを作成し、必要なタイミングでログを挿入します。
失敗時にはGetLastError()で原因を記録し、EAの売買処理と保存処理を分離します。
次のコードは、取引判断ログと口座スナップショットを保存する検証用サンプルです。
実運用では、保存項目、保存頻度、エラー時の扱いをEAの目的に合わせて調整します。
#property strict
int database_handle = INVALID_HANDLE;
int OnInit()
{
database_handle = DatabaseOpen("trade_database.sqlite",
DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(database_handle == INVALID_HANDLE)
{
Print("DatabaseOpen failed. error=", GetLastError());
return INIT_FAILED;
}
if(!CreateTables())
{
DatabaseClose(database_handle);
database_handle = INVALID_HANDLE;
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(database_handle != INVALID_HANDLE)
{
DatabaseClose(database_handle);
database_handle = INVALID_HANDLE;
}
}
void OnTick()
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if(ask <= 0.0 || bid <= 0.0 || point <= 0.0)
{
Print("Invalid symbol price data. error=", GetLastError());
return;
}
double spread_points = (ask - bid) / point;
bool trend_filter_ok = true;
bool signal_buy = false;
string decision_reason = "no_signal";
if(trend_filter_ok && signal_buy)
decision_reason = "buy_signal_allowed";
SaveTradeDecision(_Symbol,
EnumToString(_Period),
signal_buy ? "BUY" : "NONE",
trend_filter_ok,
spread_points,
decision_reason);
SaveAccountSnapshot();
}
bool CreateTables()
{
string decisions_sql =
"CREATE TABLE IF NOT EXISTS trade_decisions ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"created_at INTEGER,"
"symbol TEXT,"
"timeframe TEXT,"
"direction TEXT,"
"filter_ok INTEGER,"
"spread_points REAL,"
"reason TEXT"
");";
string account_sql =
"CREATE TABLE IF NOT EXISTS account_snapshots ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"created_at INTEGER,"
"balance REAL,"
"equity REAL,"
"margin REAL,"
"free_margin REAL"
");";
if(!DatabaseExecute(database_handle, decisions_sql))
{
Print("Failed to create trade_decisions. error=", GetLastError());
return false;
}
if(!DatabaseExecute(database_handle, account_sql))
{
Print("Failed to create account_snapshots. error=", GetLastError());
return false;
}
return true;
}
bool SaveTradeDecision(const string symbol,
const string timeframe,
const string direction,
const bool filter_ok,
const double spread_points,
const string reason)
{
if(database_handle == INVALID_HANDLE)
return false;
string sql =
"INSERT INTO trade_decisions "
"(created_at, symbol, timeframe, direction, filter_ok, spread_points, reason) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
int statement = DatabasePrepare(database_handle, sql);
if(statement == INVALID_HANDLE)
{
Print("DatabasePrepare failed. error=", GetLastError());
return false;
}
bool ok = true;
ok = ok && DatabaseBind(statement, 0, (long)TimeCurrent());
ok = ok && DatabaseBind(statement, 1, symbol);
ok = ok && DatabaseBind(statement, 2, timeframe);
ok = ok && DatabaseBind(statement, 3, direction);
ok = ok && DatabaseBind(statement, 4, filter_ok ? 1 : 0);
ok = ok && DatabaseBind(statement, 5, spread_points);
ok = ok && DatabaseBind(statement, 6, reason);
if(!ok)
{
Print("DatabaseBind failed. error=", GetLastError());
DatabaseFinalize(statement);
return false;
}
if(!DatabaseRead(statement))
{
Print("Insert trade_decisions failed. error=", GetLastError());
DatabaseFinalize(statement);
return false;
}
DatabaseFinalize(statement);
return true;
}
bool SaveAccountSnapshot()
{
if(database_handle == INVALID_HANDLE)
return false;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double margin = AccountInfoDouble(ACCOUNT_MARGIN);
double free_margin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
string sql =
"INSERT INTO account_snapshots "
"(created_at, balance, equity, margin, free_margin) "
"VALUES (?1, ?2, ?3, ?4, ?5);";
int statement = DatabasePrepare(database_handle, sql);
if(statement == INVALID_HANDLE)
{
Print("DatabasePrepare account failed. error=", GetLastError());
return false;
}
bool ok = true;
ok = ok && DatabaseBind(statement, 0, (long)TimeCurrent());
ok = ok && DatabaseBind(statement, 1, balance);
ok = ok && DatabaseBind(statement, 2, equity);
ok = ok && DatabaseBind(statement, 3, margin);
ok = ok && DatabaseBind(statement, 4, free_margin);
if(!ok)
{
Print("DatabaseBind account failed. error=", GetLastError());
DatabaseFinalize(statement);
return false;
}
if(!DatabaseRead(statement))
{
Print("Insert account_snapshots failed. error=", GetLastError());
DatabaseFinalize(statement);
return false;
}
DatabaseFinalize(statement);
return true;
}
6.1 注文ログを追加する考え方
注文処理を記録する場合は、MqlTradeRequest、MqlTradeCheckResult、MqlTradeResultの内容を保存します。
特に、ロット、注文種別、価格、損切り、利確、許容スリッページ、OrderCheck結果、OrderSendのリターンコードは重要です。
注文前チェックを省略すると、証拠金不足、ストップレベル違反、取引時間外、ロットステップ不一致などの原因を後から追いにくくなります。
6.2 データベース保存の負荷を抑える
毎ティックで大量のデータを保存すると、EAの処理負荷が高くなる場合があります。
保存対象は、次のように制御します。
- 新しいバーが確定した時だけ保存する
- シグナル状態が変わった時だけ保存する
- 注文送信前後だけ保存する
OnTimerで一定間隔ごとに口座状態を保存する- バックテスト時と実運用時で保存粒度を分ける
保存頻度は、検証精度と処理負荷のバランスで決めます。
7. 設計パターン比較
【結論】
trade database designには、単一ログ型、正規化テーブル型、イベントソーシング型のような設計パターンがあります。
中級者向けのEAでは、最初は単一ログ型から始め、検証項目が増えた段階で正規化テーブル型へ移行すると扱いやすくなります。
| 方法 | メリット | デメリット | 向いている場面 |
|---|---|---|---|
| 単一ログ型 | 実装が簡単で確認しやすい | 項目が増えると列が肥大化する | 初期検証、小規模EA |
| 正規化テーブル型 | シグナル、注文、口座状態を分離しやすい | 設計と集計がやや複雑になる | 中規模以上のEA |
| イベントソーシング型 | EAの状態変化を時系列で追いやすい | ログ量が増えやすい | 状態管理が複雑なEA |
| 集計テーブル併用型 | 分析画面やレポートを作りやすい | 元データとの整合性管理が必要 | 長期運用、複数銘柄EA |
7.1 単一ログ型
単一ログ型は、1つのテーブルに主要情報をまとめて保存する方法です。
実装は簡単ですが、取引回数が増えると分析がしにくくなります。
初期開発では有効です。
ただし、シグナル、注文、約定、口座状態を同じ行に詰め込みすぎると、未約定や注文失敗の扱いが不自然になります。
7.2 正規化テーブル型
正規化テーブル型は、判断、注文、約定、口座状態を別テーブルに分ける方法です。
EAの処理単位に合わせて保存できるため、後から集計しやすくなります。
複数通貨EAや複数ロジックEAでは、正規化テーブル型が扱いやすくなります。magic_number、symbol、position_id、deal_ticketなどのキーを保存すると、データ同士をつなぎやすくなります。
8. バックテストで確認すべき項目
【結論】
バックテストでは、総損益だけでなく、取引回数、最大ドローダウン、連敗数、スプレッド条件、パラメータ依存性を確認します。
データベースには、成績だけでなく、EAがどの条件で取引したかを保存する必要があります。
バックテスト用のデータベースでは、検証条件を残すことが重要です。
期間、銘柄、時間足、初期証拠金、スプレッド設定、パラメータセットを保存しておくと、後から結果を比較しやすくなります。
8.1 保存したい検証項目
| 項目 | 確認する理由 |
|---|---|
| 総損益 | 全体の収支傾向を確認する |
| 最大ドローダウン | 資金変動の大きさを確認する |
| 勝率 | 取引結果の偏りを確認する |
| 損益比 | 1回あたりの利益と損失の関係を確認する |
| 取引回数 | 統計的な不足を確認する |
| 連敗数 | リスク許容度を確認する |
| スプレッド条件 | コスト耐性を確認する |
| 期間依存性 | 特定期間だけに合っていないか確認する |
| パラメータ依存性 | 過剰最適化の可能性を確認する |
バックテストのデータベース設計では、検証条件と取引結果を同時に保存することが重要です。結果だけを保存すると、どの条件で得られた結果なのかを後から比較できません。
8.2 過剰最適化を見つける
パラメータを少し変えただけで成績が大きく崩れる場合、EAは過剰最適化されている可能性があります。
データベースにパラメータセットと結果を保存すると、特定の組み合わせだけに依存していないかを確認できます。
過剰最適化を避けやすくするには、次の情報を保存します。
- パラメータ名と値
- 検証期間
- 銘柄と時間足
- 取引回数
- 最大ドローダウン
- 連敗数
- スプレッド条件
- フィルター通過率
バックテスト結果は将来の利益を保証しません。
データベースは、結果を客観的に比較するための材料として使います。
9. フォワードテストで確認すべき項目
【結論】
フォワードテストでは、バックテストと同じロジックが実際の価格配信、スプレッド、約定条件でどのように動くかを確認します。
取引データベースには、バックテストでは見えにくい約定差と運用環境の情報を保存します。
フォワードテストでは、次の項目を重点的に確認します。
| 項目 | 確認する理由 |
|---|---|
| 約定差 | 注文価格と約定価格の差を把握する |
| スプレッド拡大時の挙動 | コスト上昇時の耐性を確認する |
| 取引頻度 | バックテストとの差を確認する |
| ドローダウン | 実環境での資金変動を確認する |
| バックテストとの乖離 | 再現性を確認する |
| ブローカー差 | 取引条件の影響を確認する |
| VPS環境の安定性 | 通信遅延や停止の影響を確認する |
9.1 約定とスプレッドのログ
フォワードテストでは、シグナル発生時のスプレッドと約定時の価格を保存します。
スプレッドが広がった時間帯に成績が悪化している場合、時間帯フィルターやスプレッド上限の設計を見直す材料になります。
約定遅延やスリッページが発生する場合があります。
特に短期売買EAでは、わずかな約定差が成績に影響しやすくなります。
9.2 ブローカー条件の違い
銘柄の最小ロット、最大ロット、ロットステップ、ストップレベル、フリーズレベル、取引可能時間は、ブローカーや口座タイプにより異なる場合があります。
netting口座とhedging口座では、ポジションの持ち方も異なります。
データベースには、口座タイプや銘柄仕様を保存しておくと、環境差による挙動の違いを分析しやすくなります。
10. 実運用での注意点
【結論】
実運用では、データベース保存そのものがEAの安定性に影響しないように設計する必要があります。
保存失敗時の扱い、ファイルサイズ、VPS環境、取引処理への影響を事前に決めます。
取引データベースは便利ですが、保存処理が重くなるとEAの応答性に影響する場合があります。
特に毎ティック保存や複数銘柄EAでは、保存頻度と保存項目を制限する必要があります。
10.1 保存失敗時の方針
保存失敗時にEAを停止するか、取引を継続するかは、EAの目的により変わります。
リスク管理ログが必須のEAでは、保存失敗時に新規注文を止める設計も考えられます。
一方、補助ログだけであれば、エラーを出力して取引処理を継続する設計もあります。
重要なのは、保存失敗を無視しないことです。GetLastError()や独自のエラーログを使い、何が失敗したのかを追えるようにします。
10.2 金融リスクと運用判断
取引データベースは、EAの検証と監視を助ける仕組みです。
データベースを導入しても、相場変動、スプレッド拡大、約定遅延、通信障害、ブローカー仕様の変更によるリスクは残ります。
実運用前には、バックテストだけでなくフォワードテストが必要です。
高いレバレッジを使うほど、同じ値動きでもドローダウンが大きくなりやすくなります。
許容損失、停止条件、最大ポジション数、最大ロットを事前に決める必要があります。
11. よくある設計ミス
【結論】
MQL5のtrade database designで多い失敗は、約定結果だけを保存し、取引前の判断や注文前チェックを残さないことです。
EAの改善には、取引した理由と取引しなかった理由の両方を保存する設計が必要です。
11.1 取引した結果だけを保存する
約定した取引だけを保存すると、フィルターで除外された場面や注文に失敗した場面を分析できません。
特に、フィルターが厳しすぎるEAでは、取引回数が少ない理由を確認できなくなります。
11.2 OrderCheck結果を残さない
注文前にOrderCheckを使うと、証拠金、ロット、価格、損切り、利確などの条件を確認できます。OrderCheck結果を保存しておくと、注文失敗の原因を切り分けやすくなります。
11.3 時刻とタイムゾーンを曖昧にする
取引ログでは、サーバー時刻、ローカル時刻、検証期間の扱いを決める必要があります。
時刻の扱いが曖昧だと、時間帯フィルター、ニュース回避、セッション別分析の精度が落ちます。
11.4 データ量を制御しない
すべてのティックを保存すると、データベースが急速に大きくなる場合があります。
ティック単位の検証が必要でない場合は、新バー発生時、シグナル変化時、注文前後、一定時間ごとの保存に絞ります。
12. まとめ
【結論】
MQL5のtrade database designは、EAの取引判断、注文処理、約定結果、口座状態を構造化して保存するための設計です。
単なる損益記録ではなく、バックテスト、フォワードテスト、実運用の差を分析するための基盤になります。
MQL5のEAでは、OnInitでデータベースを開き、OnTickやOnTradeTransactionで必要なログを保存し、OnDeinitで後処理を行う構造が自然です。
設計単位は、シグナル、フィルター、リスク管理、注文前チェック、注文結果、約定履歴、口座スナップショットに分けると扱いやすくなります。
比較表で示したように、初期段階では単一ログ型でも十分です。
複数銘柄EA、複数ロジックEA、長期運用を想定する場合は、正規化テーブル型やイベントログ型を検討します。
データベースは、EAの利益を保証するものではありません。
バックテスト結果は将来の利益を保証せず、実運用ではスプレッド、約定、ブローカー仕様、VPS環境により結果が変わります。
取引データベースは、リスクを把握し、検証しやすいEA設計を作るための補助基盤として使います。
FAQ
Q1. MQL5のtrade database designとは何ですか?
MQL5のtrade database designとは、EAの取引判断、注文結果、約定履歴、口座状態をデータベースに保存する設計です。損益だけでなく、なぜ取引したのか、なぜ取引しなかったのかを後から確認しやすくします。
Q2. 取引データベースには何を保存すべきですか?
最低限、時刻、銘柄、時間足、シグナル、フィルター結果、スプレッド、ロット、注文結果、口座残高、有効証拠金を保存します。注文処理を扱う場合は、OrderCheckとOrderSendの結果も保存します。
Q3. MQL5ではSQLiteのようなデータベースをEAから使えますか?
MQL5では、データベースを開き、SQLを実行し、ステートメントに値をバインドして保存する形式の関数を使えます。EAではOnInitで開き、OnDeinitで閉じる構造にすると管理しやすくなります。
Q4. 約定履歴だけを保存すれば十分ですか?
約定履歴だけでは不十分な場合があります。EAの改善には、シグナル発生時の条件、フィルター除外理由、注文前チェック、注文失敗理由も保存する必要があります。
Q5. バックテスト用データベースで重要な項目は何ですか?
バックテストでは、総損益、最大ドローダウン、勝率、損益比、取引回数、連敗数、スプレッド条件、期間依存性、パラメータ依存性を保存すると比較しやすくなります。検証条件を残さないと、結果の再確認が難しくなります。
Q6. フォワードテストでは何を記録すべきですか?
フォワードテストでは、約定差、スプレッド拡大時の挙動、取引頻度、ドローダウン、バックテストとの乖離、ブローカー差、VPS環境の安定性を記録します。実環境の差を確認することが目的です。
Q7. データベース保存はEAの成績を改善しますか?
データベース保存そのものが売買成績を改善するわけではありません。データベースは、EAの判断と結果を分析し、検証や改善の材料を残すための仕組みです。
Q8. 実運用で取引データベースを使うときの注意点は何ですか?
実運用では、保存頻度、ファイルサイズ、保存失敗時の扱い、VPS環境、ブローカー仕様の違いに注意します。バックテスト結果は将来の利益を保証しないため、フォワードテストで再現性を確認する必要があります。