Hatalar, hatalar, sorular - sayfa 105

 
Interesting :

Test cihazının kendi ayrı cihaz listesi vardır ve oluşturulması gerekir (Bunu Uzman Danışman başlatılırken yapılması istenir).

Çok teşekkürler! Olmuş. çok özledim...
 
Renat :

Kod yaklaşıktı (iki parçanın kopyala-yapıştır), ancak yorumlarınız doğru.

İşte düzeltilmiş versiyon:

Aslında nasıl çalıştığını netleştirmek için birkaç Print() çağrısı ekledim:

 double CalculateMaxVolume( string symbol)
  {
   double price= 0.0 ;
   double margin= 0.0 ;
//--- select lot size
   if (! SymbolInfoDouble (symbol, SYMBOL_ASK ,price))                 return ( 0.0 );
   if (! OrderCalcMargin ( ORDER_TYPE_BUY ,symbol, 1.0 ,price,margin)) return ( 0.0 );
   if (margin<= 0.0 )                                             return ( 0.0 );

   double lot_pure= AccountInfoDouble ( ACCOUNT_FREEMARGIN )/margin;
   double lot= NormalizeDouble (lot_pure, 2 );
   Print ( "lot_pure = " , lot_pure, ", lot = " , lot);
//--- normalize and check limits
   double stepvol= SymbolInfoDouble (symbol, SYMBOL_VOLUME_STEP );
   if (stepvol> 0.0 )
     {
       double newlot=stepvol* NormalizeDouble (lot/stepvol, 0 );
       if (newlot>lot) { Print ( "Чёрт побери: lot = " , lot, ", newlot = " , newlot);
                       lot= NormalizeDouble (newlot-stepvol, 2 );
                     }
       else            lot=newlot;
     }

   double minvol= SymbolInfoDouble (symbol, SYMBOL_VOLUME_MIN );
   if (lot<minvol) lot= 0.0 ;   // 

   double maxvol= SymbolInfoDouble (symbol, SYMBOL_VOLUME_MAX );
   if (lot>maxvol) lot=maxvol;
//--- return trading volume
   return (lot);
  }

void OnStart ()
{
   Print ( "CalculateMaxVolume(Symbol()) = " , CalculateMaxVolume( Symbol ()));
}

/* Вывод в лог (хронология - сверху вниз)
CO      0       1 (EURUSD,M15)  01:40:33        lot_pure = 7.799703611262773, lot = 7.8
JG      0       1 (EURUSD,M15)  01:40:33        Чёрт побери: lot = 7.8, newlot = 7.800000000000001
MQ      0       1 (EURUSD,M15)  01:40:33        CalculateMaxVolume(Symbol()) = 7.7
*/

Şimdi düzgün çalışıyor. Ancak bir uyarı ile - şu anda gerçekten karşılaşılan koşullar altında. İleride genişletilirlerse, bu kod da belirli koşullar altında bazı durumlarda hata yapmaya başlayacaktır. Aşağıda anlatacağım.

Aslında biraz araştırma yapmam gerekti, sonuç olarak çok ilginç sonuçlar aldım. Ama önce ilk şeyler.

Gözünüze çarpan ilk şey: Neden NormalizeDouble() ile bu kadar çok dans var? Sonuçta, NormalizeDoubel() ne yapar? Izgaraya ücretsiz bir değer yakalar. Örneğin, bu kod parçasında:

 double lot= NormalizeDouble (lot_pure, 2 );

NormalizeDouble() bir parametre olarak lot_pure (serbest bir değer, yani, herhangi bir yuvarlama ve diğer bağlamalar olmadan 1 lot için serbest marjdan ve gerekli marjdan hesaplanan değer) alır ve bir başlangıç ile en yakın ızgara değerine bağlı bir değer döndürür 0'da ve bir adım 0.01.
Burada şunu not etmek önemlidir: daha büyük olanı da dahil olmak üzere en yakın ızgara düğümüne!

Bu bağlama neden kodun bu noktasında gerçekleştiriliyor? Ve neden tam olarak 0.01 ızgaraya göre ve örneğin 0.001'e değil?

Bu arada, logda CO sembolleriyle işaretlenen çıktıya göre (günlüğün verilen parçasının ilk satırı), bağlamanın sadece değerde bir artışa yol açtığı açıktır.

