1. DatabaseImport関数の概要と実務での活用法
MQL5に標準搭載されているDatabaseImport関数は、CSVなどの外部ファイルからデータを読み込み、SQLiteデータベースのテーブルへ一括でインポートするための強力な関数です。
実務レベルのシステムトレード開発では、数万行、数十万行を超えるヒストリカルデータや、外部ツールで算出したセンチメント指標などを扱う場面が増えています。これらを従来のFileReadStringなどの関数で1行ずつパースして処理するのは、コードが複雑になるだけでなく、実行速度の面でも非常に非効率です。
DatabaseImportを活用することで、「外部データのデータベース化」を一瞬で完了させることができます。一度データベース化してしまえば、SQL文(SELECT文)を用いて特定の期間や条件に合致するデータだけを高速に抽出できるようになり、EAのロジック開発や分析の自由度が飛躍的に向上します。
2. 構文と戻り値
DatabaseImport関数の基本的な構文は以下の通りです。
bool DatabaseImport(
int database, // DatabaseOpenで取得したハンドル
const string table, // インポート先のテーブル名
const string filename, // インポート元のファイル名(MQL5/Filesフォルダ内)
uint flags, // インポート設定(フラグ)
const string separator, // 区切り文字(カンマ、タブなど)
uint skip_rows, // スキップする行数(ヘッダー飛ばしなど)
const string comment_chars // コメントと見なす文字列(例: "//")
);
戻り値
- 成功時:
true - 失敗時:
false(詳細はGetLastError()で確認可能)
主要なフラグ(flags)
DATABASE_IMPORT_HEADER:最初の行をカラム名として使用します。DATABASE_IMPORT_CRLF:改行コードをCRLFとして処理します。DATABASE_IMPORT_APPEND:既存のテーブルがある場合、末尾にデータを追加します。
3. 具体的な使い方・実践サンプルコード
以下のサンプルコードは、MQL5/Files フォルダにある signals.csv というファイルを読み込み、SQLiteデータベース内にインポートするスクリプトの例です。
//+------------------------------------------------------------------+
//| ImportExample.mq5 |
//+------------------------------------------------------------------+
void OnStart()
{
string filename = "signals.csv";
string db_name = "TradingData.sqlite";
string table_name = "SignalTable";
// 1. データベースを開く(存在しない場合は作成される)
int db_handle = DatabaseOpen(db_name, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(db_handle == INVALID_HANDLE)
{
Print("データベースのオープンに失敗しました。エラーコード: ", GetLastError());
return;
}
// 2. CSVデータをインポートする
// 最初の1行をヘッダーとして扱い、カンマ区切りでインポート
bool success = DatabaseImport(
db_handle,
table_name,
filename,
DATABASE_IMPORT_HEADER | DATABASE_IMPORT_CRLF,
",",
0,
NULL
);
if(success)
{
Print("データのインポートに成功しました。テーブル名: ", table_name);
// インポートされた件数を確認してみる
int query_handle = DatabasePrepare(db_handle, "SELECT COUNT(*) FROM " + table_name);
if(query_handle != INVALID_HANDLE)
{
long count = 0;
if(DatabaseRead(query_handle))
{
DatabaseColumnLong(query_handle, 0, count);
Print("合計レコード数: ", count);
}
DatabaseFinalize(query_handle);
}
}
else
{
Print("インポートに失敗しました。エラーコード: ", GetLastError());
}
// 3. データベースを閉じる
DatabaseClose(db_handle);
}
4. 使用上の注意点とよくあるエラー
開発中につまずきやすいポイントをいくつか挙げます。
- ファイルの場所:
DatabaseImportが参照できるファイルは、セキュリティ上の制約からMQL5/Filesフォルダ(または共通フォルダ)内に限られます。それ以外の場所にあるファイルは、一旦このフォルダに移動またはコピーする必要があります。 - テーブル名とカラム名の制限:
SQLiteの仕様により、テーブル名やカラム名に数字から始まる名前やハイフン(-)を含む名前を使用すると、SQLクエリ実行時にエラーになることがあります。英字から始まる名前を推奨します。 - データ型の自動判別:
DatabaseImportはデータの型を推測してテーブルを作成しますが、意図しない型(例えば、数値として扱いたいのに文字列型になる等)になる場合があります。厳密な型管理が必要な場合は、予めDatabaseExecuteでテーブルを作成してからDATABASE_IMPORT_APPENDフラグを使ってインポートしてください。 - エンコーディング:
CSVファイルの文字コードは原則としてUTF-8(BOMなし)またはUTF-16を使用してください。Shift-JISなどの日本語特有のエンコードは文字化けの原因になります。
5. 【重要】自動売買における約定スピードと環境の罠
どれほど高度なデータベース管理やアルゴリズムを構築しても、最終的にその注文を市場に届けるのは「ネットワーク」です。多くの日本人開発者が陥る罠が、自宅PCからの自動売買です。日本の一般家庭用回線は、海外にある証券会社のサーバー(主にニューヨークやロンドン)に到達するまでに数十、数百ものプロキシやノードを経由するため、物理的な遅延(レイテンシ)が致命的なレベルで発生します。
この遅延は、バックテストでは現れない「スリッページ」を招き、期待収益を大幅に削り取ります。プロのクオンツや専業トレーダーにとって、証券会社のサーバーと同じデータセンター内、あるいは極めて近距離に配置された専用のVPS(仮想専用サーバー)を利用することは、もはやオプションではなく必須のインフラです。極限まで約定スピードを高め、執行精度を安定させることこそが、理論上の利益を現実のキャッシュに変えるための最後の壁となります。
💡 この記事の内容を実運用で活かすには?
この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント