danışman projesi - sayfa 3

 
Alexey Volchanskiy :

Ve sonra, alttaki 4 parantezin ne anlama geldiğini gözlerinizle araştırın.

Bu arada, yuvalama iki seviyeden fazla olduğunda çok gerginim. Kodu fonksiyonlara 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):

 int CMT5TradeHistory::Select( ulong ulMagic,ECurrencySymbol csSymbol, datetime dtFrom = MIN_DATETIME, datetime dtTill = NEVER_EXPIRES)
{
   ASSERT(dtFrom <= dtTill);

   // Очистим список ядер позиции
   m_aoPosCores.Clear();
   
   // Запросим историю ордеров и сделок
   if ( HistorySelect (dtFrom,dtTill)!= true )
       return ( WRONG_VALUE );
   
   // Соберем тикеты исторических позиций
   // Просмотрим все сделки выхода, и выпишем оттуда тикеты позиций.
   int iHistoryDealsTotal= HistoryDealsTotal ();

   CArrayLong   alHistoryPosIDs;
   int iI = WRONG_VALUE ;
   ulong ulCurTicket = 0 ;
   long lCurPosID = 0 ;
   long lCurMagic = 0 ;
   long lCurEntry = 0 ;
   string strCurSymbol;
   
   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 ;
         };
      
       // Получим символ сделки
       if ( HistoryDealGetString (ulCurTicket, DEAL_SYMBOL ,strCurSymbol)!= true )
         {
         TRACE_INTEGER( "Не удалось получить символ ордера ! Тикет: " ,ulCurTicket);
         continue ;
         };
      
       // Проверим символ
       if (csSymbol != CS_UNKNOWN)
         if (csSymbol == CS_CURRENT)
            {
             if (_Symbol2CurrencyEnum(strCurSymbol) != _Symbol2CurrencyEnum( Symbol ()))
               {
               //TRACE2("Symbol выбираемой позиции: ",_Enum2CurrencySymbol(csSymbol));
               //TRACE2("Выбранный ордер имеет неверный символ: ",strCurSymbol);
               continue ;
               };
            }
         else 
            {
             if (_Symbol2CurrencyEnum(strCurSymbol) != csSymbol)
               {
               //TRACE2("Symbol выбираемой позиции: ",_Enum2CurrencySymbol(csSymbol));
               //TRACE2("Выбранный ордер имеет неверный символ ! Символ ордера: ",poiBuffer.GetSymbolString());
               continue ;
               };
            };

       // Получим ID позиции
       if ( HistoryDealGetInteger (ulCurTicket, DEAL_POSITION_ID ,lCurPosID)!= true )
         {
         TRACE_INTEGER( "Не удалось получить ID позиции ! Тикет: " ,ulCurTicket);
         continue ;
         };
         
       // Проверим ID позиции
       if (lCurPosID <= NULL )
         continue ;        
         
       if (alHistoryPosIDs.Add(lCurPosID)!= true )
         return ( WRONG_VALUE );
      };   // цикл перебора всех сделок
   
   // Здесь ID всех позиций собраны в массиве alHistoryPosIDs, необходимо убрать повторения (в позиции может быть много ордеров)
   CArrayLong alUnicalHistoryPosIDs;   
   
   if (_DeleteDoubles( GetPointer (alHistoryPosIDs), GetPointer (alUnicalHistoryPosIDs))!= true )
       return ( WRONG_VALUE );

   TRACE_INTEGER( "Уникальных ID позиций в истории: " ,alUnicalHistoryPosIDs.Total());

   // Здесь массив alUnicalHistoryPosIDs заполнен уникальными ID позиций в истории.
   // Заполним ядра позиции
   CMT5HistoryPositionInfoCore* phpiHistPosCore = NULL ;
   
   for (iI= 0 ;iI<alUnicalHistoryPosIDs.Total(); ++iI)
      {
       //TRACE_INTEGER("Выберем позицию: ",iI);
      
       // Выберем очередной тикет
      lCurPosID = alUnicalHistoryPosIDs.At(iI);

       // Позиция является нужной компонентой 
      ASSERT(phpiHistPosCore == NULL );
      
      phpiHistPosCore = new CMT5HistoryPositionInfoCore;
      
       if (phpiHistPosCore == NULL )
         {
         m_aoPosCores.Clear();
         ASSERT_DSC( false , "Не удалось создать объект CMT5HistoryPositionInfoCore по new" );
         return ( WRONG_VALUE );
         };
      
      ASSERT_MYPOINTER(phpiHistPosCore);

       if (phpiHistPosCore.SelectByID(lCurPosID)!= true )
         {
         TRACE( "Не удалось создать выбрать позицию ! Возможно, позиция открыта, и еще не полностью в истории." );
         TRACE_INTEGER( "ID невыбранной позиции: " ,lCurPosID);
         delete phpiHistPosCore;
         phpiHistPosCore = NULL ;
         continue ;
         };
      
      ASSERT(phpiHistPosCore.GetTPCOpenTime() > MIN_DATETIME && phpiHistPosCore.GetTPCOpenTime() < phpiHistPosCore.GetTPCCloseTime() && phpiHistPosCore.GetTPCCloseTime() < NEVER_EXPIRES);
      
       // Найдена и выбрана еще одна компонента позиции
       if (m_aoPosCores.Add(phpiHistPosCore) == false )
         {
         delete phpiHistPosCore;
         m_aoPosCores.Clear();
         ASSERT_DSC( false , "Не удалось добавить новый объект в список ядер позиции" );
         return ( WRONG_VALUE );
         };
      
      phpiHistPosCore = NULL ;   
      }; // цикл перебора уникальных PosID

   // TRACE_INTEGER("Ядер в выбранной позиции: ",m_aoPosCores.Total());     
   
   return (m_aoPosCores.Total());
};

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

 class CTradeHistoryI: public CMyObject
{
public :
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
   virtual void ~CTradeHistoryI() {};
   
   // Выбор существующей истории. 
   // Указывается магик и символ, по которому выбираются исторические ордера, а также промежуток времени, в котором необходимо искать их.
   // Если ulMagic = 0 - выбираются все позиции по всем магикам.
   // Если ECurrencySymbol = CS_UNKNOWN - выбираются все позиции по всем символам
   // Если ECurrencySymbol = CS_CURRENT - запрашивается функция Symbol(), и выбираются все позиции по этому символу
   // Возвращает число компонент позиции внутри истории (может быть нулевым если ничего не найдено) или WRONG_VALUE в случае ошибок
   // NOTE !!! 
   // При выборе - отложенные ордера не учитываются.
   virtual int Select( ulong ulMagic = 0 ,ECurrencySymbol csSymbol = CS_CURRENT, datetime dtFrom = MIN_DATETIME, datetime dtTill = NEVER_EXPIRES) = 0 ;

   virtual uint GetTotalComponents() const = 0 ;   // Получение общего числа компонент
   virtual CHistoryPosComponentI* GetComponent( uint uiComponentIdx) const = 0 ;
   
   // Расширенный интерфейс
   virtual void Sort(ESortTPCMode stmMode = STM_BY_OPEN_TIME_A) = 0 ;
   
   
   // Функция ищет внутри истории компоненту с указанным тикетом. 
   // В случае, если ее нет - возвращается false.
   // Если компонента найдена - возвращается true, и uiComponentIdx устанавливается на индекс компоненты внутри позиции.
   virtual bool FindComponentByTicket( long lTicket, uint &uiComponentIdx) const = 0 ;
};

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:

 class CTradePosComponentI: public CMyObject
{
public :
   void CTradePosComponentI() {    SetMyObjectType(MOT_TRADEPOS_COMPONENT_I); };
   virtual void ~CTradePosComponentI() {};
   
   // Основной интерфейс
   virtual long                GetTPCTicket()       const = 0 ;
   virtual long                GetTPCMagic()         const = 0 ;
   virtual ECurrencySymbol    GetTPCSymbol()       const = 0 ;
   virtual ENUM_POSITION_TYPE GetTPCType()         const = 0 ;
   virtual datetime            GetTPCOpenTime()     const = 0 ;
   virtual double              GetTPCVolume()       const = 0 ;
   virtual double              GetTPCOpenPrice()     const = 0 ;
   virtual double              GetTPCStopLoss()     const = 0 ;
   virtual double              GetTPCTakeProfit()   const = 0 ;
   virtual string              GetTPCCommentary()   const = 0 ;
   
   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 ); };
   virtual double              GetTPDistance() const { if (GetTPCTakeProfit() == 0 || GetTPCTakeProfit() == EMPTY_VALUE ) return ( EMPTY_VALUE ); if (GetTPCType() == POSITION_TYPE_BUY ) return (GetTPCTakeProfit() - GetTPCOpenPrice()); return (GetTPCOpenPrice() - GetTPCTakeProfit());  };
   virtual double              GetSLDistance() const { if (GetTPCStopLoss() == 0 || GetTPCStopLoss() == EMPTY_VALUE ) return ( EMPTY_VALUE ); if (GetTPCType() == POSITION_TYPE_BUY ) return (GetTPCOpenPrice()- GetTPCStopLoss()); return (GetTPCStopLoss() - GetTPCOpenPrice());  };
};

class CHistoryPosComponentI: public CTradePosComponentI
{
public :
   void CHistoryPosComponentI() {    SetMyObjectType(MOT_HISTORYPOS_COMPONENT_I); };
   virtual void ~CHistoryPosComponentI() {};

   virtual datetime            GetTPCCloseTime()     const = 0 ;
   virtual double              GetTPCClosePrice()   const = 0 ;
   virtual double              GetTPCProfit()       const = 0 ;   // Возвращает профит по исторической позиции
   
   virtual bool                IsProfitClosePrice() const = 0 ;   // Возвращает true, если цена зарытия отличается от цены открытия в прибыльную сторону   
   
   // Возвращает профит исторической позиции для случая, когда бы ход цены (в сторону профита) был бы равен dPriceMove, а лот был бы единичным.
   // Функция используется для расчета лота для такой же позиции с нужным ходом цены 
   // Рекомендуется отнимать от цены двойной спред.
   virtual double              CalculateOneLotProfit( double dPriceMove) const = 0 ;  
  
};

MT4 için - bu arayüzlerden miras alınan karşılık gelen geçmiş sınıfları vardır - böylece ç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.

 
Vitaly Muzichenko :

Bu tarzda her zaman sabit olan ve asla değişmeyen fonksiyonlar yazmayın.

Bunları kısaca yazın, zaten kimse onlara bakmaz ve satırlar bunun yarısını alır.

Bu işlevler değişmediğine göre, neden oraya bir sürü gereksiz kaşlı ayraç koydunuz? Onları kaldırın ve her şey kendi kendine küçülecek. Aksi takdirde, örneğiniz saçma görünüyor: kodu kendiniz bulaştırdınız ve sonra kısaltmak için koltuk değneği icat ettiniz.
 
Alexey Navoykov :
Bu işlevler değişmediğine göre, neden oraya bir sürü gereksiz kaşlı ayraç koydunuz? Onları kaldırın ve her şey kendi kendine küçülecektir. Aksi takdirde, örneğiniz saçma görünüyor: kodu kendiniz bulaştırdınız ve sonra kısaltmak için koltuk değneği icat ettiniz.

Katılıyorum, 3 satır daha kesebilir ve kodu kısaltabilirsiniz, ancak amaç kullanım için kodu düzenlemek değildi, aslında benim bile değil, kısaltmak ve bu tür beş işlevi bir tanesine koyabilirsiniz. ekran, bir değil. Bundan sonra programların okunması daha kolay oluyor ve 150 defa kaydırma yapmanıza gerek kalmıyor. Ve dosyanın boyutu küçülür.

 
George Merts :

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.

Vitaly Muzichenko :

Katılıyorum, 3 satır daha kesebilir ve kodu kısaltabilirsiniz, ancak amaç kullanım için kodu düzenlemek değildi, aslında benim bile değil, kısaltmak ve bu tür beş işlevi bir tanesine koyabilirsiniz. ekran, bir değil. Bundan sonra programların okunması daha kolay oluyor ve 150 defa kaydırma yapmanıza gerek kalmıyor. Ve dosyanın boyutu küçülür.

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

Samimi olarak.
 
Vitaly Muzichenko :

Çalışma ekranı 27"

Yazıyı tekrar okumayacağım, alıntı yapacağım: " Bu tarzda her zaman sabit olan ve asla değişmeyen fonksiyonlar yazmayın "

Platform yayınlandığında bir kez yazılan ve gelecekte asla değişmeyecek bir fonksiyona neden gözünüzü dikiyorsunuz? Parti büyüklüğünü,sipariş sayısını ve tipik olanları almak için işlevlerdeki kodu sık sık değiştiriyor/düzenliyor musunuz? O zaman neden 32" bir monitörün 3 ekranına uzatalım?

PS Kod eklenmiştir, kod tabanından alınmıştır.


Karşı soru)) MyFunc.mqh dosyasında bu tür işlevlerim var, sıkıştırmak için en ufak bir neden göremiyorum. Neden, diskte 10-20 Kb tasarruf edin? Ve dürüst olmak gerekirse, bu kod stili beni kötü hissettiriyor))

 
Alexey Volchanskiy :

Karşı soru)) MyFunc.mqh dosyasında bu tür işlevlerim var, sıkıştırmak için en ufak bir neden göremiyorum. Neden, diskte 10-20 Kb tasarruf edin? Ve dürüst olmak gerekirse, bu kod stili beni kötü hissettiriyor))

Ben de eklenti dosyaları kullanıyorum, kullanışlı. özellikle sipariş üzerine yazarken birçok fonksiyon aynı ve aynı şeyi yazmak biraz saçma oluyor, dosyayı ve fonksiyonu danışmanda birleştirdim.
benim için kod anlaşılır, kısa, operasyonda hızlı olmalı, her koşulda hatasız çalışmalı.


Samimi olarak.

 
Alexey Volchanskiy :

Karşı soru)) MyFunc.mqh dosyasında bu tür işlevlerim var, sıkıştırmak için en ufak bir neden göremiyorum. Neden, diskte 10-20 Kb tasarruf edin? Ve dürüst olmak gerekirse, bu kod stili beni kötü hissettiriyor))

Kişi "Her şeyi yanımda taşıyorum" ilkesine sahip olduğunu yazdı, danışmanın tüm kodu tek bir dosyaya doldurulacak. Buna göre, tüm bu işlevleri kopyalayıp her danışmana yapıştırır.
Yani sayın: 1000 Uzman Danışman x 10 kb = 10 Mb - zaten tasarruf hakkında düşünmek için bir neden var))
 
Alexey Volchanskiy :

Karşı soru)) MyFunc.mqh dosyasında bu tür işlevlerim var, sıkıştırmak için en ufak bir neden göremiyorum. Neden, diskte 10-20 Kb tasarruf edin? Ve dürüst olmak gerekirse, bu kod stili beni kötü hissettiriyor ))

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.

 
George Merts :

Bu arada, yuvalama iki seviyeden fazla olduğunda çok gerginim. Kodu fonksiyonlara 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 - böylece ç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.


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

 
Vitaly Muzichenko :

bir dosyayı başka bir terminale sürüklemek veya paylaşmak için bir dosyayı değil, birkaç dosyayı sürüklemeniz gerekir. Elbette, eklentileri tüm terminallere aktarabilirsiniz, ancak birinde bir şeyi düzelttiyseniz veya eklediyseniz, hepsini yenisiyle değiştirmeniz gerekir.

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.