dinamik olarak nesneler nasıl oluşturulur? (Bazı OOP şeyler)

 

İşte bazı OOP şeyler geliyor.

Program için fikir:

* Grafikte bir trend çizgisi çizerim ve buna "bip" adını veririm - fiyat bu çizgiyi bir daha geçtiğinde bir bip sesi duyarım

* Bir trend çizgisi çizerim ve buna "al" adını veririm - fiyat bu çizgiyi bir daha geçtiğinde, uzun bir pozisyon alacağım.

Ben zaten "CSmartLine" adında bip sesi çıkarabilen, alıp satabilen ve kapatabilen bir nesne yazdım ve ... (şimdiye kadar kahve servisi yok).

EA'mda üç satır kod var:

CSmartLinie mSmartLinie1;     // Create one object of class CSmartLine  


void OnTick()
      mSmartLinie1.CheckForAction(); // check for crossing prices

void OnChartEvent()
      if(id == CHARTEVENT_OBJECT_CLICK  ||
         id == CHARTEVENT_OBJECT_DRAG   ||
         id == CHARTEVENT_OBJECT_CHANGE ||
         id == CHARTEVENT_OBJECT_CREATE)
         if (sparam == "beep" || sparam == "buy" || sparam == "sell" || sparam == "close")
            {
            mSmartLinie1.CheckForAction(sparam) ;  // activation and tracking changes
            return;
            };

Şimdiye kadar iyi çalışıyor.

Şimdi . . . . Grafikte herhangi bir sayıda akıllı trend çizgisi çizmek istiyorum.

Nesnenin, hattın kontrolü altında olduğunu göstermek için hattın adını (örneğin "SmartLine_x" olarak) değiştirdiğini varsayarsak.

EA her yeni satır algıladığında, "CSmartLine" sınıfının yeni bir nesnesini oluşturmalıdır.

kod olabilir

OnChartEvent()
      if (sparam = "beep")
             mSmartLine2 = new CSmartLine;

OnTick()
      if(mSmartLine2 != Null)
             mSmartLine2.CheckForAction();

Ama nasıl .... hmmm ....

Belki "mSmartLine" bir dizi işaretçi olmalıdır? Eğer öyleyse, hangi tür?

Kılavuz onun noktasında anlayamadığım bir örnek gösteriyor.


Eğilim çizgisi kaybolduğunda (örneğin kullanıcı bunu grafikten sildiği için).

Kod olmalıdır. . .

       delete  mSmartLine2;
      mSmartLine2=NULL;

Çizginin uygunsuzluğunu tanıyan nesnenin kendisi olduğu için, EA'dan onu silmesini istemek yerine, kendisini silen nesne olmalıdır.

WIllbur

 

Birinin basitçe kullanabileceği yer

 ObjectCreate ( 0 , "mSmartLinie" + IntegerToString (X), OBJ_HLINE , 0 , 0 , 0 );

nerede basit

X++;

oluşturmak için X tamsayısını artıracak

 "mSmartLinie0"
"mSmartLinie1"
"mSmartLinie2"
"mSmartLinie3"

Ve benzeri.

 
Marco haklı.

Sorununuz, bir "bip" nesnesi varsa, yeni bir nesnenin oluşturulmamasıdır.
marco'nun belirttiği gibi
artı
Komutları, nesne adının ilk Karakterine ekleyin.
tanınabilir karakter dizisi

eski:

A->Bip Sesi
B->Satın al
C->Sat
sıra -> SMRTLN_

bu nedenle, bir bip akıllı hattının ilk oluşumu "SMRTLN_A_"+TotalBeepCount olarak adlandırılır
 

OOP'de nesneleri depolamak ve yinelemek için ortak tasarım kalıpları vardır. Bunlara Kapsayıcılar, Kümeler, Koleksiyonlar, Haritalar, Vektörler (ve diğer benzer adlar) tasarım desenleri denir, ancak hiçbiri temel MQL dağıtımıyla teslim edilmez. Bunları kendiniz kodlamanız veya kod tabanında bulmanız gerekir.

C++ Programming/Code/Design Patterns - Wikibooks, open books for an open world
C++ Programming/Code/Design Patterns - Wikibooks, open books for an open world
  • en.wikibooks.org
