2019年1月4日金曜日

[MQL4] 他通貨の Bid, Ask を取得する方法2種

他通貨のバー情報を取得するには [iHigh()](https://docs.mql4.com/series/ihigh) 等の関数が使えます。
通常はこれで十分なのですが、リアルタイムで Bid, Ask の情報を取得したいことも時としてあります。

その場合、以下のようにして取得することが可能です。



### SymbolInfoDouble() を使う方法
[SymbolInfoDouble()](https://docs.mql4.com/marketinformation/symbolinfodouble) を使うと以下のように他通貨の Bid, Ask を取得することが可能です。

```mq4
string symbol = "EURUSD";
double eurusd_bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double eurusd_ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
```

実運用時には、何らかのエラーで値を取得できなかった場合にメールを送るなどの処理をしておくべきでしょう。
エラーハンドリングは以下のようにします。

```mq4
string symbol = "EURUSD";
double eurusd_bid;
if (!SymbolInfoDouble(symbol, SYMBOL_BID, eurusd_bid)) {
    int error = GetLastError();
    // TODO Error handling
}
double eurusd_ask;
if (!SymbolInfoDouble(symbol, SYMBOL_ASK, eurusd_ask)) {
    int error = GetLastError();
    // TODO Error handling
}
```

エラーとして取得できるのは以下のようです。
- 4106 — 通貨が「気配値表示」 ウィンドウに表示されていない
- 4051 — symbol 名が間違っている
- 4024 — 内部エラー

> 参考
> - [SymbolInfoDouble - Market Info - MQL4 Reference](https://docs.mql4.com/marketinformation/symbolinfodouble)
> - [Symbol Properties - Environment State - Constants, Enumerations and Structures - MQL4 Reference](https://docs.mql4.com/constants/environment_state/marketinfoconstants#enum_symbol_info_double)


###  SymbolInfoTick() を使用する方法
[SymbolInfoTick()](https://docs.mql4.com/marketinformation/symbolinfotick) でも他通貨の Bid, Ask を取得する事が出来ます。

```mq4
string symbol = "EURUSD";
MqlTick tick;
if (!SymbolInfoTick(symbol, tick)) {
    int error = GetLastError();
    // TODO Error handling
} else {
   // Print(tick.bid, tick.ask);
}
```

こちらはリファレンスにエラー番号一覧が無いのですが、`SymbolInfoDouble()` とほぼ同じ値が返ってくるようです。

> 参考
>
> [SymbolInfoTick - Market Info - MQL4 Reference](https://docs.mql4.com/marketinformation/symbolinfotick)

### 注意点
上記の関数に限らず、`SymbolInfoxxx()` という関数は、以下のような制約があるので注意が必要です`iHigh()` 等はこの限りではない。

#### 「気配値表示」 ウィンドウに表示していない通貨の情報はとれない
上記のエラー `4106` を見ると明らかなのですが、「気配値表示」ウィンドウに通貨を表示していない場合、値を取得することができません。

#### ストラテジーテスター内では情報はとれない ストラテジーテスター内ではこれらの関数は 0 を返します。厄介なのは、エラーにならず、成功しているのに 0 を返すという点です。 なので、うっかりこれらの関数をストラテジーテスター内で使用してしまうと想定外の動作をしてしまう可能性が高いので注意が必要です。 バックテストで使用できない関数は扱いが非常に難しいです。 私は、結局これらの関数を実運用で使うことは諦めました。