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.
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.
- en.wikibooks.org
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
@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.
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.
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz
İş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:
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