Duplicate values in Dynamic Array after ArraySort()

 

Hi Guys - I'm struggling with something that should be really simple and I'm not sure what I am doing wrong here.

I have 2 simple Dynamic Arrays. 

The first one stores a list of all my "Winning" (positive) trades and works fine after I sort them (MODE-DESCENDING):

for(int i=NoTradesBest-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) >= 0)
            {
             BestPositionArray[i,0] = (OrderProfit() + OrderSwap() + OrderCommission());
             BestPositionArray[i,1] = OrderTicket();
             BestPositionArray[i,2] = OrderMagicNumber();
             ArraySort(BestPositionArray,WHOLE_ARRAY,0,MODE_DESCEND);
            }
   }

ArraySort(BestPositionArray,WHOLE_ARRAY,0,MODE_DESCEND);


...but then, the second Array that lists all my "Losing" trades gives me "Duplicate" values after a MODE-ASCENDING sort:

for(int i=NoTradesWorst-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) <= 0)
            {
             WorstPositionArray[i,0] = (OrderProfit() + OrderSwap() + OrderCommission());
             WorstPositionArray[i,1] = OrderTicket();
             WorstPositionArray[i,2] = OrderMagicNumber();
             ArraySort(WorstPositionArray,WHOLE_ARRAY,0,MODE_ASCEND);
            }
   }
ArraySort(WorstPositionArray,WHOLE_ARRAY,0,MODE_ASCEND);


I've tried ArraySetAsSeries() and can't seem to find anything in the Documentation. Can someone please point me in the right direction here or explain why I am having this problem.

Thanks...

 

What duplicate values ?

Why are you sorting inside the loop ?

 
Alain Verleyen:

What duplicate values ?

Why are you sorting inside the loop ?

Hi Alain...

I've check the values in the Arrays and they are - Correct

What sent me on this tangent is that I convert the information from these Arrays into Objects (a small GUI on the main chart). Like this:


Looking at just the "Best" trades... 1. and 2. are both EURAUD.... but, if I put the Sort function inside the loop then it works fine...


...BUT... it does not matter what I do to the "Worst" trades....LMAO.....


Hehehhh... ok, so it must have something to do with the Object Labels... To get the Variables for the Object Labels I run this code:

for(int i=NoTradesBest-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) >= 0)
            {
             BestPositionArray[i,0] = (OrderProfit() + OrderSwap() + OrderCommission());
             BestPositionArray[i,1] = OrderTicket();
             BestPositionArray[i,2] = OrderMagicNumber();
            }
   }

ArraySort(BestPositionArray,WHOLE_ARRAY,0,MODE_DESCEND);

//--- Run Best Pair Calculations -------------------------------------------
if(NoTradesBest >=1)
   {
      for(int i=OrdersTotal()-1; i>=0; i--)
         {
            if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
               && OrderTicket() == BestPositionArray[0,1])
                  {
                   PairText = OrderSymbol();
                  }
         }
      
      Best1Pair = PairText;
      
      TFNumber = StringSubstr(DoubleToString(BestPositionArray[0,2]),0,2);
      Get_TimeFrame_Text();
      Best1TF = TFText;
      
      MANumber = StringSubstr(DoubleToString(BestPositionArray[0,2]),4,3);
      Get_TMA_Text();
      Best1MA = MAText;
   }

Which gives me the variables to use when creating the Object Labels...

   string BestPair1 = "Roxy_BestTrade_Pair1";

      ObjectCreate(0,BestPair1,OBJ_LABEL,0,0,0,0,0);
         ObjectSet(BestPair1,OBJPROP_CORNER,CORNER_LEFT_UPPER);
         ObjectSetInteger(0,BestPair1,OBJPROP_ANCHOR,ANCHOR_CENTER);
         ObjectSet(BestPair1,OBJPROP_XDISTANCE,65*ChartCoeff);         
         ObjectSet(BestPair1,OBJPROP_YDISTANCE,205*ChartCoeff); 
         ObjectSetInteger(0,BestPair1,OBJPROP_BACK,false);
         ObjectSetInteger(0,BestPair1,OBJPROP_ZORDER,100);
         ObjectSet(BestPair1,OBJPROP_HIDDEN,true);
         ObjectSetText(BestPair1,Best1Pair+"   "+"$'"+NormalizeDouble(B1,2),Text9,"Cambria",Gray);


   string BestValue1 = "Roxy_BestTrade_Value1";

      ObjectCreate(0,BestValue1,OBJ_LABEL,0,0,0,0,0);
         ObjectSet(BestValue1,OBJPROP_CORNER,CORNER_LEFT_UPPER);
         ObjectSetInteger(0,BestValue1,OBJPROP_ANCHOR,ANCHOR_CENTER);
         ObjectSet(BestValue1,OBJPROP_XDISTANCE,65*ChartCoeff);         
         ObjectSet(BestValue1,OBJPROP_YDISTANCE,220*ChartCoeff); 
         ObjectSetInteger(0,BestValue1,OBJPROP_BACK,false);
         ObjectSetInteger(0,BestValue1,OBJPROP_ZORDER,100);
         ObjectSet(BestValue1,OBJPROP_HIDDEN,true);
         ObjectSetText(BestValue1,Best1MA+"   "+Best1TF,Text9,"Cambria",Gray);

I'm thinking that deleting the Object Labels before Creating them again might work... but I remember years ago you told me that it was not necessary to "Delete" objects before creating them...

I'll play around with deleting the Labels... but if you do see anything wrong with the above code then please let me know and get me out of my misery....


Thanks

NOTE: There are currently only 2 trades open per Currency Pair (Symbol()) - 1 Long and 1 Short... so it is not possible for there to be 2 "winning" trades open on the same Symbol()...
 

It's hard to say anything useful from these snippets of code. I am wondering how is your array BestPositionArray is initialized and managed between each filling.

About the objects, you may need to call ChartRedraw() to update your chart.

 
Alain Verleyen:

It's hard to say anything useful from these snippets of code. I am wondering how is your array BestPositionArray is initialized and managed between each filling.

About the objects, you may need to call ChartRedraw() to update your chart.

I just declare the Array... I did not realize I had to "Initialize" it... 

//+------------------------------------+
//| Number of Best Trades              |
//+------------------------------------+
void No_Best_Trades()
{
NoTradesBest=0;
for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) > 0)
            {
             NoTradesBest += 1;
            }
   }
}




//+------------------------------------+
//| Populate Best Position Array       |
//+------------------------------------+
double B1,B2,B3,B4,B5,B6,B7,B8,B9,B10;
double BestPositionArray[][3];
void Populate_Best_Position_Array()
{
No_Best_Trades();

ArrayResize(BestPositionArray,NoTradesBest);

for(int i=NoTradesBest-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) >= 0)
            {
             BestPositionArray[i,0] = (OrderProfit() + OrderSwap() + OrderCommission());
             BestPositionArray[i,1] = OrderTicket();
             BestPositionArray[i,2] = OrderMagicNumber();
            }
   }

ArraySort(BestPositionArray,WHOLE_ARRAY,0,MODE_DESCEND);

//--- Run Best Pair Calculations -------------------------------------------
if(NoTradesBest >=1)
   {
      for(int i=OrdersTotal()-1; i>=0; i--)
         {
            if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
               && OrderTicket() == BestPositionArray[0,1])
                  {
                   PairText = OrderSymbol();
                  }
         }
      
      Best1Pair = PairText;
      
      TFNumber = StringSubstr(DoubleToString(BestPositionArray[0,2]),0,2);
      Get_TimeFrame_Text();
      Best1TF = TFText;
      
      MANumber = StringSubstr(DoubleToString(BestPositionArray[0,2]),4,3);
      Get_TMA_Text();
      Best1MA = MAText;
   }


//--- Run 2nd Best Pair Calculations -------------------------------------------
if(NoTradesBest >=2)
   {
      for(int i=OrdersTotal()-1; i>=0; i--)
         {
            if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
               && OrderTicket() == BestPositionArray[1,1])
                  {
                   PairText = OrderSymbol();
                  }
         }
      
      Best2Pair = PairText;
      
      TFNumber = StringSubstr(DoubleToString(BestPositionArray[1,2]),0,2);
      Get_TimeFrame_Text();
      Best2TF = TFText;
      
      MANumber = StringSubstr(DoubleToString(BestPositionArray[1,2]),4,3);
      Get_TMA_Text();
      Best2MA = MAText;
   }


//--- Run 3rd Best Pair Calculations -------------------------------------------
if(NoTradesBest >=3)
   {
      for(int i=OrdersTotal()-1; i>=0; i--)
         {
            if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
               && OrderTicket() == BestPositionArray[2,1])
                  {
                   PairText = OrderSymbol();
                  }
         }
      
      Best3Pair = PairText;
      
      TFNumber = StringSubstr(DoubleToString(BestPositionArray[2,2]),0,2);
      Get_TimeFrame_Text();
      Best3TF = TFText;
      
      MANumber = StringSubstr(DoubleToString(BestPositionArray[2,2]),4,3);
      Get_TMA_Text();
      Best3MA = MAText;
   }

if(NoTradesBest >= 1)   B1 = BestPositionArray[0,0];
if(NoTradesBest >= 2)   B2 = BestPositionArray[1,0];
if(NoTradesBest >= 3)   B3 = BestPositionArray[2,0];
if(NoTradesBest >= 4)   B4 = BestPositionArray[3,0];
if(NoTradesBest >= 5)   B5 = BestPositionArray[4,0];
if(NoTradesBest >= 6)   B6 = BestPositionArray[5,0];
if(NoTradesBest >= 7)   B7 = BestPositionArray[6,0];
if(NoTradesBest >= 8)   B8 = BestPositionArray[7,0];
if(NoTradesBest >= 9)   B9 = BestPositionArray[8,0];
if(NoTradesBest >= 10)  B10 = BestPositionArray[9,0];
}

ChartRedraw() did not help...

 
Mike Tanton:

I just declare the Array... I did not realize I had to "Initialize" it... 

ChartRedraw() did not help...

I don't see the problem.

If you need more help, please post the full code that I could compile and test.

 

Thanks Alain....

Let me see if I can work it out... I don't want to waste your time on this.... I'm comfortable that the Arrays are giving the correct results... the GUI data is just superficial.... so, I'll be able to live with this glitch....

But thanks...

MikeT

 

Ok, so... I'm still not 100% sure why the chart Object Labels were not keeping up with the code... but I solved the problem by simply "refreshing" the data after the functions in the code... so... it's now working...


I simply added this function...

//+--------------------------+
//| Refresh Roxy GUI         |
//+--------------------------+
void Refresh_Roxy_GUI()
{
ObjectSetText("Roxy_Today_PL_Value",DoubleToStr(TodayPL,2),Text14,"Cambria",Goldenrod);
ObjectSetText("Roxy_Today_%_Value",DoubleToStr(TodayPercent,1)+" %",Text12,"Cambria",Gray);

ObjectSetText("Roxy_BestTrade_Pair1",Best1Pair+"   "+"$'"+NormalizeDouble(B1,2),Text9,"Cambria",Gray);
ObjectSetText("Roxy_BestTrade_Pair2",Best2Pair+"   "+"$'"+NormalizeDouble(B2,2),Text9,"Cambria",Gray);
ObjectSetText("Roxy_BestTrade_Pair3",Best3Pair+"   "+"$'"+NormalizeDouble(B3,2),Text9,"Cambria",Gray);

ObjectSetText("Roxy_WorstTrade_Pair1",Worst1Pair+"   "+"$'"+NormalizeDouble(W1,2),Text9,"Cambria",Gray);
ObjectSetText("Roxy_WorstTrade_Pair2",Worst2Pair+"   "+"$'"+NormalizeDouble(W2,2),Text9,"Cambria",Gray);
ObjectSetText("Roxy_WorstTrade_Pair3",Worst3Pair+"   "+"$'"+NormalizeDouble(W3,2),Text9,"Cambria",Gray);
}

After the Array calculations...

Populate_Best_Position_Array();
Populate_Worst_Position_Array();

Refresh_Roxy_GUI();

Seems to be ok now....

 

I wonder... when you obtain a value for NoTradesBest here:

void No_Best_Trades()
{
NoTradesBest=0;
for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) > 0)
            {
             NoTradesBest += 1;
            }
   }
}

and use it here:

for(int i=NoTradesBest-1; i>=0; i--)
   {
      if(   OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true
         && ((OrderProfit() + OrderSwap() + OrderCommission())) >= 0)
            {
             BestPositionArray[i,0] = (OrderProfit() + OrderSwap() + OrderCommission());
             BestPositionArray[i,1] = OrderTicket();
             BestPositionArray[i,2] = OrderMagicNumber();
            }
   }
So if you have 10 orders in total and 5 winners - e.g. 0, 3, 4, 7, 9, and in your second loop, you're using OrderSelect() with 0 to 4, so you'll only find winners 0, 3 and 4, and skipped 7 and 9... isn't that a problem?


 
Seng Joo Thio:

I wonder... when you obtain a value for NoTradesBest here:

and use it here:

So if you have 10 orders in total and 5 winners - e.g. 0, 3, 4, 7, 9, and in your second loop, you're using OrderSelect() with 0 to 4, so you'll only find winners 0, 3 and 4, and skipped 7 and 9... isn't that a problem?


Hi Seng... I think your math is a little bit wrong...

Using your eg. running the first loop will give NoTradesBest = 5 (5 winning trades ie. >$0)

Running the second loop using NoTradesBest  is still equal to 5 (5 winning trades ie. >$0)... but,

I need to run the "first" loop to determine how many positive trades there are... because this determines the size of the Dynamic Array  BestPositionArray[][3] - which is used in the 2nd loop

If that makes any sense to you...

 
Mike Tanton:

Hi Seng... I think your math is a little bit wrong...

Using your eg. running the first loop will give NoTradesBest = 5 (5 winning trades ie. >$0)

Running the second loop using NoTradesBest  is still equal to 5 (5 winning trades ie. >$0)... but,

I need to run the "first" loop to determine how many positive trades there are... because this determines the size of the Dynamic Array  BestPositionArray[][3] - which is used in the 2nd loop

If that makes any sense to you...

Seng is right, I don't know if it's the answer to your initial question, but it's a bug without a doubt.
Reason: