2018年12月18日火曜日

MetaTrader 4 は勝手に再起動してアップデートすることがある

本日、MetaTrader 4 を起動したら突然終了してしまいました。その後、数秒待つと自動で再起動し、以後問題なく動作しています。

実被害は無かったのですが、何が起こったのかログを確認してみたところ、アップデートが走ったようです。

2018年12月5日水曜日

MT4 Android 版の赤と緑の帯が表すもの

Android 版 MetaTrader 4 を使用していると、時々オーダーの左端に赤や緑の帯が表示されます。

気になって調べてみたのですが私は基本的に EA で売買して、確認のためだけに Android 版を使用しているので、これまであまり気にしてこなかったのです…、MetaTrader 5 のヘルプしか見つけられませんでした。 ただ、動作を確認してみたところ、MetaTrader 4 も 5 と同じように動作するようです。
2018年11月11日日曜日

[MQL4] ストラテジー毎にスレッドは別

[OnTick() と OnTimer() が同一スレッドで動いている](https://strategyofc.blogspot.com/2018/11/mql4-ontick-ontimer.html) ことは
確認したのですが、ストラテジーが異なる場合はどうなのか調べてみました。

結論から言うと、各ストラテジーは別スレッドで動いているようです当たり前というか、そうじゃないと使い物にならない気がするけど。

1つのストラテジーが `OnTick()` 内で重たい処理をしていても、他のストラテジーの `OnTick()` は呼ばれます。

とはいえ、プロセスは1つなので完全に無関係というわけにはいかないでしょう。
同時実行のストラテジーはどれくらいまで増やせるのだろうか?

2018年11月10日土曜日

[MQL4] OnTick() と OnTimer() は同一スレッドで動いている

@MetaTrader 4.00 Build 1090

Expert Adviser の `OnTick()` で何か重たい処理をしているとき本来は、なるべく重い処理はしない方が良いけれど、`OnTimer()` はどのように処理されるのか、調べてみました。

結論から言うと、以下のような動作をするようです。
(同一スレッド上で動いているか、少なくとも排他されている。)

- `OnTick()` の処理中に `OnTimer()` のタイミングが来た場合、`OnTick()` 終了直後に`OnTimer()`が実行される(`OnTimer()` はペンディングされる)
- ただし、2回以上ペンディングされたとしても、`OnTick()` 終了直後に実行される `OnTimer()` は1回のみ
- ペンディングされたとしても、`OnTimer()` が呼ばれるタイミングには影響しない(`EventSetTimer()` が呼ばれた時点から指定間隔で呼ばれ続けるただし、多少の誤差はある)

この動作、逆の場合も当てはまるようです。
つまり、`OnTimer()` で重たい処理をしていると、その間に呼ばれるはずだった `OnTick()` が無視されることになります最後の一回を除いて。

また、`OnTick()` で重たい処理をしていても、同じように `OnTick()` が無視されます。

`OnTick()` や `OnTimer()` ではなるべく重たい処理をしないようにすべきですね。
かつ `OnTimer()` の呼び出し頻度は少なめに。

2018年11月6日火曜日

[MT4] PeriodConverter はオフラインチャートで上位時間足を再生成するためのものではない

[[MT4] PeriodConverter を使うとヒストリーデータが消えることがある](https://strategyofc.blogspot.com/2018/11/mt4-periodconverter.html) を書いている時に
以下の投稿を見つけました。

[案外知られていない、MT4添付スクリプト「PeriodConverter」のバグ(正しくは制約)| nekonoteのFXで自動売買](http://nya0nekonote.blog.fc2.com/blog-entry-307.html)

オフラインチャートに「PeriodConverter」を適用するのは本来の使い方ではないらしい。

> 「PeriodConverter」の本来の目的は、オンラインのチャートに常駐させて、パラメータで指定した倍率の上位時間足をリアルタイムで生成していくものです。
> ですので、オフラインチャートの5分足~月足を生成して終わり、という使い方は、スクリプトの本来の目的から外れています。

知らなかった。
確かに「生成が終わってもスクリプトが終了せず常駐している」とは思っていたけど、そういう意味があったとは。

そのため、以下のような問題があるとのこと。

- 最新時間足が生成されない
- 週足・月足のオープン時間が異なる

最新時間足が生成されない問題は、リアルタイム用ということで理解できますが、週足・月足の問題はなぜでしょう?
今度調べてみたいと思いますと TODO に積んでおいて放置されるパターン…?

[MT4] PeriodConverter を使うとヒストリーデータが消えることがある

MetaTrader には `PeriodConverter` というスクリプトが標準で付属しています。
この `PeriodConverter` は M1 のデータ等から他の時間足のデータを再生成する際に使用します。

便利に使っていたのですが、ある日、再生成したヒストリーデータが直近数時間分になってしまう現象がおこりました。
M1 のデータは 1971年からMetaQuotes 提供のもの。1900年代のデータは飛び飛びであまり使いものにならない。あるのにも関わらずです。

先に原因を書いておくと、「チャートの最大バー数」が小さい場合、このような現象が起こります。

ツール → オプション → チャート
2018年11月5日月曜日

[MQL4] Library に strict を付けてはいけない

@ MetaTrader 4.00 Build 1090 (on Windows 10 Pro Ver. 1803)

MetaTrader でライブラリを作成する際、`#property strict` を書いてしまうと、実行時に以下のエラーが出てしまいますコンパイルは通る。

> libsumtest USDJPY,H1: unresolved import function call

`#property strict` を消すと正しく動作します。 なお、ライブラリの修正後はライブラリをコンパイルし直すのをお忘れなく。 > 参考 > > [Problem with #import library (Win XP, build 646) - Trading Strategies That Work - MQL4 and MetaTrader 4 - MQL4 programming forum](https://www.mql5.com/en/forum/152047)
2018年10月18日木曜日

[MQL4] GetLastError() で取得したエラーコードをエラーメッセージに変換する方法

MQL4 の関数の中には、失敗した場合、[GetLastError()](https://docs.mql4.com/check/getlasterror) でエラーコードを取得できるものがあります。

しかし、このエラーコードは [Trade Server Return Codes](https://docs.mql4.com/constants/errorswarnings/enum_trade_return_codes) に載ってないものが多く、そのままでは役に立ちません。

そのため、`ErrorDescription()` という標準関数が用意されています公式のサンプルの中でもよく使われています
2018/10/19 追記
「載ってないものが多く」と書いたのですが、[Runtime Errors](https://docs.mql4.com/constants/errorswarnings/errorcodes) の方には 4000番台のエラーも載っていましたどこかで見た気はしていた。 [Trade Server Return Codes](https://docs.mql4.com/constants/errorswarnings/enum_trade_return_codes) は [Runtime Errors](https://docs.mql4.com/constants/errorswarnings/errorcodes) から若い番号のものを抜粋した表のようです。
[OrderModify()](https://docs.mql4.com/trading/ordermodify) 等は 4000番台のエラーも返すのに、リンクされているドキュメントが不十分というのは不親切だなぁ。
### `ErrorDescription()` の使用方法 まず `stdlib.mqh` を include します。 ```mq4 #include <stdlib.mqh> ``` あとは以下のように `GetLastError()` で取得したエラーコードを与えると、対応したエラーメッセージが返されます。 ```mq4 if (!OrderModify(ticket, price, stoploss, takeprofit, expiration)) { int error = GetLastError(); printf("OrderModify error \"%s\"(%d)", ErrorDescription(error), error); } // 結果 // OrderModify error "invalid ticket"(4108) ``` なお、`GetLastError()` は2度呼ぶと値が変わってしまうので、上記のように変数で一度受けて使用しましょう。 > 参考 > > [[MQL4] GetLastError() は2度呼んではいけない](https://strategyofc.blogspot.com/2018/10/mql4-getlasterror-2.html)

[MQL4] GetLastError() は2度呼んではいけない

MQL4 では直前の関数が失敗した場合、[GetLastError()](https://docs.mql4.com/check/getlasterror) を使ってエラーコードを取得することが出来ます。

しかし、この関数を連続して呼び出すと値が変わってしまうので要注意です。


### 2度目は値が0
具体的には以下のように、2度目の呼び出しでは値が 0 になってしまいますなお、4108 は "Invalid Ticket"。

```mq4
if (!OrderModify(ticket, price, stoploss, takeprofit, expiration)) {
    printf("GetLastError1 %d", GetLastError());
    printf("GetLastError2 %d", GetLastError());
}

// 結果
// GetLastError1 4108
// GetLastError2 0
```

こんなあからさまに2度呼ぶことは無いと思うのですが、後述の `ErrorDescription()` を使う場合など、うっかり書いてしまうことはありそうです。


### GetLastError() は必ず変数で受けてから使う
対策としては、エラー発生直後に必ず変数で受けるよう習慣づけるのが一番かと思います。

```mq4
if (!OrderModify(ticket, price, stoploss, takeprofit, expiration)) {
    int error = GetLastError();
    printf("GetLastError1 %d", error);
    printf("GetLastError2 %d", error);
}    

// 結果
// GetLastError1 4108
// GetLastError2 4108
```


### エラーコードをエラーメッセージに変換する方法
このエラーコード、[Trade Server Return Codes](https://docs.mql4.com/constants/errorswarnings/enum_trade_return_codes) に一覧があると思いきや、この表には一部のコードしか載っていません4108 も載っていない。

これではエラーの原因がわからないので、これを文字列に変換する標準ライブラリが用意されています。

> 参考
>
> [[MQL4] GetLastError() で取得したエラーコードをエラーメッセージに変換する方法](https://strategyofc.blogspot.com/2018/10/mql4-getlasterror.html)

2018/10/19 追記
「一部のコードしか載っていません」と書いたのですが、[Runtime Errors](https://docs.mql4.com/constants/errorswarnings/errorcodes) の方には 4000番台のエラーも載っていましたどこかで見た気はしていた。 [Trade Server Return Codes](https://docs.mql4.com/constants/errorswarnings/enum_trade_return_codes) は [Runtime Errors](https://docs.mql4.com/constants/errorswarnings/errorcodes) から若い番号のものを抜粋した表のようです。
[OrderModify()](https://docs.mql4.com/trading/ordermodify) 等は 4000番台のエラーも返すのに、リンクされているドキュメントが不十分というのは不親切だなぁ。
2018年10月16日火曜日

[MT4] 「チャートの最大バー数」は何を意味するのか

@MetaTrader 4.00 Build 1090

MetaTrader 4 の設定には「チャートの最大バー数」という項目があります。

この設定値が何を意味するのか調べてみました。 と言っても、正式なドキュメントを見つけることができなかったので動作からの推察です。 なお、この値は** MT4 を再起動しないと反映されません**何度も再起動するのが地味に面倒くさい
2018年10月15日月曜日

[MQL4] CArrayObj と CList の違い

`include/Arrays` 以下にはオブジェクトを格納できる [CArrayObj](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayobj) と [CList](https://www.mql5.com/en/docs/standardlibrary/datastructures/clist) が定義されています。
どちらも大体同じような機能を提供しているのですが、何が違うのか見てみました。

結論から言うと、`CArrayObj` の方は内部で配列を持っているのに対し、`CList` は [CObject](https://www.mql5.com/en/docs/standardlibrary/cobject) の持つリンクリスト機能を使っています。

### CArrayObj
`CArrayObj` は一般的な配列同様に使用できます。
ランダムアクセスする場合などはこちらを使うと良いでしょう。

> 参考
>
> [MQL4 で可変長配列を使用する方法 | Strategy of C](https://strategyofc.blogspot.com/2018/10/mql4.html)

### CList
`CList` は内部にポジションを持っており、`GetNextNode()` のようにイテレーティブな処理をする場合、高速に処理できます。

全要素に対して一気に処理をかけるような処理に向いています。

以下に簡単な例を挙げます。

```mq4
#property strict
 
#include <Object.mqh>
#include <Arrays/List.mqh>
 
class Item : public CObject {
private:
    const int m_value;
 
public:
    Item(int value) : m_value(value) {
    }
 
    virtual ~Item() {
    }
 
    int GetValue() const {
        return m_value;
    }
 
    virtual int Compare(const CObject *node, const int mode=0) const {
        int diff = this.GetValue() - dynamic_cast(node).GetValue();
        return (diff == 0) ? 0 : (diff > 0) ? 1 : -1;
    }
};
 
CList m_item_list;
 
void OnStart()
{
    for (int i = 0; i < 10; i++) {
        int value = (i % 2 == 0) ? i : i + 10;
        m_item_list.Add(new Item(value));
    }    
 
    // 内部ポインタを最初にもどす
    m_item_list.MoveToIndex(0);
    
    Item* item;
    // 「最後まで一気に処理する」みたいなのに向いている
    while ((item = m_item_list.GetNextNode()) != NULL) {
        printf("%d", item.GetValue());
    }
}
```

なお、`CList` も `CArrayObj` と同様、Sort 済みでないと検索が出来ません。
また、`Compare()` の実装によっては検索結果が想定外になることもあるので気をつけてください。

> 参考
>
> [[MQL4] CArrayObj はソート済みじゃないと Search() の結果が -1 になってしまう](https://strategyofc.blogspot.com/2018/10/mql4-carrayobj-search-1.html)
2018年10月14日日曜日

[MQL4] CArrayObj::Insert() に最大値以上の index を指定すると Add と同じ動作になる

[CArrayObj](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayobj) の `Insert()` で `Total` 以上の値を指定したらどのようになるかやってみました。

結果は、「どんなに大きな値を指定しても最後に挿入される」でした。
エラーが返ってこない仕様なのでそして、ソースコードも読めるので、そうだろうとは思ってたけど、念の為。

```mq4
    // index 0〜9 の要素を追加
    for (int i = 0; i < 10; i++) {
        int value = (i % 2 == 0) ? i : i + 10;
        m_item_array.Add(new Item(value));
    }    
 
    Item* item = new Item(99);

    // index 99?に挿入
    // 実際は index 10 (最後)に挿入される
    m_item_array.Insert(item, 99);
```

`Item` 等の実装は以下のリンク先に掲載したものと同じです。

> 参考
> 
> [MQL4 で可変長配列を使用する方法 | Strategy of C](https://strategyofc.blogspot.com/2018/10/mql4.html)

2018年10月13日土曜日

[MQL4] CArrayObj::Search() が想定外のインデックスを返してくることがある

[MQL4 で可変長配列を使用する方法](https://strategyofc.blogspot.com/2018/10/mql4.html) に書いたのですが、`Sort()` 済みの [CArrayObj](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayobj) から `Search()` でインデックスを取得しても正しいインデックスを返さない場合があるので注意が必要です。

具体的な例を以下に挙げます。

2018年10月12日金曜日

[MQL4] CArrayObj はソート済みじゃないと Search() の結果が -1 になってしまう

[MQL4 で可変長配列を使用する方法](https://strategyofc.blogspot.com/2018/10/mql4.html) で既に書いたのですが、以下のように `CArrayObj::Search()` を呼んでも正しくインデックスが返ってこない時があります。

`Item` 等の定義は [MQL4 で可変長配列を使用する方法](https://strategyofc.blogspot.com/2018/10/mql4.html) を参照してください。

```mq4
    for (int i = 0; i < 10; i++) {
        int value = (i % 2 == 0) ? i : i + 10;
        m_item_array.Add(new Item(value));
    }    

    // 途中に挿入
    Item* item_100 = new Item(100);
    m_item_array.Insert(item_100, 5);
    
    // 今挿入したばかりのオブジェクトを検索する
    int index = m_item_array.Search(item_100);

    printf("index: %d", index);
    
    // 結果
    // index: -1
```

2018年10月11日木曜日

MQL4 で可変長配列を使用する方法

2019/4/12 追記
[CArray](https://www.mql5.com/en/docs/standardlibrary/datastructures/carray) 系クラスの中で使用されているメモリの動的確保について書きました。
[MQL4 で配列用メモリを動的確保する方法 | Strategy of C](https://strategyofc.blogspot.com/2019/04/mql4.html)
場合によっては、こちらを直接使った方が良いかもしれません。
@MetaTrader 4 (Version 4.00 Build 1090) MQL4 では C++ の [std::vector](http://www.cplusplus.com/reference/vector/vector/) のような動的配列が標準で使用できますBuild 600 で入った変更を受けて作成された模様。 `Include/Arrays/` 以下に定義されており、#include <Arrays/ArrayObj.mqh> のように include するだけで使用可能です。 今回はその中の [CArrayObj](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayobj) について簡単な使い方を書こうと思いますが、 [CArrayInt](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayint)、[CArrayChar](https://www.mql5.com/en/docs/standardlibrary/datastructures/carraychar) 等他の class も基本の思想は同じです。 公式のリファレンスを探したのですが、 MQL5 用のものしか見つけられませんでした。 ただ、確認した限り、MQL4 でも同様に使用できるようですMQL5 から逆移植されたものと思われる。 > 参考 > > [Standard Library / Data Collections - Reference on algorithmic/automated trading language for MetaTrader 5](https://www.mql5.com/en/docs/standardlibrary/datastructures) なお、完全に動作するソースコードは最後に載せておきます。
2018年8月9日木曜日

[MQL4] mqh ファイルはどこに置けばよいのか

MQL4 のヘッダファイル (.mqh) は `Include` ディレクトリに置くのが普通ですが、実は `Experts`, `Script`, `Libraries` 等に置くこともできます。

2018年8月8日水曜日

MT4 Android 版で Notification の音が変更できない

2019/4/11 追記
Android の設定画面から変更する方法を見つけました。
[MT4 Android 版で Notification の音を変更する方法](https://strategyofc.blogspot.com/2019/04/mt4-android-notification.html#more)
[MetaTrader の EA から Android, iOS に通知を送る](https://strategyofc.blogspot.com/2018/07/metatrader-ea-android-ios.html#more) で「通知音を変更しておくと便利」と書いたのですが、私の Android 端末では最新のアップデートで通知音が変更出来なくなってしまいました。 正確には以下のように設定変更は出来るのですが、それが反映されずデフォルトの通知音が鳴ってしまいます。
2018年7月28日土曜日

[MT4] MetaQuotes ID が勝手に変わった

ここ数日、MetaTrader から Android への通知が届かないと思っていたら、MetaQuotes ID が勝手に変わっていました。
2018年7月27日金曜日

MetaTrader の EA から Android, iOS に通知を送る方法

EA を使った自動売買派でも、MetaTrader のモバイルアプリは便利に使えます。

特に通知機能。
注文が通った時など、EA の中から任意のタイミングでモバイル端末に通知を送る事が出来ます。
EA からメールを送信することも出来ますが、通知の方が速く届くことが多いです特に Build 1129 以降はプッシュ通知になった模様。

設定の仕方は以下の通り。

2018年7月13日金曜日

[MQL4] リスク許容額からロット数を求める方法

FXで重要なのは資産管理。
1トレードで許容されるリスクは、総資産の N% 以内に収めるべし。という教えはよくききます。

これを実現するには、最大ストップロスが総資産の N% になるよう、1トレードのロット数を求めれば良いわけです。
Metatrader ではこれも自動化することが出来ます。

2018年7月12日木曜日

[MQL4] 値幅を基準通貨の金額に換算する方法

2019/4/13 追記
ここで紹介している `SYMBOL_TRADE_TICK_VALUE` は Strategy Tester の中では使用できないのでご注意ください。
[[MQL4] SYMBOL_TRADE_TICK_VALUE は過去の値がとれない | Strategy of C](https://strategyofc.blogspot.com/2019/03/mql4-symboltradetickvalue.html)
「ストップロスに引っかかったらどれくらいの損失になるのか」等、値幅を基準通貨の金額に換算したいケースがあります。 そういった場合、[SystemInfoDouble()](https://docs.mql4.com/marketinformation/symbolinfodouble) の `SYMBOL_TRADE_TICK_VALUE` を使うと、値幅を基準通貨の金額に換算することが出来ます。 なお、[SystemInfoDouble()](https://docs.mql4.com/marketinformation/symbolinfodouble) の代わりに [MarketInfo()](https://docs.mql4.com/marketinformation/marketinfo) を使っても同じ結果が出るとは思いますが、 環境によっては、どちらか一方しか動かない可能性もあるので、事前に確認してください。 > 参考 > > [[MQL4] MarketInfo は使わない方が良いらしい | Strategy of C](https://strategyofc.blogspot.com/2018/07/mql4-marketinfo.html) ### 1ロットあたりの金額を求める ある値幅を基準通貨の金額に換算するには、以下のようにします。 この時の金額は 1ロット分です。 ```mq4 // (high - low) = 値幅が与えられているとして (high > low) // 値幅が 何 ticks 相当か計算する double ticks = (high - low) / SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE); // SYMBOL_TRADE_TICK_VALUE は 1 tick 当たりの基準通貨の金額になるので、ticks とかけると金額が求まる double price_per_lot = ticks * SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE); ``` ### 実際の金額に変換する 上記の値は 1ロット当たりの金額なので、実際に取引するロット数をかければ基準通貨での金額になります。 例えば、以下は最小ロット国内の業者の場合、最小ロットは1ロットではなく、0.1 や 0.01 のところが多い。もはやロットは何だっけという話。で取引した場合の金額を求める方法です。 ```mq4 // 最小ロットでの金額を求める。 double price_per_min_lot = price_per_lot * MarketInfo(Symbol(), MODE_MINLOT); ``` なお、ロットに関する情報は [SystemInfoDouble()](https://docs.mql4.com/marketinformation/symbolinfodouble) で取れないようなので、[MarketInfo()](https://docs.mql4.com/marketinformation/marketinfo) を使用しています。 ### 基準通貨を含まない通貨ペアは不正確 この方法、便利なのですが、基準通貨を含まない通貨ペアの場合、正確な値は求められないので注意してください。 例えば、基準通貨が日本円で EUR/GBP の取引をする場合、値幅を円に変換するには GBP/JPY の値を(内部で)使用します。しかし、GBP/JPY も変化していますし、将来どのように動くかはわかりません。 つまり、あくまで現在の GBP/JPY を使った換算値しか求められないということになります。 ### 決済済みポジションの損益 余談ですが、決済済みポジションの損益は、[OrderProfit()](https://docs.mql4.com/trading/orderprofit) で求められます。
2018年7月11日水曜日

[MQL4] Metatrader の口座残高に関わる情報 6種

[Account Information - MQL4 Reference](https://docs.mql4.com/account) で得られる情報の中で、口座残高に関わるものをまとめました。
2018年7月10日火曜日

[MQL4] MarketInfo() は使わない方が良いらしい

こんな投稿をみつけた。

> [MarketInfo(Symbol(), MODE_POINT) failed to return valid value in MT4 - MetaTrader 4 - General - MQL5 programming forum](https://www.mql5.com/en/forum/4846)

大分昔のもので、かつ MQL5 の話だけど…

[MarketInfo()](https://docs.mql4.com/marketinformation/marketinfo) を使うのではなく [SymbolInfoDouble()](https://www.mql5.com/en/docs/marketinformation/symbolinfodouble) 等を使ったほうが良いらしい。

MQL5 から移ってきた機能は動作が不安定なものもあるので、一概に良いとは言えないですが、将来的な移行も見据えるのなら動作確認をしっかりした上で従っておくのが良いかもしれません。
2018年7月9日月曜日

[MQL4] Point と Tick の違い

[MarketInfo()](https://docs.mql4.com/marketinformation/marketinfo) で指定できるモードには `MODE_POINT` と `MODE_TICKSIZE` という項目があります。

何が違うのか気になりつつ、今まで放置してきたのですが、今回ちょっと時間が出来たので調べてみました。

結論としては…やはりよくわかりません。
私の環境では `MODE_POINT` と `MODE_TICKSIZE` は常に同じ値を返すので、検証しようにも出来ないのです。

ただ、ドキュメント等を読んで推測した結果、以下のような状況があり得るのではないかと思われます。

MODE_POINT0.001
MODE_TICKSIZE0.025
つまり、`MODE_POINT` は最小の桁を表すので必ず 10 の N乗になるNは整数。 それに対し、`MODE_TICKSIZE` は最小変動幅を表すので、様々な値を取りうる、ということですただし、最小桁は一致するはず。 しつこいですが、あくまで推測です。 誰か詳しい方がいたら教えてください。 なお、`MODE_TICKSIZE` が最後の変動幅を返すという記述を見かけたのですが、動作を確認してみたところ、少なくとも私の環境ではそのような動きはしませんでした。
2018/7/10 追記
[MarketInfo は使わない方が良いらしい](https://strategyofc.blogspot.com/2018/07/mql4-marketinfo.html) ので、[SymbolInfoDouble](https://www.mql5.com/en/docs/marketinformation/symbolinfodouble) の `SYMBOL_POINT` と `SYMBOL_TRADE_TICK_SIZE` でもやってみましたが、結果変わらず。
2018年7月7日土曜日

[MQL4] INDICATOR_CALCULATIONS を有効にするには IndicatorBuffers を使う

@MetaTrader 4 (Version 4.00 Build 1090)

MT4 のカスタムインジケーターでは計算用のバッファーを用意する機能があり、計算の途中結果等を保存しておくことが出来ます。
当然、それは非表示になる…はずなのですが、普通に作ると何故か表示されてしまうのです。

これを想定通りに動作させるには少し工夫が必要なので書いておきます。

2018年6月21日木曜日

[MQL4] 現在のタイムフレームを秒で取得する

[Period()](https://docs.mql4.com/check/period) は現在のチャートの時間軸を**分**で返すので、この値に60をかければ、秒に変換できます。

また、[PeriodSeconds()](https://docs.mql4.com/common/periodseconds) は入力タイムフレームの時間軸を**秒**で返します。

私は`PeriodSeconds()` の存在を知らずに、ずっと `Period()` を60倍していました。
どちらを使っても大した差はありませんが。
2018年6月17日日曜日

MT4 のヒストリカルデータを Python で読み込んでみた

MetaTrader のフォーラムに `.hst` ファイルフォーマットについて書かれていたので、Python で読み込むクラスを作ってみました。

> 参考
>
> [.hst file format . . . Old and New (Jan 2014) - Symbols - MQL4 and MetaTrader 4 - MQL4 programming forum](https://www.mql5.com/en/forum/149178)

2018年6月16日土曜日

[MT4] 指定日時のチャートを表示する方法

MT4 には Fast Navigation という機能があり、これを使うとチャートを指定した日時までジャンプさせることが出来ますチャートの時間指定ジャンプはこれしか方法が無いようなので、Fast Navigation という名前はいかがなものかと思う
2018年6月8日金曜日

[MQL4] マルチタイムフレーム対応インジケーターの作り方

[iBarShift()](https://docs.mql4.com/series/ibarshift) を使うと比較的簡単に作ることが出来ます。

2018年6月7日木曜日

[MQL4] カスタムインジケーターを最新値で更新する方法2種

2019/06/05 追記
コードを少し修正しました。 理由については以下にまとめてあります。 [カスタムインジケーターを更新する際、最新値だけでは足りない](https://strategyofc.blogspot.com/2019/06/mql4.html)
MQL のカスタムインジケーターは便利ですが、 作り方を間違えると不思議な動作をするので注意が必要です。
2018年6月6日水曜日

[MQL4] input parameters をドロップダウンリストにする方法

MQL で input を定義する際、型を [enum](https://docs.mql4.com/basis/types/integer/enumeration) にすることで input parameters をドロップダウンリストにすることができます。

2018年6月3日日曜日

[MQL4] input parameters にスペースを入れたりして見やすくする方法

`input` の終わりにコメントを書くとそちらが表示されます。

```mq4
#property strict
//--- input parameters
input int    MiddleMa;  // 中期トレンドを見るためのEMA期間 [本数]
input int    ShortMa;   // 仕掛けのためのEMA期間 [本数]
input double StopPoint; // 許容される最大ストップ [Point]
```

> 参考 > > [Input Variables - Variables - Language Basics - MQL4 Reference](https://docs.mql4.com/basis/variables/inputvariables) 特に単位などを明示するのに便利。 ### 注意点 使用に際して以下のような制約があるので気をつけましょう。 - 長さは63文字まで - strict モードじゃないといけない ### 日本語は使わない方が良い ところで、例として日本語を使っておいて何ですが、日本語は使わない方がよいと思います。 > 参考 > > [MQL4 内で日本語は使わない方が良い | Strategy of C](https://strategyofc.blogspot.com/2018/05/mql4.html)
2018年6月2日土曜日

[MQL4] metaeditor.exe を使ってコマンドラインで mq4 ファイルをコンパイルする方法

コマンドラインで mql4 ファイルをコンパイルしたい場合、`metaeditor.exe` のオプションが使えます。

> 参考
>
> [コンパイル - プログラム作成 - MetaTrader 5](https://www.metatrader5.com/ja/metaeditor/help/development/compile)

2018年5月13日日曜日

[MT4] ExpertsEnable は機能していない?

@ MetaTrader 4 Version 4.00 build 1090

[MetaTrader 4](https://www.metatrader4.com) には config ファイルを指定して起動する機能がありますこの機能を使うと、自動で Strategy Tester を走らせたりできる。

> 参考
>
> [Configuration at Startup - Tools - MetaTrader 4 Help](https://www.metatrader4.com/en/trading-platform/help/service/start_conf_file)

2018年5月12日土曜日

[MT4] 気配値表示ウィンドウにスプレッドを表示する方法

気配値表示ウィンドウ内で右クリック

スプレッドを選択
`!` がスプレッドになります
その他、「高値」・「安値」・「時間最後の tick 時間」の表示も出来ます。 このスプレッドの単位は point なので注意しましょう。 > 参考 > > [[MT4] pips とpoint の使い分け](https://strategyofc.blogspot.com/2018/05/mt4-pips-point.html)
2018年5月11日金曜日

[MT4] pips とpoint の使い分け

Metatrader の point(s) と pip(s) の使い分け方について私見ですが書いてみようと思います。

まずは簡単に違いから。

> 詳しい違いについては以下を参考にしてください
>
> [MT4のpoint(ポイント)とpips(ピップス)の違い | MT4ラボ|メタトレーダーの使い方/EA・インジケーター検証](http://mt4.click/chart_sosa/point_pips_chigai/)

2018年5月10日木曜日

[MQL4] SELECT_BY_POS のソート順は保証されていない

[OrdersHistoryTotal()](https://docs.mql4.com/trading/ordershistorytotal) のドキュメントに以下のような記述があります。

> Consecutive selection of orders using the SELECT_BY_POS parameter returns information in the sequence in which it was received from the trading server. Sorting of the resulting list of orders cannot be guaranteed.

最後にさらりと、「ソート順は保証されていません」と書いてあるではないですか。

つまり、直近の履歴だけを見たい場合でも、最低1回はループを回さないといけないわけですね。

そりゃ、「口座履歴」タブで取得期間を絞っておく必要があるわけだ。

> 参考
>
> [[MQL4] OrderHistoryTotal() は口座履歴タブで設定した期間しか取得できない](https://strategyofc.blogspot.com/2018/05/mql4-orderhistorytotal.html)

[MQL4] OrderHistoryTotal() は口座履歴タブで設定した期間しか取得できない

[OrdersHistoryTotal()](https://docs.mql4.com/trading/ordershistorytotal) のドキュメントに以下のような記述があります。

> The number of closed orders in the account history loaded into the terminal. The history list size depends on the current settings of the "Account history" tab of the terminal.

つまり、"Account history"(口座履歴)タブの設定によって取得できるリストの期間が異なるとのこと。

2018年5月9日水曜日

[MQL4] オーダー約定時刻からの足の本数を求める方法

### オーダー約定時刻からの時間を求める
オーダー約定時刻からの時間は [OrderOpenTime()](https://docs.mql4.com/trading/orderopentime) と [TimeCurrent()](https://docs.mql4.com/dateandtime/timecurrent) の差分で求められます。
なお、OrderOpenTime() を実行する前には [OrderSelect()](https://docs.mql4.com/trading/orderselect) で対象の Order を指定しておく必要があります。

```mq4
// OrderSelect() は実行済みとする
long diff = TimeCurrent() - OrderOpenTime();
printf("%lld", diff); // 約定時刻からの秒
```

この値は**秒**で求められます。

> 参考
>
> [[MQL4] datetime を long にキャストすると 1970/1/1 からの秒になる | Strategy of C](https://strategyofc.blogspot.com/2018/05/mql4-datetime-long-197011.html)

この時、土日に入っている場合は [TimeCurrent()](https://docs.mql4.com/dateandtime/timecurrent) が正確ではない可能性があるので注意が必要です。

> 参考
> 
> [[MQL4] TimeCurrent() は土日の間は更新されない | Strategy of C](https://strategyofc.blogspot.com/2018/05/mql4-timecurrent.html)

2018年5月8日火曜日

[MQL4] TimeCurrent() は土日の間は更新されない

[TimeCurrent()](https://docs.mql4.com/dateandtime/timecurrent) のドキュメントに以下のような記述があります。

> Returns the last known server time,

`last known` ということは、実際のサーバータイムとは異なっている可能性もあるということです。

2018年5月7日月曜日

[MQL4] string と datetime 型の相互変換方法5種

[string と datetime の加算演算は strict モードかどうかで動作が変わる](https://strategyofc.blogspot.com/2018/05/mql4-string-datetime-strict.html) に書いたように datetime の string への変換は明示的に行ったほうが良いと思います。

基本的には、MQL4 の固定フォーマット "yyyy.mm.dd hh:mi" を使うのが簡単ですが、独自のフォーマットで出力することも可能です後述するように、独自フォーマットの string を datetime に変換する際は注意が必要
2018年5月6日日曜日

[MQL4] string と datetime の加算演算は strict モードかどうかで動作が変わる

MQL4 のコンパイラは strict モードか否かで微妙に動作を変えます。

strict モードは、変数のスコープ等が厳格になっており、特別な理由が無い場合は使用すべきかと思います。
ただ、string と datetime の加算は混乱を招く仕様となっているので、注意が必要です。

> 参考
>
> [Updated MQL4 - MQL4 Reference](https://docs.mql4.com/mql4changes#compiler_difference)

2018年5月5日土曜日

MT4 で Mail: not enough space for "Subject" と表示されてしまう場合の原因と対策

### 原因 エラーの理由は単純で、64個の mail queue がいっぱいになったということです。 > 参考 > - [Mail: not enough space for "............. subject.........." - General - MQL5 programming forum](https://www.mql5.com/en/forum/46410) Queue というのは窓口の列みたいなものです。 (マ○ドナルドのレジが1つしかない状況を想像してください) MT4 のメール用 Queue は 64通しか保持することができないので、それ以上のメール送信リクエストがくると、このエラーが起こります。

[MQL4] printf は PrintFormat のエイリアスだった

MetaEditor がサジェストしてきた関数の中に [PrintFormat()](https://docs.mql4.com/common/printformat) というのがあって、リファレンスを読んでみたら、printf と同等との記述が。

printf のリファレンスがないことから、[PrintFormat()](https://docs.mql4.com/common/printformat) の方が本家で printf はエイリアスのようです。

知らなかった。
けど、今まで printf をずっと使ってきてしまったから、もう変えないけど。
2018年5月4日金曜日

[MQL4] datetime を long にキャストすると 1970/1/1 からの秒になる

2018/6/12 追記
負数の扱いと最大値について加筆・修正しました。
> 参考 > > [Datetime Type - Integer Types - Data Types - Language Basics - MQL4 Reference](https://docs.mql4.com/basis/types/integer/datetime) 公式ドキュメントによると、`datetime` は 1970/1/1 からの秒を格納する 8 bytes の型だそうです。 これは `long` と同じサイズで、相互変換が可能です。 どちらを使っていても動作上問題はないのですが、以下のような特徴があるので使い分けると良いでしょう。 - `datetime`
日付文字列との相互変換が容易。実際の日付を表す場合に使用。 - `long`
純粋な秒を表す場合に使用。
2018年5月3日木曜日

MQL 内で日本語は使わない方が良い

MQL4 のコンパイラ自体は UTF-8 や UTF-16 のマルチバイト文字を問題なく扱えているように見えます。

`printf` 内の文字列も出力できています。
コメントも日本語で大丈夫のようです。

```mq4
// コメントも OK
printf("テスト");
```

動作確認環境は - Windows 10 - Metatrader 4.00 build 1090 - Shift-JIS と UTF-16