Sıfırdan bir ticaret Uzman Danışmanı geliştirme

Daniel Jose | 19 Mayıs, 2022

Giriş

Finansal piyasalardaki yeni kullanıcıların sayısı sürekli artmaktadır. Birçoğunun emir sisteminin nasıl çalıştığına dair doğru bilgiye sahip olmaması beklenebilir. Ancak, durumu daha iyi kontrol etmek ve yaptıkları her şeyi anlamak için gerçekten neler olduğunu bilmek isteyenler de vardır.

MetaTrader 5 elbette ticaret işlemleri üzerinde yüksek düzeyde kontrol sağlamaktadır. Ancak, yalnızca manuel olarak emir verme yeteneğinin kullanılması, daha az deneyimli kullanıcılar için oldukça zor ve riskli olabilir. Örneğin vadeli işlem sözleşmeleriyle ticaret yaparken emir göndermek için çok az zaman olduğunda, bu tür bir ticaret işlemi bir kabusa dönüşebilir, çünkü tüm alanların zamanında doğru bir şekilde doldurulması gerekir, bu süre zarfında iyi bir fırsat kaçırılabilir ve hatta acele ederken, bir şeyin yanlış doldurulması sonucu para dahi kaybedilebilir.

Ancak bunun yerine emir gönderme sürecini basitleştirecek bir Uzman Danışman (EA) kullanılsaydı ne olurdu? Emir büyüklüğü, ne kadar zararın göze alındığı ve ne kadar kârın istendiği (parasal olarak, oldukça net olmayan puan ve pip terimleri yerine) gibi bazı parametreler ayarlanabilir. Ardından, piyasaya nereden girileceğini göstermek için grafik üzerinde fare imlecini kullanarak alış mı, satış mı, ... olacağı belirtilebilir.


Planlama

Bir şey yaratmanın en zor kısmı, nasıl çalışması gerektiğini belirlemektir. Bunu yapmak için gerekli minimum kodu oluşturacağız - sonuçta, kod ne kadar karmaşık olursa, çalışma zamanı hataları olma olasılığı da o kadar yüksek olur. Bu yüzden, MetaTrader 5'in yeteneklerini maksimum düzeyde kullanarak kodu olabildiğince basit tutmaya çalıştım. Tüm bu işleyişteki en güvenilir kısım, sürekli test edilen platformun kendisidir.

Kod, OOP (nesne yönelimli programlama) kullanacak. Bu yaklaşım, kodun izole edilmesine olanak sağlar ve yeni özellikler eklemek ve iyileştirmeler yapmak istenmesi durumunda da bakımını ve gelecekteki gelişimini kolaylaştırır.

Bu makalede tartışılan EA, B3 (Brezilya borsası) ve özellikle vadeli işlemler (Mini Index ve Mini Dollar) üzerinde ticaret yapmak için tasarlanmış olsa da, minimum düzenlemeyle tüm piyasalara genişletilebilir. İşleri kolaylaştırmak ve işlem gerçekleştirilen enstrümanların listelenmesini ve kontrolünü tekrarlamamak için şu numaralandırmayı kullanacağız:

enum eTypeSymbolFast {WIN, WDO, OTHER};


Yeni bir enstrüman ile işlem gerçekleştirmek istiyorsanız, onu numaralandırmaya ekleyin. Bu aynı zamanda kodda bazı küçük değişiklikler de gerektirir, ancak numaralandırmayla bu süreç, hata olasılığını da azalttığı için çok daha kolay olur. Kodun ilginç bir kısmı da, AdjustPrice fonksiyonudur:

   double AdjustPrice(const double arg)
     {
      double v0, v1;
      if(m_Infos.TypeSymbol == OTHER)
         return arg;
      v0 = (m_Infos.TypeSymbol == WDO ? round(arg * 10.0) : round(arg));
      v1 = fmod(round(v0), 5.0);
      v0 -= ((v1 != 0) || (v1 != 5) ? v1 : 0);
      return (m_Infos.TypeSymbol == WDO ? v0 / 10.0 : v0);
     };

Bu fonksiyon, çizgilerin grafikte doğru noktalarda konumlanması için fiyatta kullanılacak değeri ayarlar. Neden grafiğe basitçe bir çizgi koyamıyoruz? Bunun nedeni, enstrümanların farklı fiyat adımlarına sahip olabilmesidir. Bu adım, WDO (Mini Dollar) için 0,5 puan, WIN (Mini Index) için 5 puan, hisse senetleri içinse 0,01 puandır. Başka bir deyişle, farklı enstrümanlar farklı tik değerlerine sahip olabilir. Bu fonksiyon, emirde fiyatı doğru tik değerine ayarlar, aksi takdirde yanlış doldurulmuş bir emir işlem sunucusu tarafından reddedebilir.

Bu fonksiyon olmadan, emirde kullanılacak doğru değerleri bilmek zor olurdu. Dolayısıyla, işlem sunucunun emrin yanlış doldurulduğunu bildirerek gerçekleşmesini reddetme ihtimali de yükselirdi. Şimdi Uzman Danışmanın kalbi olan fonksiyona geçelim: CreateOrderPendent. Fonksiyon aşağıdaki gibidir:

   ulong CreateOrderPendent(const bool IsBuy, const double Volume, const double Price, const double Take, const double Stop, const bool DayTrade = true)
     {
      double last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action        = TRADE_ACTION_PENDING;
      TradeRequest.symbol        = m_szSymbol;
      TradeRequest.volume        = Volume;
      TradeRequest.type          = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));
      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);
      TradeRequest.type_time     = (DayTrade ? ORDER_TIME_DAY : ORDER_TIME_GTC);
      TradeRequest.stoplimit     = 0;
      TradeRequest.expiration    = 0;
      TradeRequest.type_filling  = ORDER_FILLING_RETURN;
      TradeRequest.deviation     = 1000;
      TradeRequest.comment       = "Order Generated by Experts Advisor.";
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return 0;
        };
      return TradeResult.order;
     };

Bu fonksiyon son derece basit ve güvenilirdir. Burada işlem sunucusuna gönderilecek bir OCO (One Cancels the Other, biri diğerini iptal eder) emri oluşturacağız. Lütfen LIMIT veya STOP emirlerini kullandığımızı unutmayın. Bunun nedeni, bu tür emirlerin daha basit olması ve ani fiyat hareketlerinde bile gerçekleşmesini garanti etmesidir.

Kullanılacak emir türü enstrümanın mevcut fiyatına, işlemin gerçekleştirilmek istendiği fiyata ve alış veya satış girişi olup olmayacağına bağlıdır. Bu, şu satırda uygulanır:

TradeRequest.type = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));

Ayrıca, çapraz emir oluşturmak da mümkündür; bunun için, ticaret enstrümanının aşağıdaki satırda belirtilmesi gerekir:

TradeRequest.symbol = m_szSymbol;

Ancak bunu yaparken, "yanlış" grafiğe sahip olunacağından, çapraz emir sistemi aracılığıyla açık veya bekleyen emirleri işleyebilmek için bazı kodlar eklenmesi gerekecektir. Bunu bir örnekle inceleyelim. Tüm endeks (IND) grafiğinden Mini Index (WIN) için ticaret işlemi gerçekleştirebilirsiniz, ancak MetaTrader 5, IND grafiğinde açık veya bekleyen WIN emirlerini göstermez. Bu nedenle bu tür emirlerin görünür olması için bazı kodlar eklenmesi gerekir. Bu, emir değerlerinin okunup, grafikte çizgiler olarak sunulmasıyla yapılabilir. Ticaret işlemi gerçekleştirirken ve sembolün işlem geçmişini takip ederken bu çok kullanışlıdır. Çapraz emirle örneğin WIN$ grafiğinden (Mini Index'in geçmiş grafiği) WIN (Mini Index) için ticaret işlemi gerçekleştirebilirsiniz.

Dikkat edilmesi gereken bir sonraki şey aşağıdaki kod satırlardır:

      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);

Bu 3 satır, OCO emri için pozisyon açma fiyatını ve durma seviyelerini oluşturur. Sadece birkaç saniye sürebilen kısa vadeli işlemler gerçekleştiriyorsanız, volatilite net bir yön olmadan fiyatı bir noktadan diğerine götürebileceğinden, OCO emirlerini kullanmadan işleme girmeniz tavsiye edilmez. OCO emri kullandığınızda, işlem sunucusu pozisyonla kendisi ilgilenecektir. OCO emri aşağıdaki gibi görünür.

Düzenleme penceresinde aynı emir şu şekilde görünür:

Gerekli tüm alanları doldurduğunuzda, işlem sunucusu pozisyonu kendisi yönetecektir. Kârı Al veya Zararı Durdur seviyesine ulaşır ulaşmaz sistem pozisyonu kapatacaktır. Ancak Kârı Al veya Zararı Durdur seviyesi belirtmezseniz, pozisyon başka bir olay gerçekleşene kadar açık kalacaktır. Emir süresi Bugün olarak ayarlanmışsa, sistem işlem gününün sonunda emri kapatacaktır. Aksi takdirde, siz manuel olarak kapatana kadar emir açık kalacaktır.

Pozisyonları kapatmak için bazı Uzman Danışman sistemleri emirleri kullanır, yani, pozisyon açıldığında, pozisyonun kapatılması istenen seviyeye aynı hacimde bir zıt emir gönderilir. Ancak bu, bazı senaryolarda çalışmayabilir, çünkü enstrüman herhangi bir nedenle işlem seansı sırasında müzayedeye girerse, bekleyen emir iptal edilebilir ve yeniden yerleştirilmesi gerekir. Bu, Uzman Danışmanın çalışmasını karmaşık hale getirecektir, çünkü hangi emirlerin etkin olup olmadığının kontrol edilmesi gerekecek ve herhangi bir yanlışlık olması durumunda da, Uzman Danışman herhangi bir kriter olmaksızın emirleri birbiri ardına gönderebileceği için sorunlar ortaya açacaktır.

   void Initilize(int nContracts, int FinanceTake, int FinanceStop, color cp, color ct, color cs, bool b1)
     {
      string sz0 = StringSubstr(m_szSymbol = _Symbol, 0, 3);
      double v1 = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
      m_Infos.Id = ChartID();
      m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));
      m_Infos.nDigits = (int) SymbolInfoInteger(m_szSymbol, SYMBOL_DIGITS);
      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);
      m_Infos.IsDayTrade = b1;
      CreateHLine(m_Infos.szHLinePrice, m_Infos.cPrice = cp);
      CreateHLine(m_Infos.szHLineTake, m_Infos.cTake = ct);
      CreateHLine(m_Infos.szHLineStop, m_Infos.cStop = cs);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_VOLUME, m_Infos.cPrice);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_STOP_LEVEL, m_Infos.cStop);
     };

Yukarıdaki kod, kullanıcı tarafından belirtilen ayarlara göre Uzman Danışman verilerinin başlatılmasından ve OCO emrinin oluşturulmasından sorumludur. Bu kodda sadece şu değişikliği yapmamız gerekiyor:

m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));

Yeni eklemek istediğiniz semboller varsa, mevcut olanlara ek olarak işlem sembolü türünü buraya ekliyoruz.

      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);

Yukarıdaki üç satır, doğru emir oluşturma için gerekli ayarlamaları yapar. nContracts kaldıraç katsayısıdır, değeri 1, 2, 3 vb. şeklinde kulanın. Başka bir deyişle, sembolle işlem gerçekleştirmek için olan minimum hacmi bilmenize gerek yoktur. İhtiyacınız olan tek şey, bu minimum hacim için kaldıraç katsayısını belirtmektir. Örneğin, gerekli minimum hacim 5 sözleşmeyse ve kaldıraç katsayısını 3 olarak belirtirseniz, sistem 15 sözleşmelik emir açacaktır. Diğer iki satır, kullanıcı tarafından belirtilen parametrelere göre Kârı Al ve Zararı Durdur seviyelerini ayarlar. Seviyeler, emir hacmi ile ayarlanır: emir hacmi artarsa, seviyeler azalır ve bunun tersi de geçerlidir. Bu kodla pozisyon oluştururken hesaplama yapmak zorunda kalmayacaksınız - Uzman Danışman her şeyi kendisi hesaplayacak: siz Uzman Danışmana hangi finansal enstrümanın hangi kaldıraç katsayısıyla işlem gerçekleştireceğini, ne kadar kazanç sağlamak istediğinizi ve ne kadar kaybetmeye hazır olduğunuzu bildirirsiniz, Uzman Danışman sizin için uygun emri verecektir.

   inline void MoveTo(int X, int Y, uint Key)
     {
      int w = 0;
      datetime dt;
      bool bEClick, bKeyBuy, bKeySell;
      double take = 0, stop = 0, price;
      bEClick  = (Key & 0x01) == 0x01;    //Left mouse button click
      bKeyBuy  = (Key & 0x04) == 0x04;    //Pressed SHIFT
      bKeySell = (Key & 0x08) == 0x08;    //Pressed CTRL
      ChartXYToTimePrice(m_Infos.Id, X, Y, w, dt, price);
      ObjectMove(m_Infos.Id, m_Infos.szHLinePrice, 0, 0, price = (bKeyBuy != bKeySell ? AdjustPrice(price) : 0));
      ObjectMove(m_Infos.Id, m_Infos.szHLineTake, 0, 0, take = price + (m_Infos.TakeProfit * (bKeyBuy ? 1 : -1)));
      ObjectMove(m_Infos.Id, m_Infos.szHLineStop, 0, 0, stop = price + (m_Infos.StopLoss * (bKeyBuy ? -1 : 1)));
      if((bEClick) && (bKeyBuy != bKeySell))
         CreateOrderPendent(bKeyBuy, m_Infos.Volume, price, take, stop, m_Infos.IsDayTrade);
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLinePrice, OBJPROP_COLOR, (bKeyBuy != bKeySell ? m_Infos.cPrice : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineTake, OBJPROP_COLOR, (take > 0 ? m_Infos.cTake : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineStop, OBJPROP_COLOR, (stop > 0 ? m_Infos.cStop : clrNONE));
     };

Yukarıdaki kod, emrin nasıl oluşturulacağını ifade etmektedir. Emrin yerleştirileceği seviye fare hareketine göre gösterilir. Ancak, alış mı (SHIFT'e basılı tutun) yoksa satış mı (CTRL'ye basılı tutun) gerçekleştirmek istediğinizi Uzman Danışmana bildirmeniz gerekiyor. Bunu yaparken sol fare düğmesine tıkladığınızda, fare imlecinin bulunduğu seviyeye bir bekleyen emir oluşturulacaktır.

Ayrıca, örneğin breakeven seviyesi gibi ek verileri görüntülemek için bu koda ek nesneler de ekleyebilirsiniz.

Artık çalışan ve OCO emirleri oluşturabilen bir Uzman Danışmana sahibiz. Ancak tam anlamıyla her şey mükemmel değil...


OCO emirleriyle ilgili sorun

OCO emirlerinin MetaTrader 5 sistemiyle veya işlem sunucusuyla ilgili olmayan bir sorunu vardır. Bu, piyasada sürekli olarak mevcut olan volatiliteyle ilgilidir. Teorik olarak fiyat, sıçrama olmadan doğrusal olarak hareket etmelidir. Ancak bazen yüksek volatilite mum içerisinde gapler oluşturur. Bu gapler Zararı Durdur veya Kârı Al fiyatlarının olduğu seviyelerde oluşursa, bu eylemler tetiklenmez ve dolayısıyla pozisyon kapanmaz. Bu seviyeler kullanıcı tarafından hareket ettirildiğinde de, fiyat Zararı Durdur ve Kârı Al seviyelerinin oluşturduğu koridorun ötesinde kaldığı olabilir. Bu durumda da pozisyon kapanmayacaktır. Bunlar, ne zaman olacağı tahmin edilmesi imkansız olan çok tehlikeli durumlardır. Programcılar olarak bu sorunun olası zararlarını en aza indirecek mekanizmalar oluşturmalıyız.

Fiyatı yenilemek ve koridor dahilinde tutmaya çalışmak için aşağıdaki iki kod parçasını kullanacağız. İlk kod parçası şu şekildedir:

   void UpdatePosition(void)
     {
      for(int i0 = PositionsTotal() - 1; i0 >= 0; i0--)
         if(PositionGetSymbol(i0) == m_szSymbol)
           {
            m_Take      = PositionGetDouble(POSITION_TP);
            m_Stop      = PositionGetDouble(POSITION_SL);
            m_IsBuy     = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
            m_Volume    = PositionGetDouble(POSITION_VOLUME);
            m_Ticket    = PositionGetInteger(POSITION_TICKET);
           }
     };

Bu kod parçası OnTrade'de çağrılır - her pozisyon değişiminde MetaTrader 5 tarafından çağrılan fonksiyon. Kullanılacak bir sonraki kod parçası OnTick'de çağrılır. Fiyatın koridor dahilinde olup olmadığını kontrol eder ve dahilinde olmasını sağlar. Bu kod parçası da şu şekildedir:

   inline bool CheckPosition(const double price = 0, const int factor = 0)
     {
      double last;
      if(m_Ticket == 0)
         return false;
      last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      if(m_IsBuy)
        {
         if((last > m_Take) || (last < m_Stop))
            return ClosePosition();
         if((price > 0) && (price >= last))
            return ClosePosition(factor);
        }
      else
        {
         if((last < m_Take) || (last > m_Stop))
            return ClosePosition();
         if((price > 0) && (price <= last))
            return ClosePosition(factor);
        }
      return false;
     };

Burası kritiktir. Bu kod parçası, her tik değişiminde çalıştırılacaktır, bu nedenle, hesaplamaların verimli bir şekilde gerçekleştirilebilmesi için mümkün olduğunca basit olmalıdır. Ayrıca, fiyatı koridor dahilinde tutarken bir ek kontrol daha gerçekleştirdiğimizi unutmayın. Dilerseniz bu kontrolü kaldırabilirsiniz. Bu ek kontrolü bir sonraki bölümde daha ayrıntılı olarak ele alacağım. Bu kod parçasında aşağıdaki fonksiyon çağrısı gerçekleşir:

   bool ClosePosition(const int arg = 0)
     {
      double v1 = arg * m_VolMinimal;
      if(!PositionSelectByTicket(m_Ticket))
         return false;
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action     = TRADE_ACTION_DEAL;
      TradeRequest.type       = (m_IsBuy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY);
      TradeRequest.price      = SymbolInfoDouble(m_szSymbol, (m_IsBuy ? SYMBOL_BID : SYMBOL_ASK));
      TradeRequest.position   = m_Ticket;
      TradeRequest.symbol     = m_szSymbol;
      TradeRequest.volume     = ((v1 == 0) || (v1 > m_Volume) ? m_Volume : v1);
      TradeRequest.deviation  = 1000;
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return false;
        }
      else
         m_Ticket = 0;
      return true;
     };

Bu fonksiyon pozisyondan belirtilen hacmi kapatır, dolayısıyla bir koruma görevi görür. Ancak fonksiyon MetaTrader 5 müşteri terminalinde çalıştığı için sunucuya bağlı olmanız gerektiğini unutmayın. Sunucuya bağlantı başarısız olursa, bu fonksiyon tamamen işe yaramaz hale gelecektir.

Bu son iki koda baktığımızda belirli hacmi belirli bir seviyede kapatabileceğimizi görebiliriz. Bunu yaparak ya kısmi kapatma yapıyoruz ya da riskimizi azaltıyoruz. Bu özelliği nasıl kullanacağımıza bakalım.


Kısmi emirlerle çalışma


Kısmi emirler, birçok yatırımcının sevdiği ve kullandığı bir emir türüdür. Uzman Danışman, kısmi kapatmayla çalışmaya izin vermesine rağmen, burada bu kodun nasıl uygulanacağını göstermeyeceğim. Kısmi emirler özel bir durumdur. Ancak, kısmi kapatmayla çalışmak istiyorsanız, CheckPosition'ı çağırın ve emrin gerçekleşeceği fiyatı ve hacmi belirtin, Uzman Danışman gerisini halledecektir.

Şu nedenden dolayı kısmi emirlerin özel bir durum olduğunu söylüyorum çünkü çok bireyseldir ve bu nedenle herkesi memnun edecek genel bir çözüm yaratmak zordur. Dinamik dizi kullanımı, swing ticareti konusunda uygun olmaz - günlük ticaret için, pozisyondayken, Uzman Danışmanı kapatmadığınız sürece ise çalışır. Herhangi bir nedenle Uzman Danışmanı kapatmanız gerekirse, dizi çözümü çalışmayacaktır. Bunun yerine, bir tür veri saklama ortamı kullanılmalıdır, burada verilerin biçimlendirilme şekli, ne yapmak istediğinize bağlı olacaktır.

Emin olacağımız bir şey var ki mümkün olduğunca pozisyon açma emirleri kullanılarak kısmi kapatmalardan kaçınılmalıdır, çünkü bundan sorun yaşama riski çok yüksektir. Şu şekilde açıklayayım: diyelim ki 3x kaldıraçlı bir alış pozisyonunuz var ve 2x'inin kârını almak istiyorsunuz, 1x'inin kalmasını istiyorsunuz. Bu, 2x kaldıraç satarak yapılabilir. Ancak bunun için Uzman Danışman satış piyasa emri gönderirse, volatilite, satış emri fiilen yerine getirilmeden önce fiyatın Kârı Al seviyesine çarpmasına neden olabilir. Bu durumda Uzman Danışman, istemediğimiz yönde yeni bir satış pozisyonu açmış olacaktır. Alternatif olarak, pozisyonu 2x kaldıraç azaltmak için Sell Limit veya Sell Stop emri verilebilir. Bu yeterli bir çözüm gibi görünebilir. Ancak, fiyat kısmi kapatma seviyesine ulaşmadan önce başka bir emir gönderilirse - çok tatsız bir sürprizle karşılaşabilirsiniz: açık pozisyon kapanacak ve bir süre sonra pozisyon tekrar açılacak ve zarar artacaktır. Volatilite yüksekse durum yukarıda bahsettiğimiz gibi olacaktır.

Dolayısıyla, bir programcı olarak benim görüşüme göre, kısmi emirler vermek için en iyi seçenek, piyasa emirlerinin gönderilmesini taklit etmektir. Ancak hacmin zaten açık olan hacmi aşmamasına çok dikkat etmelisiniz. Bu Uzman Danışmanda tam olarak bu şekilde yaptım. İsteğinize göre diğer kısmi kapatma yöntemlerini de uygulayabilirsiniz.


Sonuç

Bit ticaret Uzman Danışmanı oluşturmak, ilk bakışta göründüğü kadar karmaşık değildir. Programlama yaparken sıklıkla karşılaştığımız diğer bazı sorunlara kıyasla oldukça basittir. Zorluk, paranızı riske atacak kadar istikrarlı ve güvenilir bir şey inşa etmekte yatar. Bu makalede MetaTrader 5 ile çalışmaya yeni başlayan ve Uzman Danışman yazacak kadar bilgi birikimine sahip olmayanlar için hayatı kolaylaştıracak bir çözüm önerdim. Bu Uzman Danışman, emirleri kendi başına açmadığı, yalnızca daha güvenilir bir şekilde emirlerin açılmasına yardımcı olduğu için iyi bir başlangıçtır. Emir yerleştirildikten sonra, Uzman Danışmanın yapacak başka bir şeyi kalmıyor, sonrasında yukarıda bahsedilen kod parçaları dışında Uzman Danışman değil MetaTrader 5 çalışmaya devam ediyor.

Bu makalede sunulan Uzman Danışman, parametre kümeleriyle çalışmak için birçok yönden geliştirilebilir, ancak bu, onu MetaTrader 5'ten daha bağımsız hale getirecek daha fazla kod gerektirecektir.

Bu Uzman Danışmanın büyük başarısı, kodunda olmayan eylemleri gerçekleştirmek için MetaTrader 5'in kendisini kullanması ve böylece son derece kararlı ve güvenilir olmasıdır.