A design pattern is neither a static solution, nor is it an algorithm. A pattern is a way to describe and address by name (mostly a simplistic description of its goal), a repeatable solution or approach to a common design problem, that is, a common way to solve a generic problem (how generic or complex, depends on how restricted the target goal...
 

Sanırım anladım - sihirli satırlar bunlar (umarım):

CSmartLine *ArrayOfSmartLineS[10]; // An array of pointers to CSmartLine object


On ChartEvent

           //--- Create another object
           CSmartLine*mSmartLine = new CSmartLine();
           // Make the new object the owner of the new trend line
           mSmartLine.SetName(sparam);
           //--- Place the pointer value in an Array
           ArrayOfSmartLineS[NoLines]=mSmartLine;

Kılavuzda "CSmartLine*mSmartLine = new CSmartLine();" formu kullanılmıştır. yalnızca bu sınıfın ilk örneğini oluşturduklarında.
Bir dahaki sefere sadece "mSmartLine = new CSmartLine();"
Test çerçevemde bu mümkün değil (derleme hataları). ? ? ?


İşlevselliği çok zayıf olan basit bir test çerçevesi yazdım, ancak nesnelerin dinamik olarak oluşturulması için bir test.

EA, "bip" adlı bir eğilim çizgisi algıladığında, çizgiyi yeniden adlandıran ve bundan sonra onu kontrol eden bir "SmartLine" nesnesi oluşturur.

//+------------------------------------------------------------------+
//| Test frame OOP                                                   |
//+------------------------------------------------------------------+
class CSmartLine
{
protected:
string   iName;
double   iRate;

public:
   void   SetName(string xName)
            {
            for(int i=0;i<99;i++)
               {
               iName = "SmartLine_"+IntegerToString(i);
               if(ObjectFind(0,iName) < 0) break; // find unused name
               }
            ObjectSetString(0,xName,OBJPROP_NAME,0,iName); // rename trend line
            // --- Get rate
            iRate = ObjectGetDouble(0,iName,OBJPROP_PRICE,0);
            // signal identification of the line
               Sleep(300); PlaySound("ok.wav");
               ObjectSetInteger(0,iName,OBJPROP_WIDTH,4); ChartRedraw();
               Sleep(300);
               ObjectSetInteger(0,iName,OBJPROP_WIDTH,1); ChartRedraw();
            //
            };
           
   string GetName(void) {return(iName);}
  
   void   checkForChange(string xName)
            {
            if(xName != iName) return;
            // Check whether the line has been moved
            // get the new position
                        // --- Get rate
            iRate = ObjectGetDouble(0,iName,OBJPROP_PRICE,0);
            MessageBox("New rate: "+iName+" = "+DoubleToString(iRate,5));
            };
   void   checkForAction(double iAsk)
            {
            if(MathAbs(100 * (iRate - iAsk)/iAsk) < 0.005)
              {
              MessageBox("it's hit me "+iName+
              "\n myRate "+DoubleToString(iRate,5)+
              "\n actAsk "+DoubleToString(iAsk, 5)+
              "\n actDiff "+DoubleToString(100 * (iRate - iAsk)/iAsk,5) );
              }
            // Calculation whether the price hits the line
            // action: beep, buy, sell, close
            };         

};

//################# E N D - - - C S m a r t L i n e ##########################

//################# B E G I N of E A program ##################################

//--- Declare an array of object pointers of type CSmartLine

      CSmartLine *ArrayOfSmartLineS[10]; // An array of pointers to CSmartLine object

int   NoLines=0;

//----------------------------------------------------------------------------
void OnInit(void)
{
// --- do I need this?
   for(int i=0;i<10;i++)
     ArrayOfSmartLineS[i]=NULL;     

//--- delete all old trend lines
    ObjectsDeleteAll(0,"SmartLine",-1);

}
//+--------------------------------------------------------------------------
void OnChartEvent(const int id,        
                  const long& lparam,  
                  const double& dparam,
                  const string& sparam) 
{
      if(id == CHARTEVENT_OBJECT_CLICK  ||
         id == CHARTEVENT_OBJECT_DRAG   ||
         id == CHARTEVENT_OBJECT_CHANGE ||
         id == CHARTEVENT_OBJECT_CREATE)
         {
         if(sparam == "beep" || sparam == "buy" || sparam == "sell") 
           {
           //--- Create another object
           CSmartLine*mSmartLine = new CSmartLine();
           // Make to new object the owner of the new line
           mSmartLine.SetName(sparam);
           //--- file the pointer value in the array[0]
           ArrayOfSmartLineS[NoLines]=mSmartLine;
           //--- ask the new object for it's line name
           MessageBox("new object: " + ArrayOfSmartLineS[NoLines].GetName());
           //
           NoLines++;
           };
         if(StringSubstr(sparam,0,10) == "SmartLine_")
           {
           for(int i=0;i<10;i++)  // Ask all exsisting objects to pick up the change if concerns
             {
             if(ArrayOfSmartLineS[i] != NULL)
                ArrayOfSmartLineS[i].checkForChange(sparam);
             }
           }

         }
}
//----------------------------------------------------------------------------
void OnTick(void)
{
      MqlTick last_tick;
  
      SymbolInfoTick(_Symbol,last_tick);
     
      for(int i=0;i<10;i++)  // Ask all exsisting objects
             {
             if(ArrayOfSmartLineS[i] != NULL)
                ArrayOfSmartLineS[i].checkForAction(last_tick.ask);
             }
}
//+------------------------------------------------------------------+
void OnDeinit(const int xReason)
{
      if(xReason == REASON_RECOMPILE   ||
         xReason == REASON_CHARTCHANGE ||
         xReason == REASON_PARAMETERS  ||
         xReason == REASON_ACCOUNT)    return;
     
//--- We must delete all created dynamic objects
      for(int i=0;i<10;i++)
         {
         //--- We can delete only the objects with pointers of POINTER_DYNAMIC type
         if(CheckPointer(ArrayOfSmartLineS[i])==POINTER_DYNAMIC)
            {
            //--- Notify of deletion
            MessageBox("Deleting object "+IntegerToString(i)+" named "+ArrayOfSmartLineS[i].GetName());
            //--- Delete an object by its pointer
            delete ArrayOfSmartLineS[i];
            ArrayOfSmartLineS[i] = NULL;
            }
         }   // Loop i=0;i<10;i++
  }

 

@Marco

Fikrinizi anladığımdan emin değilim.

Standart grafik nesnelerle gitmeli, ondan her şeyi miras alan ve işlevselliği SmartLines için planladığım aralığa yükselten bir sınıf yazmalı mıyım?!?

Bu fikri düşünüyordum ve MT5'in kullanıcının grafik nesnesi oluşturmasına izin verip vermediğini merak ediyorum (normal arayüz aracılığıyla).

Bu problemin yanı sıra, fiyat değiştiğinde SmartLine nesnelerimin tetiklenmesi gerekiyor ve bu sorunu nasıl aşacağım hakkında hiçbir fikrim yok.

Bu alanda herhangi bir deneyiminiz var mı?

Willbur

 
Willbur :

@Marco

Fikrinizi anladığımdan emin değilim.

Standart grafik nesnelerle gitmeli, ondan her şeyi miras alan ve işlevselliği SmartLines için planladığım aralığa yükselten bir sınıf yazmalı mıyım?!?

Bu fikri düşünüyordum ve MT5'in kullanıcının grafik nesnesi oluşturmasına izin verip vermediğini merak ediyorum (normal arayüz aracılığıyla).

Bu problemin yanı sıra, fiyat değiştiğinde SmartLine nesnelerimin tetiklenmesi gerekiyor ve bu sorunu nasıl aşacağım hakkında hiçbir fikrim yok.

Bu alanda herhangi bir deneyiminiz var mı?

Willbur

Bu sadece bir şeyler yapmanın bir örneğiydi.

Bir GUI veya Grafik Kullanıcı Arayüzü oluşturduğumda, her zaman bir döngüde kontrol çerçeveleri oluştururum.

Bu, kontrol düğmelerinin basitçe B0,B1,B2,B3,B4,B5 ve benzeri olarak oluşturulduğu anlamına gelir, bu da düğme 0 düğme 1 düğme 2 vb. anlamına gelir.

Ve sayısal tamsayıyı nesne adına eklemek için her zaman IntegerToString() kullanırım.

Tetiği istiyorsanız, şunları da kullanabilirsiniz:

 if (( Ask + Bid )/ 2 > ObjectGetDouble ( 0 , "object name" , OBJPROP_PRICE )
 {
   // Trigger 1
 }

else if (( Ask + Bid )/ 2 < ObjectGetDouble ( 0 , "object name" , OBJPROP_PRICE )
 {
   // Trigger 2
 }

Ya da bir varyasyon çünkü bu sadece size bazı fikirler vermek içindir.

Yani temel olarak bir Fiyat Sor veya Teklif veya Medyan alır ve bunu Hline'ınızın şu anda bulunduğu İki Kat ile karşılaştırırsınız.

Tek sınır kendi hayal gücünüzdür.

 

Marco, Hâlâ EA-Kodunuzdasınız. Sen?

Bahsettiğim şey bu değil.

Buradaki fikir, orijinal grafik nesnesinden miras alan kendi nesnemi yazarak verilen grafik nesnesine işlevsellik eklemek ve "satın al" ve "sat" işlevleriyle artırmaktı.

Bu yöne gittiğinizde SmartLine nesnem MT5 menüsünde trend çizgisinin, okların, metin nesnesinin ve tüm bu şeylerin yanında görünmelidir.

Diğer grafik nesneleri gibi fare ile seçip grafiğe ekleyebilirsiniz.

MT5 buna izin veriyorsa, ancak o zaman kalan soruyu, fiyat değiştiğinde nesnenin terminal programı tarafından nasıl tetiklenebileceğini tartışmalıyız.

Mevcut grafik nesnesinin hiçbiri fiyat değişikliklerine tepki veremez (bildiğim kadarıyla ücret).

Willbur

 

Tamamen yanlış yaptığınızı söylemek istemiyorum ama yapıyorsunuz, çünkü bu yapı programlaması ve OOP değil. Büyük fark, kalıtımın ve aşırı yüklemenin gücüdür. Bu arada, gerçek grafik nesnelerinden gerçekten miras alamazsınız, ancak herhangi bir şeyi bir kod nesnesi olarak temsil edebilir ve bu nesneden bir satıra veya herhangi bir şeye başvurabilirsiniz. MFC veya MQL sınıfı olsun, herhangi bir sınıfta genellikle böyle yapılır, hepsi aynıdır.

Çizgileriniz nesnelerse, onlara öyle davranın. Dışarıdaki dizilerle uğraşmayın, bunu bir sınıf koleksiyonu içinde yapın ve işaretçilerle çalışın. CWndContainer'a bir göz atın ve onun hakkında bir fikir edinin. Bu sınıf, esas olarak CWnd nesneleri için işaretçi dizilerini yöneten bir kapsayıcıdır. Bir adım ileri gidin, yapınız şöyle olmalıdır:

Her nesne için temel olarak CObject

Çizgiler gibi her fiyat/zamana dayalı nesne için temel olarak CPriceTimeObjects, CObject'den türetilmiştir. Oluşturmayı kontrol eder, zamanı ve fiyatı tutar ve bir sonraki mirasçı tarafından kullanılabilecek bir OnCreate() çağırır. Ayrıca, mirasçılar tarafından aşırı yüklenen sanal OnTick()'i çağıran bir Tick işlevine de sahiptir.

Trend çizgileri için temel olarak CTrendLine, CPriceTimeObjects öğesinden miras alır ve ObjectCreate işlevini kullanarak son satırı oluşturduğu OnCreate öğesini işler. Ayrıca Tick olaylarına tepki vermek/cevap vermek için bir OnTick() işleyicisine sahip olmalıdır, çünkü anladığım kadarıyla fiyata duyarlı olacaktır.

Bunun yanı sıra, istediğiniz tüm CTimePriceObject nesnelerini tutan bir işaretçi dizisini yöneten bir kapsayıcı sınıfınız var, kendisini CTimePriceObject'ten de devralır ve OnTick()'i "childs" e geçirir. Kap, ayrıca satır eklemek veya satırları kaldırmak için OnChartEvent()'i işleyen bir işleve sahiptir. Ayrıca vaka için mevcut tüm nesneleri taramak için bir tarama işlevine sahip olmalıdır, satırlar oluşturulduktan sonra uzman eklendi. Ayrıca, CTimePrice'den aşırı yüklenmiş OnTick()'i işler, diziyi orada döngüler, içindeki her CTrendLine nesnesine, sanal bir OnTick tarafından işlenen her alt nesnenin Tick işlevini çağırarak tepki vermekten bir şekilde sorumlu olup olmadığını sorar. Neden bu tekrar? CTrendLine bu işlevi CTimePrice'den de aşırı yüklediğinden ve bu şekilde bu sınıf, başka işlevlere sahip diğer mirasçılar tarafından da devralınabilir.

Kodunuz daha sonra şöyle görünmelidir:

CTPContainer kapsayıcı;

::OnChartEvent(...)

container.ChartEvent(id, lparam, dparam, sparam) //.. her CTrendLineObject'de OnCreate() ve OnDelete() ile sonuçlanır. Ne yapacağınıza EA'nız değil, kapsayıcı karar verir.

::OnTick()

container.Tick() // .. her CTrendLine "alt" nesnede OnTick() ile sonuçlanır

ve benzeri.

Bu, bu sınıfları kullanan herhangi bir EA'nın kendisine bir daha dokunmadan, kullanışlı işlevlerle kolayca geliştirilebilen açık bir OOP tabanıdır.

 
Tamamen yanlış yaptığını söylemekten hoşlanmıyorum ama yapıyorsun. . .

Vay ... ders için teşekkürler.

Her nasılsa, doğru yaklaşıma sahipmişsin gibi geliyor.

Kodumu geri dönmeden önce bu yönde değiştirmeye çalışacağım.

Willbur

 

Sonuç olarak ve hemen nesne odaklı kodlama yapacaksanız asla pişman olmayacaksınız. Başlangıç, normal yukarıdan aşağıya yoldan daha zor olabilir, ancak daha fazla güç, daha fazla olasılık, daha fazla esneklik ve gelecekteki değişikliklere daha kolay uyum içeren çok daha yüksek bir düzeyde gelişebileceksiniz.

MQL harikadır, ancak OOP olmadan gerçekte ne kadar olduğunu asla anlayamazsınız.

Herhangi bir sorunuz varsa, sadece onları gönderin ve ben yardımcı olmaya çalışacağım.