How to get close positions's results?

 

Hi,


I'ld like to have the results of all of my positions (or of last year, whatever). Doing that with current open positions is easy, since there are functions that give the current data of open positions (PositionsTotal, PositionSelect, etc.). The problem is that, once finished, the history in HistorySelect only saves deals and orders info, not positions. With that in mind, in order to get my close position's results/info, it seems what I need to do is:

1) HistorySelect to get all deals in cache

2) Get HistoryDealsTotal

3) Iterate using HistoryDealGetTicket while getting a full list of all HistoryDealGetInteger(ticket, DEAL_POSITION_ID)

4) Iterate over the previous results to eliminate repeated POSITION_IDs

5) Iterate over this POSITION_ID list calling HistorySelectByPosition, getting the results of every deal related to every POSITION_ID, sum the results


Is that right? Well I guess it is, but the problem is that this seems very processor-consuming :| Isn't there a smarter, faster way of getting the results of all my closed positions, some "HistoryPositionsSelect-equivalent" way ?

 

Your approach is correct, as there are currently no system functions like 'HistoryPositionsSelect'.

 
Vladimir Karputov #:

Your approach is correct, as there are currently no system functions like 'HistoryPositionsSelect'.

Gosh, that's very sad :/ I hope MetaQuotes will someday add such functionality. Is there any place we can send them improvement suggestions?

 

Hi,

by request, the following is the code I've been using to get the information of positions since there is no native functions to do it:

struct IndicatorMainData
{
   struct HistoryBasicData
   {
      double allPosResults[];
      int positionCount;
      int profitPositionCount;
      int lossPositionCount;
      
      int profitDealsCount;
      double profitDealsVolume;
      double profitDealsTotal;
      double profitDealsTotalByVol;
      double profitDealsTotalPoints;
      double profitDealsTotalPointsForAllVol;
      
      int lossDealsCount;
      double lossDealsVolume;
      double lossDealsTotal;
      double lossDealsTotalByVol;
      double lossDealsTotalPoints;
      double lossDealsTotalPointsForAllVol;
      
      void clear()
      {
         ArrayResize(allPosResults,0);
         
         positionCount =
         profitPositionCount =
         lossPositionCount = 0;
         
         profitDealsCount = 0;
         profitDealsVolume =
         profitDealsTotal =
         profitDealsTotalByVol = 
         profitDealsTotalPoints =
         profitDealsTotalPointsForAllVol = 0.0;
         
         lossDealsCount = 0;
         lossDealsVolume =
         lossDealsTotal = 
         lossDealsTotalByVol = 
         lossDealsTotalPointsForAllVol = 
         lossDealsTotalPoints = 0.0;
      }
   };
      
