Alım Satım için MQL5'te Aktif Kontrol Panelleri Oluşturma
Giriş
Bir çalışma ortamında, özellikle de hızın ve doğruluğun büyük rol oynadığı yatırımcıların çalışmalarında verimlilik çok önemlidir. Terminali işe hazırlarken, analizleri uygulamak ve bir an önce piyasaya girebilmek için her biri çalışma alanını kendisi için olabildiğince konforlu hale getirir. Ancak işin gerçeği şu ki, geliştiriciler her zaman herkesi memnun edemez ve belirli işlevleri kişinin arzusuna göre ayarlamak imkansızdır.
Örneğin, bir scalper için, saniyenin her bir kesri ve "Yeni Talimat" tuşuna her tıklama önemlidir ve ardından tüm parametrelerin ayarlanması zaman açısından kritik olabilir.
Peki nasıl bir çözüm bulacağız? Çözüm, öğelerin özelleştirilmesinde yatmaktadır; zira MetaTrader 5 "Düğme", "Düzenleme" ve "Etiket" gibi mükemmel bileşenler sağlar. O halde bunu yapalım.
2. Panel Seçenekleri
Öncelikle, bir panel için ne tür işlevlerin gerekli olduğuna karar verelim. Paneli kullanarak temel önemi alım satıma vereceğiz ve bu nedenle aşağıdaki işlevleri ekleyeceğiz:
- Pozisyon açma
- Bekleyen bir talimat verme
- Pozisyonu/talimatı değiştirme
- Pozisyonu kapatma
- Bekleyen bir talimatı silme
Ayrıca, renk şeması panelini, yazı tipi boyutlarını ve kaydetme ayarlarını özelleştirme özelliğinin eklenmesinin hiçbir zararı olmaz. Gelecekteki panelin tüm öğelerinin daha ayrıntılı bir açıklamasını verelim. Panelin her işlevi için nesnenin adını, türünü ve amacının açıklamasını belirteceğiz. Her nesnenin adı "ActP" ile başlayacak; bu, nesnenin panele ait olduğunu gösteren bir tür anahtar olacaktır.
2.1. Açık Pozisyonlar
Aşağıda pozisyonun açılması için gerekli tüm parametreleri tanıtacağız ve bir düğmeye tıklayarak bunu uygulayacağız. Bir kutu işaretlenerek etkinleştirilen yardımcı çizgiler, Zararı Durdur ve Kar Al düzeylerini ayarlamamıza yardımcı olacaktır. Yürütme türünün seçimi radyo düğmeleri kullanılarak yapılacaktır.
Adı | Tür | Açıklama |
---|---|---|
ActP_buy_button1 | Düğme | Alış işlemi için düğme |
ActP_sell_button1 | Düğme | Satış işlemi için düğme |
ActP_DealLines_check1 | Bayrak | Yardımcı çizgileri ayarlama/sıfırlama bayrağı |
ActP_Exe_radio1 | Radyo düğmesi | Alım satım türünü seçmek için radyo düğmeleri grubu |
ActP_SL_edit1 | Giriş alanı | Zararı Durdur öğesine giriş yapma alanı |
ActP_TP_edit1 | Giriş alanı | Kar Al öğesine giriş yapma alanı |
ActP_Lots_edit1 | Giriş alanı | Tutar girme alanı |
ActP_dev_edit1 | Giriş alanı | Açılış sırasında kabul edilebilir bir sapma girmek için alan |
ActP_mag_edit1 | Giriş alanı | Sayı girme alanı |
ActP_comm_edit1 | Giriş alanı | Açıklama girme alanı |
Tablo 1 Panel öğelerinin listesi, "Alım satım açılışı"
2.2 Bekleyen Bir Talimat Verme
Aşağıda bekleyen bir talimatın verilmesi için gerekli tüm parametreleri tanıtacağız ve bunları bir tuşa basarak yerleştireceğiz. Bir bayrak işaretlenerek etkinleştirilen destekleyici çizgiler, Zararı Durdur, Kar Al, durdurma limiti düzeyleri ve sona erme sürelerinin ayarlanmasına yardımcı olacaktır. Yürütme türü ve sona erme süresi türü seçimi, bir grup radyo düğmesinin yardımıyla gerçekleştirilecektir.
Adı | Tür | Açıklama |
---|---|---|
ActP_buy_button2 | Düğme | Al talimatını ayarlama düğmesi |
ActP_sell_button2 | Düğme | Alım satım talimatını ayarlama düğmesi |
ActP_DealLines_check2 | Bayrak | Yardımcı çizgileri ayarlama / sıfırma bayrağı |
ActP_lim_check2 | Bayrak | Talimat durdurma limitini ayarlama/sıfırlama bayrağı |
ActP_Exe_radio2 | Radyo düğmesi | Talimat yürütme türünü seçmek için radyo düğmesi grubu |
ActP_exp_radio2 | Radyo düğmesi | Talimat sona erme süresi türünü seçmek için radyo düğmesi grubu |
ActP_SL_edit2 | Giriş alanı | Zararı Durdur öğesine giriş yapma alanı |
ActP_TP_edit2 | Giriş alanı | Kar Al öğesine giriş yapma alanı |
ActP_Lots_edit2 | Giriş alanı | Tutar girme alanı |
ActP_limpr_edit2 | Giriş alanı | Durdurma limiti talimatının fiyatını girme alanı |
ActP_mag_edit2 | Giriş alanı | Sihirli sayıyı girme alanı |
ActP_comm_edit2 | Giriş alanı | Açıklamalar için alan |
ActP_exp_edit2 | Giriş alanı | Sona erme süresi girme alanı |
ActP_Pr_edit2 | Giriş alanı | Talimat yürütme fiyatını girme alanı |
Tablo 2 "Bekleyen talimatları verme" panelindeki öğelerin listesi
2.3. Alım Satım İşlemlerini Değiştirme / Kapatma
Aşağıda, bir alım satım işleminin değiştirilmesi ve kapatılması için gerekli tüm parametreleri tanıtacağız. Bir kutu işaretlenerek etkinleştirilen yardımcı çizgiler, Zararı Durdur ve Kar Al düzeylerinin kurulumunda bize yardımcı olacaktır. Alım satım işlemlerinin seçimi bir açılır listeden oluşturulacaktır.
Adı | Tür | Açıklama |
---|---|---|
ActP_ord_button5 | Açılır liste | Alım satım işlemi için seçim listesi |
ActP_mod_button4 | Düğme | Alım satım işlemi değiştirme düğmesi |
ActP_del_button4 | Düğme | Alım satım işlemi kapatma düğmesi |
ActP_DealLines_check4 | Bayrak | Yardımcı çizgileri ayarlama/sıfırlama bayrağı |
ActP_SL_edit4 | Giriş alanı | Zararı Durdur öğesine giriş yapma alanı |
ActP_TP_edit4 | Giriş alanı | Kar Al öğesine giriş yapma alanı |
ActP_Lots_edit4 | Giriş alanı | Tutar girme alanı |
ActP_dev_edit4 | Giriş alanı | Kabul edilebilir bir sapma girmek için alan |
ActP_mag_edit4 | Giriş alanı | Sihirli sayıyı görüntüleme alanı (salt okunur) |
ActP_Pr_edit4 | Giriş alanı | Açılış fiyatını görüntüleme alanı (salt okunur) |
Tablo 3. "Alım satım değişikliği / kapanışı" panelinin öğelerinin listesi
2.4. Talimatları Değiştirme / Kaldırma
Aşağıda, bekleyen talimatların değiştirilmesi ve kaldırılması için gerekli tüm parametreleri tanıtacağız. Bir kutu işaretlenerek etkinleştirilen destekleyici çizgiler, stop, take, stop-limit düzeyleri ve sona erme sürelerinin kurulumunda bize yardımcı olacaktır. Bir grup radyo düğmesinin yardımıyla sona erme sürelerinin türünün seçimi yapılacaktır. Talimatların seçimi, bir açılır listeden oluşturulacaktır.
Adı | Tür | Açıklama |
---|---|---|
ActP_ord_button5 | Açılır liste | Talimatı seçmek için liste |
ActP_mod_button3 | Düğme | Talimat değiştirme düğmesi |
ActP_del_button3 | Düğme | Talimat kaldırma düğmesi |
ActP_DealLines_check3 | Bayrak | Yardımcı çizgileri ayarlama/sıfırlama bayrağı |
ActP_exp_radio3 | Radyo düğmesi | Bir talimatın sona erme süresi türünü seçmek için radyo düğmeleri grubu |
ActP_SL_edit3 | Giriş alanı | Zararı Durdur öğesine giriş yapma alanı |
ActP_TP_edit3 | Giriş alanı | Kar Al öğesine giriş yapma alanı |
ActP_Lots_edit3 | Giriş alanı | Hacim görüntüleme alanı (salt okunur) |
ActP_limpr_edit3 | Giriş alanı | Stoplimit talimatının fiyatını girmek için alan |
ActP_mag_edit3 | Giriş alanı | Sihirli sayıları görüntüleme alanı (salt okunur) |
ActP_comm_edit3 | Giriş alanı | Açıklamalar için alan |
ActP_exp_edit3 | Giriş alanı | Sona erme süresi girme alanı |
ActP_Pr_edit3 | Giriş alanı | Talimat yürütme fiyatını girme alanı |
ActP_ticket_edit3 | Giriş alanı | Talimat bileti görüntüleme alanı (salt okunur) |
Tablo 4. "Talimatların değiştirilmesi / kaldırılması" panelinin öğelerinin listesi
2.5 Ayarlar
Aşağıda, açılır listeden düğmelerin, etiketlerin ve metinlerin rengini seçeceğiz ve çeşitli yazı tipi boyutlarını ayarlayacağız.
Adı | Tür | Açıklama |
---|---|---|
ActP_col1_button6 | Açılır liste | Düğmeler için renk seçimi listesi |
ActP_col2_button6 | Açılır liste | Etiketler için renk seçimi listesi |
ActP_col3_button6 | Açılır liste | Metin rengi seçimi listesi |
ActP_font_edit6 | Giriş alanı | Metin boyutunu belirtme alanı |
Tablo 5. "Ayarlar" panelinin öğelerinin listesi
Kullanılmıyorsa, paneli küçültme olasılığını oluşturmak için bir düğme de eklenir. "Destek çizgileri" gibi bir enstrümanın varlığını fark etmiş olabilirsiniz. Bunlar nedir ve neden onlara ihtiyacımız var? Bu çizgilerin kullanımı yoluyla, yalnızca fareyi kullanarak bu satırları istenen fiyata/zamana sürükleyerek Zararı Durdur, Kar Al, bekleyen bir talimatın tetiklenme fiyatı, bir durdurma limiti talimatının fiyatı (yatay çizgiler) ve ayrıca ertelenmiş bir talimatın (dikey çizgi) sona erme süresini belirleyebileceğiz.
Sonuçta, görsel bir kurulum, metinsel olandan daha elverişlidir (uygun alana fiyatları / zamanı manuel olarak girerek). Ayrıca, bu çizgiler bize seçilen bir talimatın parametresinin "vurguları" olarak hizmet edecektir. Çok fazla talimat olabileceği için, genellikle fiyatları gösteren standart terminal gölgeli çizgiler çok kafa karıştırıcı olabilir.
3. Arayüz Oluşturmaya Genel Yaklaşım
Böylece hedefimizi başarılı bir şekilde ortaya koyduk; alım satımda bir grafik asistan biçimi oluşturmak. Bu amaç doğrultusunda, en kullanıcı dostu arayüze ihtiyacımız var. İlk olarak, tüm kontrol öğelerinin (ve çok sayıda olacak) yazılım kullanılarak oluşturulması gerekeceği ve dolayısıyla nesnelerin pozisyonunun ve boyutunun önceden hesaplanması gerektiği net olmalıdır.
Şimdi, nesnelerin koordinatlarını hesaplayarak, üst üste binmemelerine ve net bir şekilde görülebilir olmalarına dikkat ettiğimiz uzun, meşakkatli ve zor bir süreçten geçtiğimizi hayal edin; tüm bu süreçten sonra yeni bir nesne eklemeye ihtiyacımız oldu; bu durumda tüm planımızı yeniden tasarlamamız gerekiyor!
Hızlı Uygulama Geliştirme ortamı (Delphi, C++ Builder vb.) hakkında bilgi sahibi olanlar, en karmaşık kullanıcı arayüzünün ne kadar hızlı oluşturulabileceğini bilirler.
O halde MQL5 kullanarak bunu uygulamaya çalışalım. İlk olarak, fare yardımıyla, kontrol nesnelerini en uygun şekilde konumlandırıyor ve boyutlarını ayarlıyoruz. Ardından, grafikteki tüm nesnelerin özelliklerini okuyan ve bunları bir dosyaya kaydeden basit bir script dosyası yazıyoruz; gerektiğinde bu özellikleri kolayca alabileceğiz ve nesneleri herhangi bir grafik üzerinde tamamen yeniden oluşturabileceğiz.
Script dosyasının kodu şu şekilde görünebilir:
//+------------------------------------------------------------------+ //| Component properties writer.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" #property script_show_inputs input int interfaceID=1; //input parameter - the identifier of the stored interface //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- //Open file for writing int handle=FileOpen("Active_Panel_scheme_"+IntegerToString(interfaceID)+".bin", FILE_WRITE|FILE_BIN); if(handle!=INVALID_HANDLE) { //We will go all the objects on the chart for(int i=0;i<ObjectsTotal(0);i++) { string name=ObjectName(0,i); //And write their properties in the file FileWriteString(handle,name,100); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_TYPE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_XDISTANCE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_YDISTANCE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_XSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_YSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_COLOR)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_STYLE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_WIDTH)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_BACK)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_SELECTED)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_SELECTABLE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_READONLY)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_FONTSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_STATE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_BGCOLOR)); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_TEXT),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_FONT),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_BMPFILE,0),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_BMPFILE,1),100); FileWriteDouble(handle,ObjectGetDouble(0,name,OBJPROP_PRICE)); } //Close file FileClose(handle); Alert("Done!"); } } //+------------------------------------------------------------------+
Gördüğünüz gibi, kod son derece basittir; tüm grafik nesnelerinin bazı özelliklerini bir ikili dosyaya yazar. En önemli şey, dosyayı okurken kaydedilen özelliklerin sıra düzenini unutmamaktır.
Script dosyası hazır; arayüzün oluşturulmasına dönelim.
Yapacağımız ilk şey, ana menüyü sekmelerinin türüne göre düzenlemek. Peki neden sekmelere ihtiyacımız var? Çünkü çok fazla nesne var ve hepsini ekrana sığdırmak sorun olurdu. Ve nesneler buna göre gruplandırıldığı için (yukarıdaki tabloya bakınız), her grubu ayrı bir sekmeye yerleştirmek daha kolaydır.
Böylece, Ekle -> Nesne -> Düğme terminal menüsünü kullanarak, grafiğin üst kısmında ana menümüz olarak işlev görecek olan beş düğme oluşturacağız.
Şek. 1 Panel sekmeleri
Nesnelerin "Ctrl" tuşu basılı tutulurken biri seçilip fare ile sürüklenerek kolayca kopyalanabileceğini unutmayın. Bunu yaparak, orijinalinin yerini değiştirmek yerine nesnenin bir kopyasını oluşturacağız.
Nesnelerin adlarına özel dikkat gösterilerek tümünün "ActP" ile başlaması gerektiği unutulmamalıdır. Ayrıca, nesnenin ana menü çubuğuna ait olduğunu gösteren dizenin adına "ana" öğesini ekliyoruz.
Şekil 2. Nesnelerin listesi (panel sekmeleri)
Benzer şekilde, sekme içeriklerini yeni grafiğe uygulayalım. Her sekmenin içeriği ayrı bir grafiğe yerleştirilmelidir!
"Piyasa" sekmesi:
Şekil 3. "Piyasa" sekmesinin öğeleri
Şekil 4. "Bekleyen" sekmesinin öğeleri
Ayarlar sekmesi:
Şekil 5. "Ayarlar" sekmesinin öğeleri
Son "Değiştir / kapat" sekmesi farklıdır; bekleyen talimatları değiştirme / silme ve ayrıca alım satım yatırımlarını değiştirme ve kapatma görevi görecektir. Alım satım işlemlerini içeren işleri ve talimatları içeren işleri iki ayrı alt sekmeye ayırmak mantıklı olacaktır. Öncelikle, çalışmak için bir talimat veya alım satım işlemi seçeceğimiz açılır listeyi etkinleştirecek bir düğme oluşturalım.
Şekil 6. "Değiştir/Kapat" sekmesinin öğeleri" tab
Daha sonra, alt sekmeler oluşturuyoruz. Alım satım işlemleriyle çalışmak için:
Şekil 7. Pozisyonlarla çalışma öğeleri
Ve talimatlarla çalışmak için:
Şekil 8. Talimatlarla çalışma alt sekmesi
Hepsi bu kadar, arayüz oluşturuldu.
Her sekmeyi ayrı bir dosyaya kaydetmek için script dosyasını grafiklerin her birine uygularız. "interfaceID" giriş parametresi her sekme için farklı olmalıdır:
- 0 - Giriş sayfası
- 1 - Piyasa
- 2 - Bekleyen
- 3 - Alım satım / talimat seçim listesini etkinleştirmek için düğme
- 4 - Ayarlar
- 6 - Alım satım işlemleriyle çalışmak için alt sekme
- 7 - Talimatlarla çalışmak için alt sekme
5 numaralı sekme, ana menüdeki "Pencereyi simge durumuna küçült" düğmesine karşılık gelir; bu nedenle üzerinde herhangi bir nesne yoktur ve onu atlayabiliriz.
Tüm bu işlemlerden sonra, terminalin -> MQL5 -> dizin klasöründe aşağıdaki dosyalar görünecektir:
Şekil 9. Panel şemalarının dosya listesi
4. Arayüz Öğelerini İndirme
Artık arayüz öğeleri dosyalarda saklanır ve çalıştırılmaya hazırdır. İlk olarak panelimizin konumlandırılacağı yeri belirleyelim. Doğrudan ana grafiğe konumlandırırsak bu, fiyatlar grafiğini bloke edecektir; bu, çok elverişsizdir olur. Bu nedenle paneli ana grafiğin alt penceresine yerleştirmek en mantıklısı olacaktır. Bir gösterge bu bölmeyi oluşturabilir.
O halde, onu oluşturalım.
#property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" #property indicator_separate_window //place the indicator in a separate window int OnInit() { //--- indicator buffers mapping //Set the short name of the indicator IndicatorSetString(INDICATOR_SHORTNAME, "AP"); //--- return(0); } int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { //--- //--- return value of prev_calculated for next call return(rates_total); }
Kod çok basittir; zira bu göstergenin ana işlevi çeşitli hesaplamalar yapmaktan ziyade alt pencerelerin oluşturulmasıdır. Yapacağımız tek şey, alt penceresini bulabileceğimiz göstergenin "kısa" bir adını yüklemektir. Göstergeye bir grafik derleyip uygulayacağız ve bir pencere görünecek.
Şimdi Expert Advisor paneline odaklanalım. Yeni bir Expert Advisor oluşturacağız.
OnInit() işlevi aşağıdaki işleçleri içerecektir:
double Bid,Ask; //variables for current prices datetime time_current; //time of last tick int wnd=-1; //index of the window with an indicator bool last_loaded=false; //flag indicating whether it's a first initialization or not //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //Start the timer at intervals of 1 second EventSetTimer(1); //Get the latest prices get_prices(); //Define the window with an indicator wnd=ChartWindowFind(0,"AP"); //If the first initialization - create interface if(!last_loaded) create_interface(); //--- return(0); }
Burada bir zamanlayıcı başlatıyoruz (bunun neden yapıldığı aşağıda açıklanacaktır), ChartWindowFind'ı kullanarak piyasadaki en son fiyatları alın, gösterge penceresini bulun ve bunu bir değişken olarak kaydedin. last_loaded bayrağı - bunun Expert Advisor'ın ilk başlatılışı olup olmadığını gösterir. Bu bilgiler, yeniden başlatma sırasında arayüzün yeniden yüklenmesini önlemek için gereklidir.
create_interface() işlevi şu şekilde görünür:
//+------------------------------------------------------------------+ //| Function of the interface creation | //+------------------------------------------------------------------+ void create_interface() { //if reset settings is selected if(Reset_Expert_Settings) { //Reset GlobalVariableDel("ActP_buttons_color"); GlobalVariableDel("ActP_label_color"); GlobalVariableDel("ActP_text_color"); GlobalVariableDel("ActP_font_size"); } //Create the main menu interface ApplyScheme(0); //Create the interface tab "Market" ApplyScheme(1); //Set all objects as unmarked Objects_Selectable("ActP",false); //redraw the chart ChartRedraw(); }
İlk adım, "ayarları sıfırla" giriş parametresini kontrol etmektir ve yüklüyse, ayarlardan sorumlu genel değişkenleri kaldırın. Bu işlemin paneli nasıl etkilediği aşağıda açıklanacaktır. Ayrıca, ApplyScheme () işlevi bir dosyadan bir arayüz oluşturacaktır.
//+------------------------------------------------------------------+ //| The function for the interface loading | //| ID - ID of the saved interface | //+------------------------------------------------------------------+ bool ApplyScheme(int ID) { string fname="Active_Panel_scheme_custom_"+IntegerToString(ID)+".bin"; //download the standard scheme if there isn't saved scheme if(!FileIsExist(fname)) fname="Active_Panel_scheme_"+IntegerToString(ID)+".bin"; //open file for reading int handle=FileOpen(fname,FILE_READ|FILE_BIN); //file opened if(handle!=INVALID_HANDLE) { //Loading all objects while(!FileIsEnding(handle)) { string obj_name=FileReadString(handle,100); int _wnd=wnd; //the auxiliary lines are in the main window if(StringFind(obj_name,"line")>=0) _wnd=0; ENUM_OBJECT obj_type=FileReadInteger(handle); //creating object ObjectCreate(0, obj_name, obj_type, _wnd, 0, 0); //and apply the properties ObjectSetInteger(0,obj_name,OBJPROP_XDISTANCE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_YDISTANCE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_XSIZE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_YSIZE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_COLOR,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_STYLE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_WIDTH,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_BACK,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_SELECTED,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_SELECTABLE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_READONLY,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_FONTSIZE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_STATE,FileReadInteger(handle)); ObjectSetInteger(0,obj_name,OBJPROP_BGCOLOR,FileReadInteger(handle)); ObjectSetString(0,obj_name,OBJPROP_TEXT,FileReadString(handle,100)); ObjectSetString(0,obj_name,OBJPROP_FONT,FileReadString(handle,100)); ObjectSetString(0,obj_name,OBJPROP_BMPFILE,0,FileReadString(handle,100)); ObjectSetString(0,obj_name,OBJPROP_BMPFILE,1,FileReadString(handle,100)); ObjectSetDouble(0,obj_name,OBJPROP_PRICE,FileReadDouble(handle)); //Set color for the objects if(GlobalVariableCheck("ActP_buttons_color") && obj_type==OBJ_BUTTON) ObjectSetInteger(0,obj_name,OBJPROP_BGCOLOR,GlobalVariableGet("ActP_buttons_color")); if(GlobalVariableCheck("ActP_label_color") && obj_type==OBJ_LABEL) ObjectSetInteger(0,obj_name,OBJPROP_COLOR,GlobalVariableGet("ActP_label_color")); if(GlobalVariableCheck("ActP_text_color") && (obj_type==OBJ_EDIT || obj_type==OBJ_BUTTON)) ObjectSetInteger(0,obj_name,OBJPROP_COLOR,GlobalVariableGet("ActP_text_color")); if(GlobalVariableCheck("ActP_font_size") && (obj_type==OBJ_EDIT || obj_type==OBJ_LABEL)) ObjectSetInteger(0,obj_name,OBJPROP_FONTSIZE,GlobalVariableGet("ActP_font_size")); //Set global variable font size if(obj_name=="ActP_font_edit6" && GlobalVariableCheck("ActP_font_size")) ObjectSetString(0,obj_name,OBJPROP_TEXT,IntegerToString(GlobalVariableGet("ActP_font_size"))); } //Close file FileClose(handle); return(true); } return(false); }
Bir kez daha, bu konuda karmaşık herhangi bir şey yok. İşlev, önceden kaydedilmiş bir arayüz şeması ile istenen dosyayı açacak ve bunu, daha önce tanımladığımız pencerede (gösterge penceresi) oluşturacaktır. Ayrıca nesnelerin renklerini ve yazı tipi boyutlarını terminalin genel değişkenlerinden seçiyoruz.
Objects_Selectable () işlevi, düğmelerin hareketlerini açmak ve gerekli bir nesnenin yanlışlıkla silinmesini önlemek için yardımcı çizgiler hariç tüm nesneleri işaretsiz hale getirir.
//+------------------------------------------------------------------+ //| Function of setting objects as unselectable | //+------------------------------------------------------------------+ void Objects_Selectable(string IDstr,bool flag) { //Check all the objects for(int i=ObjectsTotal(0);i>=0;i--) { string n=ObjectName(0,i); //If the object belongs to the panel if(StringFind(n,IDstr)>=0) { //Lines remain untouched if(!flag) if(StringFind(n,"line")>-1) continue; //Set everything unselectable except the lines ObjectSetInteger(0,n,OBJPROP_SELECTABLE,flag); } } }
Şimdi OnTick() işlevine bakalım. Bu, piyasadaki en son fiyatları elde etmemize yardımcı olacaktır.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //Get the latest prices get_prices(); }
get_prices() işlevi şu şekildedir:
//+------------------------------------------------------------------+ //| Function obtain information on tick | //+------------------------------------------------------------------+ void get_prices() { MqlTick tick; //if the tick was if(SymbolInfoTick(Symbol(),tick)) { //obtain information Bid=tick.bid; Ask=tick.ask; time_current=tick.time; } }
Ve OnDeinit () hakkında şunu unutmayın:
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- //if the deinitialisation reason isn't the timeframe or symbol change if(reason!=REASON_CHARTCHANGE) { //reset initialization flag last_loaded=false; //Delete all panel objects ObjectsDeleteAll_my("ActP"); //Delete files with the saved state of the tabs FileDelete("Active_Panel_scheme_custom_1.bin"); FileDelete("Active_Panel_scheme_custom_2.bin"); FileDelete("Active_Panel_scheme_custom_3.bin"); FileDelete("Active_Panel_scheme_custom_4.bin"); FileDelete("Active_Panel_scheme_custom_5.bin"); } //otherwise set a flag else last_loaded=true; //stop the timer EventKillTimer(); }
İlk önce başlatmadan kaldırmanın nedenini kontrol edin: Bu, bir zaman dilimi ve / veya sembollerdeki bir değişiklikten kaynaklanıyorsa panel öğesini silmeyeceğiz. Diğer tüm durumlarda, ObjectsDeleteAll_my () işlevini kullanarak tüm öğeleri kaldırın.
//+------------------------------------------------------------------+ //| The function deletes all panel objects | //| IDstr - object identifier | //+------------------------------------------------------------------+ void ObjectsDeleteAll_my(string IDstr) { //check all the objects for(int i=ObjectsTotal(0);i>=0;i--) { string n=ObjectName(0,i); //if the name contains the identifier - remove the object if(StringFind(n,IDstr)>=0) ObjectDelete(0,n); } }
Expert Advisor'ı derleyip çalıştırdıktan sonra aşağıdaki sonucu elde ederiz:
Şekil 10. Expert Advisor çalışma örneği
Ancak, bu nesnelerin işlemimize yanıt vermesini sağlayana kadar tüm bunlardan çok az fayda görürüz.
5. Olay İşleme
Arayüz oluşturuldu; şimdi onu çalıştırmamız gerekiyor. Nesnelerle yaptığımız tüm işlemlerimiz belirli olaylar üretir. OnChartEvent işlevi OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam), ChartEvent olaylarının işleme mekanizmasıdır. Olayların arasından şunlarla ilgileniyoruz:
- CHARTEVENT_CLICK - grafiğe tıklayın
- CHARTEVENT_OBJECT_ENDEDIT - giriş alanını düzenlemeyi bitirin
- CHARTEVENT_OBJECT_CLICK - grafik nesnesine tıklayın
Bizim durumumuzda, id işlevinin parametresi olayın kimliğini gösterir, sparam bu olayı oluşturan nesnenin adını gösterir; diğer tüm parametreler bizi ilgilendirmiyor.
Keşfedeceğimiz ilk olay: Ana menü düğmesine tıklayın.
5.1. Ana Menü Olaylarını İşleme
Ana menünün beş düğmeden oluştuğunu hatırlayın. Bunlardan birine tıklandığında bunun basılı bir moda geçmesi, bizi doğru arayüze yönlendirmesi ve uygun sekmeleri yüklemesi gerekir. Ardından diğer menü düğmelerinin tümü basılmamış moda geçmelidir.
//+------------------------------------------------------------------+ //| Event handlers | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //main menu button click if(sparam=="ActP_main_1") {Main_controls_click(1); ChartRedraw(); return;} //Here we execute the corresponding operators if(sparam=="ActP_main_2") {Main_controls_click(2); ChartRedraw(); return;} if(sparam=="ActP_main_3") {Main_controls_click(3); ChartRedraw(); return;} if(sparam=="ActP_main_4") {Main_controls_click(4); ChartRedraw(); return;} if(sparam=="ActP_main_5") {Main_controls_click(5); ChartRedraw(); return;} ... } ... }
Menü düğmesine tıklandığında, Main_controls_click() işlevini gerçekleştirdik. ChartRedraw() işlevini kullanarak grafiği yeniden çizelim ve işlevi tamamlayalım. Yürütmeyi tamamlamalıyız; zira aynı anda yalnızca bir nesneye tıklanabilir; bu nedenle diğer tüm uygulamalar CPU zamanının boşa harcanmasına neden olacaktır.
//+------------------------------------------------------------------+ //| Tab processor | //| ID - index of clicked tab | //+------------------------------------------------------------------+ void Main_controls_click(int ID) { int loaded=ID; //we will go all tabs for(int i=1;i<6;i++) { //for all except the selected set inactive if(i!=ID) { //also remember the last active tab if(ObjectGetInteger(0,"ActP_main_"+IntegerToString(i),OBJPROP_STATE)==1) loaded=i; ObjectSetInteger(0,"ActP_main_"+IntegerToString(i),OBJPROP_STATE,0); } } //if(loaded==ID) return; //set an active state for the selected ObjectSetInteger(0,"ActP_main_"+IntegerToString(ID),OBJPROP_STATE,1); //delete the drop-down lists DeleteLists("ActP_orders_list_"); DeleteLists("ActP_color_list_"); //and set the list buttons to the unpressed state ObjectSetInteger(0,"ActP_ord_button5",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_col1_button6",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_col2_button6",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_col3_button6",OBJPROP_STATE,0); //save state of the last active tab SaveScheme(loaded); //remove old tab DeleteScheme("ActP"); //and load a new ApplyScheme(ID); //Set all objects as unselected Objects_Selectable("ActP",false); }
Objects_Selectable() ve ApplyScheme() işlevleriyle tanıştık, daha sonra DeleteLists() işlevine döneceğiz.
SaveScheme() işlevi, yeniden yükleme sırasında nesnelerin tüm özelliklerini koruması için bir arayüz dosyası kaydeder:
//+------------------------------------------------------------------+ //| Interface saving function | //+------------------------------------------------------------------+ void SaveScheme(int interfaceID) { //open file for writing int handle=FileOpen("Active_Panel_scheme_custom_"+IntegerToString(interfaceID)+".bin",FILE_WRITE|FILE_BIN); //if file opened if(handle!=INVALID_HANDLE) { //go all the chart objects for(int i=0;i<ObjectsTotal(0);i++) { string name=ObjectName(0,i); //if the object belongs to the panel if(StringFind(name,"ActP")<0) continue; //and it isn't a tab if(StringFind(name,"main")>=0) continue; //write the object properties to a file FileWriteString(handle,name,100); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_TYPE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_XDISTANCE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_YDISTANCE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_XSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_YSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_COLOR)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_STYLE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_WIDTH)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_BACK)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_SELECTED)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_SELECTABLE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_READONLY)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_FONTSIZE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_STATE)); FileWriteInteger(handle,ObjectGetInteger(0,name,OBJPROP_BGCOLOR)); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_TEXT),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_FONT),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_BMPFILE,0),100); FileWriteString(handle,ObjectGetString(0,name,OBJPROP_BMPFILE,1),100); FileWriteDouble(handle,ObjectGetDouble(0,name,OBJPROP_PRICE)); } //Close file FileClose(handle); } }
DeleteScheme() işlevi, sekme nesnelerini kaldırır.
//+------------------------------------------------------------------+ //| Function to delete all the panel objects, except tabs | //+------------------------------------------------------------------+ void DeleteScheme(string IDstr) { //we will go through all the objects for(int i=ObjectsTotal(0);i>=0;i--) { string n=ObjectName(0,i); //remove everything but the tab if(StringFind(n,IDstr)>=0 && StringFind(n,"main")<0) ObjectDelete(0,n); } }
Böylece, Main_controls_click() işlevini gerçekleştirerek eski sekmeyi kaldıracağız, önceden kaydedeceğiz ve yeni bir tane yükleyeceğiz.
Expert Advisor'ı derleyerek sonuçları göreceğiz.
Şimdi ana menü düğmesine tıklayacağız, yeni sekmeleri yükleyerek onları orijinal sekmelerin durumunda tutacağız.
Şekil 11. "Bekleyen" sekmesinin öğeleri
Şekil 12. "Değiştir/Kapat" sekmesinin öğeleri
Şekil 13. "Ayarlar" sekmesinin öğeleri
Bu noktada, ana menünün işlemesini bitirebiliriz; zira artık işlevlerini tam olarak yerine getiriyor.
5.2. "Bayrak" Bileşen Olayını İşleme
Yardımcı çizgilerin ve durdurma limiti talimatlarının ayarı "bayrak" bileşenleri kullanılarak yapılır, ancak bu, MT5'in grafik nesneleri listesinde değildir. O halde, onu oluşturalım. Gerçekte "açık" ve "kapalı" durumuna sahip bir resim olan bir "grafik etiket" nesnesi vardır. Durum, nesneye tıklanarak değiştirilebilir. Her durum için ayrı bir resim ayarlanabilir. Her durum için bir resim seçin:
- Etkinleştirildi
- Devre dışı bırakıldı
Resimleri nesnenin özelliklerinde ayarlayalım:
Şekil 13. "Bayrak" öğesinin özelliklerini ayarlama
Resimlerin listede yer alabilmesi için "Terminal klasörü-> MQL5-> Resimler" klasöründe konumlandırılması ve ".Bmp" uzantılı olması gerektiğini hatırlatmak isteriz.
Bir nesneye tıkladığınızda meydana gelen olayları işlemeye dönelim. Alım satım işleminin açılışında yardımcı çizgilerin yerleştirilmesinden sorumlu olan bayrak örneğini kullanacağız.
//click on the flag of the setting of auxiliary lines during transaction opening if(sparam=="ActP_DealLines_check1") { //Check the flag state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //If the flag is set if(selected) { //Retrieve the value of the stop loss and take profit from the input fields string SL_txt=ObjectGetString(0, "ActP_SL_edit1", OBJPROP_TEXT); string TP_txt=ObjectGetString(0, "ActP_TP_edit1", OBJPROP_TEXT); double val_SL, val_TP; //If the Stop field is not empty //save the value if(SL_txt!="") val_SL=StringToDouble(SL_txt); //if empty else { //Take the max. and min. prices of chart double pr_max=ChartGetDouble(0, CHART_PRICE_MAX); double pr_min=ChartGetDouble(0, CHART_PRICE_MIN); //Set the stop at the 1/3 of the chart price range val_SL=pr_min+(pr_max-pr_min)*0.33; } //Similarly processes the Take if(TP_txt!="") val_TP=StringToDouble(TP_txt); else { double pr_max=ChartGetDouble(0, CHART_PRICE_MAX); double pr_min=ChartGetDouble(0, CHART_PRICE_MIN); val_TP=pr_max-(pr_max-pr_min)*0.33; } //Move the line to new positions ObjectSetDouble(0, "ActP_SL_line1", OBJPROP_PRICE, val_SL); ObjectSetDouble(0, "ActP_TP_line1", OBJPROP_PRICE, val_TP); } //If the flag is unset else { //remove the lines ObjectSetDouble(0, "ActP_SL_line1", OBJPROP_PRICE, 0); ObjectSetDouble(0, "ActP_TP_line1", OBJPROP_PRICE, 0); } //redraw the chart ChartRedraw(); //and finish the function return; }
Bekleyen talimatların kapatılması / değiştirilmesi sekmesinde yardımcı çizgilerin işlenmesinden ve yüklenmesinden sorumlu olan bayraklar için de aynı yöntem kullanılır. Bu nedenle, bu makalede onlarla ilgili ayrıntılara girmeyeceğiz. Bunlar hakkında bilgi sahibi olmak isteyenler Expert Advisor kodunu kullanabilirler.
"Bekleyen" sekmesindeki stoplimit talimatları bayrağının ayarı aşağıdaki işleyiciyi içerir:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //Click on the orders stoplimit check box if(sparam=="ActP_limit_check2") { //Check the flag state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); if(selected) //if flag is set { //set the new color for the price edit ObjectSetInteger(0, "ActP_limpr_edit2", OBJPROP_BGCOLOR, White); //enable it for the edit ObjectSetInteger(0, "ActP_limpr_edit2", OBJPROP_READONLY, false); //установим в поле значение текущей цены //Set the current price as the field value ObjectSetString(0, "ActP_limpr_edit2", OBJPROP_TEXT, DoubleToString(Bid, _Digits)); //if the auxiliary lines are allowed //move them if(ObjectGetInteger(0, "ActP_DealLines_check2", OBJPROP_STATE)==1) ObjectSetDouble(0, "ActP_lim_line2", OBJPROP_PRICE, Bid); } //if flag is unset else { //set the field unavailable for editing ObjectSetInteger(0, "ActP_limpr_edit2", OBJPROP_BGCOLOR, LavenderBlush); //set the field color ObjectSetInteger(0, "ActP_limpr_edit2", OBJPROP_READONLY, true); //and "empty" text ObjectSetString(0, "ActP_limpr_edit2", OBJPROP_TEXT, ""); //if the auxiliary lines are allowed //move them to the zero point if(ObjectGetInteger(0, "ActP_DealLines_check2", OBJPROP_STATE)==1) ObjectSetDouble(0, "ActP_lim_line2", OBJPROP_PRICE, 0); } } ... } ... }
Artık bayraklarla çalışmayı tamamladık. Kendi üretimimiz olan şu nesneyi ele alalım; "radyo düğmeleri grubu".
5.3. "Radyo düğmeleri Grubu" Bileşen Olayını İşleme
Bu bileşeni kullanarak, bir alım satım işleminin türünü ve talimatın sona erme süresi türünü seçiyoruz. Tıpkı bayraklarda olduğu gibi, grafik etiketleri kullanacağız, ancak bu kez yeni resimlerle birlikte.
- Etkinleştirildi
- Devre dışı bırakıldı
Ancak burada sorun, tıkladığınız düğme dışındaki tüm radyo düğmelerini etkin olmayan bir duruma sıfırlama gerekliliği nedeniyle karmaşıktır. Talimat yürütme türünün radyo düğmesi örneğini göz önünde bulundurun:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on radion button 1 - order execution type if(sparam=="ActP_Exe1_radio2") { //check the radio button state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //set the appropriate state ObjectSetInteger(0,sparam,OBJPROP_STATE, 1); //if it selected if(selected) { //reset the other radio buttons ObjectSetInteger(0, "ActP_Exe2_radio2", OBJPROP_STATE, false); ObjectSetInteger(0, "ActP_Exe3_radio2", OBJPROP_STATE, false); //redraw the chart ChartRedraw(); //finish the execution of function return; } //redraw the chart ChartRedraw(); //finish the execution of function return; } //Similarly for the radio button 2 if(sparam=="ActP_Exe2_radio2") { bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); ObjectSetInteger(0,sparam,OBJPROP_STATE, 1); if(selected) { ObjectSetInteger(0, "ActP_Exe1_radio2", OBJPROP_STATE, false); ObjectSetInteger(0, "ActP_Exe3_radio2", OBJPROP_STATE, false); ChartRedraw(); return; } ChartRedraw(); return; } //Similarly for the radio button 3 if(sparam=="ActP_Exe3_radio2") { bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); ObjectSetInteger(0,sparam,OBJPROP_STATE, 1); if(selected) { ObjectSetInteger(0, "ActP_Exe1_radio2", OBJPROP_STATE, false); ObjectSetInteger(0, "ActP_Exe2_radio2", OBJPROP_STATE, false); ChartRedraw(); return; } ChartRedraw(); return; } ... } ... }
Talimat sona erme süresi türü radyo düğmeleri, yalnızca üçüncü düğmeye tıkladığınızda ek bir adım gerçekleştirmeniz gerektiği gerçeğinde farklılık gösterir; bir talimatın sona erme süresinin giriş saatinde yeni bir tarih ayarlamanız gerekir:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //Click on the 3rd radio button - order expiration date if(sparam=="ActP_exp3_radio2") { //checking it state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); ObjectSetInteger(0,sparam,OBJPROP_STATE, 1); //if it selected if(selected) { //reset the remained radio buttons ObjectSetInteger(0, "ActP_exp1_radio2", OBJPROP_STATE, false); ObjectSetInteger(0, "ActP_exp2_radio2", OBJPROP_STATE, false); //set the new date to the date edit field ObjectSetInteger(0, "ActP_exp_edit2", OBJPROP_BGCOLOR, White); ObjectSetInteger(0, "ActP_exp_edit2", OBJPROP_READONLY, false); ObjectSetString(0, "ActP_exp_edit2", OBJPROP_TEXT, TimeToString(time_current)); //if auxiliary lines are allowed //set the new time line if(ObjectGetInteger(0, "ActP_DealLines_check2", OBJPROP_STATE)==1) ObjectSetInteger(0, "ActP_exp_line2", OBJPROP_TIME, time_current); ChartRedraw(); return; } //if it isn't selected else { //set the edit field as not available for editing ObjectSetInteger(0, "ActP_exp_edit2", OBJPROP_BGCOLOR, LavenderBlush); ObjectSetInteger(0, "ActP_exp_edit2", OBJPROP_READONLY, true); //remove the auxiliary line if(ObjectGetInteger(0, "ActP_DealLines_check2", OBJPROP_STATE)==1) ObjectSetInteger(0, "ActP_exp_line2", OBJPROP_TIME, 0); } ChartRedraw(); return; ... } ... }
Artık radyo düğmeleriyle çalışmayı tamamladık.
5.4. Açılır listelerin olaylarını oluşturma ve işleme
Değiştirme / kapatma / kaldırma ve renk seçimleri paneli için talimat / alım satım işlemi seçimi için açılır listeyi kullanacağız. Alım satım işlemleri / talimatlar listesiyle başlayalım.
"Değiştirme / Kapatma" sekmesinde görünen ilk şey "Bir talimat seç " etiketli bir düğmedir; bu, listeyi etkinleştiren düğme olacaktır. Bunun üzerine tıkladığınızda açılır liste açılmalı ve seçimimizi yaptıktan sonra tekrar kapanmalıdır. Bu düğmenin CHARTEVENT_OBJECT_CLICK işleyicisine bir göz atalım:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the drop-down list activate button (order select) if(sparam=="ActP_ord_button5") { //check status bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //the list is activated if(selected)// the list is selected { //delete interface DeleteScheme("ActP", true); //arrays for serving the information about the orders string info[100]; //array for the tickets int tickets[100]; //initialize it ArrayInitialize(tickets, -1); //get orders info get_ord_info(info, tickets); //create the list create_list(info, tickets); } //the list isn't active else { //delete it DeleteLists("ActP_orders_list_"); } //redraw the chart ChartRedraw(); //finish the function return; } ... } ... }
Öncelikli hedefimiz, alım satım işlemlerinin/talimatların piyasada olup olmadığını belirlemek ve varsa bunlardan bilgi çıkarıp listede görüntülemektir. get_ord_info() işlevi, bu rolü gerçekleştirir:
//+------------------------------------------------------------------+ //| The function for obtaining the information about orders | //+------------------------------------------------------------------+ void get_ord_info(string &info[],int &tickets[]) { //initialize the counter int cnt=0; string inf; //if there is an open position if(PositionSelect(Symbol())) { //combine all order infomation in a single line double vol=PositionGetDouble(POSITION_VOLUME); int typ=PositionGetInteger(POSITION_TYPE); if(typ==POSITION_TYPE_BUY) inf+="BUY "; if(typ==POSITION_TYPE_SELL) inf+="SELL "; inf+=DoubleToString(vol, MathCeil(MathAbs(MathLog(vol)/MathLog(10))))+" lots"; inf+=" at "+DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN), Digits()); //write the results info[cnt]=inf; tickets[cnt]=0; //increment the counter cnt++; } //all orders for(int i=0;i<OrdersTotal();i++) { //get ticket int ticket=OrderGetTicket(i); //if order symbol is equal to chart symbol if(OrderGetString(ORDER_SYMBOL)==Symbol()) { //combine all order infomation in a single line inf="#"+IntegerToString(ticket)+" "; int typ=OrderGetInteger(ORDER_TYPE); double vol=OrderGetDouble(ORDER_VOLUME_CURRENT); if(typ==ORDER_TYPE_BUY_LIMIT) inf+="BUY LIMIT "; if(typ==ORDER_TYPE_SELL_LIMIT) inf+="SELL LIMIT "; if(typ==ORDER_TYPE_BUY_STOP) inf+="BUY STOP "; if(typ==ORDER_TYPE_SELL_STOP) inf+="SELL STOP "; if(typ==ORDER_TYPE_BUY_STOP_LIMIT) inf+="BUY STOP LIMIT "; if(typ==ORDER_TYPE_SELL_STOP_LIMIT) inf+="SELL STOP LIMIT "; inf+=DoubleToString(vol, MathCeil(MathAbs(MathLog(vol)/MathLog(10))))+" lots"; inf+=" at "+DoubleToString(OrderGetDouble(ORDER_PRICE_OPEN), Digits()); //write the results info[cnt]=inf; tickets[cnt]=ticket; //increment the counter cnt++; } } }
Bu, bir blok bilgisinde birleşecek ve bilet ve alım satım talimatı verecektir.
Ayrıca create_list() işlevi bu bilgilere dayanarak bir liste oluşturacaktır:
//+------------------------------------------------------------------+ //| The function creates list of positions | //| info - array for the positions | //| tickets - array for the tickets | //+------------------------------------------------------------------+ void create_list(string &info[],int &tickets[]) { //get the coordinates of the list activation button int x=ObjectGetInteger(0,"ActP_ord_button5",OBJPROP_XDISTANCE); int y=ObjectGetInteger(0, "ActP_ord_button5", OBJPROP_YDISTANCE)+ObjectGetInteger(0, "ActP_ord_button5", OBJPROP_YSIZE); //get colors color col=ObjectGetInteger(0,"ActP_ord_button5",OBJPROP_COLOR); color bgcol=ObjectGetInteger(0,"ActP_ord_button5",OBJPROP_BGCOLOR); //get window height int wnd_height=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,wnd); int y_cnt=0; //proceed arrays for(int i=0;i<100;i++) { //break if end reached if(tickets[i]==-1) break; //calculate the list item coordinates int y_pos=y+y_cnt*20; //if the windiow limits are reachedl, start a new column if(y_pos+20>wnd_height) {x+=300; y_cnt=0;} y_pos=y+y_cnt*20; y_cnt++; string name="ActP_orders_list_"+IntegerToString(i)+" $"+IntegerToString(tickets[i]); //create element create_button(name,info[i],x,y_pos,300,20); //and set its properties ObjectSetInteger(0,name,OBJPROP_COLOR,col); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,0); ObjectSetInteger(0,name,OBJPROP_STATE,0); ObjectSetInteger(0,name,OBJPROP_FONTSIZE,8); ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bgcol); } }
Ve son olarak, DeleteLists () işlevleri listenin öğelerini kaldırır:
//+------------------------------------------------------------------+ //| The function for the list deletion | //+------------------------------------------------------------------+ void DeleteLists(string IDstr) { //proceed all objects for(int i=ObjectsTotal(0);i>=0;i--) { string n=ObjectName(0,i); //delete lists if(StringFind(n,IDstr)>=0 && StringFind(n,"main")<0) ObjectDelete(0,n); } }
Yani etkinleştirme düğmesine tıkladığınızda bir liste oluşturulur. Listedeki herhangi bir öğeye her tıklandığında belirli bir işlem gerçekleşmesi gerektiği için, onu çalıştırmamız gerekir. Spesifik olarak: Bir talimatla çalışmak için bir arayüzün yüklenmesi ve bu arayüzün talimat/alım satım hakkında bilgilerle doldurulması.
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... // Event - click on a graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //Click not on an item of order selection list if(StringFind(sparam, "ActP_orders_list_")<0) { //Remove it DeleteLists("ActP_orders_list_"); //Set the activation button to "unpressed" ObjectSetInteger(0, "ActP_ord_button5", OBJPROP_STATE, 0); //redraw chart ChartRedraw(); } //Click on the order selection list item else { //Set a new name for the activation button ObjectSetString(0, "ActP_ord_button5", OBJPROP_TEXT, ObjectGetString(0, sparam, OBJPROP_TEXT)); //Set the activation button to "unpressed" ObjectSetInteger(0, "ActP_ord_button5", OBJPROP_STATE, 0); //get ticket from the list item description int ticket=StringToInteger(StringSubstr(sparam, StringFind(sparam, "$")+1)); //Load the interface SetScheme(ticket); //and delete the list DeleteLists("ActP_orders_list_"); //chart redraw ChartRedraw(); } ... } ... }
İş bu noktada karmaşıklaşıyor. Listenin boyutunu ve nesnelerinin adlarını önceden bilmediğimiz için, listenin öğesinin adına erişerek ondan bilgi almamız gerekecek. SetScheme() işlevi, bir alım satım işlemiyle veya bekleyen bir talimatla çalışmak için uygun arayüzü kuracaktır:
//+------------------------------------------------------------------+ //| The function sets the interface depending on type: | //| position or pending order | //| t - ticket | //+------------------------------------------------------------------+ void SetScheme(int t) { //if position if(t==0) { //check for its presence if(PositionSelect(Symbol())) { //delete old scheme DeleteScheme("ActP",true); //and apply new ApplyScheme(6); //set position parameters SetPositionParams(); //the objects are unavailable for the selection Objects_Selectable("ActP",false); } } //if order if(t>0) { //check for its presence if(OrderSelect(t)) { //delete old scheme DeleteScheme("ActP",true); //and apply new ApplyScheme(7); //set order parameters SetOrderParams(t); //the objects are unavailable for the selection Objects_Selectable("ActP",false); } } }
SetPositionParams() ve SetOrderParams() işlevleri, yüklenen arayüzün gerekli özelliklerini yükler:
//+------------------------------------------------------------------+ //| Set position parameters for the objects | //+------------------------------------------------------------------+ void SetPositionParams() { //if position is exists if(PositionSelect(Symbol())) { //get its parameters double pr=PositionGetDouble(POSITION_PRICE_OPEN); double lots=PositionGetDouble(POSITION_VOLUME); double sl=PositionGetDouble(POSITION_SL); double tp=PositionGetDouble(POSITION_TP); double mag=PositionGetInteger(POSITION_MAGIC); //and set new values to the objects ObjectSetString(0,"ActP_Pr_edit4",OBJPROP_TEXT,str_del_zero(DoubleToString(pr))); ObjectSetString(0,"ActP_lots_edit4",OBJPROP_TEXT,str_del_zero(DoubleToString(lots))); ObjectSetString(0,"ActP_SL_edit4",OBJPROP_TEXT,str_del_zero(DoubleToString(sl))); ObjectSetString(0,"ActP_TP_edit4",OBJPROP_TEXT,str_del_zero(DoubleToString(tp))); if(mag!=0) ObjectSetString(0,"ActP_mag_edit4",OBJPROP_TEXT,IntegerToString(mag)); //redraw chart ChartRedraw(); } //if there isn't position, show message else MessageBox("There isn't open position for "+Symbol()); } //+------------------------------------------------------------------+ //| Set pending order parameters for the objects | //| ticket - order ticket | //+------------------------------------------------------------------+ void SetOrderParams(int ticket) { //if order exists if(OrderSelect(ticket) && OrderGetString(ORDER_SYMBOL)==Symbol()) { //get its parameters double pr=OrderGetDouble(ORDER_PRICE_OPEN); double lots=OrderGetDouble(ORDER_VOLUME_CURRENT); double sl=OrderGetDouble(ORDER_SL); double tp=OrderGetDouble(ORDER_TP); double mag=OrderGetInteger(ORDER_MAGIC); double lim=OrderGetDouble(ORDER_PRICE_STOPLIMIT); datetime expir=OrderGetInteger(ORDER_TIME_EXPIRATION); ENUM_ORDER_TYPE type=OrderGetInteger(ORDER_TYPE); ENUM_ORDER_TYPE_TIME expir_type=OrderGetInteger(ORDER_TYPE_TIME); //of order type is stoplimit, modify the interface if(type==ORDER_TYPE_BUY_STOP_LIMIT || type==ORDER_TYPE_SELL_STOP_LIMIT) { //set new value to the order price edit ObjectSetString(0,"ActP_limpr_edit3",OBJPROP_TEXT,DoubleToString(lim,_Digits)); ObjectSetInteger(0,"ActP_limpr_edit3",OBJPROP_BGCOLOR,White); //set order price available for edit ObjectSetInteger(0,"ActP_limpr_edit3",OBJPROP_READONLY,false); } //if order type isn't stoplimit, modify the interface else { ObjectSetString(0,"ActP_limpr_edit3",OBJPROP_TEXT,""); ObjectSetInteger(0,"ActP_limpr_edit3",OBJPROP_BGCOLOR,LavenderBlush); ObjectSetInteger(0,"ActP_limpr_edit3",OBJPROP_READONLY,true); } //check expiration type //and set interface elements switch(expir_type) { case ORDER_TIME_GTC: { ObjectSetInteger(0,"ActP_exp1_radio3",OBJPROP_STATE,1); ObjectSetInteger(0,"ActP_exp2_radio3",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_exp3_radio3",OBJPROP_STATE,0); break; } case ORDER_TIME_DAY: { ObjectSetInteger(0,"ActP_exp1_radio3",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_exp2_radio3",OBJPROP_STATE,1); ObjectSetInteger(0,"ActP_exp3_radio3",OBJPROP_STATE,0); break; } case ORDER_TIME_SPECIFIED: { ObjectSetInteger(0,"ActP_exp1_radio3",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_exp2_radio3",OBJPROP_STATE,0); ObjectSetInteger(0,"ActP_exp3_radio3",OBJPROP_STATE,1); //in addition, set new value to the edit ObjectSetString(0,"ActP_exp_edit3",OBJPROP_TEXT,TimeToString(expir)); break; } } //set new values for the objects ObjectSetString(0,"ActP_Pr_edit3",OBJPROP_TEXT,str_del_zero(DoubleToString(pr))); ObjectSetString(0,"ActP_lots_edit3",OBJPROP_TEXT,str_del_zero(DoubleToString(lots))); ObjectSetString(0,"ActP_SL_edit3",OBJPROP_TEXT,str_del_zero(DoubleToString(sl))); ObjectSetString(0,"ActP_TP_edit3",OBJPROP_TEXT,str_del_zero(DoubleToString(tp))); ObjectSetString(0,"ActP_ticket_edit3",OBJPROP_TEXT,IntegerToString(ticket)); if(mag!=0) ObjectSetString(0,"ActP_mag_edit3",OBJPROP_TEXT,IntegerToString(mag)); ChartRedraw(); } //if there isn't such order, show message else MessageBox("There isn't an order with ticket "+IntegerToString(ticket)+" for "+Symbol()); }
Ve son dokunuş - bu olay için CHARTEVENT_CLICK kullanarak grafiğe tıkladığınızda liste kaldırılmalıdır:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - is click on the chart if(id==CHARTEVENT_CLICK) { //delete all lists DeleteLists("ActP_orders_list_"); DeleteLists("ActP_color_list_"); //Set the activate buttons to the unpressed state ObjectSetInteger(0, "ActP_ord_button5", OBJPROP_STATE, 0); ObjectSetInteger(0, "ActP_col1_button6", OBJPROP_STATE, 0); ObjectSetInteger(0, "ActP_col2_button6", OBJPROP_STATE, 0); ObjectSetInteger(0, "ActP_col3_button6", OBJPROP_STATE, 0); ChartRedraw(); return; } ... }
Sonuç olarak, güzel bir açılır listemiz var:
Şekil 14. "Değiştir /Kapat" açılır liste paneli örneği
Şimdi Ayarlar sekmesinde bir renk seçimi listesi oluşturmamız gerekiyor.
Etkinleştirme düğmelerinin işleyicilerini göz önünde bulundurun:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the chart if(id==CHARTEVENT_OBJECT_CLICK) { ... //Click on the button to activate the colors drop-down list if(sparam=="ActP_col1_button6") { //check state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //the list is active if(selected)//the list is active { //creat list create_color_list(100, "ActP_col1_button6", 1); //Set the position of the remaining buttons to "unpressed" ObjectSetInteger(0, "ActP_col2_button6", OBJPROP_STATE, 0); ObjectSetInteger(0, "ActP_col3_button6", OBJPROP_STATE, 0); //delete other lists DeleteLists("ActP_color_list_2"); DeleteLists("ActP_color_list_3"); } //the list isn't selected else { //delete it DeleteLists("ActP_color_list_"); } //redraw chart ChartRedraw(); //finish the execution of function return; } ... } ... }
Burada talimat seçim listesiyle aynı yöntemi izliyoruz.
Liste oluşturma işlevi farklıdır:
//+------------------------------------------------------------------+ //| Function for creating the colors list | //| y_max - maximal list widthа | //| ID - list ID | //| num - interface number | //+------------------------------------------------------------------+ void create_color_list(int y_max,string ID,int num) { //Get the coordinates of the list activation button int x=ObjectGetInteger(0,ID,OBJPROP_XDISTANCE); int y=ObjectGetInteger(0, ID, OBJPROP_YDISTANCE)+ObjectGetInteger(0, ID, OBJPROP_YSIZE); //get color color col=ObjectGetInteger(0,ID,OBJPROP_COLOR); //and window width int wnd_height=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,wnd); y_max+=y; int y_cnt=0; //We will go through the colors array for(int i=0;i<132;i++) { color bgcol=colors[i]; //calculate list item coordinates int y_pos=y+y_cnt*20; //if we reached the boundaries of the window, start new column if(y_pos+20>wnd_height || y_pos+20>y_max) {x+=20; y_cnt=0;} y_pos=y+y_cnt*20; y_cnt++; //create new element string name="ActP_color_list_"+IntegerToString(num)+ID+IntegerToString(i); create_button(name,"",x,y_pos,20,20); //and set its properties ObjectSetInteger(0,name,OBJPROP_COLOR,col); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,0); ObjectSetInteger(0,name,OBJPROP_STATE,0); ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bgcol); } }
Ayrıca liste öğesi için tıklama işlemini ele alalım:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on chart if(id==CHARTEVENT_OBJECT_CLICK) { ... //click isn't on the color list button if(StringFind(sparam, "ActP_color_list_1")<0) { //delete list DeleteLists("ActP_color_list_1"); //set color list activation button to "unpressed" ObjectSetInteger(0, "ActP_col1_button6", OBJPROP_STATE, 0); //redraw chart ChartRedraw(); } //click on the color list else { //get color from the list color col=ObjectGetInteger(0, sparam, OBJPROP_BGCOLOR); //set it for all the buttons SetButtonsColor(col); //set button to unpressed ObjectSetInteger(0, "ActP_col1_button6", OBJPROP_STATE, 0); //delete list DeleteLists("ActP_color_list_1"); //redraw chart ChartRedraw(); } ... } ... }
SetButtonsColor() işlevi, düğmelerin rengini ayarlar:
//+------------------------------------------------------------------+ //| The function sets color for all buttons | //| col - color | //+------------------------------------------------------------------+ void SetButtonsColor(color col) { //We will go through all the objects for(int i=ObjectsTotal(0);i>=0;i--) { string n=ObjectName(0,i); //If the object belongs to the panel and its has a button type //set color if(StringFind(n,"ActP")>=0 && ObjectGetInteger(0,n,OBJPROP_TYPE)==OBJ_BUTTON) ObjectSetInteger(0,n,OBJPROP_BGCOLOR,col); } //set global variable GlobalVariableSet("ActP_buttons_color",col); }
Aşağıdaki sonuçlara bakalım:
Şekil 15. Düğmelerin renklerini ayarlama
Renk seçimi ve metin etiketleri listeleri benzerdir. Sonuç olarak, yalnızca birkaç tıklamayla paneli güzel bir şekilde renkli hale getirebiliriz:
Şekil 16 Panellerin, düğmelerin ve metnin renklerini değiştirme
Listelerle çalışmayı tamamladık. Giriş alanlarına geçelim.
5.5. Giriş Alanını Olayını İşleme
Giriş alanı, alandaki metnin düzenlenmesinin tamamlanmasının ardından meydana gelen bir CHARTEVENT_OBJECT_ENDEDIT olayı oluşturacaktır. Bu olayı işlememizin tek nedeni, giriş alanlarındaki fiyatlar ile ilgili fiyatlar için yardımcı çizgilerin ayarlanmasıdır.
Durma çizgisi örneğini ele alalım:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //End edit event if(id==CHARTEVENT_OBJECT_ENDEDIT)//end edit event { ... //if edit field is SL field if(sparam=="ActP_SL_edit1") { //and auxiliary lines are enabled if(ObjectGetInteger(0,"ActP_DealLines_check1",OBJPROP_STATE)==1) { //get text from the field double sl_val=StringToDouble(ObjectGetString(0, "ActP_SL_edit1", OBJPROP_TEXT)); //move lines at new position ObjectSetDouble(0, "ActP_SL_line1", OBJPROP_PRICE, sl_val); } //redraw chart ChartRedraw(); //it ins't necessary to proceed the other objects, because the event from the one return; } ... } ... }
Diğer giriş alanları benzer şekilde işlenir.
5.6 Zamanlayıcı Olaylarını İşleme
Zamanlayıcı, yardımcı çizgileri izlemek için kullanılır. Bu şekilde, çizgileri hareket ettirdiğinizde bağlı oldukları fiyatların değerleri otomatik olarak giriş alanına taşınır. Zamanlayıcının her tick'iyle OnTimer() işlevi yürütülür.
Etkin "Piyasa" sekmesi ile Zararı Durdur ve Kar Al çizgilerinin takibini yerleştirme örneğini göz önünde bulundurun:
void OnTimer()// Timer handler { //panel 1 is active if(ObjectGetInteger(0, "ActP_main_1", OBJPROP_STATE)==1) { //if auxiliary lines are allowed if(ObjectGetInteger(0,"ActP_DealLines_check1",OBJPROP_STATE)==1) { //set new values to the edit fields double sl_pr=NormalizeDouble(ObjectGetDouble(0, "ActP_SL_line1", OBJPROP_PRICE), _Digits); //stop loss ObjectSetString(0, "ActP_SL_edit1", OBJPROP_TEXT, DoubleToString(sl_pr, _Digits)); //take profit double tp_pr=NormalizeDouble(ObjectGetDouble(0, "ActP_TP_line1", OBJPROP_PRICE), _Digits); ObjectSetString(0, "ActP_TP_edit1", OBJPROP_TEXT, DoubleToString(tp_pr, _Digits)); } } ... //redraw chart ChartRedraw(); } //+------------------------------------------------------------------+
Diğer çizgilerin takibi de benzer şekilde uygulanır.
6. Alım Satım İşlemleri Yapma
Bu noktada gerekli tüm giriş alanlarını, onay kutularını, satırları ve radyo düğmelerini tamamladık. Şimdi elimizdeki tüm verilere dayanarak biraz alım satım işlemi denemesi yapma zamanı.
6.1. Yatırım Açma
"Piyasadan" sekmesinde "Al" ve "Sat" düğmeleri yer alır. Tüm alanlar doğru doldurulursa, düğmelerden birine tıkladığımızda bir alım satım işleminin yapılması gerekir.
Bu düğmelerin işleyicilerine bakalım:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the object on the chart if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the Buy button if(sparam=="ActP_buy_button1") { //check its state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //if it "pressed" if(selected) { //try to perform a deal deal(ORDER_TYPE_BUY); //and set the button to the unpressed state ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //and finish the function execution return; } //****************************************** //the similar for the sell button if(sparam=="ActP_sell_button1") { bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); if(selected) { deal(ORDER_TYPE_SELL); ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } ChartRedraw(); return; } ... } ... }
Gördüğünüz gibi deal() işlevi çalışıyor.
//+------------------------------------------------------------------+ //| Deal function | //+------------------------------------------------------------------+ int deal(ENUM_ORDER_TYPE typ) { //get the data from the objects double SL=StringToDouble(ObjectGetString(0,"ActP_SL_edit1",OBJPROP_TEXT)); double TP=StringToDouble(ObjectGetString(0, "ActP_TP_edit1", OBJPROP_TEXT)); double lots=StringToDouble(ObjectGetString(0,"ActP_Lots_edit1",OBJPROP_TEXT)); int mag=StringToInteger(ObjectGetString(0, "ActP_Magic_edit1", OBJPROP_TEXT)); int dev=StringToInteger(ObjectGetString(0, "ActP_Dev_edit1", OBJPROP_TEXT)); string comm=ObjectGetString(0,"ActP_Comm_edit1",OBJPROP_TEXT); ENUM_ORDER_TYPE_FILLING filling=ORDER_FILLING_FOK; if(ObjectGetInteger(0,"ActP_Exe2_radio1",OBJPROP_STATE)==1) filling=ORDER_FILLING_IOC; //prepare request MqlTradeRequest req; MqlTradeResult res; req.action=TRADE_ACTION_DEAL; req.symbol=Symbol(); req.volume=lots; req.price=Ask; req.sl=NormalizeDouble(SL, Digits()); req.tp=NormalizeDouble(TP, Digits()); req.deviation=dev; req.type=typ; req.type_filling=filling; req.magic=mag; req.comment=comm; //send order OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Mucizevi bir durum yok. Önce nesnelerden gerekli bilgileri okuruz ve bunlara dayalı olarak bir alım satım talebi oluştururuz.
Şimdi işimizi kontrol edelim:
Şekil 17. Alım satım işlemleri - Alış işlemi uygulamasının sonucu
Gördüğünüz gibi, Alış işlemi başarıyla tamamlandı.
6.2. Bekleyen Bir Talimat Ayarlama
Bekleyen talimatların verilmesi için "Bekleyen" sekmesindeki "Al" ve "Sat" düğmeleri kullanılır.
İşleyicileri ele alalım:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the chart object if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the pending order set button if(sparam=="ActP_buy_button2") { //check the button state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //if it pressed if(selected) { ENUM_ORDER_TYPE typ; //get the pending order from the edit double pr=NormalizeDouble(StringToDouble(ObjectGetString(0, "ActP_Pr_edit2", OBJPROP_TEXT)), Digits()); //if it isn't stoplimit order if(ObjectGetInteger(0, "ActP_limit_check2", OBJPROP_STATE)==0) { //if the order price is below the current price, set limit order if(Ask>pr) typ=ORDER_TYPE_BUY_LIMIT; //overwise - stop order else typ=ORDER_TYPE_BUY_STOP; } //if stoplimit order is specified else { //set operation type typ=ORDER_TYPE_BUY_STOP_LIMIT; } //try to place order order(typ); //set button to the unpressed state ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //and finish the execution of function return; } //****************************************** //similar for the sell pending order if(sparam=="ActP_sell_button2") { bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); if(selected) { ENUM_ORDER_TYPE typ; double pr=NormalizeDouble(StringToDouble(ObjectGetString(0, "ActP_Pr_edit2", OBJPROP_TEXT)), Digits()); if(ObjectGetInteger(0, "ActP_limit_check2", OBJPROP_STATE)==0) { if(Bid<pr) typ=ORDER_TYPE_SELL_LIMIT; else typ=ORDER_TYPE_SELL_STOP; } else { typ=ORDER_TYPE_SELL_STOP_LIMIT; } order(typ); ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } ChartRedraw(); return; } ... } ... }
Burada, mevcut piyasa fiyatının belirlenen fiyatla ilişkisine dayanarak gelecekteki talimatların türünü belirleriz, ardından order() işlevi talimatı belirler:
//+------------------------------------------------------------------+ //| The function places an order | //+------------------------------------------------------------------+ int order(ENUM_ORDER_TYPE typ) { //get the order details from the objects double pr=StringToDouble(ObjectGetString(0,"ActP_Pr_edit2",OBJPROP_TEXT)); double stoplim=StringToDouble(ObjectGetString(0,"ActP_limpr_edit2",OBJPROP_TEXT)); double SL=StringToDouble(ObjectGetString(0, "ActP_SL_edit2", OBJPROP_TEXT)); double TP=StringToDouble(ObjectGetString(0, "ActP_TP_edit2", OBJPROP_TEXT)); double lots=StringToDouble(ObjectGetString(0,"ActP_Lots_edit2",OBJPROP_TEXT)); datetime expir=StringToTime(ObjectGetString(0,"ActP_exp_edit2",OBJPROP_TEXT)); int mag=StringToInteger(ObjectGetString(0,"ActP_Magic_edit2",OBJPROP_TEXT)); string comm=ObjectGetString(0,"ActP_Comm_edit2",OBJPROP_TEXT); ENUM_ORDER_TYPE_FILLING filling=ORDER_FILLING_FOK; if(ObjectGetInteger(0, "ActP_Exe2_radio2", OBJPROP_STATE)==1) filling=ORDER_FILLING_IOC; if(ObjectGetInteger(0, "ActP_Exe3_radio2", OBJPROP_STATE)==1) filling=ORDER_FILLING_RETURN; ENUM_ORDER_TYPE_TIME expir_type=ORDER_TIME_GTC; if(ObjectGetInteger(0, "ActP_exp2_radio2", OBJPROP_STATE)==1) expir_type=ORDER_TIME_DAY; if(ObjectGetInteger(0, "ActP_exp3_radio2", OBJPROP_STATE)==1) expir_type=ORDER_TIME_SPECIFIED; //prepare request MqlTradeRequest req; MqlTradeResult res; req.action=TRADE_ACTION_PENDING; req.symbol=Symbol(); req.volume=lots; req.price=NormalizeDouble(pr,Digits()); req.stoplimit=NormalizeDouble(stoplim,Digits()); req.sl=NormalizeDouble(SL, Digits()); req.tp=NormalizeDouble(TP, Digits()); req.type=typ; req.type_filling=filling; req.type_time=expir_type; req.expiration=expir; req.comment=comm; req.magic=mag; //place order OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Şimdi işimizi kontrol edelim:
Şekil 18. Alım satım işlemleri - Bekleyen talimat verme sonucu
Buy stoplimit başarıyla ayarlandı.
6.3. Pozisyon Değiştirme
"Değiştir/Kapat" sekmesindeki Düzenle düğmesi, seçilen pozisyonun değiştirilmesinden sorumludur:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the graphic object on the chart if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the modify position button if(sparam=="ActP_mod_button4") { //check the button state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //if it pressed if(selected)//if pressed { //modify position modify_pos(); //delete the elements of the scheme DeleteScheme("ActP" ,true); //and reset it (update the interface) SetScheme(0); //set the button to the unpressed state ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //finish the execution of function return; } ... } ... }
Modify_pos() işlevi, değişiklikten doğrudan sorumludur:
//+------------------------------------------------------------------+ //| The function modifies the position parameters | //+------------------------------------------------------------------+ int modify_pos() { if(!PositionSelect(Symbol())) MessageBox("There isn't open position for symbol "+Symbol(),"Message"); //get the details from the edit objects double SL=StringToDouble(ObjectGetString(0,"ActP_SL_edit4",OBJPROP_TEXT)); double TP=StringToDouble(ObjectGetString(0, "ActP_TP_edit4", OBJPROP_TEXT)); int dev=StringToInteger(ObjectGetString(0,"ActP_dev_edit4",OBJPROP_TEXT)); //prepare request MqlTradeRequest req; MqlTradeResult res; req.action=TRADE_ACTION_SLTP; req.symbol=Symbol(); req.sl=NormalizeDouble(SL, _Digits); req.tp=NormalizeDouble(TP, _Digits); req.deviation=dev; //send request OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Sonuçlar:
Şekil 19. Alım satım işlemleri - Alım satımın özelliklerini değiştirmenin sonucu (TP ve SL)
Zararı Durdur ve Kar Al düzeyleri başarıyla değiştirildi.
6.4. Pozisyonu Kapatma
"Değiştir/Kapat" sekmesindeki Kapat düğmesi, pozisyonun kapatılmasından (muhtemelen kısmen) sorumludur:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the chart object if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the close button if(sparam=="ActP_del_button4") { //check the button state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //if pressed if(selected) { //try to close position int retcode=close_pos(); //if successful if(retcode==10009) { //delete scheme elements DeleteScheme("ActP" ,true); //set the new text for the list activisation ObjectSetString(0, "ActP_ord_button5", OBJPROP_TEXT, "Select order -->"); } //set button state to unpressed ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //finish the execution of function return; } ... } ... }
close_pos() işlevi kapatma işleminden sorumludur:
//+------------------------------------------------------------------+ //| Closes the position | //+------------------------------------------------------------------+ int close_pos() { if(!PositionSelect(Symbol())) MessageBox("There isn't open position for symbol "+Symbol(),"Message"); //get the position details from the objects double lots=StringToDouble(ObjectGetString(0,"ActP_lots_edit4",OBJPROP_TEXT)); if(lots>PositionGetDouble(POSITION_VOLUME)) lots=PositionGetDouble(POSITION_VOLUME); int dev=StringToInteger(ObjectGetString(0, "ActP_dev_edit4", OBJPROP_TEXT)); int mag=StringToInteger(ObjectGetString(0, "ActP_mag_edit4", OBJPROP_TEXT)); //prepare request MqlTradeRequest req; MqlTradeResult res; //the opposite deal is dependent on position type if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { req.price=Bid; req.type=ORDER_TYPE_SELL; } else { req.price=Ask; req.type=ORDER_TYPE_BUY; } req.action=TRADE_ACTION_DEAL; req.symbol=Symbol(); req.volume=lots; req.sl=0; req.tp=0; req.deviation=dev; req.type_filling=ORDER_FILLING_FOK; req.magic=mag; //send request OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Sonuç - seçilen işlemden üç adet 1,5 lot kapatıldı:
Şekil 20. Alım satım işlemi - kısmi pozisyon kapatma
6.5. Bekleyen Bir Talimatı Değiştirme
"Değiştirme/kapatma" sekmesindeki Düzenle düğmesi, seçilen talimatın değiştirilmesinden sorumludur:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the chart graphic object if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the order modify button if(sparam=="ActP_mod_button3") { bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); if(selected) { //get the order ticket from the edit string button_name=ObjectGetString(0, "ActP_ord_button5", OBJPROP_TEXT); long ticket=StringToInteger(StringSubstr(button_name, 1, StringFind(button_name, " ")-1)); //modifying an order modify_order(ticket); //update interface DeleteScheme("ActP" ,true); SetScheme(ticket); //set button to unpressed state ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //and finish the execution of function return; } ... } ... }
Modify_order () işlevi değişiklikten sorumludur:
//+------------------------------------------------------------------+ //| The function modifies an order | //| ticket - order ticket | //+------------------------------------------------------------------+ int modify_order(int ticket) { //get the order details from the corresponding chart objects double pr=StringToDouble(ObjectGetString(0,"ActP_Pr_edit3",OBJPROP_TEXT)); double stoplim=StringToDouble(ObjectGetString(0,"ActP_limpr_edit3",OBJPROP_TEXT)); double SL=StringToDouble(ObjectGetString(0, "ActP_SL_edit3", OBJPROP_TEXT)); double TP=StringToDouble(ObjectGetString(0, "ActP_TP_edit3", OBJPROP_TEXT)); double lots=StringToDouble(ObjectGetString(0,"ActP_Lots_edit3",OBJPROP_TEXT)); datetime expir=StringToTime(ObjectGetString(0,"ActP_exp_edit3",OBJPROP_TEXT)); ENUM_ORDER_TYPE_TIME expir_type=ORDER_TIME_GTC; if(ObjectGetInteger(0, "ActP_exp2_radio3", OBJPROP_STATE)==1) expir_type=ORDER_TIME_DAY; if(ObjectGetInteger(0, "ActP_exp3_radio3", OBJPROP_STATE)==1) expir_type=ORDER_TIME_SPECIFIED; //prepare request to modify MqlTradeRequest req; MqlTradeResult res; req.action=TRADE_ACTION_MODIFY; req.order=ticket; req.volume=lots; req.price=NormalizeDouble(pr,Digits()); req.stoplimit=NormalizeDouble(stoplim,Digits()); req.sl=NormalizeDouble(SL, Digits()); req.tp=NormalizeDouble(TP, Digits()); req.type_time=expir_type; req.expiration=expir; //send request OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Sonuca bakalım - Bir talimat başarıyla değiştirildi:
Şekil 21. Bekleyen talimatı değiştirme
6.6. Bekleyen Talimatı Silme
"Değiştirme/Kapatma" sekmesindeki Sil düğmesi, seçilen talimatın silinmesinden sorumludur:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ... //Event - click on the graphic object on the chart if(id==CHARTEVENT_OBJECT_CLICK) { ... //click on the order delete button if(sparam=="ActP_del_button3") { //check the button state bool selected=ObjectGetInteger(0,sparam,OBJPROP_STATE); //if pressed if(selected) { //get the ticket from the list string button_name=ObjectGetString(0, "ActP_ord_button5", OBJPROP_TEXT); long ticket=StringToInteger(StringSubstr(button_name, 1, StringFind(button_name, " ")-1)); //try to delete order int retcode=del_order(ticket); //if successful if(retcode==10009) { //delete all objects of the scheme DeleteScheme("ActP" ,true); //set new text for the list activation button ObjectSetString(0, "ActP_ord_button5", OBJPROP_TEXT, "Select an order -->"); } //set button state to unpressed ObjectSetInteger(0, sparam, OBJPROP_STATE, 0); } //redraw chart ChartRedraw(); //and finish the execution of function return; } ... } ... }
Del_order() işlevi, talimatların kaldırılmasından sorumludur:
//+------------------------------------------------------------------+ //| The function for pending order deletion | //| ticket - order ticket | //+------------------------------------------------------------------+ int del_order(int ticket) { //prepare request for deletion MqlTradeRequest req; MqlTradeResult res; req.action=TRADE_ACTION_REMOVE; req.order=ticket; //send request OrderSend(req,res); //show message with the result MessageBox(RetcodeDescription(res.retcode),"Message"); //return retcode return(res.retcode); }
Sonuca bakalım - Talimat kaldırıldı.
Şek. 22 Alım satım işlemleri - Bekleyen bir talimatı kaldırma
Sonuç
Son olarak panelin tüm işlevleri test edilmiş olup bunlar başarılı bir şekilde çalışmaktadır.
Umarım bu makaleyi okuyarak edindiğiniz bilgiler, piyasada çalışmak için eşsiz yardımcılar işlevi görecek aktif kontrol panellerinin geliştirilmesinde size yardımcı olacaktır.
Paneli kullanmaya başlamak için arşivi terminal ile bir klasöre açmanız, ardından grafiğe AP göstergesini uygulamanız gerekir; ancak o zaman Aktif Panel Expert Advisor'ı başlatabilirsiniz.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/62
- Ücretsiz ticaret 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