ちょっとしたミスを発見する手助けが必要です。 - ページ 2

 
どなたか手を貸してください.
 

問題の一つは、あなたのコードの書き方が、&& や || などの長い if 条件や、関数 呼び出しに次ぐ関数呼び出しで、デバッグを困難にしていることです。ドキュメントにあるコーディング例を見て、コードがどのようにもっと短い行でフォーマットされ、コメントされるべきかを確認する必要があります。

 

"デバッグが難しくなる"? :( こんなの聞いたことないんだけど、本当なの......。

コンパイラも私のコードのデバッグに苦労しています。

もしそれが理由なら、私はこの部分のコーディングのアイデアをすべて考え直さなければならなかったということになりますね?そうなると全く別のものになってしまう・・・・・・ :( :(

 

そうですね、デバッグは難しいです。例えば、トレーリングストップのコードを見てください。それぞれの行が何をしているのかがわかりやすいので、間違いを発見しやすいのです。

   int total=OrdersTotal();
   
   for(int cnt=0; cnt<total; cnt++)
   {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
    {if(OrderType()==OP_BUY)
     {if(TrailingStop>0)
      {if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {if(OrderStopLoss()<Bid-Point*TrailingStop)
        {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
         {Print("OrderModify error ",GetLastError());
          return;
   }}}}}}}
 
という条件を削除して、if文の中に入れてみたのですが・・・。しかし、それでも常に動作するわけではなく、ストップロスを一度だけ動かすこともあれば、買い注文と売り 注文の両方でうまく動作することもありました。
 
SDC: そうですね、デバッグは難しいです。例えばこのトレーリングストップのコードを見てください。各行が何をしているのかがわかりやすいので、間違いを 発見しやすいのです。
   int total=OrdersTotal();
   
   for(int cnt=0; cnt<total; cnt++)
   {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
    {if(OrderType()==OP_BUY)
     {if(TrailingStop>0)
      {if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {if(OrderStopLoss()<Bid-Point*TrailingStop)
        {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
         {Print("OrderModify error ",GetLastError());
          return;
   }}}}}}}
  1. 複数注文がある場合の決済・削除はカウントダウン しなければならない。他のチャートでEAを考えてみてください。習慣づけましょう。
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
        {if(OrderType()==OP_BUY)
         {if(TrailingStop>0)
          {if(Bid-OrderOpenPrice()>Point*TrailingStop)
           {if(OrderStopLoss()<Bid-Point*TrailingStop)
            {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
             {Print("OrderModify error ",GetLastError());
              return;
       }}}}}}}
    また、x++よりも++xの方が良い(特にクラスを扱う場合)。
  2. 言語はfor() 文、if() 文なので、一つの文を中括弧で囲むのはあまり意味がない。
    例えば
    しかし
    { i = 1 + 2; }
    { if(i == 3) { Print(i); } }
    i = 1 + 2;
    if(i == 3) Print(i);
    というわけで簡略化
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       if(OrderType()==OP_BUY)
       if(TrailingStop>0)
       if(Bid-OrderOpenPrice()>Point*TrailingStop)
       if(OrderStopLoss()<Bid-Point*TrailingStop)
       if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  3. 今、"&&" (と "||") は短絡的な演算子であるため、if を 連鎖させることはない
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && TrailingStop>0)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  4. 順序選択が失敗 したときに順序を変更するか?
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(O rderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && TrailingStop>0)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  5. 変更しないテストはすべてループから外す。
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
    }
  6. 同じことを 計算し続けないこと
       if(Bid-OrderOpenPrice()>Point*TrailingStop)
       if(OrderStopLoss()<Bid-Point*TrailingStop)
       if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,O...
    何をしたいのか、すべきなのかを見極める
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY){
          double SL = Bid - Point*TrailingStop;
          if(SL > OrderOpenPrice()    // Start trailing above open price
          && SL > OrderStopLoss()     // And it moves up ONLY
          && !OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,Green))
          {  Print("OrderModify error ",GetLastError());
             return;
          }
       }
    }
  7. 他のケースは どうする?他のチャートやEAでは どうでしょうか?
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)
       && OrderMagicNumber() == MyExternal
       && OrderSymbol()      == Symbol()  
       ){  
          if(OrderType()==OP_BUY)
          {
             double SL = Bid - Point*TrailingStop;
             if(SL > OrderOpenPrice()    // Start trailing above open price
             && SL > OrderStopLoss()     // And it moves up ONLY
             && !OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,Green))
             {  Print("OrderModify error ",GetLastError());
                return;
             }
          }  // OP_BUY
          else // OP_SELL (or pending)
          { ...                       
          }                           
       }  // OrderSelect
    }  // Trailing

 
WHRoeder:
  1. 複数の注文がある場合、クローズ/デリート時にカウントダウンを しなければならない(MUST)。他のチャートでEAを考えてみてください。また、x++よりも+xの方が良い(特にクラスを扱う場合)。
  2. 言語はfor() 文、if() 文なので、一つの文に中括弧をつけるのはあまり意味がない。
    とは書かないでしょう。

    だから簡略化する
  3. 今、"&&" (と "||") は短絡的な演算子なので、ifを 連鎖させない。
  4. 順序選択が失敗 したときに、順序を変更しますか?
  5. 変更しないテストはすべてループから外す。
  6. 同じことを 計算し続けないこと何をしたいのか、どちらをすべきかを把握する
  7. 他の 場合はどうなのか?他のチャートやEAは どうなのか?

このコードは読みやすいコードの例として掲載しただけで、単独で完成した機能の例として掲載したわけではありません。

MT4付属のMetaQuotes MACDサンプルEAのトレイリングストップコードの買い注文部分です。

1) そうではありません、上にも下にもカウントできます、ループはより効率的です、OrdersTotal()は一度呼ばれ、ローカル変数に代入されます。

 
SDC: そのコードを例として掲載しただけですo
私はちょうど被写体の拡大図を投稿しました。
 

SDCありがとうございました。WHRoederもヒントをありがとうございました。それは便利です.

私はOrderClosePrice()を前のコードのMarketInfoのものに交換し、編集してみました(&&条件を削除 し、次のようにif文としてそれらを置く、2番目のループのもの)、しかし結果はまだ時々動作しているときに動作しませんです。

プールの合計注文にカウントするためのループは、私はカウントダウンループを使用しますが、x - 。私はあなたが--xを提案する理由を理解していない。

このような場合、"short circuit operators "をググってみたのですが、mql4ではどういう意味なのかよくわかりませんので、少し説明していただけますか^_^?なぜ'if'を連鎖させるのは良くないのでしょうか?

ところで、SDCが提案した上記のコードは、私が使っているコードではありません >.< .

 

ifを連鎖させるのは悪いことではありません。上に掲載したコードはMQL4という言語の開発者が書いたものです。これは私が彼らのmacdサンプルEAから例として切り取ったコードです。

WHRは最近&& ||条件の評価方法が変更され、連鎖するif条件と同等に効率化されたことに言及しています。以前はあまり効率的ではありませんでした。どちらの方法も使うことができます。連鎖したifは、コードに分岐がある場合に便利なので、'else'を使用することができます。

長い行のif( && || ) 条件は、括弧の混乱を引き起こし、エラーを見つけるのがより困難になるため、私はこれを行うのが好きではありません。また、コーディングの基準として、80文字を超えてはいけないというものがあります。しかし、多くのコーダーはその標準を守ろうとしません。MQL4の開発者は、大きな長い名前の列挙型識別子を作り続け、同じように大きな長い名前の関数への 呼び出しに使っています。