   HistoryBasicData basicData;
};
void getDataFromSelectedHistory(const uint historyCount)
{
   ulong ticket = 0;
   long entry, posID;
   long positionIDs[];
   
   ArrayResize(positionIDs,historyCount);
   
   for (uint aaa = 0; aaa < historyCount; ++aaa)
   {
      if ((ticket = HistoryDealGetTicket(aaa)) > 0) 
      {
         if (glInputs.magicNumberFilt > 0 
               && HistoryDealGetInteger(ticket,DEAL_MAGIC) != glInputs.magicNumberFilt)
            continue;
            
         //--- obter as propriedades negócios 
         //price = HistoryDealGetDouble(ticket,DEAL_PRICE); 
         //datetime time = (datetime)HistoryDealGetInteger(ticket,DEAL_TIME); 
         //symbol = HistoryDealGetString(ticket,DEAL_SYMBOL); 
         //type = HistoryDealGetInteger(ticket,DEAL_TYPE); 
         posID = HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         entry = HistoryDealGetInteger(ticket,DEAL_ENTRY);
         
         if (entry == DEAL_ENTRY_OUT)
         {
            const double dealResult = HistoryDealGetDouble(ticket,DEAL_PROFIT);
            const double dealVol = HistoryDealGetDouble(ticket,DEAL_VOLUME);
            
            if (dealResult > 0.0)
            {
               ++glIndData.basicData.profitDealsCount;
               glIndData.basicData.profitDealsTotal += dealResult;
               glIndData.basicData.profitDealsVolume += dealVol;
               
               glIndData.basicData.profitDealsTotalPoints += dealResult / 
                     dealVol * getAssetTick();
               glIndData.basicData.profitDealsTotalPointsForAllVol += dealResult * getAssetTick();
            }
            else if (dealResult < 0.0)
            {
               ++glIndData.basicData.lossDealsCount;
               glIndData.basicData.lossDealsTotal += dealResult;
               glIndData.basicData.lossDealsVolume += dealVol;
               
               glIndData.basicData.lossDealsTotalPoints += dealResult / 
                     dealVol * getAssetTick();
               glIndData.basicData.lossDealsTotalPointsForAllVol += dealResult * getAssetTick();
            }
         }
         else if (entry == DEAL_ENTRY_IN)
         {
            bool foundPosIDInArray = false;
            
            for (int bbb = 0; bbb < glIndData.basicData.positionCount; ++bbb)
            {
               if (positionIDs[bbb] == 0)
                  break;
                  
               if (positionIDs[bbb] == posID)
               {
                  foundPosIDInArray = true;
                  
                  break;
               }
            }
            
            if (!foundPosIDInArray)
            {
               positionIDs[glIndData.basicData.positionCount] = posID;
               
               ++glIndData.basicData.positionCount;
            }
         }
      }
      else
         Print("Error getting deal from position ",aaa
               ," (error code: ",GetLastError(),")");
   }
   
   if (glIndData.basicData.profitDealsVolume > 0.0)
   {
      glIndData.basicData.profitDealsTotalByVol = glIndData.basicData.profitDealsTotal 
            / glIndData.basicData.profitDealsVolume;
      //glIndData.basicData.profitDealsTotalPoints = glIndData.basicData.profitDealsTotalByVol * getAssetTick();
   }
   else
   {
      glIndData.basicData.profitDealsTotalPoints = 
      glIndData.basicData.profitDealsTotalByVol = 0.0;
   }
      
   if (glIndData.basicData.lossDealsVolume > 0.0)
   {
      glIndData.basicData.lossDealsTotalByVol = glIndData.basicData.lossDealsTotal 
            / glIndData.basicData.lossDealsVolume;
      //glIndData.basicData.lossDealsTotalPoints = glIndData.basicData.lossDealsTotalByVol * getAssetTick();
   }
   else
   {
      glIndData.basicData.lossDealsTotalPoints =
      glIndData.basicData.lossDealsTotalByVol = 0.0;
   }
   
   //
   double posResult;
   ArrayResize(glIndData.basicData.allPosResults,glIndData.basicData.positionCount);
   
   for (int aaa = 0; aaa < glIndData.basicData.positionCount; ++aaa)
   {
      if (!HistorySelectByPosition(positionIDs[aaa]))
      {
         Print("Error selecting position with ID ",positionIDs[aaa]
               ," (error code: ",GetLastError(),")");
         
         continue;
      }
      
      const int allDealsFromPosCount = HistoryDealsTotal();
      posResult = 0.0;
      
      for (int bbb = 0; bbb < allDealsFromPosCount; ++bbb)
      {
         if ((ticket = HistoryDealGetTicket(bbb)) > 0)
         {
            if (glInputs.magicNumberFilt > 0 
                  && HistoryDealGetInteger(ticket,DEAL_MAGIC) != glInputs.magicNumberFilt)
               continue;
            
            if (HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT)
            {
               posResult += HistoryDealGetDouble(ticket,DEAL_PROFIT);
            }
         }
         else
            Print("Error getting position's deal from position ",bbb
                  ," (error code: ",GetLastError(),")");
      }
      
      glIndData.basicData.allPosResults[aaa] = posResult;
      
      if (glIndData.basicData.allPosResults[aaa] > 0.0)
      {
         ++glIndData.basicData.profitPositionCount;
      }
      else if (glIndData.basicData.allPosResults[aaa] < 0.0)
      {
         ++glIndData.basicData.lossPositionCount;
      }
   }
}

Probably there are some variables that are not declared, but I suppose their names will be sufficiently indicative of their meaning and anybody wanting an example of how to get close position data will be able to understand it. I also let some code with examples on how one may use the information. I hope it may help someone.

Reason: