English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Diğer Uygulamalar için MetaTrader 5 Fiyat Teklifleri Nasıl Hazırlanır?

Diğer Uygulamalar için MetaTrader 5 Fiyat Teklifleri Nasıl Hazırlanır?

MetaTrader 5Örnekler | 22 Aralık 2021, 15:10
207 0
Anatoli Kazharski
Anatoli Kazharski

İçindekiler

Giriş
1. Ele Alınan Konular
2. Veri Biçimi
3. Programın Harici Parametreleri
4. Bir Kullanıcı Tarafından Girilen Parametreleri Kontrol Etme
5. Genel Değişkenler
6. Bilgi Paneli
7. Uygulamanın Ana Bloğu
8. Klasörler Oluşturma ve Verileri Dosyalama
Sonuç


Giriş

MQL5 ile çalışmaya başlamadan önce, alım satım sistemlerinin geliştirilmesi için birçok başka uygulama denedim. Zamanımı boşa harcadığımı söyleyemem. Bunların bazıları, kullanıcıların zamandan tasarruf etmesine, birçok sorunla başa çıkmasına, bazı yanlış kanılardan kurtulmasına ve programlama dilleri bilgisi olmadan geliştirme için hızlı bir şekilde başka yollar seçmesine olanak tanıyan birkaç faydalı araç içerir.

Bu uygulamalar, geçmiş verilere ihtiyaç duyar. Bazı belirli standart veri biçimlerinin olmaması nedeniyle, gerekli programa uygulanabilir biçimle uyumlu olmaları için (örneğin Excel'de) kullanılmadan önce genellikle düzenlenmeleri gerekti. Gerekli tüm ayrıntıları çözebilseniz dahi, birçok şey yine de manuel olarak yapılmalıdır. Kullanıcılar, MetaTrader 4'ten fiyat tekliflerini gerekli biçime kopyalamak için tasarlanmış farklı script dosyası sürümleri bulabilir. Böyle bir talep olması halinde, MQL5 için script dosyasının sürümünü de geliştirebiliriz.


1. Ele Alınan Konular

Makalede, aşağıdaki konuları ele alınmaktadır:

  • Piyasa İzleme penceresindeki sembol listesi ve sunucudaki ortak sembol listesi ile çalışma.
  • Mevcut veri derinliğini kontrol etme ve gerekirse çeşitli durumların doğru şekilde ele alınmasıyla eksik miktarı indirme.
  • Özel panel grafiğinde ve günlüğünde istenen verilerle ilgili bilgileri görüntüleme.
  • Kullanıcı tanımlı biçimde dosyalama için veri hazırlama.
  • Dosya dizinleri oluşturma.
  • Veri dosyalama.


2. Veri Biçimi

NeuroShell DayTrader Professional'da (NSDT) kullanılması amaçlanan verilerin hazırlanmasına bir örnek vereceğim. NSDT sürüm 5 ve 6'yı denedim ve veri biçimi için farklı gereklilikleri olduğunu öğrendim. NSDT sürümü 5'in tarih ve saat verileri farklı sütunlarda olmalıdır. Dosyadaki ilk satır aşağıdaki görünüme sahip olmalıdır:

"Tarih" "Saat" "Açılış" "Yüksek" "Düşük" "Kapanış" "Hacim"

NSDT sürümü 6'daki başlık satırı, uygulamanın bir dosyayı kabul etmesine izin vermek için farklı bir görünüme sahip olmalıdır. Bu, tarih ve saatin aynı sütunda olması gerektiği anlamına gelir:

Tarih,Açılış,Yüksek,Düşük,Kapanış,Hacim

MetaTrader 5, kullanıcıların fiyat tekliflerini *.csv dosyalarına kaydetmesine olanak tanır. Bir dosyadaki veriler, aşağıdaki gibi görünür:

Şek. 1. MetaTrader 5 terminali tarafından kaydedilen veriler

Şek. 1. MetaTrader 5 terminali tarafından kaydedilen veriler


Ancak, tarihin başka bir biçimi olması gerektiği için, yalnızca başlık satırını düzenleyemeyiz. NSDT s.5 için:

gg.aa.yyyy,ss:dd,Açılış,Yüksek,Düşük,Kapanış,Hacim
NSDT s.6 için:
gg/aa/yyyy ss:dd,Açılış,Yüksek,Düşük,Kapanış,Hacim

Açılır listeler, kullanıcıların gerekli biçimi seçebilecekleri script dosyası harici parametrelerinde kullanılacaktır. Başlık ve tarih biçimlerini seçmenin yanı sıra, kullanıcılara dosyalara yazmak istedikleri verileri, sembollerin sayısını seçme imkanı sunacağız. Bunu yapmak için, üç sürüm hazırlayacağız:

  • Verileri yalnızca (YALNIZCA MEVCUT SEMBOL) script dosyası başlatılmış olan mevcut sembolün üzerine yazın.
  • Verileri, Piyasa İzleme penceresinde yer alan sembollerin üzerine yazın (MARKETWATCH SEMBOLLERİ).
  • Verileri sunucuda bulunan tüm sembollerin üzerine yazın (TÜM LİSTE SEMBOLLERİ).

Bu tür listeleri oluşturmak için script dosyası kodunda harici parametrelerden önce aşağıdaki kodu girelim:

//_________________________________
// HEADER_FORMATS_ENUMERATION
enum FORMAT_HEADERS
  {
   NSDT_5 = 0, // "Date" "Time" "Open" "High" "Low" "Close" "Volume"
   NSDT_6 = 1  // Date,Open,High,Low,Close,Volume
  };
//---
//___________________________
// ENUMERATION_OF_DATA_FORMATS
enum FORMAT_DATETIME
  {
   SEP_POINT1 = 0, // dd.mm.yyyy hh:mm
   SEP_POINT2 = 1, // dd.mm.yyyy, hh:mm
   SEP_SLASH1 = 2, // dd/mm/yyyy hh:mm
   SEP_SLASH2 = 3  // dd/mm/yyyy, hh:mm
  };
//---
//____________________________
// ENUMERATION_OF_FILING_MODES
enum CURRENT_MARKETWATCH
  {
   CURRENT          = 0, // ONLY CURRENT SYMBOLS
   MARKETWATCH      = 1, // MARKETWATCH SYMBOLS
   ALL_LIST_SYMBOLS = 2  // ALL LIST SYMBOLS
  };

Numaralandırmalar hakkında daha fazla bilgi MQL5 Referansı'nda bulunabilir.


3. Programın Harici Parametreleri

Şimdi, script dosyasının tüm harici parametrelerinin tam listesini oluşturabiliriz:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| EXTERNAL_PARAMETERS                                              |
//+------------------------------------------------------------------+
input datetime            start_date     = D'01.01.2011'; // Start Date
input datetime            end_date       = D'18.09.2012'; // End Date
input FORMAT_HEADERS      format_headers = NSDT_5;     // Format Headers
input FORMAT_DATETIME     format_date    = SEP_POINT2; // Format Datetime
input CURRENT_MARKETWATCH curr_mwatch    = CURRENT;    // Mode Write Symbols
input bool                clear_mwatch   = true;        // Clear Market Watch
input bool                show_progress  = true;        // Show Progress (%)

Harici parametreler, aşağıdaki amaçlar için kullanılır:

  • Kullanıcılar, Başlangıç Tarihi (start_date) ve Bitiş Tarihi (end_date) parametrelerini kullanarak bir tarih aralığı belirleyebilir.
  • Başlık Biçimi (format_headers) açılır listesi, kullanıcıların bir başlık biçimi seçmesine olanak tanır.
  • Tarih Saat Biçimi (format_date) açılır listesi, kullanıcıların tarih ve saat biçimlerini seçmesine olanak tanır.
  • Mod Yazma Sembolleri (curr_mwatch) açılır listesi, kullanıcıların dosyalama için sembol sayısını seçmesine olanak tanır.
  • Piyasa İzlemeyi Temizle (clear_mwatch) parametresi true ise, kullanıcıların dosyalamadan sonra Piyasa İzleme penceresinden tüm sembolleri silmesine olanak tanır. Bu, yalnızca şu anda etkin olmayan grafikleri içeren sembollerle ilgilidir.
  • İlerlemeyi Göster (%) (show_progress) parametresi, veri panelinde dosyalama ilerlemesini gösterir. Bu parametre devre dışı bırakılırsa dosyalama daha hızlı gerçekleştirilecektir.

Başlatma sırasında harici parametrelerin nasıl görüneceği aşağıda açıklanmıştır:

Şek. 2. Uygulamanın harici parametreleri

Şek. 2. Uygulamanın harici parametreleri


4. Bir Kullanıcı Tarafından Girilen Parametreleri Kontrol Etme

Temel koddan önce kullanıcılar tarafından girilen parametreleri kontrol etmek için işlev oluşturalım. Örneğin, Başlangıç Tarihi parametresindeki başlangıç tarihi, Bitiş Tarihindekinden önce olmalıdır. Başlıkların biçimi, tarih ve saat biçimleriyle eşleşmelidir. Bir kullanıcı, parametreleri ayarlarken bazı hatalar yaptıysa aşağıdaki uyarı mesajı görüntülenir ve program durur.

Örnek uyarı mesajı:

Şek. 3. Hatalı şekilde belirtilen değerlere ilişkin uyarı

Şek. 3. Hatalı şekilde belirtilen parametrelere ilişkin örnek hata mesajı


ValidationParameters() işlevi:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| CHECKING_CORRECTNESS_OF_PARAMETERS                               |
//+------------------------------------------------------------------+
bool ValidationParameters()
  {
   if(start_date>=end_date)
     {
      MessageBox("The start date should be earlier than the ending one!\n\n"
                 "Application cannot continue. Please retry.",
                 //---
                 "Parameter error!",MB_ICONERROR);
      //---
      return(true);
     }
//---
   if(format_headers==NSDT_5 && 
      (format_date==SEP_POINT1 || format_date==SEP_SLASH1))
     {
      MessageBox("For the headers of the following format:\n\n"
                 "\"Date\" ""\"Time\" ""\"Open\" ""\"High\" ""\"Low\" ""\"Close\" ""\"Volume\"\n\n"
                 "Date/time format can be selected out of two versions:\n\n"
                 "dd.mm.yyyy, hh:mm\n"
                 "dd/mm/yyyy, hh:mm\n\n"
                 "Application cannot continue. Please retry.",
                 //---
                 "Header and date/time formats do not match!",MB_ICONERROR);
      //---
      return(true);
     }
//---
   if(format_headers==NSDT_6 && 
      (format_date==SEP_POINT2 || format_date==SEP_SLASH2))
     {
      MessageBox("For the headers of the following format:\n\n"
                 "Date,Open,High,Low,Close,Volume\n\n"
                 "Date/time format can be selected out of two versions:\n\n"
                 "dd.mm.yyyy hh:mm\n"
                 "dd/mm/yyyy hh:mm\n\n"
                 "Application cannot continue. Please retry.",
                 //---
                 "Header and date/time formats do not match!",MB_ICONERROR);
      //---
      return(true);
     }
//---
   return(false);
  }


5. Genel Değişkenler

Ardından, script dosyasında kullanılacak tüm genel değişkenleri ve dizileri belirlemeliyiz:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| GLOBAL_VARIABLES_AND_ARRAYS                                      |
//+------------------------------------------------------------------+
MqlRates rates[]; // Array for copying data
//---
string symbols[]; // Symbol array
//---
// Array of graphic object names
string arr_nmobj[22]=
  {
   "fon","hd01",
   "nm01","nm02","nm03","nm04","nm05","nm06","nm07","nm08","nm09","nm10",
   "nm11","nm12","nm13","nm14","nm15","nm16","nm17","nm18","nm19","nm20"
  };
//---
// Array of displayed text containing graphic objects
string arr_txtobj[21];
//---
string path="";         // File path
int cnt_symb=0;         // Number of symbols
int sz_arr_symb=0;      // Symbol array size
int bars=0;             // Number of bars according to the specified TF
int copied_bars=0;      // Number of bars copied for writing
double pgs_pcnt=0;      // Writing progress
int hFl=INVALID_HANDLE;  // File handle
//---
string   // Variables for data formatting
sdt="",  // Date line
dd="",   // Day
mm="",   // Month
yyyy="", // Year
tm="",   // Time
sep="";  // Separator
//---
int max_bars=0; // Maximum number of bars in the terminal settings
//---
datetime
first_date=0,        // First available data in a specified period
first_termnl_date=0, // First available data in the terminal's database
first_server_date=0, // First available data in the server's database
check_start_date=0;  // Checked correct date value


6. Bilgi Paneli

Şimdi, bilgi panelinde görüntülenecek olan öğelerle ilgilenmeliyiz. Arka plan olarak üç tür grafik nesnesi kullanılabilir:

  • En basit ve bariz olanı – "Dikdörtgen etiket" (OBJ_RECTANGLE_LABEL).
  • Arayüzlerinin benzersiz bir görünüme sahip olmasını isteyenler "Bitmap" nesnesini (OBJ_BITMAP) kullanabilirler.
  • "Düzenle" nesnesi (OBJ_EDIT) arka plan olarak da kullanılabilir. Metin girme olasılığını kaldırmak için "salt okunur" özelliğini ayarlayın. "Düzenle" nesnesini kullanmanın başka bir avantajı daha vardır. Bir Expert Advisor'da bir bilgi paneli oluşturduysanız ve görselleştirme modundaki testler sırasında aynı görünüme sahip olmasını istiyorsanız, son tür bunu başarmanın tek yöntemidir. Görselleştirme modunda testler sırasında ne OBJ_RECTANGLE_LABEL ne de OBJ_BITMAP görüntülenmez.

Bizim durumumuzda Expert Advisor yerine yalnızca bir script dosyası geliştirilse de, örnek olarak OBJ_EDIT nesneli arka plan yapılacaktır. Sonuç, aşağıdaki şekilde gösterilmiştir:

Şek. 4. Bilgi paneli

Şek. 4. Bilgi paneli


Panelde gösterilen tüm verileri açıklayalım:

  • Sembol (geçerli/toplam) – O anda indirilen/kopyalanan/yazılan verinin bulunduğu sembol. Parantez içindeki soldaki sayı, geçerli sembol numarasını gösterir. Sağdaki sayı, script dosyasının çalışacağı ortak sembol sayısını gösterir.
  • Yol Sembolü – Ait olduğu sembol yolu veya kategorisi. Piyasa İzleme penceresinde sağ tıklayıp "Semboller…" öğesini seçerek bağlam menüsünü açarsanız, tüm sembollerin listesini içeren pencere görüntülenir. Bununla ilgili daha fazla bilgiyi terminalin Kullanım Kılavuzunda bulabilirsiniz.
  • Zaman dilimi – Dönem (zaman dilimi). Script dosyasının başlatılacağı zaman dilimi kullanılacaktır.
  • Giriş Başlangıç Tarihi – Script dosyası parametrelerinde bir kullanıcı tarafından belirtilen veri başlangıç tarihi.
  • İlk Tarih (H1) – Mevcut zaman diliminin ilk kullanılabilir veri tarihi (çubuk).
  • İlk Terminal Tarihi (M1) – Halihazırda mevcut terminal verilerinde M1 zaman diliminin ilk kullanılabilir tarihi.
  • İlk Sunucu Tarihi (M1) – Sunucudaki M1 zaman diliminin ilk kullanılabilir tarihi.
  • Seçenekler Terminalindeki Maks. Çubuk – Terminal ayarlarında belirtilen grafikte görüntülenecek maksimum çubuk sayısı.
  • Kopyalanan Çubuklar – Yazılmak üzere kopyalanan çubukların sayısı.
  • İlerleme Değeri Mevcut Sembolü – Mevcut sembolün yazılı verilerinin yüzde değeri.

Aşağıda, bu tür bilgi panelinin kodu bulunmaktadır:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| INFORMATION_PANEL                                                |
//|------------------------------------------------------------------+
void InfoTable(int s)
  {
   int fnt_sz=8;            // Font size
   string fnt="Calibri";     // Header font
   color clr=clrWhiteSmoke;  // Color
//---
   int xH=300;
   int height_pnl=0;
   int yV1=1,yV2=12,xV1=165,xV2=335,xV3=1;
//---
   string sf="",stf="",ssf="";
   bool flg_sf=false,flg_stf=false,flg_ssf=false;
//---
   if(show_progress) { height_pnl=138; } else { height_pnl=126; }
//---
   flg_sf=SeriesInfoInteger(symbols[s],_Period,SERIES_FIRSTDATE,first_date);
   flg_stf=SeriesInfoInteger(symbols[s],PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,first_termnl_date);
   flg_ssf=SeriesInfoInteger(symbols[s],PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date);
//---
   if(flg_sf) { sf=TSdm(first_date); } else { sf="?"; }
   if(flg_stf) { stf=TSdm(first_termnl_date); } else { stf="?"; }
   if(flg_ssf) { ssf=TSdm(first_server_date); } else { ssf="?"; }
//---
   if(cnt_symb==0) { cnt_symb=1; }
//---
   int anchor1=ANCHOR_LEFT_UPPER,anchor2=ANCHOR_RIGHT_UPPER,corner=CORNER_LEFT_UPPER;
//---
   string path_symbol=SymbolInfoString(symbols[s],SYMBOL_PATH);
   path_symbol=StringSubstr(path_symbol,0,StringLen(path_symbol)-StringLen(symbols[s]));
//---
   arr_txtobj[0]="INFO TABLE";
   arr_txtobj[1]="Symbol (current / total) : ";
   arr_txtobj[2]=""+symbols[s]+" ("+IS(s+1)+"/"+IS(cnt_symb)+")";
   arr_txtobj[3]="Path Symbol : ";
   arr_txtobj[4]=path_symbol;
   arr_txtobj[5]="Timeframe : ";
   arr_txtobj[6]=gStrTF(_Period);
   arr_txtobj[7]="Input Start Date : ";
   arr_txtobj[8]=TSdm(start_date);
   arr_txtobj[9]="First Date (H1) : ";
   arr_txtobj[10]=sf;
   arr_txtobj[11]="First Terminal Date (M1) : ";
   arr_txtobj[12]=stf;
   arr_txtobj[13]="First Server Date (M1) : ";
   arr_txtobj[14]=ssf;
   arr_txtobj[15]="Max. Bars In Options Terminal : ";
   arr_txtobj[16]=IS(max_bars);
   arr_txtobj[17]="Copied Bars : ";
   arr_txtobj[18]=IS(copied_bars);
   arr_txtobj[19]="Progress Value Current Symbol : ";
   arr_txtobj[20]=DS(pgs_pcnt,2)+"%";
//---
   Create_Edit(0,0,arr_nmobj[0],"",corner,fnt,fnt_sz,clrDimGray,clrDimGray,345,height_pnl,xV3,yV1,2,C'15,15,15');
//---
   Create_Edit(0,0,arr_nmobj[1],arr_txtobj[0],corner,fnt,8,clrWhite,C'64,0,0',345,12,xV3,yV1,2,clrFireBrick);
//---
   Create_Label(0,arr_nmobj[2],arr_txtobj[1],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2,0);
   Create_Label(0,arr_nmobj[3],arr_txtobj[2],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2,0);
//---
   Create_Label(0,arr_nmobj[4],arr_txtobj[3],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*2,0);
   Create_Label(0,arr_nmobj[5],arr_txtobj[4],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*2,0);
//---
   Create_Label(0,arr_nmobj[6],arr_txtobj[5],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*3,0);
   Create_Label(0,arr_nmobj[7],arr_txtobj[6],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*3,0);
//---
   Create_Label(0,arr_nmobj[8],arr_txtobj[7],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*4,0);
   Create_Label(0,arr_nmobj[9],arr_txtobj[8],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*4,0);
//---
   Create_Label(0,arr_nmobj[10],arr_txtobj[9],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*5,0);
   Create_Label(0,arr_nmobj[11],arr_txtobj[10],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*5,0);
//---
   Create_Label(0,arr_nmobj[12],arr_txtobj[11],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*6,0);
   Create_Label(0,arr_nmobj[13],arr_txtobj[12],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*6,0);
//---
   Create_Label(0,arr_nmobj[14],arr_txtobj[13],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*7,0);
   Create_Label(0,arr_nmobj[15],arr_txtobj[14],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*7,0);
//---
   Create_Label(0,arr_nmobj[16],arr_txtobj[15],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*8,0);
   Create_Label(0,arr_nmobj[17],arr_txtobj[16],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*8,0);
//---
   Create_Label(0,arr_nmobj[18],arr_txtobj[17],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*9,0);
   Create_Label(0,arr_nmobj[19],arr_txtobj[18],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*9,0);
//---
   if(show_progress)
     {
      Create_Label(0,arr_nmobj[20],arr_txtobj[19],anchor2,corner,fnt,fnt_sz,clr,xV1,yV1+yV2*10,0);
      Create_Label(0,arr_nmobj[21],arr_txtobj[20],anchor2,corner,fnt,fnt_sz,clr,xV2,yV1+yV2*10,0);
     }
  }
//____________________________________________________________________
//+------------------------------------------------------------------+
//| CREATING_LABEL_OBJECT                                            |
//+------------------------------------------------------------------+
void Create_Label(long   chrt_id,   // chart id
                  string lable_nm,  // object name
                  string rename,    // displayed name
                  long   anchor,    // anchor point
                  long   corner,    // attachment corner
                  string font_bsc,  // font
                  int    font_size, // font size
                  color  font_clr,  // font color
                  int    x_dist,    // X scale coordinate
                  int    y_dist,    // Y scale coordinate
                  long   zorder)    // priority
  {
   if(ObjectCreate(chrt_id,lable_nm,OBJ_LABEL,0,0,0)) // creating object
     {
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TEXT,rename);          // set name
      ObjectSetString(chrt_id,lable_nm,OBJPROP_FONT,font_bsc);        // set font
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_COLOR,font_clr);      // set font color
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_ANCHOR,anchor);       // set anchor point
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_CORNER,corner);       // set attachment corner
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_FONTSIZE,font_size);  // set font size
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XDISTANCE,x_dist);    // set X coordinates
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YDISTANCE,y_dist);    // set Y coordinates
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_SELECTABLE,false);     // unable to highlight the object, if FALSE
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_ZORDER,zorder);       // Higher/lower priority
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TOOLTIP,"\n");         // no tooltip, if "\n"
     }
  }
//____________________________________________________________________
//+------------------------------------------------------------------+
//| CREATING_EDIT_OBJECT                                             |
//+------------------------------------------------------------------+
void Create_Edit(long   chrt_id,       // chart id
                 int    nmb_win,       // window (subwindow) index
                 string lable_nm,      // object name
                 string text,          // displayed text
                 long   corner,        // attachment corner
                 string font_bsc,      // font
                 int    font_size,     // font size
                 color  font_clr,      // font color
                 color  font_clr_brd,  // font color
                 int    xsize,         // width
                 int    ysize,         // height
                 int    x_dist,        // X scale coordinate
                 int    y_dist,        // Y scale coordinate
                 long   zorder,        // priority
                 color  clr)           // background color
  {
   if(ObjectCreate(chrt_id,lable_nm,OBJ_EDIT,nmb_win,0,0)) // creating object
     {
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TEXT,text);                     // set name
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_CORNER,corner);                // set attachment corner
      ObjectSetString(chrt_id,lable_nm,OBJPROP_FONT,font_bsc);                 // set font
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_ALIGN,ALIGN_CENTER);         // center alignment
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_FONTSIZE,font_size);           // set font size
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_COLOR,font_clr);               // font color
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_BORDER_COLOR,font_clr_brd);    // background color
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_BGCOLOR,clr);                  // background color
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XSIZE,xsize);                  // width
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YSIZE,ysize);                  // height
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XDISTANCE,x_dist);             // set X coordinate
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YDISTANCE,y_dist);             // set Y coordinate
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_SELECTABLE,false);              // unable to highlight the object, if FALSE
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_ZORDER,zorder);                // Higher/lower priority
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_READONLY,true);                // Read only
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TOOLTIP,"\n");                  // no tooltip if "\n"
     }
  }

Script dosyası işlemi tamamlandıktan veya script dosyası önceden bir kullanıcı tarafından silindikten sonra, script dosyası tarafından oluşturulan tüm grafik nesneleri silinmelidir. Bunun için aşağıdaki işlevler kullanılacaktır:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| DELETE_ALL_GRAPHICAL_OBJECTS_CREATED_BY_THE_SCRIPT               |
//+------------------------------------------------------------------+
void DelAllScriptObjects()
  {
// Receive the size of graphical object names array
   int sz_arr1=ArraySize(arr_nmobj);
//---
// Delete all objects
   for(int i=0; i<sz_arr1; i++)
     { DelObjbyName(arr_nmobj[i]);  }
  }
//____________________________________________________________________
//+------------------------------------------------------------------+
//| DELETE_OBJECTS_BY_NAME                                           |
//+------------------------------------------------------------------+
int DelObjbyName(string Name)
  {
   int nm_obj=0;
   bool res=false;
//---
   nm_obj=ObjectFind(ChartID(),Name);
//---
   if(nm_obj>=0)
     {
      res=ObjectDelete(ChartID(),Name);
      //---
      if(!res) { Print("Object deletion error: - "+ErrorDesc(Error())+""); return(false); }
     }
//---
   return(res);
  }


7. Uygulamanın Ana Bloğu

Script dosyalarının ana işlevi OnStart()'tır. Bu, yürütme için diğer tüm işlevleri çağırmak için kullanılan işlevdir. Programın çalışmasına ilişkin ayrıntılar kodda gösterilmiştir:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| SCRIPT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
//+------------------------------------------------------------------+
void OnStart()
  {
// If user-defined parameters are incorrect,
// error message is shown and the program is closed
   if(ValidationParameters()) { return; }
//---
   max_bars=TerminalInfoInteger(TERMINAL_MAXBARS); // Receive available number of bars in the window
//---
   GetSymbolsToArray();           // Filling symbol array with names
   sz_arr_symb=ArraySize(symbols); // Receive symbol array size
//---
   SetSeparateForFormatDate();    // Set a separator for date format
//---
// Revise all symbols and write their data to file
   for(int s=0; s<=sz_arr_symb-1; s++)
     {
      copied_bars=0; // Reset copied bars variable to zero for writing
      pgs_pcnt=0.0;  // Reset variable of the symbol data writing progress 
      //---
      InfoTable(s); ChartRedraw();
      //---
      // Receive current symbol data
      int res=GetDataCurrentSymbol(s);
      //---
      if(res==0) { BC } // If zero, break the loop or start the next iteration
      //---
      if(res==2)        // Program operation interrupted by user
        {
         DelAllScriptObjects(); // Deleted objects created by the script from the chart
         //---
         Print("------\nUser deleted the script!"); break;
        }
      //---
      // Receive the path for creating the file and create directories for them
      // If the string is empty, break the loop or start the next iteration
      if((path=CheckCreateGetPath(s))=="") { BC }
      //---
      WriteDataToFile(s); // Write data to file
     }
//---
// Delete symbols from Market Watch window if necessary
   DelSymbolsFromMarketWatch();
//---
// Delete objects created by the script from the chart
   Sleep(1000); DelAllScriptObjects();
  }

Temel etkinliklerin gerçekleştiği işlevleri inceleyelim.

Sembol dizisi (symbols[]), GetSymbolsToArray() işlevinde sembol adlarıyla doldurulur. Dizi boyutu ve içindeki sembol sayısı, bir kullanıcı tarafından Mod Yazma Sembolleri (curr_mwatch) parametresinde seçilen değişkene bağlıdır.

Kullanıcının yalnızca bir sembolden gelen verilere sahip olması gerekiyorsa, dizi boyutu 1'e eşittir.

ArrayResize(symbols,1); // Set the array size to be equal to 1
symbols[0]=_Symbol;     // Specify the current symbol's name

Kullanıcı, Piyasa İzleme penceresinden tüm sembollere veya mevcut tüm sembollere ilişkin verileri almak isterse, dizi boyutu aşağıdaki işlev ile tanımlanacaktır:

int SymbolsTotal(
   bool selected   // true – only MarketWatch symbols
);

Neredeyse aynı koda sahip iki değişken için iki blok oluşturulmasını önlemek için, true veya false değerini döndürecek olan MWatchOrAllList() işaretçi işlevi yapacağız. Bu değer, sembol listesinin nereden alınacağını tanımlar - yalnızca Piyasa İzleme penceresinden (true) veya mevcut sembollerin ortak listesinden (false).

//____________________________________________________________________
//+------------------------------------------------------------------+
//| POINTER_TO_MARKET_WATCH_WINDOW_OR_TO_COMMON_LIST                 |
//+------------------------------------------------------------------+
bool MWatchOrAllList()
  {
   if(curr_mwatch==MARKETWATCH) { return(true); }
   if(curr_mwatch==ALL_LIST_SYMBOLS) { return(false); }
//---
   return(true);
  }

Döngüdeki sembol sayısını elde ettikten sonra, tüm listeyi gözden geçirmeli ve dizi boyutunu bir değer artırarak her yinelemede sembol adını diziye eklemeliyiz. Sembol adı ise SymbolName() işlevi kullanılarak indeks numarasıyla elde edilir.

int SymbolName(
   int pos,        // list index number
   bool selected   // true – only MarketWatch symbols
);

Sembol listesini seçmek için SymbolName() işlevinde MWatchOrAllList() işaretçi işlevi de kullanılır. GetSymbolsToArray() işlevi tam kodu:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| FILLING_SYMBOL_ARRAY_WITH_NAMES                                  |
//+------------------------------------------------------------------+
void GetSymbolsToArray()
  {
// If only the current symbol data is required
   if(curr_mwatch==CURRENT)
     { ArrayResize(symbols,1); symbols[0]=_Symbol; }
//---
// If data on all symbols  from Market Watch window or
// or the entire symbol list is required
   if(curr_mwatch==MARKETWATCH || curr_mwatch==ALL_LIST_SYMBOLS)
     {
      // Receive the number of symbols in Market Watch window
      cnt_symb=SymbolsTotal(MWatchOrAllList());
      //---
      for(int i=0; i<=cnt_symb-1; i++)
        {
         string nm_symb="";
         //---
         ArrayResize(symbols,i+1); // Increase the array size by one once again
         //---
         // Receive a name of a symbol from Market Watch window
         nm_symb=SymbolName(i,MWatchOrAllList());
         symbols[i]=nm_symb; // Put the symbol name into the array
        }
     }
  }

SetSeparateForFormatDate() işlevi çok basittir. Tarih Saat Biçimi (format_date) parametresinin açılır listesinde kullanıcının tercihine göre tarihte ne tür bir ayırıcı kullanılacağını tanımlamak için kullanılır.

//____________________________________________________________________
//+------------------------------------------------------------------+
//| DEFINING_SEPARATOR_FOR_DATE_FORMAT                               |
//+------------------------------------------------------------------+
void SetSeparateForFormatDate()
  {
   switch(format_date)
     {
      case SEP_POINT1 : case SEP_POINT2 : sep="."; break; // Full point as a separator
      case SEP_SLASH1 : case SEP_SLASH2 : sep="/"; break; // Slash as a separator
     }
  }

Ardından çeşitli kontroller içeren temel döngü gelir. Tüm kontroller başarılı olursa veriler dosyaya yazılır. Aksi takdirde, döngü bozulur, tüm nesneler grafikten silinir ve script dosyası kaldırılır (bir sembol olması durumunda) veya bir sonraki yineleme başlar (birden fazla sembol olması durumunda). symbols[] dizisinin her sembolü döngüde tutarlı bir şekilde çağrılır. İndeks numarası, döngünün her işlevine gönderilir. Böylece, tüm işlevlerdeki doğru dizi korunur.

Döngüdeki mevcut sembol üzerindeki veriler, döngü gövdesinin en başında her yinelemede alınır. Bunun için GetDataCurrentSymbol() işlevi kullanılır. Bu işlevde neler olacağına bakalım.

Veri kullanılabilirliği, sembol verilerini rate[] dizisine kopyalamadan önce CheckLoadHistory() işlevi kullanılarak kontrol edilir. Bu işlev, geliştiriciler tarafından örnek olarak verilmiştir. İlk sürümü MQL5 Referansı'nda bulunabilir. Bu script dosyasında kullanmak için yalnızca küçük düzeltmeler yaptım. Referans, ayrıntılı bir açıklama içermektedir (onu incelemek de iyi bir fikir olabilir); bu nedenle, hemen hemen aynı olduğu için burada kendi sürümümü göstermeyeceğim. Ayrıca, ayrıntılı açıklamalar içeren kodda bulunabilir.

Şu anda söz edilecek tek şey, CheckLoadHistory() işlevinin hata veya başarılı yürütme kodunu döndürmesidir; buna göre switch işleç bloğundan gelen uygun mesaj günlüğe kaydedilir. Alınan koda göre GetDataCurrentSymbol() işlevi ya işlemine devam eder ya da kodunu döndürür.

Her şey yolunda giderse, geçmiş verileri CopyRates() işlevi kullanılarak kopyalanır. Dizi boyutu genel değişkene kaydedilir. Ardından, 1 kodunun döndürülmesi eşliğinde işlevden çıkış gerçekleştirilir. Bir şeyler ters giderse, işlev, switch işecinde çalışmasını durdurur ve 0 veya 2 kodunu döndürür.

//____________________________________________________________________
//+------------------------------------------------------------------+
//| RECEIVE_SYMBOL_DATA                                              |
//+------------------------------------------------------------------+
int GetDataCurrentSymbol(int s)
  {
   Print("------\n№"+IS(s+1)+" >>>"); // Save a symbol number in the journal
//---
// Check and download the necessary amount of requested data
   int res=CheckLoadHistory(s,_Period);
//---
   InfoTable(s); ChartRedraw(); // Update the data in the data table
//---
   switch(res)
     {
      case -1 : Print("Unknown symbol "+symbols[s]+" (code: -1)!");                        return(0);
      case -2 :
         Print("Number of requested bars exceeds the maximum number that can be displayed on a chart (code: -2)!...\n"
               "...The available amount of data will be used for writing.");                break;
      //---
      case -3 : Print("Execution interrupted by user (code: -3)!");                         return(2);
      case -4 : Print("Download failed (code: -4)!");                                      return(0);
      case  0 : Print("All symbol data downloaded (code: 0).");                             break;
      case  1 : Print("Time series data is sufficient (code: 1).");                          break;
      case  2 : Print("Time series created based on existing terminal data (code: 2).");      break;
      //---
      default : Print("Execution result is not defined!");
     }
//---
// Copy data to the array
   if(CopyRates(symbols[s],_Period,check_start_date,end_date,rates)<=0)
     { Print("Error when copying symbol data "+symbols[s]+" - ",ErrorDesc(Error())+""); return(0); }
   else
     {
      copied_bars=ArraySize(rates); // Receive array size
      //---
      Print("Symbol: ",symbols[s],"; Timeframe: ",gStrTF(_Period),"; Copied bars: ",copied_bars);
     }
//---
   return(1); // Return 1, if all is well
  }

Bunun ardından, program tekrar OnStart() işlevinin ana döngü gövdesinde yer alır. Kod res yerel değişkeni tarafından atanır ve değerine göre kontrol yapılır. Sıfır değeri, bir hata olduğu anlamına gelir. Bu, döngüdeki mevcut sembolün verilerinin yazılamadığı anlamına gelir. Hata açıklaması günlüğe kaydedilir ve döngünün kesilip kesilmeyeceği (bozulup bozulmayacağı) veya bir sonraki yinelemenin başlatılıp başlatılmayacağı (devam) kararı verilir.

if(res==0) { BC } // If zero, the loop is interrupted or the next iteration starts

Yukarıdaki kod satırı, bu seçimin bazı gizemli BC karakterleri tarafından yapıldığını göstermektedir. Bu, bir makro açılımdır. Bununla ilgili daha fazla bilgi MQL5 Referansı'nda bulunabilir. Burada belirtilmesi gereken tek şey, yukarıdaki örnekte (BC) gösterildiği gibi tüm ifadelerin (bir satıra yazılan) kısa bir girişe yapıştırılabilmesidir. Bazı durumlarda, bu yöntem bir işlevden daha kullanışlı ve kompakt olabilir. Mevcut durumda, bu, aşağıdaki gibi görünür:

// Macro expansion with further action selection
#define BC if(curr_mwatch==CURRENT) { break; } if(curr_mwatch==MARKETWATCH || curr_mwatch==ALL_LIST_SYMBOLS) { continue; }

Aşağıda, bu script dosyasında kullanılan diğer makro açılım örnekleri verilmiştir:

#define nmf __FUNCTION__+": " // Macro expansion of the function name before sending the message to the journal
//---
#define TRM_DP TerminalInfoString(TERMINAL_DATA_PATH) // Folder for storing the terminal data

GetDataCurrentSymbol(), 2 değerini döndürürse, program bir kullanıcı tarafından silinmiş demektir. MQL5, bu olayı tanımlamak için IsStopped() işlevini içerir. Bu işlev, programın çalışmasını doğru ve zamanında durdurmak için döngülerde çok yardımcı olabilir. İşlev true değerini döndürürse, program zorla silinmeden önce tüm işlemleri gerçekleştirmek için yaklaşık üç saniye vardır. Bizim durumumuzda, tüm grafik nesneleri kaldırılır ve mesaj günlüğe gönderilir:

if(res==2) // Program execution interrupted by user
   {
    DelAllScriptObjects(); // Delete all objects created by the script from the chart
    //---
    Print("------\nUser deleted the script!"); break;
   }


8. Klasörler Oluşturma ve Verileri Dosyalama

CheckCreateGetPath() işlevi, kök veri klasörünün varlığını kontrol eder. Bunu DATA_OHLC olarak adlandıralım ve C:\Metatrader 5\MQL5\Files'a yerleştirelim. Bu, sembol adlarına sahip klasörler içerecektir. Verileri yazmak için dosyalar orada oluşturulacaktır.

Döngüdeki mevcut sembol için kök klasör veya klasör yoksa, işlev onu oluşturur. Her şey yolunda giderse, işlev, dosya oluşturma yolunu içeren bir dize döndürür. Bir hata durumunda veya kullanıcı tarafından grafikten bir hata veya programı silme girişimi olması durumunda, işlev boş bir dize döndürür.

Aşağıdaki kod, anlaşılmasını kolaylaştıran ayrıntılı açıklamalar içerir:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| CHECK_DIRECTORY_AND_CREATE_NECESSARY_DATA_FOLDERS                |
//+------------------------------------------------------------------+
string CheckCreateGetPath(int s)
  {
   int i=1;
   long search=-1;
   string ffname="",lpath="";
   string file="*.csv",folder="*";
   string
   root="DATA_OHLC\\",         // Root data folder
   fSmb=symbols[s]+"\\",     // Symbol name
   fTF=gStrTF(_Period)+"\\"; // Symbol time frame
//---
   bool flgROOT=false,flgSYMBOL=false;
//---
//+------------------------------------------------------------------+
//| SEARCHING_FOR_DATA_OHLC_ROOT_FOLDER                              |
//+------------------------------------------------------------------+
   lpath=folder;
   search=FileFindFirst(lpath,ffname); // Set search handle in Metatrader 5\MQL5\Files
//---
   Print("Directory: ",TRM_DP+"\\MQL5\\Files\\");
//---
// Set the flag if the first folder is a root one
   if(ffname==root)
     { flgROOT=true; Print("Root folder "+root+" present"); }
//---
   if(search!=INVALID_HANDLE) // If search handle received
     {
      if(!flgROOT) // If the first folder is not a root one
        {
         // Sort out all files searching for the root folder
         while(FileFindNext(search,ffname))
           {
            if(IsStopped()) // Execution interrupted by user
              {
               // Delete objects created by the script from the chart
               DelAllScriptObjects();
               //---
               Print("------\nUser deleted the script!"); return("");
              }
            //---
            if(ffname==root) // Set the flag if found
              { flgROOT=true; Print("Root folder "+root+" present"); break; }
           }
        }
      //---
      FileFindClose(search); search=-1; // Close root folder search handle
     }
   else { Print("Error when receiving the search handle or directory "+TRM_DP+" is empty: ",ErrorDesc(Error())); }
//---
//+------------------------------------------------------------------+
//| SEARCHING_SYMBOL_FOLDER                                          |
//+------------------------------------------------------------------+
   lpath=root+folder;
//---
// Set search handle in the root folder ..\Files\DATA OHLC\
   search=FileFindFirst(lpath,ffname);
//---
// Set the flag if the first folder of the current symbol
   if(ffname==fSmb) { flgSYMBOL=true; Print("Symbol folder "+fSmb+" present"); }
//---
   if(search!=INVALID_HANDLE) // If search handle is received
     {
      if(!flgSYMBOL) // If the first folder is not of the current symbol
        {
         // Sort out all the files in the root folder searching the symbol folder
         while(FileFindNext(search,ffname))
           {
            if(IsStopped()) // Execution interrupted by user
              {
               // Delete objects created by the script from the chart
               DelAllScriptObjects();
               //---
               Print("------\nUser deleted the script!"); return("");
              }
            //---
            if(ffname==fSmb) // Set the flag if found
              { flgSYMBOL=true; Print("Symbol folder"+fSmb+" present"); break; }
           }
        }
      //---
      FileFindClose(search); search=-1; // Close symbol folder search handle
     }
   else { Print("Error when receiving search handle or the directory "+path+" is empty"); }
//---
//+------------------------------------------------------------------+
//| CREATE_NECESSARY_DIRECTORIES_ACCORDING_TO_CHECK_RESULTS          |
//+------------------------------------------------------------------+
   if(!flgROOT) // If there is no DATA_OHLC... root folder
     {
      if(FolderCreate("DATA_OHLC")) // ...we should create it
        { Print("..\DATA_OHLC\\ root folder created"); }
      else
        { Print("Error when creating DATA_OHLC: root folder",ErrorDesc(Error())); return(""); }
     }
//---
   if(!flgSYMBOL) // If there is no folder of the symbol, the values of which should be received...
     {
      if(FolderCreate(root+symbols[s])) // ...we should create it
        {
         Print("..\DATA_OHLC\\" symbol folder created+fSmb+"");
         //---
         return(root+symbols[s]+"\\"); // Return the path for creating the file for writing
        }
      else
        { Print("Error when creating ..\DATA_OHLC\\ symbol folder"+fSmb+"\: ",ErrorDesc(Error())); return(""); }
     }
//---
   if(flgROOT && flgSYMBOL)
     {
      return(root+symbols[s]+"\\"); // Return the path for creating the file for writing
     }
//---
   return("");
  }

CheckCreateGetPath() işlevi boş bir satır döndürürse, döngü kesintiye uğrar veya sonraki yineleme zaten bilinen makro açılımı (BC) kullanmaya başlar:

// Receive the path for creating a file and create directories for them
// If the line is empty, the loop is interrupted or the next iteration starts
if((path=CheckCreateGetPath(s))=="") { BC }

Bu aşamaya ulaştıysanız, bu, verilerin başarıyla kopyalandığı anlamına gelir ve path string değişkeni, mevcut sembolün verilerini döngüye yazmak için dosya oluşturma yolunu içerir.

Dosyaya veri yazmak için WriteDataToFile() işlevi oluşturun. [Yol]+[dosya adı], işlevin başında oluşturulur. Dosya adı, bir sembol adından ve geçerli zaman diliminden oluşur. Örneğin, EURUSD_H1.csv. Böyle bir ada sahip dosya zaten mevcutsa, yalnızca yazmak için açılır. Daha önce yazılmış veriler silinecektir. Bunun yerine yeni veriler yazılacaktır. Dosya başarıyla oluşturulur/açılırsa, FileOpen() işlevi, dosyaya erişmek için kullanılacak tanıtıcıyı döndürür.

Tanıtıcı kontrol ediliyor. Varsa, başlık satırı yazılır. Uygun satır, kullanıcı tarafından hangi başlıkların seçildiğine bağlı olarak yazılacaktır. Geçmiş verilerini yazma ana döngüsü daha sonra başlar.

Bir sonraki satırı yazmadan önce, bu, kullanıcı tarafından belirtilen biçime dönüştürülmelidir. Bunu yapmak için, çubuğun açılış zamanını almalı ve StringSubstr() işlevini kullanarak gün, ay, yıl ve saat değişkenlere göre ayrı ayrı sıralamalıyız. Ardından, tarih ve saatin tek sütunda mı yoksa kullanıcının belirttiği biçime göre ayrı sütunlarda mı yer alacağını belirlemeliyiz. Ardından tüm parçalar StringConcatenate() işlevi kullanılarak tek bir satırda birleştirilir. Tüm satırlar yazıldıktan sonra dosya FileClose() işlevi ile kapatılır.

WriteDataToFile() işlev kodunun tamamı aşağıda gösterilmiştir:

//____________________________________________________________________
//+------------------------------------------------------------------+
//| WRITE_DATA_TO_FILE                                               |
//+------------------------------------------------------------------+
void WriteDataToFile(int s)
  {
// Number of decimal places in the symbol price
   int dgt=(int)SymbolInfoInteger(symbols[s],SYMBOL_DIGITS);
//---
   string nm_fl=path+symbols[s]+"_"+gStrTF(_Period)+".csv"; // File name
//---
// Receive file handle for writing
   hFl=FileOpen(nm_fl,FILE_WRITE|FILE_CSV|FILE_ANSI,',');
//---
   if(hFl>0) // If the handle is received
     {
      // Write the headers
      if(format_headers==NSDT_5)
        { FileWrite(hFl,"\"Date\" ""\"Time\" ""\"Open\" ""\"High\" ""\"Low\" ""\"Close\" ""\"Volume\""); }
      //---
      if(format_headers==NSDT_6)
        { FileWrite(hFl,"Date","Open","High","Low","Close","Volume"); }
      //---
      // Write the data
      for(int i=0; i<=copied_bars-1; i++)
        {
         if(IsStopped()) // If program execution interrupted by a user
           {
            DelAllScriptObjects(); // Delete objects created by the script from the chart
            //---
            Print("------\nUser deleted the script!"); break;
           }
         //---
         sdt=TSdm(rates[i].time); // Bar open time
         //---
         // Divide the date by year, month and time
         yyyy=StringSubstr(sdt,0,4);
         mm=StringSubstr(sdt,5,2);
         dd=StringSubstr(sdt,8,2);
         tm=StringSubstr(sdt,11);
         //---
         string sep_dt_tm=""; // Separator of Date and Time columns
         //---
         // Join the data with the separator in the necessary order
         if(format_date==SEP_POINT1 || format_date==SEP_SLASH1) { sep_dt_tm=" "; }
         if(format_date==SEP_POINT2 || format_date==SEP_SLASH2) { sep_dt_tm=","; }
         //---
         // Join everything in one line
         StringConcatenate(sdt,dd,sep,mm,sep,yyyy,sep_dt_tm,tm);
         //---
         FileWrite(hFl,
                   sdt,// Date-time
                   DS_dgt(rates[i].open,dgt),      // Open price
                   DS_dgt(rates[i].high,dgt),      // High price
                   DS_dgt(rates[i].low,dgt),       // Low price
                   DS_dgt(rates[i].close,dgt),     // Close price
                   IS((int)rates[i].tick_volume)); // Tick volume price
         //---
         // Update writing progress value for the current symbol
         pgs_pcnt=((double)(i+1)/copied_bars)*100;
         //---
         // Update data in the table
         InfoTable(s); if(show_progress) { ChartRedraw(); }
        }
      //---
      FileClose(hFl); // Close the file
     }
   else { Print("Error when creating/opening file!"); }
  }

Bu, OnStart() işlevinin temel döngüsündeki son işlevdi. Son sembol değilse, bir sonraki için her şey tekrarlanır. Aksi takdirde, döngü bozulur. Kullanıcı, script dosyası parametrelerinde Piyasa İzleme penceresindeki sembol listesini temizlemeyi belirtirse, o anda aktif olmayan grafikleri içeren semboller DelSymbolsFromMarketWatch() işlevi tarafından silinecektir. Bunun ardından, script dosyası tarafından oluşturulan tüm grafik nesneleri silinir ve program durur. Veriler, kullanıma hazırdır.

Verilerin NeuroShell DayTrader Professional'a nasıl indirileceğine ilişkin ayrıntılar blogumda bulunabilir. Script dosyasının çalışmasını gösteren video aşağıda verilmiştir:



Sonuç

Alım satım stratejileri geliştirmek için hangi programı kullanırsam kullanayım, her zaman fikirlerimi daha fazla geliştirmemi engelleyen bazı sınırlamalarla karşılaştım. Nihayetinde, programlamanın bu noktada çok önemli olduğunu anladım. MQL5, gerçekten başarılı olmak isteyen kişiler için en iyi çözümdür. Ancak, yeni fikir arayışı aşamasında, veri analizi ve alım satım stratejilerinin geliştirilmesi için diğer programlar da faydalı olabilir. Tek bir araç kullanmış olsaydım, onları bulmam çok daha uzun sürerdi.

İyi şanslar!

MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/502

Ekli dosyalar |
writedatatofile.mq5 (68.96 KB)
DLL'leri Kullanmadan Adlandırılmış Kanalları Kullanarak MetaTrader 5 ile İletişim Kurma DLL'leri Kullanmadan Adlandırılmış Kanalları Kullanarak MetaTrader 5 ile İletişim Kurma
Birçok geliştirici aynı sorunla karşı karşıyadır: Güvenli olmayan DLL'ler kullanmadan alım satım terminali korumalı alanına nasıl ulaşılır? En kolay ve en güvenli yöntemlerden biri, normal dosya işlemleri gibi çalışan standart Adlandırılmış Kanalları kullanmaktır. Bunlar, programlar arasında işlemciler arası istemci-sunucu iletişimini düzenlemenize olanak tanır. C++ ve MQL5'te sunucu, istemci, bunlar arasındaki veri alışverişini ve performans karşılaştırmasını içeren pratik örneklere bir göz atın.
MetaTrader Market'tan bir alım satım robotu nasıl satın alınır ve yüklenir? MetaTrader Market'tan bir alım satım robotu nasıl satın alınır ve yüklenir?
MetaTrader Market'tan bir ürün, MQL5.com web sitesinden veya doğrudan MetaTrader 4 ve MetaTrader 5 alım satım platformlarından satın alınabilir. Alım satım tarzınıza uygun bir ürün seçin, tercih ettiğiniz ödeme yöntemini kullanarak ödeme yapın ve ürünü etkinleştirin.
Alım Satım Sinyallerine Nasıl Abone Olunur? Alım Satım Sinyallerine Nasıl Abone Olunur?
Sinyaller hizmeti, MetaTrader 4 ve MetaTrader 5 ile sosyal alım satımı tanıtmaktadır. Hizmet, alım satım platformuna entegre edilmiştir ve herkesin profesyonel yatırımcıların alım satım işlemlerini kolaylıkla kopyalamasına olanak tanır. Binlerce sinyal sağlayıcıdan herhangi birini seçin ve birkaç tıklamayla abone olun; sağlayıcının alım satım işlemleri hesabınıza kopyalanacaktır.
Nöral Ağlar: Teoriden Pratiğe Nöral Ağlar: Teoriden Pratiğe
Günümüzde her yatırımcının, nöral ağlar hakkında bilgisi olması gerekir; bunları kullanmanın ne kadar havalı olduğunu bilirler. Çoğunluk, nöral ağlarla uğraşan kişilerin insanüstü olduklarına inanıyor. Bu makalede, sizlere nöral ağ mimarisini açıklamaya, uygulamalarını anlatmaya ve pratik kullanım örneklerini göstermeye çalışacağım.