どのデザインが正しいのでしょうか? - ページ 8

 
valenok2003:

どうもありがとうございます。エラー処理をしていると、価格が違うというメッセージが来て、何が悪いのかが分かりません。

という行を 追加してください。

int err = GetLastError();

関数の最初に - エラーバッファをクリアする:時には、「誰かの」エラーを読み取ることが可能で、この方法では、関数の開始時にエラーバッファがクリアされます。

これは必須ではありませんが、実世界のためのプログラムであれば、すべてをできるだけ正しく行うことが強く望まれます。

頑張ってください。

 
VladislavVG:

という行を追加してください。

関数の最初に - エラーバッファをクリアする:時には、「誰かの」エラーを読み取ることが可能で、この方法では、関数の開始時にエラーバッファがクリアされます。

これは必須ではありませんが、実世界のためのプログラムであれば、すべてをできるだけ正しく行うことが強く望まれます。

頑張ってください。


はい、ありがとうございます。実際のソフトウェアではそうしています。
 
良い人たち、未決済の注文がないのに、関数が0を返す理由を教えてください。何かエラーが出るようになっているのでしょうか?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
int Close_This_Symbol_All(string _Symbol_Name, string _Type_Order, int _Slippage, bool _Alert_ON)
{
  bool _Result;
  ERROR = 0;
//----
  if(OrdersTotal() == 0) return(-1);
  for (int _Cnt = OrdersTotal()-1; _Cnt >= 0; _Cnt--) 
  {
    if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) break;
    if(OrderSymbol() == _Symbol_Name)
    { 
      while (!IsTradeAllowed()) Sleep(1000);
      RefreshRates();
      if(OrderType() == OP_BUY   && _Type_Order == "BUY") 
      {
        _Result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_BID), _Slippage, CLR_NONE);
        ERROR = GetLastError();
      }
      if(OrderType() == OP_SELL && _Type_Order == "SELL") 
      {
        _Result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_ASK), _Slippage, CLR_NONE);
        ERROR = GetLastError();
      }
      if(_Result == true) PlaySound(Name_Sound_Close);
      else 
      {
        Error(Name_Expert," Close "+_Type_Order+": ",ERROR,_Alert_ON);
        break;
      }
    }  
  }
//----
  return(ERROR);
}
//+------------------------------------------------------------------+
 
もう一度、バラバラにしているのか?
 
valenok2003:
良い人たち、なぜこの関数は未決済注文がないにもかかわらず0を返すのか、教えてください。何らかのエラーがあってはいけないのでしょうか?
intオーダートータル( )

未決済 注文と保留注文の 合計金額を返します。

まだ注文を書く?

 

-- アンダースコアやダブルアンダーコアで始まる名前を使うのは悪いことです。むしろ、最後にアンダースコアを使いたい。


-- なぜ_Type_Orderという文字列なのか?非現実的なほど不格好だと思います。そうすると、引用されなければならない。だって、「売る」「売れる」って書いたら、うまくいかないじゃないですか。


-- 間違えたいなら、間違えればいい。

ERROR = -1;

もっといいのは

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) break;

なぜ壊れるのか?1ミリ秒前に、TPによって注文がクローズされたとします。なぜ、残りをクローズしてはいけないのでしょうか?この方がいい。

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;

--

while (!IsTradeAllowed()) Sleep(1000);

この線は役に立たないどころか、有害です。そういう意味だったのでしょうか?

while (IsTradeContextBusy()) Sleep(1000);


--

else 
      {
        Error(Name_Expert," Close "+_Type_Order+": ",ERROR,_Alert_ON);
        break;
      }

つまり、突然注文が成立しなくなったら、「ハンドルを離し、目を閉じて叫び始める」のである。

他を閉じる必要はないのでは?再挑戦の必要はない?


-- なぜここでエラーを返すのか?例えば、全てのクローズに成功した場合はtrueを、失敗した場合はfalseを返すようにする方がよっぽど適切でしょう。


以上、今回はこの辺で。

 
TheXpert:

-- アンダースコアやダブルアンダーコアで始まる名前を使うのは悪いことです。むしろ、最後にアンダースコアをつけてほしい。