Ayrıca, parametrelerden biri olarak lot sayısını alan tüm ticaret fonksiyonlarının, bu değerin ızgaraya bağlanmasını gerektirdiği bilinmektedir: minvol + N * stepvol, burada N, 0'dan tamsayı kısmının değerine kadar bir tamsayıdır. ifadenin (maxvol - minvol ) / stepvol. Buna göre bu parçada elde edilen bedelsiz lot değeri:

 double lot_pure= AccountInfoDouble ( ACCOUNT_FREEMARGIN )/margin;

belirtilen ızgaranın en yakın düğümüne bağlanmalıdır: minvol + N * stepvol. Bu, stepvol ile bölmeden önce (aynı N tamsayısını elde etmek için) lot değerinden minvol'u çıkarmanız ve N ile çarptıktan sonra minvol eklemeniz gerektiği anlamına gelir. Hemen stepvol'a bölersiniz, dolaylı olarak stepvol'un minvol'un bir böleni olduğunu varsayarsınız, yani, ona tamsayı sayıda sığar, çünkü yalnızca bu koşul karşılanırsa, bu şekilde “basitleştirebilir” ve yan etkiler elde edemezsiniz:

 double newlot=stepvol* NormalizeDouble (lot/stepvol, 0 );

Ve yine NormalizeDouble()'ı kullanırsınız, bu sefer 0'da başlayan ve 1'lik bir adımla, yani tamsayılarla bir ızgaraya yapışmak için. Izgara yakalama seçenekleri doğrudur, ancak yakalama aracı biraz talihsizdir: daha yakınsa daha büyük düğüm de dahil olmak üzere en yakın ızgara düğümüne yapışır. Ve bizim durumumuzda bu, düzeltici kodun müteakip zorunlu geliştirilmesine yol açacaktır. NormalizeDouble() işlevini çağırmak yerine neden burada harika "tamsayı ızgarası" bağlama aracını kullanmıyorsunuz, bu bir tamsayı tipine bir döküm kullanarak, bu da döküm değerini artırmaz , ancak gerekirse onu yalnızca en yakın küçük tamsayıya düşürür , yani, neye ihtiyacın var?

Ancak bu yerde, kanıtı verilen kütüğün ikinci satırında bulunan ve JG sembolleriyle işaretlenmiş en ilginç başka bir eser ortaya çıkıyor. Sonuç olarak "0.1 * NormalizeDouble(7.8 / 0.1)" ifadesinin 7.800000000000001 verdiği ve bu da düzeltici kodun işlenmesini zorladığı ortaya çıktı! Neden işini bu kadar kötü yapan ve düzeltici bir kodla desteklenmesi gereken bir koda ihtiyacımız var?

İzin verilen lot değerlerinin ızgarasına bağlanma kodunun daha iyi bir kodla değiştirilmesi gerektiği açıktır.

Tabii ki, böyle bir kodu da bırakabilirsiniz - sonuçta, eğer varsa, kodun düzeltici kısmı çalışacaktır. Böylece günlüğün üçüncü satırı bunu kanıtlar: sonuç sonunda doğru döndürülür. Bununla birlikte, böyle bir kod, diğer şeylerin yanı sıra, yaratıcılarının profesyonellik seviyesinin ve kodun kalitesinin bir göstergesidir. MT5 platformunun kodunun kalitesi dahil. Bunun kanıtı da tarafımdan verilecektir çünkü araştırma sonucunda iki bug ile karşılaştım.

Bu arada, hesaplanan lot_pure değerinin ilk bağlama koduna ve düzeltme koduna bir kez daha bakalım:

 double lot= NormalizeDouble (lot_pure, 2 );
...
lot= NormalizeDouble (newlot-stepvol, 2 );
Her iki durumda da, ızgaraya yakalama 0,01'lik bir adımla gerçekleştirilir. Neden bu özel ağ? Sonuçta, adımın stepvol olduğu minvol + N * stepvol ızgarasına bağlanma gereklidir. Gelecekte hem minimum parti değeri hem de parti adımı olan 0.001'i karşılamak mümkün olacaksa ne olacak?

Ve çok basit - 0,01'lik bir adımla ızgaraya geçme sürecinde, lotun serbest değerinin 0,001'den fazla değiştiği durumlarda kod yanlış sonuçlar vermeye başlayacaktır. Başta bahsettiğim uyarı bu.

0,001'i aşan bir değerle "yuvarlama" durumunda, pozisyon açmak için yeterli serbest marjın olmayacağı lot değerleri, aynı tutarda "aşağı yuvarlama" durumunda ise, hafife alınan değerler veya serbest değer 0,001 - 0,004999 arasındaysa 0 bile...

Yani, kod potansiyel bir hata içeriyor - gelecek için. Bu, geliştiricilerin profesyonelliği ve kodlarının kalitesi ile ilgilidir.

Şimdi, bulunanları dikkate alarak, işlevin kendi versiyonunu sunacağım:

 double CalculateMaxVolume_New( string symbol)
{
   double stepvol = SymbolInfoDouble (symbol, SYMBOL_VOLUME_STEP );
   double minvol  = SymbolInfoDouble (symbol, SYMBOL_VOLUME_MIN );
   double maxvol  = SymbolInfoDouble (symbol, SYMBOL_VOLUME_MAX );

   // Не доверяем значениям, которые вернули функции
   if (stepvol > 0 && minvol > 0 && maxvol > minvol)
  {
     double tmp = 0 ;

     // Вычисляем цену Ask, Margin на 1 лот, лотов на FreeMargin
     if ( SymbolInfoDouble (symbol, SYMBOL_ASK , tmp)            && tmp > 0        &&
       OrderCalcMargin ( ORDER_TYPE_BUY , symbol, 1 , tmp, tmp) && tmp > 0        &&
       (tmp = AccountInfoDouble ( ACCOUNT_FREEMARGIN ) / tmp)         >= minvol &&
       tmp < ULONG_MAX * stepvol)
    {
       Print ( "pure_lot = " , tmp); // Эту строку нужно удалить из рабочего кода

       if (tmp > maxvol) // Здесь в tmp содержится недискретизированное число лотов
         return maxvol;

       // Привязываемся к сетке дискретизации
       return minvol + stepvol * ( ulong )((tmp - minvol) / stepvol);
    }
  }

   return 0 ;
}

void OnStart ()
{
   Print ( "CalculateMaxVolume_New(Symbol()) = " , CalculateMaxVolume_New( Symbol ()));
}

/* Вывод в лог (хронология - сверху вниз)
LQ      0       1 (EURUSD,M15)  01:39:07        pure_lot = 7.799095304944626
KD      0       1 (EURUSD,M15)  01:39:07        CalculateMaxVolume_New(Symbol()) = 7.7
*/

Partilerin değeriyle ilgili olarak (tmp'mde saklanan), hesaplanan, ancak henüz izin verilen değerler ızgarasına bağlanmayan birkaç durum vardır. Izgaraya eklenen değere ayrıklaştırılmış denir.

1. tmp < minvol. Bu durumda, eşitsizlik tmp örneklemesinden sonra bile kalacaktır, çünkü örnekleme işlemi yalnızca hesaplanan değerde bir düşüş anlamına gelir (aksi takdirde, yeterli serbest marj olmayacaktır, çünkü hesaplanan değer belirli bir serbest miktar için mümkün olan maksimum değerdir. marj).

Bu nedenle, bu durum ayrıklaştırmadan önce erken bir aşamada kesilebilir.

2. tmp > maxvol olduğu durum. Bu durumda limit, serbest marj değil, ticaret fonksiyonları tarafından kabul edilen lot sayısının izin verilen maksimum değeridir. Bu durumda, maxvol değerini döndürmeniz yeterlidir.

maxvol değerini basitçe döndürmek için tmp örneklemesi gerekmez, bu nedenle bu durum da örnekleme koduna kısaltılır.

3. minvol <= tmp <= maksvol. Bu durumda ayrıklaştırma yapmak gerekir ve sonuç olarak ayrıklaştırılmış değer bu durum için eşitsizlik içinde kalacaktır, yani ayrıklaştırmadan sonra hiçbir şeyin düzeltilmesine gerek yoktur.

Ayrıklaştırma kodu basit ve verimlidir:

 return minvol + stepvol * ( ulong )((tmp - minvol) / stepvol);

Burada "(tmp - minvol) / stepvol" ifadesi, aynı N sayısını (çapa ızgara parametresi) hesaplar, ancak kesirli bir kısımla. Bu noktada minvol <= tmp eşitsizliği sağlandığından (durum 3), böylece hesaplanan değerin negatif olmaması garanti edilir. Daha sonra, hesaplanan değer açıkça ulong türünde bir değere dönüştürülür. Tam olarak ulong'a, çünkü verilen değerin negatif olmadığına dair bir garanti var.

Bir tamsayı tipine döküm sürecinde, gerçek tipin kesirli kısmı atılır. En yakına yuvarlama değil, serbest marjın izin verdiği lotların maksimum değerinin artmayacağını garanti eden kesirli kısmın silinmesidir. Yani, tam olarak ihtiyacımız olan şey.

N tamsayı değeri elde edildiğinden, standart şekilde, serbest marj gereksinimlerini karşılayan parti sayısının maksimum ayrık değeri elde edilir (yani, izin verilen değerlerin örnekleme ızgarasında sıradaki bir sonraki değer). lotlar artık serbest marj gereksinimlerini karşılamayacaktır ve sonuçta elde edilen N yine : "minvol + stepvol * N" olacaktır.

Oldukça önemli bir noktayı vurgulamak istiyorum. Mesele şu ki, double türündeki sayıların yaklaşık 1.8e308'e kadar maksimum değerleri ve ulong türündeki sayıların - yalnızca yaklaşık 1.8e19'da (bu yalnızca kolaylık sağlamak için bir gösterimdir, sabit 1.8e19'un kendisi ulong türünde değildir ) ).

"(tmp - minvol) / stepvol" ifadesinin değeri 1.8e19'u aşarsa ne olur? Ardından, ulong tipine döküm yaparken "kesme" meydana gelir - değer, ifadenin değerinin ULONG_MAX ile tamsayı bölümünden kalan olacaktır.

Rakamlar çok büyük olmasaydı, MQL5 açısından "X % ULONG_MAX" değerine benzerdi, burada X, "(tmp - minvol) / stepvol" değerine eşit bir tam sayıdır.

Durum tipik değil, ancak neden kodda hatalar bırakıyorsunuz? Ayrıca, MQL5 kitaplığının işlevlerine güvenilemez, herhangi bir saçmalık döndürülebilir (bunun kanıtını sağlayacağım).

"tmp / stepvol" ifadesinin değerinin 1.8e19'a uymadığı durumlar için, özel olarak bir kontrol yapılmıştır (if koşulundaki son satır):

tmp < ULONG_MAX * stepvol

Tabii ki "tmp / stepvol < (double)ULONG_MAX" olarak da yazılabilirdi ama ilk olarak, açık bir ihtiyaç olmadığında bölme işleminden kaçınmaya çalışıyorum ve ikinci olarak, açık bir tür dönüşümü yapmak zorunda kalacağım. , ULONG_MAX sabiti ulong türünde olduğundan, işlenenler karşılaştırmalar sırasında dolaylı olarak en yüksek türe dönüştürülmez (en azından C/C++'da durum budur) ve üçüncü olarak - harika bir hatayla karşılaşmazdım dilin kendisi ve kütüphane işlevlerinde değil - hata DNA'da değil, kelimenin tam anlamıyla MQL5 molekülleri ve atomlarıdır.

Karşılaştırma işleminin sol işleneni tmp'dir ve double türündedir ve sağ işlenen "ULONG_MAX * stepvol" ifadesidir ve ayrıca double türündedir.

Bu ifadenin biri ulong, diğeri double türünde olmak üzere iki işleneni vardır. Örtülü tip döküm kurallarına göre, önce minör tipin işleneni majör tipin işleneninin tipine dönüştürülür, işlem gerçekleştirilir ve sonuç majör tipin işleneninin tipi olur. Double türü, ulong türünden "eski"dir, bu nedenle ulong türünün ULONG_MAX değeri örtük olarak bir double türüne dönüştürülür, çarpma gerçekleştirilir ve sonuç double türündedir.

Bununla birlikte, burada, bu arada, her zaman görünmeyen, ancak burada da dahil olmak üzere yalnızca belirli durumlarda ortaya çıkan bir hata var ve hata, "ULONG_MAX * stepvol" ifadesinin sonucunun basitçe değer olduğu gerçeğinde yatmaktadır. stepvol.

Bu nedenle, sunduğum işlev çalışmıyor ve MetaQuotes geliştiricileri bu hatayı düzeltene kadar çalışmayacak.

Bu işlevi hemen şimdi kullanmaya başlamak için, hatanın özelliğinden yararlanmanız gerekir: türe açık bir atama yaparsanız kaybolur:

tmp < ( double ) ULONG_MAX * stepvol

Tanımlanan kontrole geri dönersek: "tmp / stepvol" ifadesinin değerinin ULONG_MAX'ı geçmediğini garanti eder. Ancak ayrıklaştırma kodu "(tmp - minvol) / stepvol" ifadesini kullanır.

Bu ifadenin değeri de ULONG_MAX değerini geçmeyecektir, çünkü önceki kontroller minvol > 0 ve tmp >= minvol, yani tmp - minvol < tmp olmasını sağlar.

Bu nedenle ULOMG_MAX'in aşılmayacağı garantisi "(tmp - minvol) / stepvol" ifadesi için de geçerlidir.

Genel olarak, bir profesyonel ile profesyonel olmayan arasındaki temel farklardan biri, bir profesyonelin en azından bir şeyi garanti edebilmesidir, ancak profesyonel olmayan bir ...

Bulunan her iki hata da başka bir mesajda analiz edildi ve aynı zamanda MetaQuotes'un neleri yapıp neleri yapamayacağını belirtti.

 

Для чего в этом месте кода выполняется эта привязка? И почему именно к сетке 0.01, а не к, скажем, 0.001?

Sistemde minimum lot = 0.01


Notlar:

  1. Başlangıç koşulunuz minvol + N * stepvol'un doğru olması garanti edilmez, ayarlarda çoklu olmayan bir minlot değeri belirleyebilirsiniz ve tüm hesaplama mantığınız ihlal edilecektir.
  2. Boşuna ulong'a geçtiniz - kendiniz için zorluklar yarattınız ve sonra bunun hakkında bir sayfa düşünce yazdınız.
  3. Akıllıca bir ikame ve kodunuzda tmp kullanımı birçok kişinin aklını başından alacak, benim versiyonumda işlemlerin anlamı açısından her şey çok daha net.
 

Sadece kendim için konuşuyorum (ama eğer biri onun yansımasını görürse, unutmayın ki tek kişi siz değilsiniz).

Son aylarda, hata yarışı, her şeyden önce çalışmayan bir programı MetaTrader hatası olarak görme alışkanlığını geliştirdi.

Bu neden, evet, sadece işlenmiş bir şablon, eğer bir şey işe yaramazsa, o zaman bu bir hatadır ve hadi arayalım.

Örnek: bir hata buldum , servis masasına bir istek gönderdim, hatanın düzeltildiğini geri yazdım, bir doğrulama kodu yazıyorum, hiçbir şey yok.

Tekrar itiraz ediyorum ve şimdiden bir cevap beklentisiyle eğriliğimi buluyorum.

Sonuç olarak, insanların dikkatini birdenbire dağıtan bir utanç.

Ama mesajların akışını analiz ettiğimde, insan kitlesinin, hatta akıllı insanların bile, hala kalabalığın psikolojisine tabi olduğunu anlıyorum.

hatalar olduğu için, bunun bir bug olduğunu yazacağım ve bug olsa da olmasa da Renat kodumu toparlasın ve nerede hata yaptığımı belirtsin.

Hoşgörünün şunu söylemenize izin vermediğini anlıyorum: evet, siz bir koyunsunuz, bir eğri kodunuz var.

Ama sonuçta, o kadar ileri gitmeyeceksiniz ve bu şekilde devam edin, tüm MQ personeli yakında diğer insanların kodları üzerinde oturup kederli bir şekilde “tüm bunlara neden ihtiyacımız var?” Diye düşünmekle meşgul olacak ve bu arada şampiyonluk. burunda ve orada gerçek hesaplara girmek mümkün olmayacak.

Bir toparlayacağım, bugünün mottosu "Bir hata yayınlayacaktım, sorun sizin çarpık ellerinizde mi kontrol edin."

Общайтесь с разработчиками через Сервисдеск!
Общайтесь с разработчиками через Сервисдеск!
  • www.mql5.com
Ваше сообщение сразу станет доступно нашим отделам тестирования, технической поддержки и разработчикам торговой платформы.
 

Yeni yapı - yeni sorunlar. 314'te derlemeden sonra (hatasız derleme) 306'da normal olarak çalışan Expert Advisor, test cihazında çıktılar:

2010.08.21 17:03:36 Çekirdek 1 bağlantısı kesildi
2010.08.21 17:03:36 OnInit başarısız olduğu için Core 1 test cihazı durduruldu
2010.08.21 17:03:36 Core 1 2010.01.04 00:00:00 Erişim ihlali 0x00000000000000014 olarak okundu
2010.08.21 17:03:36 Çekirdek 1 2010.01.04 00:00:00 Bakiye=10000,00 Eşit=10000,00 Kar=0,00
2010.08.21 17:03:36 Core 1 2010.01.04 00:00:00 PriceChannel_multi_Ch_Timer EA EURUSD grafiğinde 01.2010 00:00 tarihinde çalışmaya başladı, H1 periyodu

Gerçek hayatta da boşaltılır. Hatanın kaynağının satır olduğu ortaya çıktı.

m_symbol[j].Name(TradeSymbols[i]);

Birkaç satırla değiştirmek

 string curSymbol=TradeSymbols[i];
m_symbol[j].Name(curSymbol);

statükoyu uzmana iade etti.

Sorun ne ???

Bu arada, önceki derlemede derlenen kod bunda da iyi çalışıyor.

 
Valmars :

Sorun ne ???

Bu arada, önceki derlemede derlenen kod bunda da iyi çalışıyor.

Hatamız - kesinlikle düzelteceğiz.
 
Renat :

Sistemde minimum lot = 0.01


Notlar:

  1. Başlangıç koşulunuz minvol + N * stepvol'un doğru olması garanti edilmez, ayarlarda çoklu olmayan bir minlot değeri belirleyebilirsiniz ve tüm hesaplama mantığınız ihlal edilecektir.
  2. Boşuna ulong'a geçtiniz - kendiniz için zorluklar yarattınız ve sonra bunun hakkında bir sayfa düşünce yazdınız.
  3. Akıllıca bir ikame ve kodunuzda tmp kullanımı birçok kişinin aklını başından alacak, benim versiyonumda işlemlerin anlamı açısından her şey çok daha net.

Bu artık sistemdeki minimum lot = 0.01'dir. Ve bir yıl içinde? İkiye?

1. Ve hangi koşul doğrudur? O halde doğru formül nedir? Diyelim ki minvol = 0.15 ve stepvol = 0.1 için - izin verilen ilk birkaç lot değeri ne olacak? a) 0.15, 0.25, 0.35...? b) 0.15, 0.2, 0.3...? içinde) ... ? A seçeneğini düşündüm.

2. Boşuna değil ulong'a geçtim - En geniş aralığa sahip bir tür seçme hakkım var, böylece mümkün olan en geniş vaka yelpazesi için yeterli, çünkü bu tür işlevler çok temel yapı taşları. Ve bir böceğe rastlamış olmam, zorlukları kendim için yaratanın ben olduğum anlamına gelmez. :) Akıl yürütme, mümkün olan en geniş çevre için açık olması için başkaları için daha fazla yazdı - burada kişisel yazışmalarımız yok.

3. Değiştirme zor değildir - tek kullanımlık değişkenlere sahip olmamak için sadece kaydetme. Ayrıcafonksiyon çağrılırken en fazla bir kez değişkenin referans olarak geçirilip geçirilmediği izlenmiş ve bu nedenle oluşabilecek hataların önüne geçilmesi için kontrol edilmiştir. Eğer bu birisi için "beyni çıkarırsa", yaptığınız gibi alınan her değer için (hatta Ask fiyatı gibi ara olanlar bile) bir değişken oluşturabilirsiniz. Bu an önemsizdir.

Çok daha önemli olan, geçerli değerlerin ızgarasına bağlanma mekanizmasıdır; burada ayrıca hiçbir şeyin ayarlanması gerekmez ve olası maksimum basitliği korurken, çok tipik olmayan çeşitli durumlarda aksaklıkların meydana gelmemesi garantisi.

Temel tuğlanın mümkün olduğunca güvenilir ve çok yönlü olması gerektiği gerçeğinden yola çıktım - o zaman büyük olasılıkla tüm ev bir depremden bile kurtulacak.

 
Urain :

Sadece kendim için konuşuyorum (ama eğer biri onun yansımasını görürse, unutmayın ki tek kişi siz değilsiniz).

Son aylarda, hata yarışı, her şeyden önce çalışmayan bir programı MetaTrader hatası olarak görme alışkanlığını geliştirdi.

Bu neden, evet, sadece işlenmiş bir şablon, eğer bir şey işe yaramazsa, o zaman bu bir hatadır ve hadi arayalım.

Burada MQL5 hatalarının kendi hatalarına acı verecek kadar benzer olması çok önemli bir rol oynamaktadır. Ve bir sürü MQL5 hatası var.

Çok daha az MQL5 hatası olurdu ve o kadar basit olmazdı - onları karıştırmak çok daha zor olurdu.

Ukrayna :

Ama sonuçta, o kadar ileri gitmeyeceksiniz ve bu şekilde devam edin, tüm MQ personeli yakında diğer insanların kodları üzerinde oturup kederli bir şekilde “tüm bunlara neden ihtiyacımız var” diye düşünmekle meşgul olacak ve bu arada şampiyonluk burunda ve orada gerçek hesaplara girmek mümkün olmayacak.

