danışman projesi - sayfa 4

 
Vitaly Muzichenko :

Ben de, ama bir şekilde, uzun zaman önce, kodun asla bakılmadığı, asla düzeltilemeyeceği ve düzeltilemeyeceği yerlerde kodun kompakt olması gerektiği sonucuna vardım.

Dahil edilenler arasında özel kodun dağıtılması, bir dosyayı başka bir terminale sürüklemek veya paylaşmak için başka bir ek baş ağrısı yaratır, bir dosyayı değil birkaç dosyayı sürüklemeniz gerekir. Tabii ki, eklentileri tüm terminallere aktarabilirsiniz, ancak birinde bir şeyi düzelttiyseniz veya eklediyseniz, hepsini yenisiyle değiştirmeniz gerekir.

Uzman Danışmanlar ve göstergeler o kadar küçüktür ki, bir şeyi programın gövdesinden uzaklaştırmak anlamsızdır. Veya daha doğrusu, küçük değiller, tek dosya, bu, sınıf ve inklüzyonlar olmadan yapamayacağınız 10.000 sayfalık bir site değil. Üstelik artık yapılar var ve bunlar kompakt, %100 verimli kodlar yazmak için oldukça yeterli.

Peki, geldik .... Klasörlere sembolik bağlantılar hakkında bilginiz var mı? http://skesov.ru/sozdanie-simvolnoy-ssylki-dlya-papki/

Tüm kitaplıklarım tek bir klasörde ve bir grup terminalde bunlardan birkaç düzine var, mql*\includes klasörlerinde bu gerçek klasöre sembolik bağlantılar var. Hiçbir şey taşımanıza gerek yok.

Ben de depolamayı aktif olarak kullanıyorum, önemli olan her şeyi orada tutarsanız 5 saniye içinde başka bir terminale indirebilirsiniz. Ancak her ikisi için de sembolik bağlantılar daha uygundur, her zaman tam senkronizasyon.

Создание символьной ссылки для папки в Windows 8.1, 8, 7, Vista
Создание символьной ссылки для папки в Windows 8.1, 8, 7, Vista
  • 2013.07.24
  • skesov.ru
Доброго времени суток! Сегодня рассмотрим интересную тему под названием «Символьные ссылки». Вариантов использования данного инструмента не так уж много. К примеру, если вы используете часть оперативной памяти как RAM-диск, можно перенести какую-либо игру или её часть (скажем папки с графикой) и создать символьную ссылку. Это значительно...
 
Alexey Navoykov :
MQL klasörü için sembolik bağlantılar veya bağlantı bağlantıları kullanmanızı öneririm. Tüm terminaller tek bir klasörde görünecektir.

Biriyle paylaşmaya ne dersin?

 
Vitaly Muzichenko :

Biriyle paylaşmaya ne dersin?

Peki, burada gerçekten sizin için neyin daha önemli olduğuna karar vermeniz gerekiyor, dama mı yoksa gitmek mi) Biriyle paylaşma sürecinin basitliği sizin için kodlamanın rahatlığından daha mı önemli? Birçok danışman tarafından kullanılan bazı işlevlerde bir hata bulursanız, her birinin koduna girmeniz ve bu işlevi iletmeniz gerekir - bu bir programcı olarak sizi rahatsız etmiyor mu?

 
Sorunumu tartıştığınız için herkese teşekkürler.
(Tekrarlanan) işlevlerimi ayrı bir dosyada (dosyalar) saklamak için mqlx'te OOP'ye bakmaya karar verdim. Ve yorum yapmaktan çekinmeyin.

Ve Windows'ta sembolik bir bağlantı için +! Bir şekilde Linux kullandım ama Windows'u unuttum. denemek gerekecek..
 
Alexey Navoykov :

Peki, burada gerçekten sizin için neyin daha önemli olduğuna karar vermeniz gerekiyor, dama mı yoksa gitmek mi) Biriyle paylaşma sürecinin basitliği sizin için kodlamanın rahatlığından daha mı önemli? Örneğin, birçok danışman tarafından kullanılan bazı işlevlerde bir hata bulursanız, her birinin koduna girmeniz ve bu işlevi iletmeniz gerekir - bu bir programcı olarak sizi rahatsız etmiyor mu?

Sadece bir kez, yaklaşık bir ay önce böyle bir durum yaşadım, ancak orada piyasanın açıklığı için bir çek eklemek zorunda kaldım, bunun dışında tüm çekler var ve bu, tüm kullanım süresi boyunca ilk kez ortaya çıktı. .

Eklenmesi gereken bir şey varsa, onu mevcut programa ekliyorum ve ondan sonra dosyayı bir sonraki program için şablon olarak kullanıyorum. Sonuç olarak, birkaç yıl içinde, şablonda her şey ya da hemen hemen her şey bulunur, bu nedenle herhangi bir karmaşıklıktaki bir bot yarım saatte yazılır.

Dosyanın 4.000 satırından biraz daha fazla olmasına rağmen, yürütme kodunun tamamı tek bir ekrana yerleştirilir, ancak bir şey eklemem gerekirse oraya nadiren bakarım. Fonksiyonları döngülerde kullanmayı reddettim, sadece ikisi kullanılıyor, biri açık, ikincisi tarih hakkında bilgi topluyor ve tüm bunlar kodun en altındaki yapıda. Her şey çok basit ve yakın. Ana kod yorumlanır. Proje herhangi bir kayıp olmadan son derece basit ve hızlı bir şekilde genişler.

 
Alexey Volchanskiy :

Lezzetli görünüyor, TRACE_*** ve ASSERT'i de görebilir miyim?

Şey ... Siyah gıpta ile gıpta ettiğim kadınları baştan çıkarma konusunda ustalık sınıfının yazarı için - her zaman beklerim.

Karşılık gelen sistem makrosu tanımlanmışsa, hata ayıklama sürümü benim için otomatik olarak etkinleştirilir. Ancak, etkinleştirilmediyse, tanımlamalarla doğrulamaları ve izlemeleri de etkinleştirebilirsiniz:

#define _FORCETRACE 1
#define _FORCEASSERT 1

Bu durumda - sistem ayarlarından bağımsız olarak - hata ayıklama izleri ve hata ayıklama iddiaları oluşturulur.

Bu makroları yönergeye bağlarım:

#include <MyLib\DebugOrRelease\DebugSupport.mqh>

Bu yönerge, gerekli tüm dosyaları ve tanımları içerir. Hepsi ayrı bir DebugOrRelease klasöründedir. onları ekliyorum. (Kod uzun zaman önce, çoğunlukla aceleyle yazılmıştır, bu yüzden arayüzler ve tarih sınıfındaki kadar güzel değildir). Hata ayıklama sürümü için onaylar ve izler AssertD ve TraceD dosyalarındadır, aslında bunlar PerformAssert() ve PerformTrace() işlevleridir.

Ek olarak, bu dosyalar ve makrolar genel günlük dosyasını kullanır (günlük dosyasının çıktısı ayarlanmışsa), zaten bir kez gönderdim, ancak tekrar. Günlük dosyası "Ortak" klasörümde.

Dosyalar:
 
Andrey Kisselyov :

iyi iş, beğendim, ama OOP'yi sevmiyorum ve onsuz yapmaya çalışıyorum. Tıpkı iş parçacığı ayırmalı işlemcileri sevmedikleri gibi (örnek 4 çekirdek ve 8 iş parçacığı). Bölünmenin ve herhangi bir sanallaştırmanın, çekirdekteki iş parçacıklarının bölünmesi veya koddaki işlevlerin sanallaştırılması olsun, uygulanması için bir performans kaybı ve makine zamanı kaybı olduğu açık olmalıdır.

kısalık yeteneğin kardeşidir, böylesi daha iyi bence.

Uzun süredir, sürdürülebilirliğin ve kodun yeniden kullanımının rahatlığının, performansı düşürmekten çok daha önemli olduğuna ikna oldum.

OOP - bir süre sonra değişiklik için koda döndüğümde bana çok yardımcı oluyor. Yeniden kullanımdan bahsetmiyorum.

Ancak, katılıyorum, kullanmak her zaman gerekli olmaktan uzaktır OOP .

Diyelim ki bir sınıfım var CDataProvider:pulic CDataProviderI, EA'ya zaman serileri, göstergeler, terminal ve ortam verileri sağlayan bir veri sağlayıcısıdır. Expert Advisor içinde çok sayıda TS olabilir - her biri veri sağlayıcıdan zaman serilerine ve göstergelere yönelik işaretçiler alır (sonuç olarak, her bir TS'nin bu zaman serilerini oluşturmaya özen göstermesi gerekmez - veri sağlayıcı, gerekli zaman serileri, zaten varsa ve yalnızca henüz oluşturulmamış olanları yaratacaktır).

Bir veri sağlayıcıdan gösterge almanız gerektiğinde, gösterge açıklama yapısını doldurmanız ve ardından sağlayıcıdan bu yapıya işaret ederek göstergeyi talep etmeniz gerekir.

Buna göre, veri sağlayıcı içindeki her gösterge kendi yapısını tanıyabilmelidir (veri sağlayıcı yalnızca yapının soyut temel sınıfını "tanımıştır") ve onu kullanarak hazır bir gösterge nesnesi yaratabilmelidir - bu, veri sağlayıcı tarafından verilecektir.

Ancak, bir tür göstergenin yeni bir fikrini test etmek için tüm bu bahçeyi çitle çevirmek elbette mantıksız. Sonuç olarak - bu tür yeni göstergeler için - her şey herhangi bir OOP olmadan "diz üzerine monte edilir". Ancak, göstergenin Uzman Danışmanlar için yararlı olduğunu görürsem, "beklendiği gibi" yazılır - tam OOP desteği ve veri sağlayıcının içinde oluşturma.

not

Bu arada, göstergeler ve bir veri sağlayıcı durumunda, miras sanallaştırmadaki avantaj açıkça görülmektedir. Temel bir gösterge parametreleri arayüzümüz var CIndicatorParametersI, bu arayüzün halefi gerekli göstergenin gerçek parametreleridir. Bir gösterge talep ederken, bu parametreleri bildiririz ve veri sağlayıcıya soyut arayüze bir işaretçi iletiriz. Bu nedenle, veri sağlayıcının kendisi hangi göstergenin talep edildiğini bile bilmiyor - bu, göstergenin ihtiyaç duyulan türden yeni tarafından oluşturulduğu bir işlevde belirlenir. Ve tam olarak hangi parametrelerin iletildiği hakkında - yalnızca bu oluşturulan gösterge bilir, bu da geçen nesneden gerekli parametreleri çıkarır.

İşin püf noktası, veri sağlayıcının içinde hemen hemen her yerde, basit bir temel parametre sınıfı (veya göstergeler) ile iş yapılmasıdır - veri sağlayıcısı için yalnızca temel arabirimlerin en basit ve en yaygın işlevleri kullanılabilir. Bu, kodun değiştirilmesini basitleştirir (gerektiğinde) ve veri sağlayıcıdan gösterge kodunu "girmek" için bir ayartma yaratmaz. Göstergeyi değiştirmeniz gerekiyorsa, bu yalnızca göstergenin kendi içinde yapılır, veri sağlayıcı yalnızca bir gösterge deposu iken, yapabileceği maksimum şey yeni bir gösterge oluşturmaktır.

 
George Merts :

Bu arada, yuvalama iki seviyeden fazla olduğunda çok gerginim. Kodu fonksiyonların üzerine yayarak asla böyle yazmamaya çalışıyorum.

Ve iki seviyeli yuvalama olsa bile - her zaman her kapanış parantezinden sonra - hangi bloğu gömdüğü hakkında yorumlar yazarım (diyelim ki, döngünün başlığını çoğaltıyorum).

Tarza gelince, MT5 için tarihsel bir konum seçme kodum (belirtilen sihir, sembol, belirtilen tarih aralığı ile):

Aynı zamanda, history sınıfının kendisi, CTradeHistoryI soyut arayüzünün bir mirasçısıdır:

Gerekli geçmişi seçtikten sonra bileşenlerini (MT5 için konumlar veya MT4 için siparişler) yeniden hesaplayabilir ve herhangi bir bileşene soyut bir arayüz şeklinde bir arayüz alabilirsiniz:

MT4 için - bu arayüzlerden miras alınan karşılık gelen geçmiş sınıfları vardır - bu nedenle çapraz platform da sağlanır - danışmanın nerede çalıştığını bulması gerekmez, geçmişle ilgili tüm çalışmalar soyut arayüzler aracılığıyla yapılır.


fazla eleştiri yok

 class CTradePosComponentI: public CMyObject
{
...
}

Standart ve anlaşılır bir CObject varken neden tekerleği CMyObject biçiminde yeniden icat edelim?

 class class CTradeHistoryI: public CMyObject
{
// Расширенный интерфейс
   virtual void Sort(ESortTPCMode stmMode = STM_BY_OPEN_TIME_A) = 0 ;
}

Burada, CObject ve CArrayObj'nin işlevselliği zaten açıkça kopyalanmıştır. Ne için? Quicksort, standart veri kapsayıcılarında yerleşiktir. Onları kullan.

 class CTradePosComponentI: public CMyObject
{
public :
   void CTradePosComponentI() {    SetMyObjectType(MOT_TRADEPOS_COMPONENT_I); };
   virtual void ~CTradePosComponentI() {};
}

Sınıf bir arayüz ise, kurucusu korumalı bölümde gizlenmelidir. O zaman nesnesi doğrudan oluşturulamaz.

Boş bir yıkıcı tanımla? İyi bilmiyorum. Bunu yapmazdım. Yıkıcı hakkında, gerekli değilse, bundan bahsetmemek daha iyidir.

 for (iI= 0 ;iI<iHistoryDealsTotal; ++iI)
...

Standart olmayan artış iI, standart olmayan yineleme ++iI, iHistoryDealsTotal - döngüden çok önce bir yerde tanımlanmış. Daha basit:

 for ( int i = 0 ; i < HistoryDealsTotal ();i++)

Bu, önceki sürüm kadar hızlıdır, ancak çok daha açıktır.

 virtual bool                IsTPCInUnloss() const { if (GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE ) return ( false ); if (GetTPCType() == POSITION_TYPE_BUY ) { if (GetTPCStopLoss() >= GetTPCOpenPrice()) return ( true ); } else { if (GetTPCStopLoss() <= GetTPCOpenPrice()) return ( true ); }; return ( false ); };

Kendileri bu tür sayfalara karşı görünüyorlar, ancak bunu bazı yerlerde kendileri yazıyorlar. Kimse böyle bir kanoyu sökmek istemez. Beni böyle yazmaktan alıkoyan şey:

 virtual bool IsTPCInUnloss() const
{
   if (GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE )
       return ( false );
   if (GetTPCType() == POSITION_TYPE_BUY )
   { 
       if (GetTPCStopLoss() >= GetTPCOpenPrice())
         return ( true );
   } 
   else
   {
     if (GetTPCStopLoss() <= GetTPCOpenPrice())
         return ( true );
   } ; 
   return ( false );
} ;

İyi ';' küme parantezlerinin sonunda - bu eskidir, artık bunu yapmanıza gerek yok.

Dev Seçim yöntemi bir dev for döngüsünden oluşur:

for(iI= 0 ;iI<iHistoryDealsTotal; ++iI)
      {
      ulCurTicket = HistoryDealGetTicket (iI);
      
       if (ulCurTicket == 0 )
         return ( WRONG_VALUE );
      
       // Получим направление сделки   
       if ( HistoryDealGetInteger (ulCurTicket, DEAL_ENTRY ,lCurEntry)!= true )
         {
         TRACE_INTEGER( "Не удалось получить направление сделки ! Тикет: " ,ulCurTicket);
         continue ;
         };
      
       // Проверим направление сделки
       if (lCurEntry != DEAL_ENTRY_OUT )
         continue ;
      
       // Получим магик сделки
       if ( HistoryDealGetInteger (ulCurTicket, DEAL_MAGIC ,lCurMagic)!= true )
         {
         TRACE_INTEGER( "Не удалось получить магик сделки ! Тикет: " ,ulCurTicket);
         continue ;
         };
         
       // Проверим магик
       if (ulMagic != NULL && lCurMagic != ulMagic)
         {
         //TRACE_INTEGER("Сделка не подходит ! Имеет неверный магик ! Magic сделки: ",lCurMagic);
         //TRACE_INTEGER("Требуемый Magic : ",ulMagic);
         continue ;
         };
      ...
}

İşlemin mevcut Uzman Danışman ile uyumluluğuna yönelik tüm kontrollerin ayrı bir yönteme taşınmasının daha iyi olduğu açıktır, örneğin:

 for (iI= 0 ;iI<iHistoryDealsTotal; ++iI)
{
   if (!CheckDeal(iI))
       continue ;
   ...
}

Ve genel olarak, seçimin içinde neler olduğunun netleşmesi için 3-4 yönteme daha bölünmesi gerekiyor.

George Merts
Aynı zamanda, danışman dosyasının kendisi beş satırdan oluşur. Bu dosya, uzmanın parça fabrikası nesnesinin kendisini bildirir ve içeriği içerir.

Fabrika çok tartışmalı bir modeldir. Kullanım - iyi, ancak her şeyi fabrikadan yapmanızı önermiyorum.

George Merts
Ve iki seviyeli yuvalama olsa bile - her zaman her kapanış parantezinden sonra - hangi bloğu gömdüğü hakkında yorumlar yazarım (diyelim ki, döngünün başlığını çoğaltıyorum).

Bu yüzden parantezleri MQL'den kötü bir şekilde yerleştirdiğinizi yazıyorsunuz. Böyle yazdıysanız:

 if ( OrderSelect ())
{
   ...
}

Hangi parantezin hangi kod bloğunu kapattığını her zaman görürsünüz.

Kodunuzda bir düzine daha fazla uyarı bulmak mümkün olacaktır. Kod elbette mükemmel değil, ancak yazarın güzelliğe olan özlemi şimdiden hissedildi :))

 
Vasiliy Sokolov :

Küçük bir eleştiri:

A. Bu, sevdiğim türden bir tartışma. Böyle.

Standart ve anlaşılır bir CObject varken neden tekerleği CMyObject biçiminde yeniden icat edelim?

CObject ve CArrayObj'nin işlevselliği zaten burada açıkça kopyalanmıştır. Ne için? Quicksort, standart veri kapsayıcılarında yerleşiktir. Onları kullan.

CMyObject - ve standart CObject'den bir varis var, kodumdaki tüm listeler ve diziler CArray'den (ve standart kitaplığın diğer dizilerinden) varislerdir. Standart dizi[] dizilerini neredeyse hiç kullanmam.

Ve elbette, listeyi sıralamak ve listeyle çalışmak, CObject'in temel işlevselliğini kullanır.

Ve fark şudur: Standart bir CObject, "bir listenin veya sıralanmış bir dizinin nesnesi" dir. CMyObject, belirli bir türü olan ve oluşturulduğunda verilen bazı değerleri içeren bir CObject'dir. Bu nesneye, nesnelerin "gerçekten" hangi nesnenin işaret ettiğini işaretçi tarafından anlamak için temel soyut sınıfa yaygın olarak dökülmesiyle bağlantılı olarak ihtiyacım vardı. CMyObject türü, aynı SetMyObjectType() işlevi tarafından ayarlanır. Bu işlev, yaratılan nesnenin ait olduğu sınıfın tanımlayıcısını atamak için CMyObject'in herhangi bir soyundan gelenlerin yapıcılarında çağrılmalıdır.

Ayrıca, oluşturma sırasında kullanıcı tarafından tanımlanan değeri ayarlayan SetUDCreationValue() işlevine sahiptir. Nadiren kullanılmış. Aynı sınıfın farklı nesneleri arasında ayrım yapmak için gereklidir.

Sınıf bir arayüz ise, kurucusu korumalı bölümde gizlenmelidir. O zaman nesnesi doğrudan oluşturulamaz.

Korumalı yapıcı??? Şey... Evet, belki arayüzler için mantıklıdır, bunun mümkün olduğunu bilmiyordum.

Boş bir yıkıcı tanımla? İyi bilmiyorum. Bunu yapmazdım. Yıkıcı hakkında, gerekli değilse, bundan bahsetmemek daha iyidir.

Bu, "geçmişin lanetli mirası"dır. Bir kez oldukça büyük bir proje yazdılar ve orada, boş bir yıkıcı tanımlamazsanız, o zaman bir nedenden dolayı nesnelerin silinmesi uzun zaman aldı. Bu yüzden bunu uzun zamandır yapıyorum. Yıkıcı, genel olarak konuşursak, aynı zamanda sanal olmalıdır.

Standart olmayan artış iI, standart olmayan yineleme ++iI, iHistoryDealsTotal - döngüden çok önce bir yerde tanımlanmış. Daha basit:

Aynı fikirde olmamak. Artış oldukça normal, - i, sadece standartlaştırılmış gösterim - önce tamsayı türünün küçük bir harfiyle ve sonra - adının büyük harfiyle I.

Kendileri bu tür sayfalara karşı görünüyorlar, ancak bunu bazı yerlerde kendileri yazıyorlar. Kimse böyle bir kanoyu sökmek istemez. Beni böyle yazmaktan alıkoyan şey:

Bu durumda, sınıfın "görünürlüğü" ile bu işlevin güzelliği arasında seçim yapmak zorunda kaldım. Seçilmiş "görünürlük". Güzellik acı çekti.

Dev Seçim yöntemi bir dev for döngüsünden oluşur:

İşlemin mevcut Uzman Danışman ile uyumluluğuna yönelik tüm kontrollerin ayrı bir yönteme taşınmasının daha iyi olduğu açıktır, örneğin:

Ve genel olarak, seçimin içinde neler olduğunun netleşmesi için 3-4 yönteme daha bölünmesi gerekiyor.

Kabul ediyorum. Burada, prensipte, aynı döngü "genişledi", ilk başta o kadar büyük değildi.

Küçük çekleri özel fonksiyonlara taşımak her zaman uygun olmasa da, bu kontrolleri kodun ilerleyen kısımlarında her zaman takip edemezsiniz.

Fabrika çok tartışmalı bir modeldir. Kullanım - iyi, ancak her şeyi fabrikadan yapmanızı önermiyorum.

Şimdi hatırlamıyorum, bir danışman oluşturmak için birkaç seçenek vardı. "Uzman parça fabrikasında" durdu. Prensip olarak, artık saf bir klasik "fabrika" modeli değil. Başlangıçta, "klasik" olması planlanmıştı, ancak şimdi daha çok bir Uzman Danışmanın bölümlerinin sadece bir "yapıcı-yoğunlaştırıcısı". Ve bir fabrika için alışılmadık olan bu parçaların çıkarılmasından da sorumludur. Eh, isim kalır.

Bu yüzden parantezleri MQL'den kötü bir şekilde yerleştirdiğinizi yazıyorsunuz. Böyle yazdıysanız:

Hangi parantezin hangi kod bloğunu kapattığını her zaman görürsünüz.

Neden "kötü"?

Döngünün başlığı, ardından girintili açılış ayracı, ardından aynı girintiye sahip tüm blok ve son olarak da girintili kapanış ayracı.

Sizce ne daha iyi?

 
Gregory Kovalenko :

2 açık siparişte kar elde etmem gerekiyor. Son açık siparişi, OrderProfit2 ve sonraki - OrderProfit1 olarak adlandırıyorum.

Önce 1 açıldı sonra 2. sıra yani 1 döngüye takıldı ben buna 2)

Hata nerede?

Sadece siparişleri sıralıyorsun. Hangisinin birinci, hangisinin ikinci olduğu hiçbir yerde kontrol edilmez.

Açılış saati için bir çek girmeniz gerekir. Böylece daha önce açılan bir sipariş ile daha sonra açılan bir sipariş arasında ayrım yapabileceksiniz. Ya da belki aynı anda açılırlar.

Neden: