- 1 1. MQL5のSymbolInfoとは何か
- 2 2. SymbolInfoの基本構文
- 3 3. SymbolInfoで取得できる主な情報
- 4 4. SymbolInfoを使った実践コード例
- 5 5. SymbolInfoとMarketInfoの違い(MT4との比較)
- 6 6. SymbolInfo使用時の注意点
- 7 7. SymbolInfoのトラブルシューティング
- 8 8. FAQ(よくある質問)
1. MQL5のSymbolInfoとは何か
MQL5の SymbolInfo は、MetaTrader 5で扱う金融商品の情報(通貨ペア・指数・CFDなど)を取得するためのAPIです。
EA(自動売買プログラム)やインジケーターから、現在のシンボル(例:EURUSD、USDJPYなど)の 取引条件・価格関連情報・仕様 を取得するために使用します。
MetaTraderでは、ブローカーごとに次のような条件が異なることがあります。
- スプレッド
- 最小ロット
- 最大ロット
- Tickサイズ(最小価格変動)
- 取引可能状態
これらの情報を プログラムから取得して制御するための仕組み が SymbolInfoです。
例えばEAでは、次のような判断が必要になる場面があります。
- スプレッドが広すぎる場合はエントリーしない
- 最小ロット未満の注文を出さない
- 取引停止中のシンボルでは売買しない
SymbolInfoを使うことで、こうした ブローカー依存の条件をプログラム側で安全に処理できます。
1.1 SymbolInfoの基本概念
SymbolInfoは、シンボル(取引銘柄)の属性情報を取得するための関数群です。
MQL5では、取得するデータの型に応じて次の3種類の関数が用意されています。
- SymbolInfoDouble
小数値(double)を取得する
例:スプレッド、Tickサイズ、ロット情報 - SymbolInfoInteger
整数値(integer)を取得する
例:取引状態、桁数、フラグ - SymbolInfoString
文字列(string)を取得する
例:通貨名、説明
この設計は、MQL5が データ型の安全性(type safety) を重視しているためです。
つまり、取得するデータの種類ごとに関数を分けることで、誤った型の処理を防いでいます。
例えば、スプレッドを取得する場合は次のように書きます。
double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
ここで使われている要素は次の通りです。
_Symbol
現在のチャートのシンボル(例:EURUSD)SYMBOL_SPREAD
取得する情報の種類(スプレッド)
このように、SymbolInfoは
SymbolInfo(シンボル名, 取得したい情報)
という構造で使用します。
1.2 SymbolInfoが使われる場面
EA開発では、SymbolInfoは非常に頻繁に使用される関数群です。
特に以下のような処理では必須になります。
スプレッドフィルター
スプレッドが広いとトレードの期待値(平均利益)が悪化するため、
EAではスプレッドをチェックしてから注文を出すことがよくあります。
int spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spread > 30)
{
return;
}
ロットサイズの制御
ブローカーごとに最小ロットが異なるため、
注文前に確認する必要があります。
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
Tickサイズ取得
価格計算やストップロス設定で使用します。
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
取引可能状態の確認
市場が閉じている場合や取引停止中の場合、注文は通りません。
long tradeMode = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE);
つまずきやすいポイント
初心者がよく混乱するポイントがあります。
① SymbolInfoは単一の関数ではない
SymbolInfoという名前だけ覚えてしまうと、
SymbolInfo(...)
という関数があるように見えますが、実際には
- SymbolInfoDouble
- SymbolInfoInteger
- SymbolInfoString
の 3つの関数の総称です。
② ブローカーによって取得値が異なる
例えば次の値は ブローカー設定に依存します。
- 最小ロット
- 最大ロット
- スプレッド
そのためEA開発では 固定値を使うのではなくSymbolInfoで取得するのが基本です。
③ EA起動直後は値が取得できない場合がある
EAの OnInit()直後 では、環境によっては情報取得が不安定な場合があります。
そのため実務では
- OnTickで取得
- 初回Tickを待つ
という設計をするケースもあります。
2. SymbolInfoの基本構文
SymbolInfoは単一の関数ではなく、取得するデータ型に応じて3つの関数に分かれています。
MQL5では、シンボル(通貨ペア・指数・商品など)の情報を取得する際、次の関数を使用します。
- SymbolInfoDouble
小数値(double型)を取得 - SymbolInfoInteger
整数値(long型)を取得 - SymbolInfoString
文字列(string型)を取得
この設計により、MQL5ではデータ型の安全性(型ミスの防止)が保たれています。
例えば、ロットサイズやTickサイズなどの小数値を整数型で取得するミスを防ぐことができます。
2.1 SymbolInfoDoubleの構文
SymbolInfoDouble は、小数値(double型)の情報を取得する関数です。
主に以下のような情報を取得する際に使用します。
- 最小ロット
- 最大ロット
- Tickサイズ
- Tick価値
- Point値
構文
double SymbolInfoDouble(
string name,
ENUM_SYMBOL_INFO_DOUBLE prop_id
);
パラメータ
| 引数 | 内容 |
|---|---|
| name | シンボル名(例:EURUSD) |
| prop_id | 取得したい情報の種類 |
通常は現在のチャートのシンボルを意味する _Symbol を使用します。
使用例(最小ロット取得)
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
このコードは、現在の通貨ペアの最小取引ロットを取得します。
EAでは、ロットサイズ計算時にこの値を確認することで、
ブローカー条件違反の注文エラーを防ぐことができます。
2.2 SymbolInfoIntegerの構文
SymbolInfoInteger は、整数値(long型)の情報を取得する関数です。
主に取得する情報は次のようなものです。
- スプレッド
- 桁数
- 取引モード
- シンボルの状態
構文
long SymbolInfoInteger(
string name,
ENUM_SYMBOL_INFO_INTEGER prop_id
);
使用例(スプレッド取得)
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
スプレッドはポイント単位で返されます。
例えば
- EURUSD
- 5桁ブローカー
の場合
spread = 20
なら
2.0 pips
程度のスプレッドになります。
EAでは次のようなスプレッドフィルターがよく使用されます。
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spread > 30)
{
return;
}
この処理により、スプレッドが広すぎる場合にエントリーを回避できます。
2.3 SymbolInfoStringの構文
SymbolInfoString は、文字列情報を取得する関数です。
取得できる情報には次のようなものがあります。
- 通貨名
- シンボルの説明
- ベース通貨
- 利益通貨
構文
string SymbolInfoString(
string name,
ENUM_SYMBOL_INFO_STRING prop_id
);
使用例(ベース通貨)
string baseCurrency = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE);
例えば
EURUSD
の場合
EUR
が取得されます。
つまずきやすいポイント
SymbolInfoの使用では、初心者がよく間違えるポイントがあります。
① データ型の選択ミス
例えば次のようなコードはエラーになります。
double spread = SymbolInfoDouble(_Symbol, SYMBOL_SPREAD);
理由
SYMBOL_SPREAD は integer型
だからです。
正しくは
SymbolInfoInteger()
を使用します。
② ENUM値の間違い
SymbolInfoでは、取得する情報は
SYMBOL_******
という列挙型(ENUM)で指定します。
例えば
SYMBOL_VOLUME_MIN
SYMBOL_SPREAD
SYMBOL_DIGITS
などです。
スペルミスをするとコンパイルエラーになります。
③ シンボル未選択問題
シンボルがマーケットウォッチに存在しない場合、
SymbolInfoが失敗する可能性があります。
その場合は次のようにシンボルを有効化します。
SymbolSelect(symbol,true);
3. SymbolInfoで取得できる主な情報
SymbolInfoでは、シンボル(通貨ペア・指数・CFDなど)の取引条件・価格仕様・通貨情報など、さまざまなデータを取得できます。
EA開発では特に次の情報が頻繁に使用されます。
- スプレッド
- 桁数(Digits)
- Point値
- ロット条件
- Tickサイズ
- Tick価値
これらは ブローカーごとに異なる可能性があるため、プログラムで取得するのが基本です。
固定値で処理すると、ブローカー変更時にEAが正常に動作しない場合があります。
3.1 スプレッド(SYMBOL_SPREAD)
スプレッドは Bid価格とAsk価格の差を意味します。
EAでは、スプレッドが広いときにエントリーを避けるために使用されます。
スプレッド取得
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
この値は ポイント(point)単位で返されます。
例(5桁ブローカー)
| 値 | 実際のpips |
|---|---|
| 10 | 1.0 pips |
| 20 | 2.0 pips |
スプレッドフィルター例
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spread > 30)
{
Print("スプレッドが広すぎます");
return;
}
この処理により、取引コストが高いタイミングでのエントリーを防止できます。
3.2 桁数(SYMBOL_DIGITS)
桁数は、そのシンボルの価格表示の小数点桁数です。
取得コード
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
例
| 通貨ペア | digits |
|---|---|
| USDJPY | 3 |
| EURUSD | 5 |
| GOLD | 2〜3(ブローカー依存) |
EAでは、価格計算時にこの値を使うことがあります。
3.3 Point値(SYMBOL_POINT)
Pointは 価格の最小単位です。
取得コード
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
例
| 通貨ペア | Point |
|---|---|
| EURUSD | 0.00001 |
| USDJPY | 0.001 |
EAでは、次のような計算で使用されます。
double sl = Ask - 100 * point;
このコードは 100ポイントのストップロスを設定しています。
3.4 ロット情報
EAでは、注文ロットがブローカー条件に違反すると OrderSendエラーになります。
そのため、次の情報を取得して調整する必要があります。
最小ロット
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
最大ロット
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
ロットステップ
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
例
| 項目 | 値 |
|---|---|
| 最小ロット | 0.01 |
| 最大ロット | 100 |
| ロット刻み | 0.01 |
EAでは次のように調整することがあります。
lot = MathMax(lot, minLot);
lot = MathMin(lot, maxLot);
3.5 Tickサイズ(SYMBOL_TRADE_TICK_SIZE)
Tickサイズは 価格が変化する最小単位です。
取得コード
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
例
| シンボル | Tickサイズ |
|---|---|
| EURUSD | 0.00001 |
| GOLD | 0.01 |
EAでは、価格の丸め処理などに使用されます。
3.6 Tick価値(SYMBOL_TRADE_TICK_VALUE)
Tick価値は 1Tick動いたときの損益金額です。
取得コード
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
この値は リスク計算(ロット計算)で重要になります。
例えば
- 損切り幅
- ロットサイズ計算
などで使用されます。
よくある失敗
SymbolInfoでは初心者がつまずくポイントがあります。
① スプレッドをpipsと誤解する
SYMBOL_SPREADは pipsではなくpoint単位です。
5桁ブローカーでは
10 point = 1 pip
になることがあります。
② ロット条件を確認せず注文する
EAで次のエラーが出る原因になります。
Invalid volume
原因
- 最小ロット未満
- ロット刻み違反
③ ブローカー依存値を固定値にする
例えば
double lot = 0.1;
と固定すると、ブローカー変更時にエラーになる可能性があります。
そのため SymbolInfoで取得する設計が推奨されます。
4. SymbolInfoを使った実践コード例
ここまでで説明したように、SymbolInfoはシンボルの取引条件を取得するための基礎APIです。
しかし実際のEA開発では、単に情報を取得するだけではなく、取引前の安全チェックとして使用されます。
具体的には次のような用途が多いです。
- スプレッドチェック
- ロットサイズ調整
- 取引可能状態の確認
- 価格計算
このセクションでは、実際のEAでよく使われるSymbolInfoの実践コードを解説します。
4.1 スプレッドチェックEA
EAではスプレッドが広いと、トレードの期待値が悪化します。
そのため多くのEAでは、一定以上のスプレッドでトレードを禁止します。
実装例
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spread > 30)
{
Print("スプレッドが広すぎるためトレードを停止");
return;
}
このコードでは
spread > 30
の場合にトレードを回避しています。
ポイント
- スプレッドは point単位
- 通貨ペアによって基準を調整する必要あり
- ロンドン・NYオープン直前はスプレッド拡大しやすい
4.2 ロットサイズの安全調整
EAの注文エラーで最も多いのが
Invalid volume
です。
これは次の条件違反で発生します。
- 最小ロット未満
- 最大ロット超過
- ロット刻み違反
これを防ぐためにSymbolInfoを使用します。
実装例
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double lot = 0.05;
lot = MathMax(lot, minLot);
lot = MathMin(lot, maxLot);
さらに正確にする場合は lotStepで丸め処理を行います。
lot = MathFloor(lot / lotStep) * lotStep;
これにより、ブローカー条件に完全適合したロットになります。
4.3 取引可能状態チェック
すべてのシンボルが常に取引可能とは限りません。
例えば
- 市場閉鎖
- CFD停止
- ブローカー制限
などがあります。
実装例
long tradeMode = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE);
if(tradeMode == SYMBOL_TRADE_MODE_DISABLED)
{
Print("このシンボルは取引できません");
return;
}
EAではこのチェックを入れておくことで、注文失敗を回避できます。
4.4 StopLoss / TakeProfit計算
価格計算ではPoint値が重要になります。
Point取得
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
SL設定例
double sl = Ask - 200 * point;
double tp = Ask + 400 * point;
この例では
- SL = 200 point
- TP = 400 point
です。
4.5 実践EAコード例(基本テンプレート)
SymbolInfoを使った安全なトレード処理のテンプレートです。
void CheckTradeCondition()
{
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
if(spread > 30)
{
Print("スプレッドが広い");
return;
}
double lot = 0.05;
lot = MathMax(lot, minLot);
lot = MathMin(lot, maxLot);
Print("取引可能条件クリア");
}
このような関数を作ると、EA設計が整理されます。
よくある失敗
SymbolInfoを実装するとき、初心者がよく遭遇する問題があります。
① Ask / Bidを直接計算してしまう
例
double sl = Ask - 0.002;
これは 通貨ペアによって破綻する可能性があります。
正しくは
pointを使う
② ロット刻みを無視する
例えば
0.013 lot
は多くのブローカーで 注文エラーになります。
③ スプレッドチェックを入れない
特に次のタイミングでスプレッドは急拡大します。
- 指標発表
- 市場オープン
- 流動性低下
そのため、EAには必ずスプレッドフィルターを入れるのが一般的です。
5. SymbolInfoとMarketInfoの違い(MT4との比較)
MQL5の SymbolInfo を理解するうえで、多くの人が最初に混乱するのが MT4のMarketInfoとの違い です。
特に、MT4からMT5へ移行した人は
MarketInfo()が見当たらない- 何を使えばよいのかわからない
- 以前のコードがそのまま動かない
という状態になりやすいです。
結論から言うと、MQL5ではMarketInfoではなく、SymbolInfo系関数を使うのが基本です。
つまり、MT4で MarketInfo() で取得していたシンボル情報は、MT5では SymbolInfoDouble() SymbolInfoInteger() SymbolInfoString() に分かれて取得します。
5.1 MT4のMarketInfoとは何か
MT4の MarketInfo() は、シンボル情報を1つの関数で取得する仕組みです。
例えば、スプレッド・Point値・Digits・最小ロットなどを、同じ関数で取得していました。
MT4の例
double spread = MarketInfo(Symbol(), MODE_SPREAD);
double point = MarketInfo(Symbol(), MODE_POINT);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
このように、MT4では
MarketInfo(シンボル, 取得項目)
という形で多くの情報を取得できます。
初心者にとってはシンプルですが、一方で次の弱点もありました。
- 戻り値の型が実質的に統一されていて分かりにくい
- 取得項目によって意味が違う
- 型の扱いを間違えやすい
つまり、便利だが厳密さに弱い設計でした。
5.2 MQL5ではSymbolInfoへ分割された
MQL5では、この設計が整理され、取得する値の型ごとに関数が分離されました。
具体的には次の3つです。
SymbolInfoDouble()
小数値を取得SymbolInfoInteger()
整数値を取得SymbolInfoString()
文字列を取得
この変更により、MQL5では「どの種類の値を取得するのか」が明確になります。
例えば、Point値は小数なので SymbolInfoDouble()、Digitsは整数なので SymbolInfoInteger() を使います。
MQL5の例
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
この設計の利点は次の通りです。
- 型が明確で読みやすい
- ミスを見つけやすい
- 保守しやすい
- EAの安全性が上がる
特にMQL5は、MT4よりも型の厳密さを重視する設計です。
そのため、MT4の感覚で雑に移植すると、コンパイルエラーやロジックミスが起きやすくなります。
5.3 MT4からMT5へ移行するときの書き換え例
MT4の MarketInfo() をMQL5へ移すときは、MODE_系の定数を SYMBOL_系へ読み替えるのが基本です。
代表的な対応例
| MT4 | MT5 |
|---|---|
MODE_SPREAD |
SYMBOL_SPREAD |
MODE_POINT |
SYMBOL_POINT |
MODE_DIGITS |
SYMBOL_DIGITS |
MODE_MINLOT |
SYMBOL_VOLUME_MIN |
MODE_MAXLOT |
SYMBOL_VOLUME_MAX |
MODE_LOTSTEP |
SYMBOL_VOLUME_STEP |
書き換え例1:スプレッド
MT4
double spread = MarketInfo(Symbol(), MODE_SPREAD);
MT5
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
書き換え例2:Point値
MT4
double point = MarketInfo(Symbol(), MODE_POINT);
MT5
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
書き換え例3:最小ロット
MT4
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
MT5
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
つまずきやすい点
MT4からMT5へ移行する際は、次の点で失敗しやすいです。
① すべてをSymbolInfoDoubleにしてしまう
MT4では MarketInfo() の戻り値感覚で扱っていたため、MT5でも何でも SymbolInfoDouble() を使いたくなります。
しかし実際には、スプレッドやDigitsのように 整数で取得すべき情報 があります。
例えば次は誤りです。
double digits = SymbolInfoDouble(_Symbol, SYMBOL_DIGITS);
正しくは
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
です。
② Symbol() と _Symbol を混同する
MQL5でも Symbol() は使えますが、現在のチャートシンボルを指すなら _Symbol のほうが簡潔です。
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
技術記事や実務コードでは、MQL5では _Symbol を使う書き方が一般的です。
③ MODE_定数をそのまま使おうとする
MT4のコードをそのまま貼ると、MQL5では
MODE_SPREADMODE_POINT
などがそのまま通らない、または意図通りに動かないことがあります。
MT5では SYMBOL_系の定数へ置き換えるのが基本です。
④ 移植時に型変換を忘れる
SymbolInfoInteger() の戻り値は long です。
そのため、int 変数へ入れるときは必要に応じてキャスト(型変換)を明示したほうが安全です。
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
このように書くと、コードの意図が明確になります。
実務上の考え方
MT4経験者ほど、「MarketInfoのほうが簡単だった」と感じやすいですが、
長期的にはMQL5のSymbolInfo設計のほうが再現性・保守性・安全性が高いです。
特にEAを複数ブローカーで動かす場合は、型が明確なほうがバグを減らしやすくなります。
そのため、MT5ではMarketInfo的な感覚を引きずるよりも、SymbolInfoを前提に考え直したほうが結果的に速いです。
6. SymbolInfo使用時の注意点
SymbolInfoは便利ですが、「書けば必ず正しい値が取れる」関数ではありません。
特に初心者がつまずきやすいのは、取得タイミング・シンボル状態・戻り値の扱いです。
EAやスクリプトで安定して使うには、次の3点を意識する必要があります。
- 値の取得に失敗する可能性がある
- シンボルが利用可能な状態とは限らない
- 価格系情報はタイミングによって未更新の場合がある
ここを軽視すると、0が返る・想定外の値になる・注文時にエラーになるといった問題が起きます。
6.1 取得失敗を前提にコードを書く
SymbolInfo系関数は、書き方によっては取得失敗を検出しにくいことがあります。
そのため、実務では「値を直接代入して終わり」ではなく、取得できたか確認する書き方を意識したほうが安全です。
例えば、次のような書き方です。
double point = 0.0;
if(!SymbolInfoDouble(_Symbol, SYMBOL_POINT, point))
{
Print("SYMBOL_POINTの取得に失敗しました");
return;
}
この形式では、関数が true を返せば取得成功、false なら失敗です。
初心者は次のように書くことが多いですが、
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
この方法だけだと、「0.0が正常値なのか、取得失敗なのか」を見分けにくい場面があります。
特にデバッグ時は、成否を判定できる形式のほうが原因を追いやすいです。
安全に書く基本形
- 価格・条件取得はできるだけ成否判定付きで書く
- 失敗時は
Print()でログを出す - 取得失敗のまま注文処理へ進まない
例
double minLot = 0.0;
if(!SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN, minLot))
{
Print("最小ロットの取得に失敗しました");
return;
}
6.2 シンボルが選択されていないと失敗することがある
SymbolInfoで指定するシンボルは、ターミナル側で利用可能な状態である必要があります。
特に、現在のチャート以外のシンボルを扱うときは注意が必要です。
例えば、マルチシンボルEAで EURUSD のチャート上から GBPUSD の情報を取ろうとする場合、
そのシンボルがマーケットウォッチで有効になっていないと、取得に失敗することがあります。
対策
事前に SymbolSelect() で有効化します。
string symbol = "GBPUSD";
if(!SymbolSelect(symbol, true))
{
Print("シンボルを選択できませんでした");
return;
}
そのうえで取得します。
double point = 0.0;
if(!SymbolInfoDouble(symbol, SYMBOL_POINT, point))
{
Print("Point値を取得できませんでした");
return;
}
よくある失敗
- 現在のチャート以外のシンボルをそのまま扱う
- バックテストでは動いたのに実運用で失敗する
- シンボル名のスペルやブローカー独自サフィックスを見落とす
例えば、ブローカーによっては
EURUSDEURUSD.aEURUSDm
のように名前が異なることがあります。
そのため、シンボル名は固定文字列で雑に決め打ちしないほうが安全です。
6.3 価格系情報は起動直後や未更新時に不安定なことがある
SymbolInfoで取得する値のうち、価格に近い情報はタイミングの影響を受けます。
たとえば、EA起動直後や通信直後では、まだ十分なデータが揃っていないことがあります。
特に注意したいのは次のようなケースです。
- OnInit() の直後に価格系情報を使う
- 週明け直後でまだ配信が安定していない
- 対象シンボルにTickがまだ来ていない
- テスターと実運用で取得タイミングが違う
このような場面では、OnInitでは準備だけ行い、実際の判定はOnTickで行う設計が安定しやすいです。
例
void OnTick()
{
int spread = 0;
if(!SymbolInfoInteger(_Symbol, SYMBOL_SPREAD, spread))
{
Print("スプレッド取得失敗");
return;
}
if(spread > 30)
{
return;
}
Print("取引条件を確認できました");
}
このように、実際にTickが来た後で取得するほうが、価格系データは安定しやすいです。
よくある失敗と注意点
① 0が返ったのをそのまま正常値だと思う
例えば minLot = 0 のまま計算を続けると、後段で異常なロット計算になります。
取得値が不自然なときは、まず取得失敗を疑うべきです。
② OnInitですべて確定させようとする
初期化時点では、環境によっては必要な情報がまだ安定していないことがあります。
特に価格系・スプレッド系は、OnTick側で最終確認したほうが無難です。
③ 別シンボルの情報取得で SymbolSelect を省略する
単一シンボルEAでは問題が表面化しにくいため、マルチシンボル化した瞬間に不具合になりやすいです。
これは実務で非常に多い失敗です。
④ 取得した値をログ確認せずに使う
開発初期は、最低限次のように一度ログで確認したほうが安全です。
Print("spread=", spread);
Print("minLot=", minLot);
Print("point=", point);
見た目では正しそうでも、pointとtick sizeの混同や想定外のスプレッド単位が見つかることがあります。
実務での基本方針
SymbolInfoは「取得できる前提」で使うのではなく、取得成否を確認しながら使うのが基本です。
特にEAでは、注文前に次をチェックするだけで事故がかなり減ります。
- シンボルが有効か
- 必要な値が取得できたか
- スプレッドが許容範囲か
- ロット条件が正常か
この1段を入れるだけで、ブローカー差・起動直後・実運用環境差への耐性が上がります。
7. SymbolInfoのトラブルシューティング
SymbolInfoは基本的には安定したAPIですが、実際のEA開発では 「値が0になる」「取得できない」「想定外の値が返る」 といった問題に遭遇することがあります。
多くの場合、原因は 環境・タイミング・シンボル状態 にあります。
このセクションでは、実務でよく起きるトラブルと対処方法を整理します。
7.1 値が0になる場合
SymbolInfoを使って取得した値が 0 になるケースがあります。
例
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
結果
minLot = 0
これは通常の取引条件ではありえない値なので、取得失敗の可能性があります。
主な原因
- シンボル情報がまだ取得できていない
- EA起動直後
- シンボルが未選択
- バックテスト環境
対策
取得成功を確認する書き方に変更します。
double minLot;
if(!SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN, minLot))
{
Print("SYMBOL_VOLUME_MIN取得失敗");
return;
}
7.2 スプレッドが異常値になる
次のような状況があります。
spread = 0
spread = 200
spread = 1000
原因は マーケット状況やタイミング によるものです。
よくあるケース
| 状況 | 内容 |
|---|---|
| 市場オープン直後 | スプレッド拡大 |
| 指標発表 | 流動性低下 |
| 週末 | 価格配信停止 |
| テスター | モデル依存 |
そのため、EAでは次のようなチェックを入れるのが一般的です。
int spread;
if(!SymbolInfoInteger(_Symbol, SYMBOL_SPREAD, spread))
return;
if(spread <= 0)
return;
if(spread > 50)
return;
7.3 マルチシンボルEAで取得できない
マルチシンボルEAでは、別の通貨ペアの情報取得で失敗することがあります。
例
double point = SymbolInfoDouble("GBPUSD", SYMBOL_POINT);
失敗原因
- シンボルがマーケットウォッチ未登録
対策
SymbolSelect("GBPUSD", true);
その後に取得します。
double point = SymbolInfoDouble("GBPUSD", SYMBOL_POINT);
7.4 ブローカーごとのシンボル名問題
ブローカーによって、シンボル名が異なる場合があります。
例
| ブローカー | シンボル |
|---|---|
| A | EURUSD |
| B | EURUSDm |
| C | EURUSD.pro |
この場合、コードに
"EURUSD"
を固定すると失敗します。
安全な方法
現在チャートのシンボルを使う
_Symbol
例
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
これにより、ブローカー依存問題を回避できます。
7.5 Tickが来ないと値が更新されない
MT5では、Tick更新を基準にデータが更新されます。
そのため、次のような状態では値が更新されません。
- EA起動直後
- 市場停止
- 流動性が極端に低い
対策
価格系処理は OnTickで実行します。
void OnTick()
{
int spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
Print(spread);
}
よくある開発ミス
① 値チェックなしで注文する
例えば次のコード
double lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
もし取得失敗で
lot = 0
なら、注文時に
Invalid volume
エラーになります。
② スプレッド単位を誤解する
SYMBOL_SPREADは point単位です。
5桁ブローカー
10 point = 1 pip
になることがあります。
③ SymbolInfoDoubleとSymbolInfoIntegerの混同
次のコードはエラーになります。
double spread = SymbolInfoDouble(_Symbol, SYMBOL_SPREAD);
正しくは
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
トラブルを防ぐ基本テンプレート
EAでは次のような安全チェックを作ると安定します。
bool CheckSymbol()
{
int spread;
if(!SymbolInfoInteger(_Symbol, SYMBOL_SPREAD, spread))
return false;
if(spread <= 0)
return false;
if(spread > 50)
return false;
return true;
}
このような関数を トレード前に必ず呼ぶ設計にすると、
実運用でのトラブルをかなり減らせます。
8. FAQ(よくある質問)
Q1. MQL5のSymbolInfoとは何ですか?
SymbolInfo は、MetaTrader 5(MT5)で取引シンボルの情報を取得するための関数群です。
EAやインジケーターから、スプレッド・ロット条件・Tickサイズ・通貨情報などを取得できます。
主に次の関数が使われます。
SymbolInfoDouble()SymbolInfoInteger()SymbolInfoString()
取得する値の型によって使い分けるのが特徴です。
Q2. SymbolInfoとSymbolInfoDoubleの違いは何ですか?
SymbolInfoは総称であり、実際の関数は次の3種類に分かれます。
| 関数 | 用途 |
|---|---|
| SymbolInfoDouble | 小数値取得 |
| SymbolInfoInteger | 整数値取得 |
| SymbolInfoString | 文字列取得 |
例えば、スプレッドは整数なので
SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
を使用します。
Q3. SymbolInfoでスプレッドを取得する方法は?
スプレッドは SYMBOL_SPREAD を使って取得します。
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
注意点として、スプレッドは pipsではなくpoint単位で返されます。
例えば5桁ブローカーでは
10 point = 1 pip
になることがあります。
Q4. SymbolInfoが0を返すのはなぜですか?
次の原因が考えられます。
- EA起動直後で情報未取得
- シンボルがマーケットウォッチにない
- Tick未更新
- バックテスト環境
対策としては
SymbolSelect()を使う- OnTickで取得する
- 取得成功チェックを書く
などがあります。
Q5. MT4のMarketInfoはMQL5では使えますか?
基本的には使用しません。
MT4では
MarketInfo()
を使っていましたが、MQL5では SymbolInfo系関数に置き換わりました。
例
MT4
MarketInfo(Symbol(), MODE_SPREAD);
MT5
SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
Q6. SymbolInfoとPointの違いは何ですか?
Pointは 価格の最小単位を意味します。
MQL5では次のコードで取得できます。
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
例えば
| 通貨ペア | Point |
|---|---|
| EURUSD | 0.00001 |
| USDJPY | 0.001 |
EAのストップロス計算などで使用されます。
Q7. SymbolInfoはどのタイミングで取得すればよいですか?
基本的には OnTick() 内で取得するのが安全です。
理由
- Tick更新後の値を取得できる
- 起動直後の不安定状態を回避できる
例
void OnTick()
{
int spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
}
価格やスプレッドなどの情報は、Tick更新に依存することがあります。
Q8. SymbolInfoでロット情報を取得する方法は?
次のプロパティを使用します。
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
これらを確認することで、ブローカー条件に適合したロットサイズを計算できます。