sorting 2 dimensional array by second dimension

 

I have 2 pieces of data that I need to put into an array, then sort it.

First I split the orders into two arrays the first array is for buys the other is for sells. When I do so, I am collecting the OrderTicket so later I can perform an execution on the order. The second thing I am collecting is the OrderClosePrice value of the order so I can compare it to another list exactly the same.

So the first array I setup:

double AryBuys[][2];
double ArySells[][2];

AryBuy[1][0] contains the ticket, AryBuy[1][1] contains the price.

How do I sort the second dimension so that we have the array sorted by price descending?

Note: with ArraySort, you can only sort the first dimension. Here is a possible thought, I could create a temp array and make the price the first dimension in the temp array, sort it, then pipe it back to the array and do the same in reverse when I will later need to sort it by ticket. Would that work?

 

you can't, unfortunately, but you could create a second array with the data from the two dimension swapping places and sort that new array by price (the first dimension). You could then (if you still wanted to) copy the data back into the original array once again swapping the data in each dimension. Now your original array contains the original data but it is sorted by second dimension values.

it's kludgy but its the only practical way (that I've been able to figure out) to get your data sorted by dimensions >1

 

That is what I thought of in my notes. My concern was that the first dimension would get sorted, would it also rearrange the second dimension of data as well when the sort took place? I guess I could setup a test to try this out.

 
LEHayes wrote >>

That is what I thought of in my notes. My concern was that the first dimension would get sorted, would it also rearrange the second dimension of data as well when the sort took place? I guess I could setup a test to try this out.


Yes all elements of the same base index are moved with the first-dimension's sorting. Just like sorting a spreadsheet containing multiple columns of data, only in MQL you can only sort by the first column.
 

So far, I have gotten it set up as discussed. I am sure I will work this out by the time we finish the conversation, but currently getting:
2010.04.15 23:51:01,M1: incorrect start position 1 for ArraySort function
At first I tried it like this:
ArraySort(AryBuy,WHOLE_ARRAY,0,MODE_DESCEND);
and got the same message only the position value was 0, then I changed the start (position value) to 1 to see what might happen anbd I got the above.

The arrays should have data in them at this point. I am going to reset the test to see if the problem persists.

 
LEHayes:

.....
double AryBuys[][2];
double ArySells[][2];

AryBuy[1][0] contains the ticket, AryBuy[1][1] contains the price. ....

Correct me if I'm wrong but you seem to define and address the array incorrectly. Quoted from variable reference :

int    a[50];       // A one-dimensional array of 50 integers.
double m[7][50];    // Two-dimensional array of seven arrays,
                    //each of them consisting of 50 integers

the last pair of braces is the first dimension of the array... assuming the undefined size of the array is the first dimension. This is IMO the correct one:

double AryBuys[2][];
double ArySells[2][];

AryBuy[0][1] contains the ticket, AryBuy[1][1] contains the price. 
 
cameofx:
the last pair of braces is the first dimension of the array... assuming the undefined size of the array is the first dimension. This is IMO the correct one:

See also book...
FYI, I'm more comfortable naming the last pair of braces as 'first dimension' because the next dimension is added (although located more to the left) 'later'.
IMHO Regarding it as 'size of columns' also 'stick' better concept-wise.

 
cameofx:

FYI, I'm more comfortable naming the last pair of braces as 'first dimension' because the next dimension is added (although located more to the left) 'later'.

Regardless of what u would like to call it, the first dimension in a 2D array is the vector arr_name[0,1,...,n][0], so technically the first bracket holds the first dimension; this is also the vector that will be sorted by ArraySort(). From the book:

As long as we are on the subject of ArraySort() I'll mention 2 undocumented peculiarities I have found over time (and would be happy if anybody confirms or corrects me...?):

  1. If some of the elements in the first dimension are identical, they won't necessarily retain their order. Obviously this should be documented if it's 'by-design', otherwise I would consider this to be a 'bug'.
  2. OrderSort() does not work with 4D arrays (returns error 4053). Again, this should be documented but it's not.
 
cameofx wrote >>

Correct me if I'm wrong but you seem to define and address the array incorrectly. Quoted from variable reference :

the last pair of braces is the first dimension of the array... assuming the undefined size of the array is the first dimension. This is IMO the correct one:



I look at array indexing and dimensioning in the standard spreadsheet manner...Row-Column (mnemonic "Roman-Catholic").

1D Array: MyArray[RowNumber-1]

2D Array: MyArray[RowNumber-1][ColumnNumber-1]

3D Array: MyArray[RowNumber-1][ColumnNumber-1][Worksheet-1]

The leftmost set of brackets is the first dimension, everything you do that involves array manipulation of the first dimension will be done with the index of the leftmost set of brackets. Array resizing (something which can be done only to the 1st dimension) for example only changes the value of the left-most set of brackets, it cannot change the index range of the second, third or fourth dimensions (second, third, or fourth right-most set of brackets).

All my rows of data in the array are indexed by the first set of brackets, the leftmost set, and this is the "first dimension" of the array.

