English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
ORDER_MAGIC'in Tek Enstrüman Üzerinde Farklı Expert Advisor'larla Alım Satım Yapmak İçin Kullanımı

ORDER_MAGIC'in Tek Enstrüman Üzerinde Farklı Expert Advisor'larla Alım Satım Yapmak İçin Kullanımı

MetaTrader 5Örnekler | 15 Aralık 2021, 10:09
132 0
Mykola Demko
Mykola Demko


Giriş

MQL5'te, talimatı tanımlamak üzere bu bilgileri kullanmak için, bekleyen her talimata sihirli bir sayı atama olanağımız bulunmaktadır. Bu, farklı Expert Advisor'lar arasındaki büyük etkileşim imkanlarını ve daha da karmaşık sistemlerin geliştirilmesini sağlar. Bu makalede, Sihirli sayının değeri bilinmeyen fırsatları hakkında kamuoyunu bilgilendirmek istiyorum.

Ancak bu makalenin konusunun özüne geçmeden önce, Sihirli sayıyı neyin oluşturduğunu daha iyi anlamamız gerekiyor. Hangi Expert Advisor tarafından ayarlandığını belirleyen bir sayıda sihirli ne olabilir? "Mucizeler", geliştiricilerin, Sihirli sayı yoluyla bildirilen ulong, türüne yerleştirdiği fırsatlarla başlar.

ulong türü en uzundur

long tamsayı türünü ayrıntılı olarak incelersek, bu türün maksimum değerinin olağanüstü olduğunu görürüz:

Tür

Bayt cinsinden boyut

Minimum değer

Maksimum değer

C dilinde benzer + +

long

8

-9 223 372 036 854 775 808

9 223 372 036 854 775 807

__int64

ulong

8

0

18 446 744 073 709 551 615

unsigned __int64

Tablo 1. long ve ulong veri türlerinin özellikleri

fakat ulong türü, pozitif ve negatif mantisi birleştirerek ona üstün geldi.

Belirtilen uzunluk çok büyük, ancak daha önce nasıl kullanılıyordu?

mql 4'te çalışma deneyimim sırasında, çoğu geliştirici tarafından Sihirli sayıyı kodlamanın anlamsızlığını sıklıkla fark ettim. Sihirli sayı mantıklı bir şekilde kullanıldı fakat kodlaması çok saçma görünüyordu. 12345 numaralı Sihirli sayının kendine özgülüğü hakkında söylenebilecek şey, bu Sihrin, gelişmekte olan birliğin neredeyse yarısı tarafından kullanılıyor oluşu. Diğer yarısı Sihir numarası 55555, 33333 ve 77777'yi kullanıyor ve bu hemen hemen tüm kümedir. Okuyucunun dikkatini, bilgisayarında 1.000'den fazla Expert Advisor'a sahip olmasının olası olmadığı gerçeğine çekmek istiyorum; bu nedenle 1000 sayısı, tüm Expert Advisor'larınızın bireysel adını kodlamak için yeterli olacaktır.

1000 - yalnızca 3 tam kategoridir; öyleyse ulong türünde bulunan kalan 15 tam kategoriyle ne yapmalıyız? Yanıt basit: Onları kodlayın.

Wikipidia, kod sözcüğünü şu şekilde tanımlıyor:

Kod - kural (algoritma), sembollerinin harfiyen belirli bir kombinasyonunun her bir mesajının karşılaştırması (karakterler) (veya sinyaller).

Bu nedenle, kuralları biz koyacağız. Sihirli sayının kodunda yalnızca Expert Advisor'ın kimliğini değil, aynı zamanda üzerinde çalıştığı enstrümanı da belirtmeyi öneriyorum. Expert Advisor'ın örneğin EURUSD, üzerinde çalışıyor olması, Expert Advisor'ın yalnızca o enstrümanda bir sıra göstereceği anlamına gelmez. Ayrıca Expert Advisor'ların etkileşim kodunu örneğin "sizinki / haricen gelen" şeklinde yazmanın faydalı olacağını düşünüyorum; böylece Expert Advisor, pozisyonları kontrol ederken mevcut sıranın yakın bir Expert Advisor tarafından oluşturulduğunu anlayabilir. Bunun çok karmaşık bir sistem oluşturmak için yeterli olacağını düşünüyorum.

O halde elimizdekileri özetleyelim: Sisteme hangi fırsatları sunuyoruz?

  1. İki veya daha fazla Expert Advisor'ın tek bir enstrüman üzerinde çalışması ve karışmama olasılığı.
  2. İki veya daha fazla Expert Advisor'ın farklı enstrümanlar üzerinde çalışması ve birbirini tamamlama olasılığı.
  3. Expert Advisor ile birlikte çalışarak, sırayı enstrümana göre belirleme yeteneği.

Böylece, görev belirlendi; şimdi uygulamaya başlayalım.

Basit Expert Advisor

Basit Expert Advisor kodunun taslağını oluşturun- Örneğin, pozisyonu Hareket yönünde tutun. Sihirli sayıyı ayrıştırmaya karar veren okuyucuların Yeni Başlayanlar için MQL5'te Expert Advisor Yazmak için Adım Adım Kılavuz makalesini zaten okuduğunu düşünüyorum, şayet okumadıysanız okumanızı şiddetle tavsiye ederim; zira Expert Advisor'ın oluşturulması konusunda ayrıntılara girmeyeceğim. Temel olarak, Expert Advisor pozisyonu bir kez açacak ve diğer tüm zamanlar için çevirecektir. Bu nedenle, pozisyonu açmak için, yani alım satım talebinde (alım satım talimatı) bulunmak için işleve ihtiyacımız olacak.

Alım satım talebi yapısının alanlarını doldurmak için parametreleri bizim için hesaplayacak bir yardımcı sınıf oluşturun.

//+------------------------------------------------------------------+
//| The class provides auxiliary trading calculations                |
//+------------------------------------------------------------------+
class CProvision
  {
protected:
   MqlTradeRequest   trades;                 // pointer to the request structure of OrderSend
public:
   int               TYPE(const double &v[]);  // determines the type, in respect to the  readings of the moving
   double            pricetype(int type);     // calculates the level of the opening, in respect to the type 
   double            SLtype(int type);        // calculates the level of the stop-loss in respect to the type
   double            TPtype(int type);        // calculates the level of the take-profit, in respect to the type
   long              spread();               // returns the spread of the current instrument
   int               SendOrder(ENUM_ORDER_TYPE type,double volume);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CProvision::SendOrder(ENUM_ORDER_TYPE type,double volume)
  {
   trades.action          =TRADE_ACTION_DEAL;       // Type of the implemented actions
   trades.magic           =magic;                 // Stamp of the Expert Advisor (identifier of the magic number)
   trades.symbol          =_Symbol;                // Name of the trading instrument
   trades.volume          =volume;                // Request the volume of the trade in lots
   trades.price           =pricetype((int)type);  // Price       
   trades.sl              =SLtype((int)type);     // Level of Stop Loss order
   trades.tp              =TPtype((int)type);     // Level of Take Profit order         
   trades.deviation=(int)spread();                // Maximum acceptable deviation from the requested price
   trades.type=type;                              // Order type
   trades.type_filling=ORDER_FILLING_FOK;
   if(OrderSend(trades,res)){return(res.retcode);}
   return(-1);
  }
//+------------------------------------------------------------------+
//| Determines the type, in respect to the reading of the moving     |
//+------------------------------------------------------------------+
int CProvision::TYPE(const double &v[])
  {
   double t=v[0]-v[1];
   if(t==0.0)t=1.0;
   return((int)(0.5*t/fabs(t)+0.5));
  }
//+------------------------------------------------------------------+
//| Calculates the level of opening in respect to the type           |
//+------------------------------------------------------------------+
double CProvision::pricetype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.ask);
      if(type==1)return(tick.bid);
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//| Calculates the level of stop-loss in respect to the type         |
//+------------------------------------------------------------------+
double CProvision::SLtype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.bid-SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
      if(type==1)return(tick.ask+SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Calculates the level of timeframe in respect to the type         |
//+------------------------------------------------------------------+
double CProvision::TPtype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.bid+TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
      if(type==1)return(tick.ask-TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Returns the spread                                               |
//+------------------------------------------------------------------+
long CProvision::spread() 
  {
   return(SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));
  }

Böyle bir sınıfa sahip olarak, basit bir Expert Advisor için sorunsuz bir kod yazabiliriz: 

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+

//--- Input parameters
input ulong              magic       =1;           // magic
input int                SL          =300;         // Stop Loss
input int                TP          =1000;        // Take Profit
input int                MA_Period   =25;         // MA period
input double             lot         =0.1;         // Volume of position
input int                MA_shift    =0;          // Shift of indicator
input ENUM_MA_METHOD     MA_smooth   =MODE_SMA;     // Smoothing type
input ENUM_APPLIED_PRICE price       =PRICE_OPEN;    // Price type 

//--- We will store the indicator's handle
int
MA_handle,     // Handle of the indicator
type_MA,       // Type that specify the direction of MA
rezult;        // The variable takes the value of the result of the OrderSend operation
double v[2];    // Buffer for receiving values of MA

MqlTradeResult   res;   // Pointer to the structure of responding by OrderSend
MqlTick         tick;  // Pointer to the structure of last market information
CProvision      prov;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication

   if(PositionSelect(_Symbol))// If there is an open position 
     {
      if(PositionGetInteger(POSITION_TYPE)!=type_MA)// Check if its time to close
        {
         Print("#",magic,"Position by magic number has volume ",PositionGetDouble(POSITION_VOLUME),
               " reverse position of type ",PositionGetInteger(POSITION_TYPE)," by ",type_MA);
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,PositionGetDouble(POSITION_VOLUME)+lot);
         // reverse the position
         if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("#",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Position by magic number has volume ",PositionGetDouble(POSITION_VOLUME),
            " open position of type ",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);
      // open position 
      if(rezult!=-1)Print("#",magic," Code of operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  } 

Çalıştırın ve Expert Advisor'ın karlılık açısından farklılık göstermediğinden, tam olarak ondan ihtiyacımız olan şey olan belirtilen mantığa göre işlem yaptığından emin olun.

Şekil 1. Bir Expert Advisor'ın tek bir enstrüman üzerinde çalışması

Şekil 1. Bir Expert Advisor'ın tek bir enstrüman üzerinde çalışması

Şimdi bu EA'yı çalıştırmayı deneyeceğiz fakat bunu bir enstrümanın farklı zaman dilimlerinde yapacağız (denemek için EURUSD: o olan rastgele bir enstrüman seçtik)

Şekil 2. Aynı enstrüman üzerinde farklı zaman dilimlerinde iki Expert Advisor'ın çakışması

Şekil 2. Aynı enstrüman üzerinde farklı zaman dilimlerinde iki Expert Advisor'ın çakışması

Her iki Expert Advisor da tek bir enstrüman üzerinde çalıştığı ve kod, pozisyonların paylaşımını belirtmediği için her iki Expert Advisor da göstergelerinin okumalarına bağlı olarak alım satım pozisyonunu düzeltmeye çalışıyor ve bunun sonucunda, bir çakışma ortaya çıkıyor. M1 üzerinde çalışan Expert Advisor, rakibi onu durdurmaya çalışırken, Hücredeki pozisyonu değiştirmeye çalışıyor. Ayrı bir pozisyon hesaplamasına ihtiyacımız olduğu açık; şimdi yapacağımız şey de tam olarak bu.


Pozisyon mu, sanal pozisyon mu?

MetaTrader 5'te geliştiriciler talimatlardan pozisyonları dikkate almaya geçtiği için kayıt pozisyonlarıyla ilişkili işlevleri daha ayrıntılı olarak düşünmek mantıklıdır.

// Returns the number of open positions.
int     PositionsTotal();

// Returns the symbol of the open position by the number in the list of positions.
string  PositionGetSymbol(int  index);

// Selects the open position for further working with it.
bool    PositionSelect(string  symbol, uint timeout=0);

// Function returns the requested property of the open position.
double  PositionGetDouble(ENUM_POSITION_PROPERTY  property_id);

// The function returns the requested property of the open position.
long    PositionGetInteger(ENUM_POSITION_PROPERTY  property_id);

// The function returns the requested property of the open position.
string  PositionGetString(ENUM_POSITION_PROPERTY  property_id);

Tablo 2-4'te verilen PositionGetDouble, PositionGetInteger ve PositionGetString uyumlu pozisyon özelliklerinin talebini alma işlevlerine ilişkin numaralandırma tanımlayıcıları.

Tanımlayıcı

Açıklama

Tür

POSITION_VOLUME

Pozisyon hacmi

çift

POSITION_PRICE_OPEN

Pozisyon fiyatı

çift

POSITION_SL

Açık pozisyon için Zararı Durdur Düzeyi

çift

POSITION_TP

Açık pozisyon için Kar Al Düzeyi

çift

POSITION_PRICE_CURRENT

Sembole göre mevcut fiyat

çift

POSITION_COMMISSION

Komisyon

çift

POSITION_SWAP

Birikmiş swap

çift

POSITION_PROFIT

Mevcut kar

çift

Tablo 2. Numaralandırma değeri ENUM_POSITION_PROPERTY_DOUBLE

Tanımlayıcı

Açıklama

Tür

POSITION_TIME

Pozisyonların açılış zamanı

datetime

POSITION_TYPE

Pozisyon türü

ENUM_POSITION_TYPE

POSITION_MAGIC

Pozisyon için sihirli sayı (bkz. ORDER_MAGIC )

long

POSITION_IDENTIFIER

Pozisyonun tanımı - Bu, yeniden açılan her pozisyona atanan ve yaşam döngüsü boyunca değişmeyen benzersiz bir sayıdır. Bir pozisyonun cirosu kimliğini değiştirmez.

long

Tablo 3. Numaralandırma değerleri ENUM_POSITION_PROPERTY_INTEGER

Tanımlayıcı

Açıklama

Tür

POSITION_SYMBOL

Pozisyonun açıldığı sembol

dize

POSITION_COMMENT

Pozisyona ilişkin açıklama

dize

Tablo 4. Numaralandırma değerleri ENUM_POSITION_PROPERTY_STRING

İşlevlerden, "talimatı kim verdi?" prensibine dayalı olarak, dilin pozisyon ayrımını içermediğini açıkça görebiliriz fakat bu tür kayıtların olasılığı mevcuttur; zira ORDER_MAGIC, POSITION_MAGIC ve DEAL_MAGIC aynı tam sayılardır ve kullanıcı tarafından belirtilen sihirli sayıdan alınırlar. POSITION_MAGIC, pozisyonu açan DEAL_MAGIC'ten, DEAL_MAGIC ise verilen talimata ait olan ORDER_MAGIC'ten alınır.

Bir talimat, işlem veya pozisyonun belirlenmesi sorunsuz bir şekilde yapılabilir fakat belirli bir Sihirli sayı ile bir pozisyonun dışarı çıkarılması mümkün değildir. Şimdi bu eksikliği ortadan kaldırmaya çalışacağız . Yerleşik işlevlerin benzerlerini oluşturalım, ancak bunu Sihirli sayıyla tanımlayarak yapalım. Sihirli sayı üzerinde sanal bir pozisyonla çalışmak için bir sınıf bildirin.

OOP ile çalışma fırsatımız olduğu için kendi yapımızı da bildirelim (objektif olarak ek yazma pratiği kazanarak).

//+------------------------------------------------------------------+
//| Structure of the CPositionVirtualMagic class                     |
//+------------------------------------------------------------------+
struct SPositionVirtualMagic
  {
   double            volume; // volume of virt. position
   ENUM_POSITION_TYPE type;  // type of virt. position
  };
//+--------------------------------------------------------------------------------+
//| The class calculates the virtual position of an Expert Advisor by magic number |
//+--------------------------------------------------------------------------------+
class CPositionVirtualMagic
  {
protected:
   SPositionVirtualMagic pvm;
public:
   double               cVOLUME(){return(pvm.volume);}
   // Returns the volume of virtual position of an Expert Advisor
   ENUM_POSITION_TYPE   cTYPE(){return(pvm.type);}
   // Returns the type of virtual position of an Expert Advisor
   bool              PositionVirtualMagic(ulong Magic,
                                          string symbol,
                                          datetime CurrentTime
                                          );
   // the method of calculation virt. position returns the presence or absence of virt. position
private:
   void              prHistory_Deals(ulong &buf[],int HTD);
   // Fills the array of tickets
  };
//+-------------------------------------------------------------------------------------+
//| Method of calculation of virt. position, returns true if there is a virt. position  |
//+-------------------------------------------------------------------------------------+
bool  CPositionVirtualMagic::PositionVirtualMagic(ulong Magic,
                                                  string symbol,
                                                  datetime CurrentTime
                                                  )
  {
   int DIGITS=(int)-log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP));
   if(DIGITS<0)DIGITS=0;
   ulong Dticket=0;
   int History_Total_Deals=-1;
   double volume=0,volume_BUY=0,volume_SELL=0;
   ulong DTicketbuf[];

   do
     {
      if(HistorySelect(0,TimeCurrent()))
        {
         History_Total_Deals=HistoryDealsTotal();
         prHistory_Deals(DTicketbuf,History_Total_Deals);
        }
      HistorySelect(0,TimeCurrent());
     }
   while(History_Total_Deals!=HistoryDealsTotal());

   for(int t=0;t<History_Total_Deals;t++)
     {
      Dticket=DTicketbuf[t];
      if(HistoryDealSelect(Dticket))
        {
         if(HistoryDealGetInteger(Dticket,DEAL_TIME)>=CurrentTime)
           {
            if(HistoryDealGetInteger(Dticket,DEAL_MAGIC)==Magic)
              {
               if(HistoryDealGetInteger(Dticket,DEAL_TYPE)==DEAL_TYPE_BUY)
                 {
                  volume_BUY+=HistoryDealGetDouble(Dticket,DEAL_VOLUME);
                 }
               else
                 {
                  if(HistoryDealGetInteger(Dticket,DEAL_TYPE)==DEAL_TYPE_SELL)
                    {
                     volume_SELL+=HistoryDealGetDouble(Dticket,DEAL_VOLUME);
                    }
                 }
              }
           }
        }
      else{HistorySelect(0,TimeCurrent());t--;}
      // if there is a fault, load history data and pass the step again
     }
   volume=NormalizeDouble(volume_BUY-volume_SELL,DIGITS);
   if(volume<0)pvm.type=POSITION_TYPE_SELL;
   else
     {
      if(volume>0)pvm.type=POSITION_TYPE_BUY;
     }
   pvm.volume=fabs(volume);
   if(pvm.volume==0)return(false);
   else return(true);
  }

Yukarıdaki metinde (CProvision sınıfının kodunun verildiği kısımda) her şeyin nereden geldiği ve nereye gittiği açıklanmamıştır; zira Expert Advisor'ın geliştirilmesi bu makalenin konusu değildir.

Ancak CPositionVirtualMagic sınıfını ayrıntılı olarak ele alacağız.

Sınıfa yapı verilir:

struct SPositionVirtualMagic

Bu, sınıf içinde böyle bir genel bildirim hesaplama sonuçlarını almak için kullanılan, pvm (yapının değişkeni) sayesinde bu yapı, sınıfın herhangi bir yönteminde her yerde mevcut olacaktır.

Ardından sınıfın iki yöntemini takip edin:

double               cVOLUME(){return(pvm.volume);} // Returns the volume of the virtual position of the EA
ENUM_POSITION_TYPE   cTYPE()  {return(pvm.type);}   // Returns the type of the virtual position of the EA

Bu yöntemler herkese açık olarak bildirilir ve bu nedenle, programdaki herhangi bir yerde çağrılan sınıf değişkeni aracılığıyla kullanılabilir olacaklardır; bunlar, istenen konumdaki yapı değerlerinin çıktısı için tasarlanmıştır.

Bu aynı zamanda aşağıdaki yöntemin bildirildiği bölümdür:

bool              PositionVirtualMagic(ulong Magic,string symbol,datetime CurrentTime);

Bu, sınıfın ana işlevi olup ayrıntılı analizlerine daha fazla odaklanacağız ve bu arada, önce gideceğim ve işlevi özel erişim belirticisi kapsamında tanımlayacağım:

void              prHistory_Deals(ulong &buf[],int HTD);

Bu yöntem, temelde bir döngü olan ve çağrılan işlevde tanımlanabilen diziye yapılan işlemlerin bir bilet kaydını üretir fakat ben PositionVirtualMagic() işlevinin boyutunu küçültmek istedim (kodun okunabilirliğini artırmak için); böylece bu döngüyü işlevin sınırlarının ötesine taşıdım ve özel erişim belirticisinin nasıl kullanılacağını gösterdim.

Öyleyse PositionVirtualMagic() işlevine geri dönelim. Bu işlev, en başında, hesaplanan pozisyonun hacminin çift değerini yuvarlamanız gereken tek satırlık bir doğruluk hesaplamasına sahiptir.

int DIGITS=(int)-log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP)); if(DIGITS<0)DIGITS=0;

Bu, karşılaştırma işlemini sıfırla yapmak için gereklidir; aksi takdirde ondalık noktadan sonraki 8. basamakta bir miktar denge olması, değeri sıfıra eşitlememizi engelleyecek ve bir yürütme hatasına neden olacaktır.

Pozisyon hacmi minimum adıma yuvarlanır. Minimum adım 1'den büyükse yuvarlama integral kısma göre yapılır. Bir sonraki while döngüsüdür fakat doğru ifadenin doğrulanması döngünün başından ziyade sonunda yapıldığı için yeni bir şekilde (mql4'tekinden farklı olarak) kullanılır:

    do
     {
      if(HistorySelect(0,TimeCurrent()))
        {
         History_Total_Deals=HistoryDealsTotal();
         prHistory_Deals(DTicketbuf,History_Total_Deals);
        }
      HistorySelect(0,TimeCurrent());  
     }
   while(History_Total_Deals!=HistoryDealsTotal());

Doğruluk ifadesi döngü içinde hesaplandığı ve başlangıcında bu doğrulama için henüz hazır olmadığı için bu tip bir yaklaşım izlenir.

Döngü Geçmişin yüklenmesini içerir; yerleşik işlevlerin geçmişle çalışmasını sağlamak için bunun gerekli bir koşul olduğu gerçeğine okuyucunun dikkatini çekmek istiyorum.

HistorySelect(0,TimeCurrent())

Değişken isimlerini seçme sistemim konusunda bir açıklamada bulunmam gerektiğini düşünüyorum.

Dikkatli okuyucular, sınıfların adlarının "C" baş harfi ile tanımlandığını, sözdiziminde bunun gerekli olmadığını ve herhangi bir ad verilebileceğini fark etmiş olmalıdır, ancak böyle bir yol okumayı çok daha kolay hale getirir. Adın önünde "C" harfi varsa bunun sınıfın adı olduğunu, "S" harfi varsa bunun bir yapı olduğunu hemen anlarız. Değişken yerleşik bir işlevin değerini alırsa işlevin adının bileşenlerini değiştiririm ve değişken adını alırım; buna şunu örnek verebilirim:

CurrentTime = TimeCurrent();

Bu, basit ve okunaklıdır; değişkenin ne içerdiğini hemen görebiliriz. Özellikle MetaEditor, belirli bir kod parçasını belirli bir konuma sürükleme işlevini içerdiği için.

Kodu daha fazla gözden geçirdiğimizde, geçmişin yüklenmesinden sonra işlev çağrısını takip ettiğini görüyoruz:

History_Total_Deals=HistoryDealsTotal();

İşlem sayısının değişkene depolanması ile. Aynı koşulla, döngüden çıkmak için doğrulamayı uygulayacağız. Bu doğrulamaya ne için ihtiyacımız var? Ve neden yalnızca geçmişi yükleyemiyoruz ve bunun ardından işlemleri geri alamıyoruz?

Sorun, Expert Advisor'ların çalışması sırasında her EA tarafından geçmişin ayrı ayrı talep edileceği ve dolayısıyla Expert Advisor'ların farklı zamanlarda çalışması halinde geçmişin derinliğinin farklı olacağı gerçeğinde yatmaktadır. Bu, bir Expert Advisor döngüye girdiğinde ve dönemine ilişkin geçmişi yüklediğinde, döngünün sonuna gelmeden önce, bu geçmişin başka bir Expert Advisor'ın talebiyle halihazırda yüklendiğini keşfedebilir; bu nedenle özgünlük açısından bir doğrulama yapılması gerekir.

Bu arada, bu, en iyi doğrulama türü olmayabilir, ancak işe yarıyor. O halde devam edelim. Döngüde, işlemlerin bilet değerlerini özel olarak hazırlanmış bir arabelleğe giren sınıf yöntemini çağırıyoruz. prHistory_Deals() işlevini çağırdıktan sonra yine geçmişin yüklemesini üretiyoruz.

prHistory_Deals () işlevinin çalışması sırasında, alım satım işlemleri geçmişinde herhangi bir değişiklik olup olmadığının doğrulanması bu şekilde düzenlenir. Herhangi bir değişiklik olmadıysa, History_Total_Deals değişkeni HistoryDealsTotal() değerine eşit olacak ve tek bir geçiş için döngüden bir çıkış gerçekleşecektir. Değişiklik varsa sistem ikinci bir döngü başlatacak ve bilet geçmişi hatasız bir şekilde yüklenene kadar tekrar etmeye devam edecektir (ve sonuna ";" koymayı unutmayın):

while(History_Total_Deals!=HistoryDealsTotal());

for döngüsünde ayrıca, sanal pozisyonların hesaplanması gerçekleşir.

İşlem bir dizi filtreyi (işlemin zamanı ve işlemin Sihirli sayısı) başarıyla geçtiyse hacmi, işlemin ait olduğu tür olan sanal pozisyonun o kısmını artırır.

Diğer seçenekler mümkün olsa da, sanal pozisyon hesaplamalarını yalnızca Expert Advisor'ın başlatılmasından itibaren kaydettiğimi belirtmek isterim.

Burada, pozisyonun tam olarak nasıl hesaplandığına dikkat edilmelidir. Hepimizin çok eski zamanlardan beri ve günümüzde dahi kullandığı gider ve karımızı içeren kayıt defterine göre, bakiye sayımı bu değerler arasındaki fark olarak tutulur, pozisyon hesabında da aynı şema geçerlidir: 0,2 Satış ve 0,3 Alış için lot açarsanız bu, Alış için 0,1 pozisyonunu tuttuğunuz anlamına gelir. Açılış zamanı ve düzeylerdeki fark, kar kategorileridir fakat tutacağınız pozisyon, Alış türü 0,1 lottur.

Bu nedenle, Expert Advisor tarafından Alış ve ayrı olarak Satış'ta yapılan tüm işlemleri basitçe özetliyoruz, daha sonra bunları karşılaştırıyor ve genel pozisyonu alıyoruz (aslında, bu, incelenen işlevin geri kalanının ne ile ilgili olduğudur).

Pozisyonların hacminin hesaplanması:

volume=NormalizeDouble(volume_BUY-volume_SELL,DIGITS);

Yapıdaki değerin çıktısı ile pozisyon türünün tanınması:

   if(volume<0)pvm.type=POSITION_TYPE_SELL;
   else
     {
      if(volume>0)pvm.type=POSITION_TYPE_BUY;
     }

Yapıya hacim çıktısı:

pvm.volume=fabs(volume);

 İşlevin değer çıktısı: Pozisyonun hacmi 0 ise false'tur; aksi takdirde pozisyon mevcutsa true'dur:

   if(pvm.volume==0)return(false);
   else return(true);

Artık sanal pozisyon işlevine sahip olarak, "komşuları" ile çakışmayacak olan Expert Advisor kodunu kolayca ayarlayabiliriz.

Yer kazanmak için, kodun tamamı yerine, yukarıda belirtilmeyen kodun belirli kısımlarını sağlayacağım.

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+

//--- input parameters
input ulong              magic       =1;           // magic
input int                SL          =300;         // Stop Loss
input int                TP          =1000;        // Take Profit
input int                MA_Period   =25;          // MA period
input double             lot         =0.1;         // Volume of position
input int                MA_shift    =0;          // Shift of indicator
input ENUM_MA_METHOD     MA_smooth   =MODE_SMA;     // Smoothing type
input ENUM_APPLIED_PRICE price       =PRICE_OPEN;    // Price type 
//--- we will store the indicator's handle
int MA_handle,type_MA,rezult;
double v[2];
datetime  CurrentTime;  // The variable stores the time of start of the Expert Advisor
MqlTradeResult    res;   // Pointer to the structure of responding by OrderSend
MqlTick          tick;  // Pointer to the structure of last market information
CPositionVirtualMagic cpvm;
CProvision prov;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   CurrentTime=TimeCurrent();// The variable stores the time of start of the Expert Advisor
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication

   if(cpvm.PositionVirtualMagic(magic,_Symbol,CurrentTime))// If there is ab open position 
     {
      if((int)cpvm.cTYPE()!=type_MA)// Check if it is time to close
        {
         Print("#",magic,"Position by magic number has volume ",cpvm.cVOLUME(),
               " reverse position of type ",(int)cpvm.cTYPE()," by ",type_MA);
         //cpvm.cVOLUME() - volume of virtual position
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,cpvm.cVOLUME()+lot);// reverse the poistion
         if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("#",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Poistion by magic number has volume ",cpvm.cVOLUME()," open position of type ",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);// Open position 
      if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  }

Expert Advisor'ı tek bir enstrüman üzerinde fakat farklı zaman dilimlerinde olmasına dikkat ederek üç kez çalıştırın ve her seferinde farklı sihirli sayılar atayın:

Şekil 3. İki özdeş Expert Advisor'a farklı sihirli sayılar atayalım (bir enstrüman, farklı zaman dilimleri), ilk Expert Advisor'ı başlatma

Şekil 3. İki özdeş Expert Advisor'a farklı sihirli sayılar atayalım, (bir enstrüman, farklı zaman dilimleri) ilk Expert Advisor'ı başlatma

Şekil 4. İki özdeş Expert Advisor'a farklı sihirli sayılar atayalım (bir enstrüman, farklı zaman dilimleri) ikinci Expert Advisor'ı başlatma

Şekil 4. İki özdeş Expert Advisor'a farklı sihirli sayılar atayalım (bir enstrüman, farklı zaman dilimleri) ikinci Expert Advisor'ı başlatma

Şekil 5. Sonuç, çeşitli sihirli sayılarla tek bir enstrüman üzerinde Expert Advisor'ların çakışma olmadan çalışmasıdır

Şekil 5. Sonuç, çeşitli sihirli sayılarla tek bir enstrüman üzerinde Expert Advisor'ların çakışma olmadan çalışmasıdır.

Deneme çalıştırması başarıyla geçilmiş olup Expert Advisor'lar zorunlu olarak birbirine yol vermiştir; bu durumda herhangi bir çelişkili konu yok gibi görünüyor.

Teknik Şartnamenin ilk maddesi uygulandı, ancak daha fazlası da var.


Sihri kodlamak

Aşağıdaki bölümlerin uygulanması için, bilgileri kodlayacak / kodlarını çözecek ve ayrıca yerleşik işlevlerden değerleri alıp bunları belirli bir biçime dönüştürecek bir yöntemler sınıfı geliştirmemiz gerekecek.

Bunu yapmak için, kodlama şartlarını tekrarlayın (yani, geliştirme için teknik özellikler):

  • Yöntemlerin Expert Advisor'ın adını (dijital adı diyebiliriz) kodlaması gerekir.
  • Sizinkini / haricen geleni tanıma kodu (etkileşim kodu diyebiliriz)
  • Expert Advisor'ın üzerinde çalıştığı sembol kodu (işlemden EA'nın nereden çalıştığını belirleyebilmek için).

Öncelikle, yeni sınıfın adını seçelim, - sihir (genel bir ad) olsun, kodu görsel olarak daha anlaşılır hale getirmek için numaralandırmamızı atayın.

enum Emagic
  {
   ENUM_DIGITAL_NAME,    // digital name if the Expert Advisor
   ENUM_CODE_INTERACTION,// code of interaction
   ENUM_EXPERT_SYMBOL    // symbol, on which the EA is launched
  };

Numaralandırma basit bir şekilde çalışır: Adları virgülle ayırarak tanımlarsınız ve derleyici onlara sıraya göre numaralar atar.

İlk olarak, farklı türde bir değişken atarsanız (bu, sayılar için geçerli değildir), numaralandırmadan bir parametre belirtirken, derleme sırasında bir hata alırsınız ve ikinci olarak, netlik elde edersiniz: Yalnızca 0 atamazsınız, aynı zamanda ENUM_DIGITAL_NAME atama komutunu da verirsiniz.

Bir yapının veya sınıfın oluşturulmasında olduğu gibi, numaralandırma için basit bir ad seçtim. Genel olarak seçilen ada E ekledim ve sırasıyla Emagic elde ettim; karşılık gelen yapı Smagic ve sınıf Cmagic olacaktır.

Yine, bu konunun zorunlu olmadığına dikkat edin; Enumerator numaralandırmasını, Structurer yapısını ve Classifier sınıfını çağırabilirsiniz. Ancak bu, adlarda bir müştereklik sağlamayacak ve bu tür kodları okumak rahatsız edici olacaktır.

Şimdi kodlarımızı saklamak için bir yapı oluşturalım.

struct Smagic
  {
   ulong             magicnumber;      // magic in an assembled form - how it is written in the order
   int               digital_name;     // digital name
   int               code_interaction; // code of interaction
   int               expert_symbol;    // symbol, on which the Expert Advisor is launched
  };

Bundan sonra, önceki Expert Advisor'daki yöntemler de dahil olmak üzere Magic'i kodlama ve kod çözme yöntemlerinin tümünü kaydettiğimiz Cmagic sınıfını bildirin (bunları geçerli sınıfta bildirin ve başlıkları yeniden yazın)

class Cmagic
  {
protected:
   Smagic            mag;
   SPositionVirtualMagic pvm;
public:
// the function returns the assembled magic, assembled from the incoming data
   ulong             SetMagic_request(int digital_name=0,int code_interaction=0);

// the function obtains the assembled magic and divides it according to the assembly logic
   ulong             SetMagic_result(ulong magicnumber);    

// the function obtains the return identification and returns the requested part of the assembled magic
   ulong             GetMagic_result(Emagic enum_); 

// the function obtains the return identification and returns the textual interpretation of the request part of the assembled magic
   string            sGetMagic_result(Emagic enum_);

// returns the voulme of the virtual position of the Expert Advisor
   double            cVOLUME(){return(pvm.volume);}
   
// returns the type of the virtual position of the Expert Advisor
   ENUM_POSITION_TYPE  cTYPE(){return(pvm.type);}
                                           
// method of calculating the virtual position, returns the presence of absence of the virtual position   
   bool              PositionVirtualMagic(Emagic enum_,
                                          string symbol,
                                          datetime CurrentTime);
private:
// function divides the magic into three parts  of three charges, and returns the part to which the category points to
   int               decodeMagic_result(int category); 

// interpretor of instrument symbols into the digital code                                                      
   int               symbolexpert();     
   
// interpretor of the digital code into the prescribed text (Expert Advisors)
   string            expertcode(int code);    
                                 
// interpretor of the digital code into the prescribed text (interaction)   
   string            codeinterdescript(int code);

// interpretor of the digital code into the instrument symbol                                         
   string            symbolexpert(int code);

// cycle of recording tickets into the buffer
   void              prHistory_Deals(ulong &buf[],int HTD);    
  };   

Şimdi yöntemleri geliştireceğiz.

Sınıftaki ilk yöntem:

//+---------------------------------------------------------------------+
//| Function returns the assembled magic, assembled from the input data |
//+---------------------------------------------------------------------+
ulong Cmagic::SetMagic_request(int digital_name=0,int code_interaction=0)
  {
   if(digital_name>=1000)Print("Incorrectly specified digital name of the Expert Advisor (more than 1000)");
   if(code_interaction>=1000)Print("Incorrectly specified the code of recognizing yours-foreign (more than 1000)");
   mag.digital_name     =digital_name;
   mag.code_interaction =code_interaction;
   mag.expert_symbol    =symbolexpert();
   mag.magicnumber      =mag.digital_name*(int)pow(1000,2)+
                         mag.code_interaction*(int)pow(1000,1)+
                         mag.expert_symbol;
   return(mag.magicnumber);
  }

Bu yöntem iki değer alır: Expert Advisor'ın dijital adı ve etkileşim kodu.

ulong Cmagic::SetMagic_request(int digital_name=0,int code_interaction=0)

Ve doğruluğunu derhal doğrular:

   if(digital_name>=1000)Print("Incorrectly specified the digital name of the Expert Advisor(more than 1000)");
   if(code_interaction>=1000)Print("Incorrectly specifies the code of recognizing yours-foreign (more than 1000)");

Fakat kullanıcının eylemlerine karşı herhangi bir şekilde karşılık verme durumu yoktur; bir hata durumunda dahi uysal bir şekilde çalışmaya devam eder.

Ardından, kullanıcının belirttiği, ancak enstrüman sembolü belirtilmemiş ve özel yöntemden elde edilen giriş verilerinin yapısına atama gelir:

int Cmagic::symbolexpert()

Kodunu vermeyeceğim; zira söz konusu kod çok uzun ve ekli dosyada zaten verilmiş. Bu yöntemin temel olarak "piyasa görünümü" penceresindeki her sembole karşılık gelen bir sayı atayan bir tablo olduğunu söyleyebilirim: Örneğin, EURUSD için bu, 1'dir, vb.

"Piyasa görünümü" penceresinde hangi para birimlerinin bulunduğuna dair bir anket için bir kod yazarak bu verileri kesinlikle dinamik olarak elde edebilirsiniz fakat çözüm, sorunun karmaşıklığına karşılık gelmelidir ve pencereleri çağırmakla uğraşmak mantıklı değildir; bu nedenle şu yolu takip edeceğiz: - Bir para birimi listesi oluşturmak ve her birine bir indeks atamak.

Ve son olarak, yöntemin tamamına ilişkin en önemli satır şu şekildedir:

mag.magicnumber      =mag.digital_name*(int)pow(1000,2)+
                      mag.code_interaction*(int)pow(1000,1)+
                      mag.expert_symbol;

tüm Magic'in farklı parçalarından birleştirilir. Bu, Expert Advisor'ımızın talimatına tahsis edilecek olan Magic'tir.

Sınıftaki bir sonraki genel yöntem:

//+------------------------------------------------------------------+
//| Function obtains the assembled magic                             |
//| and divides it according to the logic of the assembly            |
//+------------------------------------------------------------------+
ulong Cmagic::SetMagic_result(ulong magicnumber)
  {
   mag.magicnumber      =magicnumber;
   mag.expert_symbol    =decodeMagic_result(1);
   mag.code_interaction =decodeMagic_result(2);
   mag.digital_name     =decodeMagic_result(3);
   return(mag.magicnumber);
  }

Aslında bu yöntem, tek bir özel yöntemin üç çağrısının sonuçlarını yapı aracılığıyla dağıtan bir kabuk işlevi görür. Bu tür bir belirtici altındaki bildirim, bir sınıf değişkenini çağırdığınızda, tüm işin bir genel işlev tarafından yapıldığı izlenimini yaratarak, açılır komut istemi mesajında gösterilmemeleri gerçeğinden dolayı iyidir.

Ama özel işlevlerimize dönelim:

//+------------------------------------------------------------------+
//| Function divides the magic into three parts of three charges     |
//| and returns the part, which the category points to               |
//+------------------------------------------------------------------+
int Cmagic::decodeMagic_result(int category)
  {
   string string_value=(string)mag.magicnumber;
   int rem=(int)MathMod(StringLen(string_value),3);
   if(rem!=0)
     {
      rem=3-rem;
      string srem="0";
      if(rem==2)srem="00";
      string_value=srem+string_value;
     }
   int start_pos=StringLen(string_value)-3*category;
   string value=StringSubstr(string_value,start_pos,3);
   return((int)StringToInteger(value));
  }

Görsel olarak, bu yöntem belirtilen alandan üç basamaklı bir sayının okunması olarak temsil edilebilir; örneğin elimizde Magic 123456789 varsa bunu | 123 | 456 | 789 | olarak gösterebiliriz, belirtilen alan 1 ise, alanlar sağdan sola doğru numaralandırıldığı için sonuç 789 şeklinde olacaktır.

Dolayısıyla, çağrılan yöntemdeki üç alanı da kullandıktan sonra elde edilen tüm verilerin yapısına dağıtıyoruz. Bu, Magic'i string: gibi küçük bir türe getirme prosedürüyle yapılır.

string string_value=(string)mag.magicnumber;

Tek tek hat bileşenlerinin ayrılmasını takiben.

Ardından, özünde switch anahtarları olan ve yalnızca çıkış değerlerinin türünde farklılık gösteren iki benzer işlevi takip edin:

//+------------------------------------------------------------------+
//| Function obtains the identifier of the return                    |
//| and returns the requested part of the assembled magic            |
//+------------------------------------------------------------------+
ulong Cmagic::GetMagic_result(Emagic enum_)
  {
   switch(enum_)
     {
      case ENUM_DIGITAL_NAME     : return(mag.digital_name);     break;
      case ENUM_CODE_INTERACTION : return(mag.code_interaction); break;
      case ENUM_EXPERT_SYMBOL    : return(mag.expert_symbol);    break;
      default: return(mag.magicnumber); break;
     }
  }
//+------------------------------------------------------------------------------+
//| Function obtains the identifier of the return and returns                    |
//| a textual interpretation of the requested type of the assembled magic        |
//+------------------------------------------------------------------------------+
string Cmagic::sGetMagic_result(Emagic enum_)
  {
   switch(enum_)
     {
      case ENUM_DIGITAL_NAME     : return(expertcode(mag.digital_name));            break;
      case ENUM_CODE_INTERACTION : return(codeinterdescript(mag.code_interaction)); break;
      case ENUM_EXPERT_SYMBOL    : return(symbolexpert(mag.expert_symbol));         break;
      default: return((string)mag.magicnumber); break;
     }
  }

İşlevler, Magic'in Emagic türünün parametresini belirten kısmını döndürür; ilki sonucu hesaplamalarda kullanılan ulong biçiminde, ikincisi ise görselleştirme için kullanılabilecek string türünde sonuçlar verir.

GetMagic_result () işlevinde her şey basit bir şekilde düzenlenir; bu işlev, yapının değerlerini anahtar, dalları boyunca dağıtırken sGetMagic_result () biraz daha karmaşıktır. Her durum dalı, yapının değerini görsel bir forma aktaran bir tablo işlevini çağırır. Böylece, mag.expert_symbol = 1 değeri ise ilk işlev 1 öğesini ve ikincisi EURUSD öğesini verecektir.

Bilgileri kodlamada / kodlarını çözmede tablo işlevlerinin avantajlarını zaten açıkladım; bu nedenle yalnızca, tablosuz bir yöntemin uygulanmasının karmaşıklığına ve tabloları yazmak için gereken süreye olan avantajlarına bağlı olarak her bir durumun ayrı ayrı ele alınması gerektiğini belirteceğim. Durum tablosu yazmak daha kolaysa meseleleri karmaşıklaştırmaya gerek yok. Ancak tablonun yazılması çok zaman alacaksa, açıkçası, prosedürel yöntemler tercih edilmelidir. Yerden tasarruf sağlamak için burada tabloları vermiyorum (tabloları ekteki dosyalarda bulabilirsiniz).

Bunun, temeli budur; sınıfımız geliştirildi, ancak önceki Expert Advisor'ın geliştirilmesinde kullandığımız kalan dört işlev daha var. 

Özellikle biraz değiştirilmeleri gerektiğini düşünerek onları yeni bir sınıfta tekrar bildirdim.

Şimdi ana yöntemi ele alalım:

bool  Cmagic::PositionVirtualMagic(Emagic enum_,
                                   string symbol,
                                   datetime CurrentTime)

Yalnızca Cmagic sınıfının bir yöntemi olarak bildirilmekle kalmaz, aynı zamanda farklı bir parametre kümesi de içerir.

Magic'in yerine, artık, pozisyonun hesaplandığı Magic alanına göre tanımlama alır. Ayrıca son seçenekte sembol mevcut olmasına rağmen yalnızca sembol ile lotun adımı hakkında bilgi edinmek için kullanılmıştır. Ve şimdi bu, filtrede belirtilir ve pozisyon sayımının filtrelenmesine diğerleriyle eşit olarak katılabilir.

Bu bize ne veriyor? Artık aynı Expert Advisor tarafından farklı bir enstrümanda açılmış olan işlemleri aynı anda filtreleyebiliyoruz. Böylelikle, farklı bir enstrüman üzerinde çalışan diğer benzer Expert Advisor'larla karıştırılmayacaklardır. Açık söylemek gerekirse, bu yeni hesaplama sistemini kullanmanın tüm farklı yollarını tarif etmek çok zor. Ve okuyucu, bu kadar karmaşık bir sisteme ne için ihtiyaç duyduğuna kişisel olarak karar verebilir. Yalnızca basit bir şekilde yazabileceğiniz durumları karmaşıklaştırmamanızı ve buna bariz bir ihtiyaç olduğunda bu tür karmaşıklıklar konusunda endişelenmemenizi şiddetle tavsiye ediyorum.

Sınıf tasarlandığına göre, o halde yeni bir Expert Advisor üzerinde test etmenin zamanı geldi:

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+
//--- input parameters
input ulong              digital_name_       =4;           // Digital name of Expert Advisor
input ulong              code_interaction_   =1;           // Code of interaction
input Emagic             _enum               =0;           // Model of magic number  
input int                SL                  =300;         // Stop Loss
input int                TP                  =1000;        // Take Profit
input int                MA_Period           =25;          // MA period
input double             lot                 =0.4;         // Volume of position
input int                MA_shift            =0;           // Shift of indicator
input ENUM_MA_METHOD     MA_smooth           =MODE_SMA;      // Smoothing type
input ENUM_APPLIED_PRICE price               =PRICE_OPEN;    // Price type 

//--- we will store the indicator's handle
int MA_handle,type_MA,rezult;
static ulong magic;
double v[2];
datetime  CurrentTime;// The variable stores the time of start of the Expert Advisor

MqlTradeResult  res;   // Pointer to the structure of responding by OrderSend
MqlTick         tick;  // Pointer to the structure of last market information
CProvision prov;
Cmagic mg;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   magic=mg.SetMagic_request(digital_name_,code_interaction_);
// Stamp of Expert Advisor (the magic number identifier) the magic variable is declared at the global scope
// used in int CProvision::SendOrder(ENUM_ORDER_TYPE type,double volume)
   CurrentTime=TimeCurrent();// The variable stores the time of start of the Expert Advisor
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication
   mg.SetMagic_result(magic);// put the information into the structure
   if(mg.PositionVirtualMagic(_enum,_Symbol,CurrentTime))// If three is an open position 
     {
      if((int)mg.cTYPE()!=type_MA)// Check if it is time to close
        {
         mg.SetMagic_result(magic);// put the information into the structure
         Print("#",mg.GetMagic_result(_enum),"Position by magic number has volume ",mg.cVOLUME(),
               " reverse position of type ",(int)mg.cTYPE()," by ",type_MA);
         //cpvm.cVOLUME() - volume of virtual position
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,mg.cVOLUME()+lot);// reverse position
         if(rezult!=-1)Print("№",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("№",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Position by magic number has volume  ",mg.cVOLUME()," open position of type",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);// Open position 
      if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  }

Daha önce de belirtildiği gibi, bu Expert Advisor son derece basittir ve yalnızca farklı özellikleri göstermek için oluşturulmuştur; bunu tek bir enstrüman üzerinde üç kez çalıştırın:

Şekil 6. Farklı grafiklerde farklı sihirli sayılarla üç Expert Advisor'ın kurulumu

Şekil 6. Farklı grafiklerde farklı sihirli sayılarla üç Expert Advisor'ın kurulumu

Şekil 7. Sonuç, farklı sihirli sayılarla üç Expert Advisor'ın çakışma olmadan alım satım işlemi yapmasıdır

Şekil 7. Sonuç, farklı sihirli sayılarla üç Expert Advisor'ın çakışma olmadan alım satım işlemi yapmasıdır

Expert Advisor'ların mesajlarının çıktılarından da görülebileceği üzere, üç katılımcı da başarılı bir şekilde başlatıldı ve herhangi bir çakışma göstermedi.


Sonuç

MQL5'in yaratıcıları, alım satım işlemlerine sihirli talimatlar atama fırsatı sağlayarak, Expert Advisor yazarlarının hayatını büyük ölçüde kolaylaştırdı. Ancak geliştiriciler size yalnızca enstrümanlar sağlayabilir - Elmasları gerçekten elde eden kişi olmanız gerekir.

Tekrar buluşuncaya kadar iyi şanslar.


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

Ekli dosyalar |
magic_exp0_en.mq5 (8.34 KB)
magic_exp1_en.mq5 (11.84 KB)
magic_exp2_en.mq5 (25.39 KB)
Google Chart API ile Grafik Oluşturmak için Kitaplık Google Chart API ile Grafik Oluşturmak için Kitaplık
Çeşitli diyagram türlerinin oluşturulması, piyasa durumuna ilişkin analizlerin ve bir alım satım sisteminin test edilmesinin önemli bir parçasıdır. Sıklıkla, güzel görünümlü bir diyagram oluşturmak için, veri çıktısını bir dosyada düzenlemek ve ardından MS Excel gibi uygulamalarda kullanmak gerekir. Bu, çok elverişli değildir ve bizi verileri dinamik olarak güncelleme özelliğinden mahrum eder. Google Charts API, sunucuya özel bir istek göndererek çevrimiçi modlarda grafikler oluşturmak için araçlar sağladı. Bu makalede, böyle bir istek oluşturma ve Google sunucusundan grafik alma sürecini otomatikleştirmeye çalışıyoruz.
Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler
Kullanıcı çağrıları ve teknik göstergeler, otomatik alım satım sistemlerinin program kodunda çok az yer kaplar. Bu, genellikle yalnızca birkaç kod satırıdır. Ancak bu, çoğu zaman, Expert Advisor'ı test etmek için harcanması gereken zamanın en büyük kısmını kullanan bu birkaç kod satırı olur. Bu nedenle, bir gösterge içindeki veri hesaplamalarıyla ilgili her şeyin, ilk bakışta göründüğünden çok daha kapsamlı bir şekilde düşünülmesi gerekir. Bu makalede tam olarak bu ele alınacaktır.
Adlandırılmış Kanalları kullanarak MetaTrader 5 terminalleri arasında iletişim kurmak için DLL içermeyen bir çözüm Adlandırılmış Kanalları kullanarak MetaTrader 5 terminalleri arasında iletişim kurmak için DLL içermeyen bir çözüm
Makalede, adlandırılmış kanallar kullanılarak MetaTrader 5 istemci terminalleri arasında İşlemler Arası İletişimin nasıl uygulanacağı açıklanmaktadır. Adlandırılmış kanalların kullanımı için CNamedPipes sınıfı geliştirilmiştir. Kullanımını test etmek ve bağlantı verimini ölçmek için tick göstergesi, sunucu ve istemci script dosyaları sunulur. Adlandırılmış kanalların kullanılması, gerçek zamanlı fiyat teklifleri için yeterlidir.
MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı
İlk Hareketli Ortalama göstergesinin oluşturulmasından bu yana bir dizi gösterge ortaya çıktı. Birçoğu benzer yumuşatma yöntemlerini kullanır fakat farklı hareketli ortalama algoritmalarının performansları incelenmemiştir. Bu makalede, MQL5'te Hareketli Ortalamaları kullanmanın olası yollarını ele alacak ve performanslarını karşılaştıracağız.