• Home
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • Join
  • User/Email: Password:
  • 2:33pm
Menu
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • Join
  • 2:33pm
Sister Sites
  • Metals Mine
  • Energy EXCH
  • Crypto Craft

Options

Bookmark Thread

First Page First Unread Last Page Last Post

Print Thread

Similar Threads

Need help with arrays and arraysort 8 replies

Multidimensional Arrays in MQL4 1 reply

Dynamic Multidimensional Arrays 17 replies

Functions on a Multidimensional array? 2 replies

Can arrays be boolean variables? 2 replies

  • Platform Tech
  • /
  • Reply to Thread
  • Subscribe
Tags: Help understanding multidimensional arrays, ...?
Cancel

Help understanding multidimensional arrays, ...?

  • Post #1
  • Quote
  • First Post: Apr 14, 2008 2:27pm Apr 14, 2008 2:27pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Hello,

I'm trying to work on an EA that will help hedge open orders. I would like to be able to close only a portion of the hedge orders now and then - all the negative ones and as few positive ones as possible so as to close these down at break even or a small profit while keeping as many profitable hedge orders open as possible incase the move against my primary orders actually continues (therefore I don't want to close ALL hedge orders if price looks like it might be continuing the main trend until that is crystal clear).

However, I'm not sure how to easily work with the open orders. I would like to track these in a multidimensional array that I can sort by price, and then move up the array starting with the negative hedge orders and totaling the profit until it is breakeven or positive - then close only those orders down while keeping any additional hedge orders open.

But I'm not sure how to easily keep track of the values. Is there a way to easily store the order info (price, profit, ticket #) in a multidimensional array, that if sorted, will keep the info inline across the values? That is - if I sort the array on price, will it keep the ticket #'s associated with those prices?

Is there anywhere I can go that clearly talks about multidimensional arrays and sorting them, ... I've only seen info on sorting single arrays.

Or, if someone has code that can help do what I'm trying to do - I'd appreciate that as well.

Thanks for any input!
  • Post #2
  • Quote
  • Apr 14, 2008 3:39pm Apr 14, 2008 3:39pm
  •  pippero
  • | Joined Oct 2007 | Status: Trend following is for teens | 216 Posts
I saw an array sort function somewhere, but its for one dimensional arrays. another problem you'll have is that MQL4 is limited to 2 dimensions, so you wouldnt be able to store all order info in array

Two solutions:

1) code your own sorting function using many single dimension arrays

2) wait for MQL5 (its been announced) and its C-like structs
 
 
  • Post #3
  • Quote
  • Apr 14, 2008 4:20pm Apr 14, 2008 4:20pm
  •  Royce
  • | Joined Mar 2008 | Status: Member | 25 Posts
I think the best approach for you is to store ONLY the ticket number in a single dimension array. You can use the ticket number to access other aspects of the associated order and sort the ticket numbers by those aspects.

In the sorting example I gave another poster I store the ticket numbers in array, but then I sort those ticket numbers by their opening time instead of the ticket number itself. (In most cases ticket numbers have the same order as their open time but that is besides the point.) It is not a big leap to change that sorter to sort by order profit. The sorter function itself only needs a change on three lines.

On Line 61, the variable type of the temporary variables used to determine the correct order of two orders would need to be changed from datetime to double in order to accommodate a profit instead of a time. Lines 79 and 81 would need to be changed to acquire the order's profit via the OrderProfit() function instead of the order's open time as it does now. With those changes the sorter would sort the ticket numbers in the array by their associated profit instead of by their associated open time.

There is nothing stopping you from having several single dimension arrays of tickets each sorted by a different aspect of the associated order.

Take a peak at my post and see if it helps. I don't think you need multi-dimensional arrays or structs.

http://www.forexfactory.com/showthre...83#post1941883
 
 
  • Post #4
  • Quote
  • Apr 14, 2008 4:32pm Apr 14, 2008 4:32pm
  •  Royce
  • | Joined Mar 2008 | Status: Member | 25 Posts
I guess it also helps to understand the Trading function series.

In a nutshell OrderSelect accepts a ticket number (or position index) so as to place the selection focus on to a given order. The remaining functions operate on the selected order. That is why functions like OrderOpenTime and OrderProfit do not accept any parameters.. they alway return the associated value of whatever order currently has the selection focus.

That is also why attempting to keep multiple values associated with an order "in line" is un-necessary. You just need to store the ticket number and use the Trading function series to access the extra data.
 
 
  • Post #5
  • Quote
  • Apr 14, 2008 7:01pm Apr 14, 2008 7:01pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Thanks Royce, I'll look over your code to get an idea of what I could do.

One question - since the ticket# is an integer, is there any way to use it as the index value in an array, or does each array index have to start with 0 and be sequential? - If so, it could potentially store the price and the ticket in one array... Just a thought.
 
 
  • Post #6
  • Quote
  • Apr 15, 2008 10:56am Apr 15, 2008 10:56am
  •  Royce
  • | Joined Mar 2008 | Status: Member | 25 Posts
Quoting donjames
Disliked
Thanks Royce, I'll look over your code to get an idea of what I could do.

One question - since the ticket# is an integer, is there any way to use it as the index value in an array, or does each array index have to start with 0 and be sequential? - If so, it could potentially store the price and the ticket in one array... Just a thought.
Ignored
Arrays in MQL4 have to be sequential and have to start at zero. The array is a very low level mechanism. Other languages have higher level data types called variously "map", "dictionary", "table", etc, that allow you to index array-like memory spaces with non-sequential or even non-numeric indexes. However, they are doing a lot of work in the background to translate such indexes into real indexes.
 
 
  • Post #7
  • Quote
  • Apr 15, 2008 10:58pm Apr 15, 2008 10:58pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Royce, in your code you use:

#define MAXTICKETS 20
//declare a module wide array of 20 integers that we'll used to store and sort tickets
int tickets[MAXTICKETS];

That seems to be okay. But is it possible for MAXTICKETS in this case to be an external variable (ie. for instance - if I wanted to set a maximum number of orders that can be open, but wanted to easily change it for testing rather than hardcoding it as a definition). In other words if I use:

int MAXTICKETS=20;
//declare a module wide array of 20 integers that we'll used to store and sort tickets
int tickets[MAXTICKETS];

I get an error saying "MAXTICKETS: integer number expected" Can you only use a variable if it's a definition?
 
 
  • Post #8
  • Quote
  • Apr 15, 2008 11:10pm Apr 15, 2008 11:10pm
  •  phy
  • | Joined Nov 2007 | Status: Member | 113 Posts
Quoting donjames
Disliked


int MAXTICKETS=20;

//declare a module wide array of 20 integers that we'll used to store and sort tickets

int tickets[MAXTICKETS];

I get an error saying "MAXTICKETS: integer number expected" Can you only use a variable if it's a definition?
Ignored
Do this:

int MAXTICKETS = 20;

int tickets[];
ArrayResize(tickets, MAXTICKETS);
 
 
  • Post #9
  • Quote
  • Apr 16, 2008 9:47am Apr 16, 2008 9:47am
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Thanks Phy, that worked.
 
 
  • Post #10
  • Quote
  • Apr 17, 2008 3:21pm Apr 17, 2008 3:21pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Okay, new problem. I revised the SortTickets function Royce provided earlier so I could pass info to it and retrieve a new array of ticket numbers as follows:
Inserted Code
[indent]void AcquireTickets(int MagicNumber, int MaxTickets) {
   int ticket_count = 0;
   //Erase the array of tickets and re-load based on our filters
   int tickets[];
   ArrayInitialize(tickets, -1);
   for(int idx=OrdersTotal()-1; idx >= 0; idx--) {
      if (OrderSelect(idx, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderMagicNumber()==MagicNumber) { 
            tickets[ticket_count] = OrderTicket();
            ticket_count++;
            if (ticket_count == MaxTickets) break;  //the array is full!
         }
      }
   }
   return tickets;
}

[/indent]My goal is to be able to apply different magic numbers to different types of trades (long/short, trend/hedge, etc.). Therefore, I want to pass a magic number and the max # of open orders for that type of trade (MaxTickets) and easily obtain an array of tickets for that magic number that I could then use elsewhere in the program.


However, I have a problem with the variables - it keeps saying that the following variables are not defined even though they get defined within the function or passed to it: MagicNumber, ticket_count, MaxTickets

It seems it is treating the for statement as a function as well and so it is not accepting the variables if they were not set in the for statement.

How do you resolve something like this - make them Global Variables? Thanks.
 
 
  • Post #11
  • Quote
  • Edited 4:06pm Apr 17, 2008 3:27pm | Edited 4:06pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Oh - forgot, 2 other issues:

(1) I get a "Function definition unexpected" error. Is there a particular place you have to put a function? I've tried placing it in different areas of the EA. Currently, it is in the int init() section.

(2) If I set the variables to be passed as global variables, is there any reason to pass them anymore? In other words, if using 2 different hedge magic numbers, do I have to have 3 variables to make this work:

LongMagicNumber
ShortMagicNumber
FunctionMagicNumber - used in the function

and in the EA, I set FunctionMagicNumber to be either the LongMagicNumber or ShortMagicNumber depending on which one I'm trying to work with?

Any help is appreciated. Thanks!
 
 
  • Post #12
  • Quote
  • Apr 17, 2008 5:12pm Apr 17, 2008 5:12pm
  •  Royce
  • | Joined Mar 2008 | Status: Member | 25 Posts
A few things:

1. You can not define a function within another function. init() is a function like any other, even though MT4 pre-defines it and tries to call a function by that name at startup. That is what the unexpected function definition error message is about. Move the definition to be before or after any other function instead of nested within.

2. In your revised AcquireTicks you have moved (or duplicated) the tickets array declaration to be inside your function. Tickets was intended to be a module wide variable. As a module wide variable no function need declare the variable in order to reference it.

Variables that are declared inside a function or as (normal) parameters are temporary variables. When the function completes those variables are erased. If you declare a variable/parameter inside a function with the same name as a module wide variable, then the module wide variable will become 'hidden' while the CPU is inside the function. All references to that name will go the local version that will be erased when the function ends.

This is generally known as variable scope. In regular C, module wide variables would typically be called global variables, but since MT4 has an alternate use for the term Global Variable it is better to say "module wide" to avoid confusion.

You are correct that if you make your parameters module wide variables, that there is no need to pass them to the function. However, your function becomes tied to those module variables and can't be copied without also copying the module variables. The idea is to weigh the short term development convenience of module variables vs. the long term maintenance of the code as well as its re-usability.

Try to apply some of the above to your code and see how much further you can get.
 
 
  • Post #13
  • Quote
  • Edited 6:44pm Apr 17, 2008 6:23pm | Edited 6:44pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Hi Royce,

I moved the function out of the other function, still had the same error. Then I scanned my program and found I was missing a closing } elsewhere. That seemed to solve the problem regarding the function not being recognized.

However, I am getting errors regarding my return tickets; statement.
'tickets' - left parenthesis expected
'tickets' - semicolon expected

If I want to pass the tickets array back to where I called the function, how would I do that?

Another issue related to this is that on the line in my EA that calls the function, I'm trying to put the tickets array into different arrays depending on the type of trade. For example:

MagicNumber = HedgeMagicNumber;
MaxTickets = MaxHedgeOrders;
tickets[] = AcquireTickets();
HedgeTickets[] = SortTicketsByPrice(); // SORT IN ASCENDING PRICE

Here, I first set the magic # and the max tickets for hedge orders and then I am trying to set the tickets array (which is used in the both functions here) to the resulting array with the tickets for the particular magic number. Then I want to establish a new array HedgeTickets that is the result of sorting these tickets. I will do the same type of thing for "trend orders". Then once I have these in arrays, I will manage them as I desire.

But right now, I am getting errors stating ']' wrong dimension because the [] are empty. However, I certainly don't want to use 1 element here because it is an array - not just 1 value. Also, if I remove the [], I get the error '=' - left square parenthesis expected for array. Any ideas on how I solve this?

Thanks.
 
 
  • Post #14
  • Quote
  • Apr 17, 2008 8:23pm Apr 17, 2008 8:23pm
  •  Royce
  • | Joined Mar 2008 | Status: Member | 25 Posts
I forgot the return syntax deal. I fixed it in my copy but then forget to mention it. The return argument absolutely positively has to be surrounded by parenthesis. Or, it is a syntax error. It is just an annoyance of the language caused by still-yet-another-and-beyond-and-beyond-again re-re-re-invention of a C-language parser.

Anyway, if you would like to have a function work on an array that varies by caller, the easiest thing to do is pass the array "by reference". This is a special mode of argument passing where by instead of the usual copy-of-variable-that-ultimately-gets-erased, you pass a description of how to get to the original variable itself. When you pass arguments in this way, any changes that the function makes to the "by reference" arguments will be intact after the function completes. This is completely independent of any return value for the function.

Here is an example function definition where an array is passed as an argument "by reference" and two other arguments are passed "by value" (e.g copied):

bool ModifyTakeProfits(int& tickets[], double new_takeprofit, int last_level){...

The key is the '&' after the array's variable type. That means "by reference". That also means that any changes to the tickets array during the function will be reflected in the array that was originally passed in to the function, after the function returns. This is true even though the only 'formal' return value of the function is a simple bool.

Here is a couple of example calls of that function:
ModifyTakeProfits(tickets, takeprofit, level - 1);
ModifyTakeProfits(other_tickets, takeprofit, level - 1);

In the first call the tickets array will be modified, but in the second a different array, other_tickets, will be changed instead.

This pattern works for non-array types as well. Your code might be a little more confusing if you use a lot of 'bi-directional' arguments, but sometimes it just makes sense to work on the original version of something.

Let me know if that gets you a bit closer to your goal.
 
 
  • Post #15
  • Quote
  • Edited 11:53am Apr 18, 2008 12:23am | Edited 11:53am
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
Well, I tried that and I'm not sure if it's working or not. I created a simple test script that has the functions to acquire tickets and sort them (modified slightly). It seems like the program will pass the ticket numbers so as to display them on the Strategy Tester screen, but it doesn't actually seem to sort them. I am trying to sort by the open price. But it simply displays the values as if it's sorting by the Ticket Numbers (and it always seems to have the last ticket # in the first position [0]), not ordering the ticket numbers by price. If you look at the price of each order (in the strategy tester), though some might be the same since I didn't put any restrictions on entering the order, several will be different - and these should get sorted in ascending price.

Inserted Code
 
extern int SlippageAmt = 3;
extern string TrendType = "B";
extern int TrendMagicNumber = 111111;
extern int MaxTrendOrders = 5;
int Ticket;
//DECLARE ARRAYS & ASSOCIATED VARIABLES
int TrendTickets[];
int tickets[];
int MagicNumber;
int MaxTickets;
int ticket_count = 0;
double TrendTicketPrice[];
int TrendTicketNumber[];
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
   // RESIZE TICKET ARRAYS BASED ON MAX ORDERS ALLOWED
      ArrayResize(TrendTickets, MaxTrendOrders);
      ArrayResize(tickets, MaxTrendOrders);
      ArrayResize(TrendTicketPrice, MaxTrendOrders);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
 
//----
   return(0);
  }
 
 
//**** FUNCTIONS
   //This function scans all orders with the given MagicNumber and returns the array tickets
   int AcquireTickets(int& tickets[]) {
      ticket_count = 0;
      //Erase the array of tickets and re-load based on our filters
      ArrayInitialize(tickets, -1);
      for(int idx=OrdersTotal()-1; idx >= 0; idx--)
      {
         if (OrderSelect(idx, SELECT_BY_POS, MODE_TRADES))
         {
            if (OrderMagicNumber()==MagicNumber) { 
               tickets[ticket_count] = OrderTicket();
               ticket_count++;
               if (ticket_count == MaxTickets) break;  //the array is full!
            }
 
         }
      }
      return (tickets);
   }  // END FUNCTION
 
   // ****** SORT TICKETS BY ASCENDING PRICE FUNCTION
   double SortTicketsByPrice(int& tickets[]) 
   {
 
      bool finished = false;
      int idx;
      int ooo_ticket;
      datetime openA, openB;
 
      //keep looping until we can't find any tickets out of order
      while(finished == false)
      {
         //limited scope variable. doesn't exist outside while loop and is re-init each loop
         bool found_out_of_order = false;
 
         //loop over the tickets array up to the next to last element or the first -1
         for(idx=0; idx < (MaxTickets - 1); idx++)
         {
            //look for -1's and assume we've reached the end of good data in the array      
            if (tickets[idx] == -1 || tickets[idx + 1] == -1) break;
 
            //collect the open prices for the current ticket in the array and the next one
            OrderSelect(tickets[idx], SELECT_BY_TICKET, MODE_TRADES);
            openA = OrderOpenPrice();
            OrderSelect(tickets[idx + 1], SELECT_BY_TICKET, MODE_TRADES);
            openB = OrderOpenPrice();
 
            //determine if the tickets are out of order
            if (openA > openB) {
               //swap the ticket numbers
               ooo_ticket = tickets[idx];
               tickets[idx] = tickets[idx+1];
               tickets[idx+1] = ooo_ticket;
               found_out_of_order = true;
            }
         }  // END FOR STATEMENT
 
         //If we made it though the entire array with out finding any thing that is
         //out of order then we can delcare ourselves finished sorting.
         if (found_out_of_order == false) finished = true;    
      }  // END WHILE STATEMENT
      return (tickets);
   }  // END FUNCTION
 
 
 
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//---- 
 
// PLACE 5 TEST ORDERS 
   if(OrdersTotal()<5) {
      Ticket=OrderSend(Symbol(),OP_BUY,1,Ask,SlippageAmt,0,0,"Test",TrendMagicNumber,0,Green);
   }
 
// CHECK IF FUNCTIONS TO GET TICKETS AND SORT THEM ARE WORKING 
 
   AscendingOrder = true;
   MagicNumber = TrendMagicNumber;
   MaxTickets = MaxTrendOrders;
   AcquireTickets(TrendTickets);
   SortTicketsByPrice(TrendTickets); // SORT IN ASCENDING PRICE
 
   // GET OPEN ORDER PRICES FOR TICKETS:
 
      for(int i=0; i<ArraySize(TrendTickets); i++) {
         OrderSelect(TrendTickets[i], SELECT_BY_TICKET, MODE_TRADES);
         TrendTicketPrice[i] = OrderOpenPrice();
      }
 
 
   Comment("TEST TICKET FUNCTIONS: ",Symbol(),"\n",
           "TrendTickets[0] = ", TrendTickets[0], "   Price[0] = ", TrendTicketPrice[0],"\n",
           "TrendTickets[1] = ", TrendTickets[1], "   Price[1] = ", TrendTicketPrice[1],"\n",
           "TrendTickets[2] = ", TrendTickets[2], "   Price[2] = ", TrendTicketPrice[2],"\n",
           "TrendTickets[3] = ", TrendTickets[3], "   Price[3] = ", TrendTicketPrice[3],"\n",
           "TrendTickets[4] = ", TrendTickets[4], "   Price[4] = ", TrendTicketPrice[4]);
//----
   return(0);
  }
 
//+------------------------------------------------------------------+


I even tried changing "openA > openB" to "openA < openB" to see if it would reverse the sorting - and it produced the same result. Any ideas?
 
 
  • Post #16
  • Quote
  • Last Post: Apr 18, 2008 12:08pm Apr 18, 2008 12:08pm
  •  donjames
  • | Joined Sep 2006 | Status: Member | 27 Posts
I figured out why it wasn't sorting according to price - the openA and openB were set to datetime type, but for price, I needed to set it to double type.
 
 
  • Platform Tech
  • /
  • Help understanding multidimensional arrays, ...?
  • Reply to Thread
0 traders viewing now
Top of Page
  • Facebook
  • Twitter
About FF
  • Mission
  • Products
  • User Guide
  • Media Kit
  • Blog
  • Contact
FF Products
  • Forums
  • Trades
  • Calendar
  • News
  • Market
  • Brokers
  • Trade Explorer
FF Website
  • Homepage
  • Search
  • Members
  • Report a Bug
Follow FF
  • Facebook
  • Twitter

FF Sister Sites:

  • Metals Mine
  • Energy EXCH
  • Crypto Craft

Forex Factory® is a brand of Fair Economy, Inc.

Terms of Service / ©2023