MyArray[0][ColumnNumber-1] -> first row of data

MyArray[1][ColumnNumber-1] -> second row of data

MyArray[2][ColumnNumber-1] -> third row of data

In MQL I can only sort by data contained in the first column of data...i.e. the values found in MyArray[i][0]. Values found in the same row (same "i" in this case) but different columns (the value in the second set of brackets) can not be used for sort/ranking.

Here is an example 2D array:

3 5
1 9
7 6

So MyArray[0][0] = 3, and MyArray[0][1] = 5, and MyArray[2][1] = 6, etc.

I can sort this array:

ArraySort(MyArray,WHOLE_ARRAY,0,MODE_ASCEND) and the result will be the following:

1 9
3 5
7 6

The first column is sorted, the second column of data (i.e. all the data with the same 1st dimension index) moves along with the sort/shift done in ranking the first column.

I cannot sort/rank the second column of data in MQL...meaning I CANNOT get the following (not directly anyways):

3 5
7 6
1 9

(note second column is now sorted smallest to largest)

To arrive at an array which has the second column (or any column other than the first column) sorted I must manually swap the data between columns (keeping the first dimension index the same but swapping the value of the second-dimension's index) and then sort and then swap the data back.

MyNewArray:
5 3
9 1
6 7

Now sort by first column, ArraySort(MyNewArray,WHOLE_ARRAY,0,MODE_ASCEND) and the result will be the following:

5 3
6 7
9 1

And then copy the values back into my original array once again transposing the index of the second dimension while keeping the value of the first dimension the same:

3 5
7 6
1 9

Now I have my original array but the data are sorted by the second column.

 

This whoole thing turned into a nightmare, I don't even remember if I attempted to persue it any further. The idea I had was to take the list of open trades, seperate the buys from the sells into 2 arrays, each array contained the ticket# in first column, the second contained the price value of the trade. In general the idea was to match all the large price buy values with all the large price sell values and if the highest buy value exceeded the highest sell value, then close both of those two trades and repeat the process.

Now the final hook that had me consider backing off of this idea was that after I went through this process, I wanted to leave at least 1 positive buy trade and 1 positive sell trade on the table to keep a hedged trading system going. This is basically being designed as a drawdown management tool for a hedging strategy. So I want to maintain the hedge, but take earnings off the table. It occured to me that using an array algorythm might provide a solution for this.

I am really tired and worn out from trying to push the release of about 5 strategies out the door, so this became a little of a nice-ity instead of a neccessity.

I am willing to make a deal with anyone who can write this function for me. I will give you your choice of products with a years license, for free for helping me out on this and too boot, I will give you a personal copy of this hedging strategy for free unlimited lifetime use. I am just too swamped to do it all and my dev team is heavily burdened with releasing what is already on our plates. I think the average sleep value across the team is about 4 to 6 hours a day.

So if you would be interested in a little barter and trade, that is my offer.

Objective:
1. Seperate the buys from the sells
2. sort each according to highest price value to lowest
3. If buy has highest positive prices and sell has lowest positive prices then we want to close the lowest sell trade with the highest buy trade, buy trade must exceed the expense of the sell trade. If sell has higher positive prices then we reverse this action to close the lowest buy price with the highest sell price. The idea is that for every loss, we close it with a higher prices win so that wins exceed losses with an average positive earning.

example:
buy sell
$15 $- 12
$5 $ - 6
$ 1.5 $ -1
$ 1 $ - .5

This shows a balanced number of open trades on both sides. Notice the $15 buy and $-12 sell, these can be closed because the positive buy exceeds the negative sell. We can also close the 5 and -6 because there is enough earnings from the first two closures that the balance between closing the 4 of them would result in a positive. We can do the same for the 1.5 and the -1, but we would not want to close the 1 and -.5 because we want to maintain the hedged situation.

majority of the time, the trades will not be balanced as equals on both sides. This was the basis of the design to offset the heaviest side with a higher lot size and additional trades in favor of the winning side, so it is possible that you may only have 1 sell, in which case, you would not do anything. In the event they are not balanced but there is at least 2 trades on each side, you need to make sure you leave a trade on each side open. In the event 1 positive trade outweighs more than 1 negative trade, you can close them all except for the one trade on each side that are the smallest to each other.

It should be designed to call a closing function that will close a specific ticketid, so you do not have to worry about the closure, just make the call to have the trades closed passing the ticketid. You might have to rebuild your list so that your list does not compare the closed trades but any new trades that may have occured during your processing.

Oh yeah, one more thing...
It should not be too greedy, you should provide a user extern that dictates how frequently this feature is to be fired, it can be based on a candle count or a hour or minute basis, but should not fire every tick or even every new candle. As it is there is an additional tool it will be embedded into that will first require that the other tool fires in order to invoke this one. So the other tool will fire, and the countdown will begin for your tool to fire.

 
Larry, I'm pretty sure the code for CloseBy() here -> https://book.mql4.com/trading/orderclose (it's about 2/3 down the page...) can be extended to do what u want (without using any arrays)... Just thought for your mind.
Reason: