MQL4、MQL5に関する初心者からの質問、アルゴリズムやコードに関するヘルプ、ディスカッションなど。 - ページ 1950

 
Valeriy Yastremskiy #:

を使用して、必要な価格とチケット、そして場合によっては時間などを構造体または配列に格納し、追加後すぐに価格によってソートすることができます。資源別に見ると、あまり見ない人は同じか少し高く、よく見る人は覚えておくとよいでしょう。もちろん、100500件の注文がない場合は)それでは高すぎるかもしれません。一般に、構造体や多次元配列のソートは、残念ながら最初のインデックスに対してのみ解決されます。

同じインデックス、チケット、時間、価格を持つ複数の一次元配列を使うこともあります。また、必要なプロパティのインデックスで検索します。もちろん、松葉づえではあるが、明確に機能する。

ありがとうございます - 私も見てみます・・・。
 
Valeriy Yastremskiy #:

を使用して、希望する価格とチケット、そしておそらく時間などの他のものを構造体または配列に格納し、価格によって追加した後すぐにソートします。資源別に見ると、あまり見ない人は同じか少し高く、よく見る人は覚えておくとよいでしょう。もちろん、100500件の注文がない場合は)それでは高すぎるかもしれません。一般に、構造体や多次元配列のソートは、残念ながら最初のインデックスに対してのみ解決されます。

同じインデックス、チケット、時間、価格を持つ複数の一次元配列を使うこともあります。また、必要なプロパティのインデックスで検索します。もちろん松葉杖ではあるが、これは非常に有効である。

私はこのようにしました。

enum MT_ORD_STATE
  {
   ORD_NA,  // Not available
   ORD_SENT,
   ORD_ACTIVE,
   ORD_CHANGE_SENT,
   ORD_DEL_SENT
  };

struct MTOrder
  {
   ulong id;
   ulong Ticket;
   datetime Time;
   datetime TimeNotFound;
   double   Price;
   double   Vol;
   double   VolInit;
   uint     request_id;
   ENUM_ORDER_TYPE   Type;
   ENUM_ORDER_STATE State;
   MT_ORD_STATE MTState;
   int      Reserved;
   bool     Idf; // Identified
  };

...

   MTOrder  Orders[]; // С начала массива - ордера на покупку, по убыванию цены,
                      // С конца - на продажу, по возрастанию

配列は常にソートされており、必要な位置に新しいオーダーが挿入され、他のオーダーはシフトされ、オーダーが削除されると、シフトされる。

ただし、これはMT5での話

 
JRandomTrader #:

私はこのようにしました。

配列は常にソートされており、新しいオーダーは他のオーダーをずらしながら正しい位置に挿入され、オーダーが削除されるときはずれが生じます。

しかし、これはMT5での話です。

書き込み時、削除時、ソート時にずれるようなコードがあると良い。配列構造をフィールドごとにソートするのは、私にとって些細な作業ではありません。はい、シフトもです)。

 
Valeriy Yastremskiy #:

書き込み、削除、ソートなどのシフトコードがあると良い。配列構造をフィールドでソートするのは、私にとって些細な作業ではありません。シフトも)。

bool Tr2MT::InsertOrder(MTOrder &ord_tmp) // Из AddOrder (2 варианта), единственное место добавления ордеров в массив
{
 int i=0,n=0;
 string str="";
 ord_tmp.id=++st.LastOrdID;

 switch(ord_tmp.Type)
   {
    case ORDER_TYPE_BUY:
    case ORDER_TYPE_BUY_LIMIT:
      for(i=0,n=-1;i<ArraySize(Orders);i++)
        {
         if(Orders[i].id==0)
           {
            n=i; break;
           }
        }
      if(n<0) break;
      for(i=n;i>=0;i--)
        {
         if(i==0 || Orders[i-1].Price>=ord_tmp.Price)
           {
            Orders[i]=ord_tmp;
            SaveState();
            //str=OrdString();
            //Log(str);
            return true; //добавили
           }
         else
           {
            Orders[i]=Orders[i-1];
           }
        }
      break;
    case ORDER_TYPE_SELL:
    case ORDER_TYPE_SELL_LIMIT:
      for(i=ArraySize(Orders)-1,n=-1;i>=0;i--)
        {
         if(Orders[i].id==0)
           {
            n=i;
            break;
           }
        }
      if(n<0) break;
      for(i=n;i<ArraySize(Orders);i++)
        {
         if(i==ArraySize(Orders)-1 || Orders[i+1].Price<=ord_tmp.Price)
           {
            Orders[i]=ord_tmp;
            SaveState();
            //str=OrdString();
            //Log(str);
            return true; //добавили
           }
         else
           {
            Orders[i]=Orders[i+1];
           }
        }
      break;
    default:
      return false;
      break;
   }
 str="Can't add order - out of array!";
 ErrLog(str);
 return false; //не нашли места для ордера
}
bool Tr2MT::DelOrder(int n)
{
 int i;
 MTOrder ord_tmp={};

      switch(Orders[n].Type)
         {
          case ORDER_TYPE_BUY:
          case ORDER_TYPE_BUY_LIMIT:
            for(i=n;i<ArraySize(Orders);i++)
              {
               if(i==ArraySize(Orders)-1 || Orders[i+1].id==0 || Orders[i+1].Price>Orders[i].Price)
                 {
                  Orders[i]=ord_tmp; // Обнуляем
                  break;
                 }
               else
                 {
                  Orders[i]=Orders[i+1];
                 }
              }
            break;
          case ORDER_TYPE_SELL:
          case ORDER_TYPE_SELL_LIMIT:
            for(i=n;i>=0;i--)
              {
               if(i==0 || Orders[i-1].id==0 || Orders[i-1].Price<Orders[i].Price)
                 {
                  Orders[i]=ord_tmp; // Обнуляем
                  break;
                 }
               else
                 {
                  Orders[i]=Orders[i-1];
                 }
              }
            break;
          default:
            return false;
            break;
         }
 return true;
}

そして、おそらく最も興味深いのは、その部分でしょう。

bool Tr2MT::UpdOrder(int n) // Только если есть тикет или угадываем
{
 string str;
 int i;
 bool flag=false;
 MTOrder ord_tmp={0};
 ulong ticket=Orders[n].Ticket;

 if(ticket==0)
   {
    if(!GuessOrdTicket(n))return false; // Если угадываем - он будет в Orders[n].Ticket
    else ticket=Orders[n].Ticket;
   }

 switch(FindOrder(ticket,Orders[n].Time+100000))
   {
    case ORD_FOUND: //изменён или просто проверка
      //update (sync) order
      if(Orders[n].Price==OrderGetDouble(ORDER_PRICE_OPEN)) // Цена не изменилась
        {
         if(Orders[n].State==(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)&&Orders[n].MTState!=ORD_NA)
           {
            if(Orders[n].Vol==OrderGetDouble(ORDER_VOLUME_CURRENT))
               return true; // Не нужно сохранять состояние, можно сразу выйти
            else
               Orders[n].Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
         else
           {
            //Orders[n].State=(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE);
            SetOrdState(Orders[n],(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)); // Обнулит и TimeNotFound
            if(Orders[n].Vol!=OrderGetDouble(ORDER_VOLUME_CURRENT))
               Orders[n].Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
        }
      else // Цена изменилась
        {
         ord_tmp=Orders[n];
         //ord_tmp.State=(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE);
         SetOrdState(ord_tmp,(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE));
         ord_tmp.Price=OrderGetDouble(ORDER_PRICE_OPEN);
         ord_tmp.Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
         switch(Orders[n].Type)
           {
            case ORDER_TYPE_BUY:
            case ORDER_TYPE_BUY_LIMIT:
               if(ord_tmp.Price>Orders[n].Price) // Цена ордера увеличилась, перемещаем вверх (по массиву - вниз)
                 {
                  for(i=n;i>=0;i--)
                    {
                     if(i==0 // Конец массива ордеров
                        || ord_tmp.Price<=Orders[i-1].Price) // Следующий - по большей цене, вставляем перед ним
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i-1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               else // Цена ордера умньшилась, перемещаем вниз (по массиву - вверх)
                 {
                  for(i=n;i<ArraySize(Orders);i++)
                    {
                     if(i==ArraySize(Orders)-1 // Конец массива ордеров
                        || Orders[i+1].Ticket==0 // Следующий элемент пустой
                        || ord_tmp.Price>Orders[i+1].Price // Следующий - по меньшей цене, вставляем перед ним
                        || Orders[i+1].Price>Orders[i].Price) // Следующий - ордер уже на продажу
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i+1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               break;
            case ORDER_TYPE_SELL:
            case ORDER_TYPE_SELL_LIMIT:
               if(ord_tmp.Price>Orders[n].Price) // Цена ордера увеличилась, перемещаем вверх (по массиву - вниз)
                 {
                  for(i=n;i>=0;i--)
                    {
                     if(i==0 // Конец массива ордеров
                        || Orders[i-1].Ticket==0 // Следующий элемент пустой
                        || ord_tmp.Price<Orders[i-1].Price // Следующий - по большей цене, вставляем перед ним
                        || Orders[i-1].Price<Orders[i].Price) // Следующий - ордер уже на покупку
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i-1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               else // Цена ордера умньшилась, перемещаем вниз (по массиву - вверх)
                 {
                  for(i=n;i<ArraySize(Orders);i++)
                    {
                     if(i==ArraySize(Orders)-1 // Конец массива ордеров
                        || ord_tmp.Price>Orders[i+1].Price) // Следующий - по меньшей цене, вставляем перед ним
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i+1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               break;
            default:
               return false;
               break;
           }
        }
      SaveState();
      //str=OrdString();
      //Log(str);
      break;
    case ORD_HIST_FOUND: //исполнен || снят
      //delete order
      if(!DelOrder(n))
         return false;
      SaveState();
      str=OrdHistString(ticket); // Уточнить
      Log(str);
      break;
    case ORD_NOT_FOUND: //отправлен в историю?
      if(Orders[n].MTState!=ORD_NA)
        {
         Orders[n].MTState=ORD_NA;
         Orders[n].TimeNotFound=TimeCurrent();
         SaveState();
         printf(__FUNCTION__, "Order not found, ticket:",IntegerToString(Orders[n].Ticket)," TimeNF:",TimeToString(Orders[n].TimeNotFound,TIME_SECONDS));
        }
      else
        {
         if(TimeCurrent()-Orders[n].TimeNotFound>60) // > 60 секунд не найден
           {
            if(!DelOrder(n))
              return false;
            SaveState();
            str="Order not found >60s "+IntegerToString(ticket)+"\n";
            Log(str);
           }
        }
       break;
    default:
      return false; //не тот ордер
      break;
   }
 return true;
}
 
JRandomTrader #:

ありがとうございます。

悪くないですね。私は配列が嫌いです)))、配列でデバッグしないと一回目は絶対にうまくいきません。)))特にシフト、コピー、ソートは規則的でない)))
 
Valeriy Yastremskiy #:

ありがとうございます。

悪くないですね。私は配列が嫌いです)))、配列でデバッグしないと一回目は絶対にうまくいきません。)))特にシフト、コピー、ソートは規則的でない)))

どんな道具も、それ自体が良いものです。

しかし、陰湿なオフバイエラーチェックと再チェック ))

 

古いコードを見直すということは、そういうことなのです

前バージョンの名残で、同じ欠点が2つあるのが見えます。

明らかなサブオプティマイゼーションを1つ。

そして、1つの時代遅れのデザイン。

 
こんにちは。もし、場所が間違っていたら、どこに書けばいいのかアドバイスしてください、よろしくお願いします。

設定で指定した利益または損失に達したときにポジションを すべて閉じ、設定で指定した方向にすぐに新しいポジションを開く、無料のMT5 Expert Advisorを探しています。どなたか、このスレッドのリンクを教えてください。
あるいは、オープンポジションがないことを確認したら、マーケットで1つのポジションをオープンし、クローズしないEAを知っているかもしれません。
 

MT4 1353

ログにはどのようなエラーが表示されますか?

コードが正しく動作する


 
Vitaly Muzichenko #:

MT4 1353

ログにはどのようなエラーが表示されますか?

コードは正しく動作します。


new "で作成したオブジェクトが終了時に破棄されないものがあるようです。