コメントによってコード内エラーを判断する方法
はじめに
本稿では、MQL コード内のエラーを検索するシンプルなアルゴリズムを説明します。コード内でエラーが原因のコンパイル中の問題は、プログラムを書いた後におこることが多いものです。これらはすべてある種のエラーですが、とにかくエラーが起こっているコードブロックを迅速に認識することが必要です。
人は奇妙な括弧を探すことに時間と神経を費やすことが多いものです。しかしコメントの使用によりエラーの位置を迅速に特定する方法があります。それが本稿でみなさんにお伝えする方法なのです。
コンセプト
ミスを1つもおかさず大きなコードを書くことはひじょうに楽しいことです。ですが、残念ながら、かならずしもそうはならないものです。ミスのないプログラムはありえない、という冗談もあるほどです。ここではコードの実行を誤らせるミスについて考察しません。ここでの疑問はコンパイルをできなくするエラーに関するものです。
広範囲に広がっているエラーは、複雑な条件に奇妙な括弧を挿入する、括弧が欠けている、コロンやコンマが入っていない(変数宣言の部分に)、などです。たいてい、コンパイル中すぐにどのエントリにエラーがあるか知ることができます。ただ、そのようなミスをみつけるのはそれほご簡単でない場合もあります。コンパイラや目ざとい目でもすぐにそのようなミスを見つけることに役立ってはくれません。この場合、初心者プログラマー(ではない人)は概してエラーを視覚的に検出するためにコードをくまなく調べ始めるものです。神経が枯渇するまで何度も繰り返し、そして言うのです。「最初から書き直す方が簡単だ。」
ただ、MQL も他のプログラム言語同様、すばらしいツール-コメント、を提供します。それによってコードの一部を『削除する』、『無効にする』ことができるのです。通常、解説はコメント挿入、すなわちコードの未使用部分を無効にするために使用されます。間接はまたエラー検索にもうまく活用することが可能です。
エラー検索のアルゴリズム
エラー検索は通常、エラーができたコードの部分を判断することにつながり、そうするとエラーはそこで視覚的に検索されます。『目で』は 100~150 のエントリよりも 5~10 のコードエントリを調べるのがずっと簡単で速いことを疑う人はいないと思います。
コメントを使用すると、問題は簡単に解決されるようです。まず、コードの異なる箇所(ときとしてコード全体)にコメントを入れる必要があります。それによってその箇所を『無効化』します。その後、解説はコードのその箇所から削除されます。通常コメントを削除したら、コードのコンパイルを試みます。コンパイルが正常に行われれば、そのコード箇所にエラーはありません。そして、コードの次の箇所を開き、同様のことを行います。コードに問題個所がみつかったら、エラーは可視的に検索され修正されます。再びコンパイルを試みます。すべてがうまく通過したら、エラーが解消されたことになります。
新たなエラーが発生した場合は、それが解消されるまで同じ手順を繰り返します。この方法は、大きなプログラムを書く場合、非常に便利で、往々にして比較的小さいコードを書く場合に役立ちます。
コメントを入れるコードのブロックを正確に判断することがひじょうに重要です。それが条件であれば(または別の理論的構成)、完全にコメントを入れる必要があります。変数宣言ブロックにコメントを入れる場合、そういった変数に言及するブロックを開いたままにしないようにすることが重要です。つまり、解説はプログラムロジックによって使用されるのです。この方法を侵害することは、コンパイルで新しく誤ってできたエラーが出現することにつながります。
例
実用的なコード内エラーの検索を例示します。以下のようなコードがあるとします。
#property copyright "" #property link "" extern int Level1=6; extern int Level2=2; extern double Lots=0.1; extern int TP=7; extern int SL=5000; extern int Profit_stop=10; int start() { //+--------------------------------------------------------------------------------------------------+ //| search for opened orders by symbol int pos_sell=0; for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) { if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL) &&(OrderComment()=="sar_ao")) { pos_sell=1; break; } } int pos_buy=0; for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) { if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY) &&(OrderComment()=="sar_ao")) { pos_buy=1; break; } } //| search for opened orders by symbol | //+-------------------------------------------------------------------------------------------------+ //+-------------------------------------------------------------------------------------------------+ //| stop for break-even double stop_open; for (int ia=OrdersTotal()-1; ia>=0; ia--) { if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } } //| stop for break-even | //+-------------------------------------------------------------------------------------------------+ int i; bool trend_UP=true,trend_DOWN=true; //+------------------------------------------------------------------------------- if(!pos_buy) { for(i=Level1; i>=0; i--) { if(Open[i]<iSAR(NULL,0,0.02,0.1,i)) { trend_UP=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_UP=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_UP=false; break; } } } } else { trend_UP=false; } //*************************************************************************** if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; } if(Open[0]>iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("sell"); } if(Open[0]<iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("buy"); } double MA_1; MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0) { OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT); ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen); } if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) { OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red); ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT); ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("sell", OBJPROP_COLOR, Red); } //+------------------------------------------------------------------------------- //---- return(0); } //+------------------------------------------------------------------+
コンパイルで次のようなエラーメッセージを確認します。
エラーが作成されたブロックを迅速に検出することは不可能です。コメントに頼ります。理論的構成すべてにコメントします。
#property copyright "" #property link "" extern int Level1=6; extern int Level2=2; extern double Lots=0.1; extern int TP=7; extern int SL=5000; extern int Profit_stop=10; int start() { /* //+-----------------------------------------------------------------------------------------------+ //| search for opened orders by symbol | int pos_sell=0; for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) { if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL) &&(OrderComment()=="sar_ao")) { pos_sell=1; break; } } int pos_buy=0; for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) { if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY) &&(OrderComment()=="sar_ao")) { pos_buy=1; break; } } //| search for opened orders by symbol | //+----------------------------------------------------------------------------------------------+ */ /* //+----------------------------------------------------------------------------------------------+ //| stop for break-even | double stop_open; for (int ia=OrdersTotal()-1; ia>=0; ia--) { if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } } //| stop for break-even | //+---------------------------------------------------------------------------------------------+ */ /* int i; bool trend_UP=true,trend_DOWN=true; //+------------------------------------------------------------------------------- if(!pos_buy) { for(i=Level1; i>=0; i--) { if(Open[i]<iSAR(NULL,0,0.02,0.1,i)) { trend_UP=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_UP=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_UP=false; break; } } } } else { trend_UP=false; } */ //*************************************************************************** /* if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; } */ /* if(Open[0]>iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("sell"); } if(Open[0]<iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("buy"); } */ double MA_1; MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); /* if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0) { OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT); ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen); } */ /* if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) { OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red); ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT); ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("sell", OBJPROP_COLOR, Red); } */ //+------------------------------------------------------------------------------- //---- return(0); } //+------------------------------------------------------------------+
このコードは問題なくコンパイルできることが簡単にわかります。それは、エラーができたコードの一部が『非表示になっている』ことを意味します。コード /* ... */ の箇所を交代で開き、コンパイルしてみます。
次のブロックにくるまではコンパイルは問題なく行われます。
//*************************************************************************** if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; }
よってエラーはこの理論的構成にあるのです。このコード部分を細かく調べると、構成の中に奇妙な丸括弧があるのが判ります。
for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } }
それを削除すれば、コードは問題なくコンパイルされるでしょう。
残りのコメントを削除することで、このコードにはほかにエラーがないことが確認できます。それは、われわれが目標を達成したことを意味します。コード内エラーは十分迅速に見つかりました。
おわりに
エラー検索のこのアルゴリズムの使用方法を実例で示しました。この例には小さなコード(194 エントリ)は使われていません。よってその『調査』には時間がかかることでしょう。それ自体にコメントを入れる機能により、エラー検索の問題に出会うプログラマーのみなさんの時間が十分節約されるのです。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1547
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索