エキスパートアドバイザー - 雑多な質問 - ページ 24

 

すでに例にある通りです。

注文を閉じるときには、OrderClose()関数の ブール値の戻り値を使用し、関数が成功した場合は、注文に関連するオブジェクトを削除することができます。

                           bool close=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,clrBlue);
                             {
                              if(close==0)
                                {
                                 Alert(" Order Close Error! # "+IntegerToString(OrderTicket()));
                                }
                              if(close==1)
                                {
                                 Alert(" Order: "+IntegerToString(OrderTicket())+" Closed due to TP Profit = "+DoubleToString(OrderProfit(),2));
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
                                }
                             }
 
Marco vd Heijden:

すでに例にある通りです。
注文を閉じるときは、OrderClose()関数の boolean戻り値を使用し、関数が成功した場合、注文に関連するオブジェクトを削除することができます。

私はすでにそれを知っていて、すでにそれを試してみました。多分、私は何か間違ったことをしました。もう一度やってみますが、その前に、OrderClose()を使いたくありません。(時々、手動で注文をクローズしています。)
Q: では、OrderClose()を使わずに、注文が終了した後に注文オブジェクトを削除することはできますか?

事前にありがとうございます。

 

Order Close() 関数の戻り値は、アクションが成功したかどうかを決定するため、手動で注文を閉じる場合は、少し異なるメカニズムを設計して使用する必要があります。

注文リストのシャドウコピーを作成して実際のリストと比較し、手動で注文を閉じたために何かが変更されるたびに、変更されたオブジェクトを探し、それらのオブジェクトを削除することができます。

しかし、もっと簡単な方法は、OrderTicket()がまだアクティブなオーダープールに存在するかどうかをチェックし、手動でオーダーを閉じたためにそれが消滅したときに、オブジェクトが自動的に削除されるようにすることです。

つまり、どのようにセットアップしたいかによるのです。

この時点では、最終的に何をしたいのか、その先を見据える必要があると思います。


オブジェクトの作成はすでに完全に自動化されているので、オブジェクトの削除も同じようにすれば、将来的に心配する必要がなくなります。

これには、単純に

OrdersHistoryTotal()

そして、履歴プール

MODE_HISTORY

単純に、注文履歴プールをスキャンし、各サイクルにおいて、OrderTicket()番号に関連するオブジェクトが存在するかどうかを確認し、一致するものがあれば、オブジェクトを自動的に削除します。

これを行うには、別のループを追加するだけですが、今回は履歴プールを対象とします。

例をご覧ください。

//+------------------------------------------------------------------+
//|                                                ObjectsRemove.mq4 |
//|      Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

static input int takeprofit=500;// Take Profit
static input int stoploss=500;  // Stop Loss
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   for(int order=OrdersTotal(); order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS);
        {
         if(selected==1)
           {
            if(Symbol()==OrderSymbol()) // only for current chart symbol
              {
               switch(OrderType())
                 {
                  case OP_BUY: // for buy order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()+takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()-stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;

                  case OP_SELL: // for sell order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()+stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;
                 }
              }
           }
        }
     }
//+------------------------------------------------------------------+
//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
              }
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
              }
           }
        }
     }
//+------------------------------------------------------------------+    
  } // end OnTimer() function
//+------------------------------------------------------------------+

これで、仮想の利食い ラインと損切りラインを完全に自動で追加し、またこれらのラインを完全に自動で削除することができました。

もちろん、この例ではヒストリープールを継続的にスキャンしています...

さらに、注文数を保持する整数を追加し、それを OrdersTotal() と比較し、何か変化があるたびにオブジェクト削除コードを実行することもできます。

あるいは、単純なカウンタ (60) を追加して、削除が必要なものがあれば 1 分間に 1 回だけチェックするようにすることもできます。

 

ヘイマン!これで完璧だ!ありがとうございます。

ちょっとだけ変更しました。今のところ問題なく動作しています。

//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            ObjectsDeleteAll( 0, "#" + IntegerToString( OrderTicket() ) ); // for arrows
            ObjectsDeleteAll( 0, _prefix + " #" + IntegerToString( OrderTicket() ) ); // order, sl, tp, price objects
           }
        }
     }

もし何か問題があれば、それについて私に教えてください。
改めて、ありがとうございました。

 

多分、誰も私の質問を理解していないでしょう。しかし、私はまだそれのための良いコメントを必要としています。そこで、今、私は画像で私の質問を明確にしようとしています。
質問: トレードパネルのオブジェクトの前にストップロスやテイクプロフィットのラインもあります。前回作成したオブジェクトが 原因であることは分かっています。しかし、どうすればトレードパネル・オブジェクトを他のオブジェクトの前に表示させることができるのでしょうか?

混在するオブジェクト

OBJPROP_BACKを使えばいいのは分かっているのですが、それを使いたくありません。 両者のようにラインと価格が見えればいいのです。いいコメントがもらえるといいのですが。


Open、Stop Loss、Take Profit、価格ライン、Create and Delete、これら全てを一つの関数で行う必要があります。だから今、私はそれを分割しようとしている、私はOnChartEvent()にその関数を配置する必要があるためです。しかし、私は尋ねる必要がある前に。
Q: 私はOnChartEvent()にその関数を入れた場合 - ので、その関数は、私の手動注文に影響を与えることができませんでした?

私は今、それに取り組んでいます。

どうか助けてください、ありがとうございます。

 

Onchartevent()は、チャートイベントが発生したときのみコードを実行します。

ですから、あなたが何をしているのかを正確に把握する必要があります。

例えば、スキャンコードを使っている場合。

if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))

これはOnChartEvent()では動作しません。

また、自動売買の例を使いたい場合

if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
   {
     ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
     ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
   }

これは動作しませんし、オブジェクトを作成することもできません。

コードを書き直さなければなりません。

また、H_LINEオブジェクトをOBJPROP_BACKに設定しても、問題ありません。

 

本当に素晴らしく、有用なコメント です。今、私は、私が追加で何ができるかを知るために、少なくとも一度は試してみるべきだと確信しています。

迅速な対応と有益なコメントをありがとうございました。

 
Marco vd Heijden:

コードを書き直さなければ ならないでしょう。

( あなたのコメントはすでによく読んでいますが、一度試してみたかったのです。最終的には、あなたが言ったように、OnTimer()のようには動作しません。)

そのブロックのコードをすべて変更する必要がありますか?
今私は4つの関数を持っています。私はちょうどOnChartEvent()にそれらを置くことを試みる。私はすでに試してみました私はちょうどこれがストップロス、テイクプロフィット 価格のための単なるPrint()である一つの更新を参照してください。
OrderModify()はその中で動作しません。

私は8で、この問題のために再び何かをしようとするために開始されます - 10時間。
私はちょうど本当に良いコメントを必要とする、私はそれを得ることを願っています。

本当にありがとうございました。

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG) // I already tried with take profit object - there was not any effects
     {
      SL_TPcreateobjects();
      SL_TPdrags();
      SL_TPmodify();
      deleteobjs();
     }
  }
// if objects not found - create them
SL_TPcreateobjects()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
        {
         ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,takeprofit);
        }
     }
  }
// if objects exist
SL_TPdrags()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
        {
         if(TP_Price!=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
           {
            TP_drag=1;
            TP_Price=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0);
           }
         if(TP_drag==1)
           {
            if(TP_Price==ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
              {
               Print("Take Profit Price:",DoubleToString(TP_Price,Digits));
               TP_drag=0;
              }
           }
        }
     }
  }
// order closed - delete junks
deleteobjs()
{
  for(int i=OrdersHistoryTotal()-1; i>=0; i--)
    {
     bool Selected=OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(Selected==1)
       {
        ObjectsDeleteAll(0,"#"+IntegerToString(OrderTicket())+"-TP");
       }
    }
}
// ordermodify()
SL_TPmodify()
{
  Order_Modify=OrderModify(OrderTicket(),OrderOpenPrice(),SL_Price,TP_Price,0,CLR_NONE);
}
//+------------------------------------------------------------------+
 

これらの関数は、チャートイベントが発生したときにのみ実行されます。

少なくとも、あなたがここで示しているのはそれです。

チャートイベントとは、誰かがチャート上のボタンや何かを押したときに、割り込みルーチンを起動するためのトリガーに過ぎません。

完全に自動化された例をボタンの下に置きましたが、誰もボタンを押さなければ何も起こりません。

 
Marco vd Heijden:

これらの関数は、チャートイベントが発生したときにのみ実行されます。
少なくとも、あなたがここで示しているのはそれです。
チャートイベントとは、誰かがチャート上のボタンや何かを押したときに、割り込みルーチンを起動するためのトリガーに過ぎません。
完全自動化の例をボタンの下に置いたところで、誰も押さなければ何も起こりません。

あなたの最新のコメントはとてもシンプルに見えるかもしれませんが、実はそのコメントは私に正しい道を示してくれました。
ドラッグを使うかどうかの問題は解決しました。

そして今、そのHLineオブジェクトを使った他のグラフィカル・オブジェクトの動きについて研究を始めています。

本当にありがとうございます。
これからもよろしくお願いします。


honest_knave:

また、ラインを動かす頻度についても考えてみてください。1秒に1回でしょうか?おそらくそうではないでしょう。
あなたのコードをOnChartEvent()に入れてください。

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line
どうもありがとうございます。あなたのこのコメントは本当に私をたくさん助けたように!