はじめに
EAを作成していると、何気なくint型やstring型の変数を使っていると思います。
今回はその何気ない型選びのせいで、EAがうまく動かなくなりハマった問題について記載しています。
※初心者向けです
ハマった内容
まず、ハマった内容を率直にいうと「6>4」のような数値の比較がうまくいかないといった感じです。
//+------------------------------------------------------------------+
//| test.mq4 |
//| Copyright 2020, mef Software. |
//| https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link "https://fx-prog.com/"
#property version "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
int start()
{
//---
string strBuff;
int intBuff;
strBuff = "6";
intBuff = 4;
if(strBuff > intBuff){
Print("でかいよ" +strBuff+ ">" +intBuff);
}else{
Print("でかくないよ " +strBuff+ "<=" +intBuff);
}
return(0);
}
このコードを実行した結果が
ちゃんとなってるやん!何がハマったの?という感じです。
が「strBuff = “6”」を「strBuff = “10”」にしてみてください。
すると・・・、
あれ?10が4より大きくないってなっちゃいましたね・・・。いやいや4より10の方が大きいでしょう!ってなっちゃいますよね。
これが最初全然わからなくてハマりました。初心者にありがちなミスです。※私初心者です( ;∀;)
原因
うまく数値比較できない原因は簡単で、10をセットしている変数が「string型」だからです。
「6>4」がうまく比較できたのは何故?って思うかもしれませんが、これは確かうろ覚えですが「string型」だと文字の先頭部分で見てたと思うので「6>4」は成立しますが、「10>4」は「1>4」ってなっちゃうので「1(0)<4」となります。
試しに「39」「40」「50」で見てみるとこうなります。
「39」だけおかしいですよね。先頭の3で比較されているためです。
解決策
解決策は超簡単で、数値比較するときはちゃんとどちらも合わせて数値(intやdouble型)で比較してあげましょうという事です。
間違ってもサンプルのように「string型とint型」で比較することのないようにしましょう。
途中までは文字(String型)として扱っていたけど、比較する時だけは数値にしたいといったときは
上記のような感じで文字(String型)を数値(int型)に変換してあげましょう。
こんな感じに。
//+------------------------------------------------------------------+
//| test.mq4 |
//| Copyright 2020, mef Software. |
//| https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link "https://fx-prog.com/"
#property version "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
int start()
{
//---
string strBuff;
int intBuff;
strBuff = "10";
intBuff = 4;
//ちゃんと型を合わせよう
if(StringToInteger(strBuff) > intBuff){
Print("でかいよ" +StringToInteger(strBuff)+ ">" +intBuff);
}else{
Print("でかくないよ " +StringToInteger(strBuff)+ "<=" +intBuff);
}
return(0);
}
ちゃんと数値比較できましたね!
未然に型の違いの問題を防ぎたい場合
上記のような問題はそもそもコンパイル段階で防ぐことができます。それは「#property strict」!
このコードをソースコードの先頭につけてあげるだけでコンパイル時に注意してくれるようになります。
注意文「implicit conversion from ‘number’ to ‘string’」型の暗黙変換ですかね、こんな感じで注意してくれるようになります。
「#property strict」については以下の記事でも紹介しています。
さいごに
以上が、『【EA開発初心者向け】変数の型はしっかり合わせよう!』です。
サンプルプログラムのように簡単なコードの場合はまず文字と数値で比較なんてしないと思いますが、なが~いコードになってくるとやりがちです。サンプルのように変数の最初や最後にstrやint等を付けた名前付けをしていると回避できる事も多いので変数の名前はしっかりつけましょう!
もしかしたら、あなたが動かしているEAでもうまく動いているようで実は比較がおかしくなっているところもあるかも?
そもそもこんな問題ハマりたくないって場合は、「#property strict」付けてコンパイル時にちゃんと注意メッセージ解消してね!
補足
今回自分のEAのソースコードの作りをがさっと修正したのですが、多分テスト段階で表面化しない事もありそうなこの問題ですが、バックテスト結果が少し違ったので難なく気づく事ができました。バックテストは偉大ですね!
全くの同時期(15年間ぐらい)で修正前のバックテスト結果と修正後のバックテスト結果を比較して完全一致している事を確認したら大体テストは網羅できる気がします。
こんな問題を客先で出そうもんなら、全ソースの型を見直しとかトンでも問題に発展しかねない・・・。
※ EAのサンプルソースを一覧表にまとめました
※オンラインレッスンやってます
コメント