Bir toparlayacağım, bugünün mottosu "Bir hata yayınlayacaktım, sorun sizin çarpık ellerinizde mi kontrol edin."

YALNIZCA MQL5'te yazılan Expert Advisors şampiyonluğunun bir kumar olduğu bu kararın açıklandığı tarihte açıktı. Ancak yönetimin kendi vizyonu vardır. Kendileri öyle karar verdi. Kimse onları karar vermek için rahatsız etmedi. Yani - ne yani, şampiyonluk burnunda - kendilerine böyle bir hayat kurdular.

Ve işte çok basit: Hatanın yerelleştirilmesi üzerinde kendiniz biraz çalışmanız gerekiyor: hatayı etkilemeyen her şeyi koddan atmaya başlayın. Sonunda, test senaryosu gibi bir şey elde edersiniz - oldukça küçük ve aynı zamanda, çoğunlukla hata ve gösterme. Artık "başka birinin kodu" değil, "MQL5 hatasını gösteren kod" olacaktır.

 
OrderCalcMargin() işlevini test etmek için bir komut dosyası yazdı
 void OnStart ()
  {
//---
   int total= SymbolsTotal (false);
   double marginbay;
   double marginsell;
   MqlTick last_tick;
   for ( int i= 0 ;i<total;i++)
     {

       string symbol= SymbolName (i,false);
       Print ( "************************************************" );
       Print ( "Инструмент - " ,symbol);
       Print ( "Валюта депозита = " , AccountInfoString ( ACCOUNT_CURRENCY ));
       Print ( "Базовая валюта = " , SymbolInfoString (symbol, SYMBOL_CURRENCY_BASE ));
       Print ( "Валюта маржи = " , SymbolInfoString (symbol, SYMBOL_CURRENCY_MARGIN ));
       if ( SymbolInfoTick (symbol,last_tick))
        {
         OrderCalcMargin ( ORDER_TYPE_BUY ,symbol, 1.0 ,last_tick.ask,marginbay);
         OrderCalcMargin ( ORDER_TYPE_SELL ,symbol, 1.0 ,last_tick.bid,marginsell);
         Print ( "Маржа для покупки = " ,marginbay);
         Print ( "Маржа для продажи = " ,marginsell);
        }
       else Print ( "SymbolInfoTick() failed, error = " , GetLastError ());
     }
  }
//+------------------------------------------------------------------+
Bazı araçlar için işlev sıfır döndürür, bu bir hata mı yoksa tasarımdan mı kaynaklanıyor?
 
sergey1294 :
OrderCalcMargin() fonksiyonunu kontrol etmek için bir komut dosyası yazdı.Bazı enstrümanlar için fonksiyon sıfır döndürür, bu bir hata mı yoksa amaçlanmış mı?

Bu muhtemelen MarketWatch'ta olmayan semboller içindir, çünkü SymbolName şöyle der:

SembolAdı

Belirtilen sembolün adını döndürür.

string SembolAdı (
    int     pos , // listedeki numara
    bool    seçilmiş        // true - MarketWatch'ta yalnızca semboller
);

Seçenekler

konum

[içinde] Sembol numarası sırayla.

seçilmiş

[içinde] İstek modu. Değer true ise sembol, MarketWatch'ta seçilenler listesinden alınır. Değer false ise, karakter genel a listesinden alınır.

Geri dönüş değeri

Sembol adına sahip dize türünün değeri.

Beklenmeyen sonucun elde edildiği sembolün adını yazdırın ve MarketWatch'taki listeyle karşılaştırın.