関数内でアンダースコアで始まる名前を使うことで、変数のオーバーライドのリスクを排除しているのだ。このように、start()の中でアンダースコアを使わずに同じ名前を使うことができるので、コードの透明性が高まりますね。

- なぜ_Type_Orderは文字列なのですか?非現実的な不便さ、イミフ。それなら、与えるべきでしょう。なぜなら、「売る」と書いても「売れる」と書いても、何も動かないからです。

もちろん、その通りです。しかし、文字列を使うことでコードの透明性が増し、今の私のコード量では下線は必要ない。本当にこの問題に遭遇したら、やりますが、今のところ必要ありません。私は単に売りか買いを書くだけです。


なぜ壊れるのか?さて、ある注文が1ミリ秒前にTPによってクローズされたと仮定すると、なぜ他のすべての注文をクローズしてはいけないのでしょうか?この方がいい。

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;

確かにその通りですね、ありがとうございます。


このラインは役に立たないどころか、有害です。そういうことなんでしょうか?

IsTradeContextBusy()関数はスレッドの占有率のみを通知し、IsTradeAllowed()はやや広い範囲です


つまり、突然オーダーが閉じられなくなったら、「ハンドルを離し、目をつぶって叫びだす」のですか?


はい、デバッグ期間中はそうです。

なぜ、エラーリターンが全くないのでしょうか?すべて閉じることができればtrueを返し、そうでなければfalseを返す方がはるかに適切であろう。


ありがとうございます!エラーの原因がわかったような気がします。調べて報告します。
 

その誤りは次のようなものでした。

したがって、どの条件も満たされていないので、_Result 変数は変更されておらず、すでに false が格納されています。そして、その機能は、本当に発生しなかったエラー処理に 進みます。

私はその機能を修正し、ここに投稿しています。

//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
int Close_This_Symbol_All(string _Symbol_Name, string _Type_Order, int _Slippage, bool _Alert_ON)
{
int _Cnt_Close_Orders = 0;
//----
  if(OrdersTotal() == 0) return(_Cnt_Close_Orders);
  for (int _Cnt = OrdersTotal()-1; _Cnt >= 0; _Cnt--) 
  {
    if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;
    if(OrderSymbol() == _Symbol_Name)
    { 
      while (!IsTradeAllowed()) Sleep(1000);
      RefreshRates();
      if(OrderType() == OP_BUY   && _Type_Order == "BUY") 
      {
        if(OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_BID), _Slippage, CLR_NONE))
        {
          _Cnt_Close_Orders++;
          PlaySound(Name_Sound_Close);        
        } 
        else 
        {
          Error(Name_Expert," Close "+_Type_Order+": ",GetLastError(),_Alert_ON);
          continue;
        }
      }
      if(OrderType() == OP_SELL && _Type_Order == "SELL") 
      {
        if(OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_ASK), _Slippage, CLR_NONE))
        {
          _Cnt_Close_Orders++;
          PlaySound(Name_Sound_Close);        
        } 
        else 
        {
          Error(Name_Expert," Close "+_Type_Order+": ",GetLastError(),_Alert_ON);
          continue;
        }
      }
    }  
  }
//----
  return(_Cnt_Close_Orders);
}
//+------------------------------------------------------------------+

モデレーターへの 追記私は偶然にもこのようなブランチを作成しました。これは、注文を正しく閉じる方法についての完全なセルフチュートリアルです。もしかしたら、「注文を正しく閉じる方法(例)」と改名すべきかもしれません。

PPS 参加された皆さん、どうも ありがとうございました。おそらく、もっと多くの質問が出るでしょう。

 
valenok2003:

その誤りは次のようなものだった。

したがって、どの条件も満たされていないので、_Result 変数は変更されておらず、すでに false が格納されています。そして、その機能は、本当に発生しなかったエラー処理に進みます。

私はその機能を修正し、ここに投稿しています。

モデレーターへの 追記私は偶然にもこのようなブランチを作成しました。これは、注文を正しく閉じる方法についての完全なセルフチュートリアルです。もしかしたら、「注文を正しく閉じる方法(例)」と改名すべきかもしれません。

PPS 参加された皆さん、どうも ありがとうございました。おそらく、もっと多くの質問が出るでしょう。


CodeBaseを見たり、フォーラムをよく読むと、正しい順序で閉じる例が100以上ありますが、だからといって、すべてのブランチの名前を一度に変更する必要はないでしょう。ヒーローは十分いる。
 
valenok2003:

その誤りは次のようなものでした。

bool _Result変数は初期化されていないので、falseが入ります。したがって、どの条件も満たされていないので、_Result変数を変更しておらず、すでにfalseが入っています。そして、その機能は、本当に発生しなかったエラー処理に進みます。

私はその機能を修正し、ここに投稿しています。

モデレーターへの 追記私は偶然にもこのようなブランチを作成しました。これは、注文を正しく閉じる方法についての完全なセルフチュートリアルです。もしかしたら、「注文を正しく閉じる方法(例)」と改名すべきかもしれません。

PPS 参加された皆さん、どうも ありがとうございました。おそらく、もっと多くの質問が出るでしょう。

IMHO:この機能は、ロジックが明確ではありません。テスター向けなら余計なお世話、実戦向けならエラー処理すべき。戻り値は、あなたが外部レベル(呼び出しレベルで)呼び出しがエラーで終了したことを伝えているので、あなたはエラー自体を失っている、まあ、専門家は、ログに書いた - それはどのようにカウントされるのでしょうか?

もっといいこと:(またまたIMHO)

1.エラー番号を読み取り、保存する。

2.エラーを修正可能なものとそうでないものに分ける。そのためには、ハンドラを作成する必要がある。注文が終了する可能性のあるエラー(スレッドがビジー状態、接続障害...など)は、その場ですぐに処理されるべきである。私はそのようにしました(最初に回復不可能なエラー、次に「修正」可能なエラー)。

#define MAXCYKLESCNT 20

int ErrReaction(int err)
{
    switch(err)
    {
        case ERR_TRADE_NOT_ALLOWED    :
                 Print("TRADE NOT ALLOWED ! SWITCH ON option \' Allow live trading\' (Необходимо включить опцию \'Разрешить советнику торговать\')");
        case ERR_INVALID_FUNCTION_PARAMSCNT :    
        case ERR_INVALID_FUNCTION_PARAMVALUE :    
        case ERR_INVALID_STOPS        : 
        case ERR_INVALID_TRADE_VOLUME : 
        case ERR_MARKET_CLOSED        : 
        case ERR_TRADE_DISABLED       : 
        case ERR_NOT_ENOUGH_MONEY     : 
                 return(-err);
        case ERR_NO_CONNECTION        :
                 ReScanServers();
        case ERR_BROKER_BUSY          : 
        case ERR_TRADE_CONTEXT_BUSY   : 
        case ERR_ORDER_LOCKED         :
                 int n=0;
                 while((!IsTradeAllowed())&&(n<20)){ Sleep(500);n++;}
        case ERR_PRICE_CHANGED : 
        case ERR_OFF_QUOTES    : 
        case ERR_REQUOTE       : 
                 RefreshRates();
                 break;
        default: break;
    }//switch(err)
    return(0);
}//int ErrReaction(int err)

3.難解なエラーが発生した場合、エラーフラグではなく、その番号を返すようにし、この状況を外部モジュールで処理できるようにする。演算 結果を解析する場合 :

bool res    = false;
int  ncykls =     0;

    while((!res)&&(ncykls<MAXCYKLESCNT))
    {
        res = ...............
        if(!res)
        { 
            ncykls++;
            err=GetLastError();
            Print(ncykls," Err(",err,") : ",ErrorDescription(err)); 
            err_res = ErrReaction(err); 
            if(err_res<0) return(err_res);
        } 
    }//while((!res)&&(ncykls<MAXCYKLESCNT))

頑張ってください。

SZ ブレイク/コンティニューについて

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
という質問には、議論の余地があります。注文が残っている場合、テイク/ストップがトリガーされると、注文番号が変更されます - つまり、注文はまだ選択されています:チケットではなく、注文番号で選択します。選択されていない場合は、注文がないことを意味します。毎回注文数を確認するわけではないので、ある程度の回数、サイクルを空転させることになります。