stevehopwoodforex.com
https://www.stevehopwoodforex.com/phpBB3/
Print view

Multi-Dimensional Arrays
https://www.stevehopwoodforex.com/phpBB3/viewtopic.php?t=2874
Page 1 of 2
Author:  Radar [ Sat Aug 03, 2013 3:28 pm ]
Post subject:  Multi-Dimensional Arrays

Hey Gang,

I need to do a bunch of things with a 2-dimensional array, but have no idea how to go about it :(

What I want to do is a real pita, as most things are in mql4... This is a horrible, horrible way to do things, but I can't think of anything better:(

I need to store an indicator value in dimension1, and a ticket number in dimension2 and then...

1. Resize the array when...

a. Adding scale-in trades, and

b. Removing closed trades.

2. Determine the high/low/average of dimension1.

3. Backup the array to a file, in case of crashes of the EA/Empty4/Computer.

4. Restore the array from a file on restart.

Resizing the array is a snot, because mql4 adds to/removes from index0, whereas in this particular situation, you could have 5 trades open, and then trade3 (index2) will close, so instead of just resizing, I will have to read each trade from the array, then place it in a new array if it's still open, (resizing the new array isn't a problem, as it doesn't really matter how the orders are indexed in the array).

I guess I'll need to be able to access the array through different functions, such as...

void AddTradeToArray(double IndicatorValue, double TicketNumber)

double GetHighLowAverageOfArray(string Can'tWorkOutWhatGoesHere)

void RemoveClosedTradesFromArray(double TicketNumber)

void BackUpArrayToFile(string FileName)

void RestoreArrayFromFile(string FileName)

An example of how to create the array, and how to manipulate it using these functions, (and any others that you think would come in handy), with extremely verbose commenting,would be greatly appreciated, but type slooowly, as I am a very slow reader ;)

Take care,

&

Have fun!

Radar =8^)

edit... Worked it out... Semi-tutorial script here... http://www.stevehopwoodforex.com/phpBB3 ... 138#p73138
Author:  milanese [ Sat Aug 03, 2013 7:00 pm ]
Post subject:  Re: Multi-Dimensional Arrays

Hi Radar,

maybe this thread would be helpfull for you... :)

http://www.forexfactory.com/showthread.php?t=165411

Cheers,

Tommaso
Author:  Radar [ Sun Aug 04, 2013 3:39 am ]
Post subject:  Re: Multi-Dimensional Arrays

Hey Tommaso,
milanese wrote:Hi Radar,

maybe this thread would be helpfull for you... :)

http://www.forexfactory.com/showthread.php?t=165411

Cheers,

Tommaso
Thanks for that :) I've had that one open in another tab for weeks, but it's too heavy for me at the moment :( I really need to learn it from scratch, as I can barely work out what to do with a single dimension array, and even that hurts my head :( ;)

Have fun!

Radar =8^)
Author:  dietcoke [ Wed Aug 07, 2013 3:07 pm ]
Post subject:  Re: Multi-Dimensional Arrays

Unfortunately, there are no shortuts here, MD arrays are tricky to get your head around.

Your best bet is to take alook at those EA's on the board which use them and then try and dissemble what is going on

Mr Long's 10.4 multipair a is a good one for this.

I've added some comments for you as well.
Radar wrote:Hey Gang,

I need to do a bunch of things with a 2-dimensional array, but have no idea how to go about it :(

What I want to do is a real pita, as most things are in mql4... This is a horrible, horrible way to do things, but I can't think of anything better:(

I need to store an indicator value in dimension1, and a ticket number in dimension2 and then...
I would actually index the ticket number as dimension 1. This is the dimension that is variable in an array of trades and so is the one that needs reindexing


1. Resize the array when...

a. Adding scale-in trades, and

b. Removing closed trades.
Personally, I would rebuild the array from scratch every time you open or close a trade and regardless on every new bar as well. You can do this by initialising the array and then looping through the open trades and adding the data back in, resizing the array as you process each open trade

2. Determine the high/low/average of dimension1.
You will need to write a function to do this. A couple of for loops will allow you to inspect each dimension 2 value and calculate the numbers you want

3. Backup the array to a file, in case of crashes of the EA/Empty4/Computer.
4. Restore the array from a file on restart.
No need if you follow previous advice



You've not specified what indicator you are using or how often you need to recalculate it whih may affect the above advice.
Author:  Radar [ Wed Aug 07, 2013 4:17 pm ]
Post subject:  Re: Multi-Dimensional Arrays

Hey DietCoke,

Thanks for the info :)

I've been trying to get Phil_Trade's daily system (here... http://www.stevehopwoodforex.com/phpBB3 ... f=5&t=1448 ) on an M15 chart... It uses a fixed Stochastic value to determine when to move SL to BE... I decided to try using relative stoch, rather than a fixed value, but since you can have multiple trades open at once, I wanted to put the stoch value and ticket number into a 2D array.

The reason I wanted to put the stoch value into D1 was laziness... You can get Max and Min from D1 with less coding, (and so, less confusion for me), though getting the average would mean a bit more coding. Having the ticket number in D2 was so I could clean out closed trades before grabbing the max or min stoch value.

I have a larger project in mind, which will require the ability to backup/restore multiple arrays, and thought that a simple(??) 2D array would be a good place to start. I guess it ain't so simple, considering that I can't even work out how to declare and initialize a 2D array yet ;)

I'll dig through Mr Long's 10.4 multipair, and see what I can learn from it, thanks ;) I've got 25 years until I retire, so there's plenty of time ;)

Have fun!

Radar =8^)
Author:  Radar [ Fri Aug 16, 2013 3:38 pm ]
Post subject:  Re: Multi-Dimensional Arrays

Hey Gang,

Well, I finally worked out how to git 'er done! :D

I put what I needed into a script, so I could test as I wrote... Lots of alerts to see what was happening as it happened, and a couple of functions, (void StoreTrades(double& MyArray[][], double TicketNo), and
void ClearClosedTrades(double& MyArray[][], string strSymbol, int nMagic)), which aren't used in the script, but I figured I'd put them in there, as someone might just be interested in how to do it, and a lot of comments along the way, to push the points into my head :)

Have a squizz, and if you see any errors in my assumptions or explanations, or can add some more (basic) array manipulation methods, please let me know, and I'll update the script and re-upload :)

Have fun!

Radar =8^)
Author:  milanese [ Fri Aug 30, 2013 10:27 am ]
Post subject:  Re: Multi-Dimensional Arrays

Hi Radar :)

Nice one, I will look through this weekend..

Cheers and have a nice weekend

Tommaso :)
Author:  snailbeard [ Thu Nov 07, 2013 7:29 am ]
Post subject:  Re: Multi-Dimensional Arrays

Hi Radar,

I hope you managed to get your project going!

If I could go back in time by a year I would tell myself to start working with as much code as possible in a DLL created using a better development environment and programming language.

I am being forced to use 3 dimensional arrays in a very awkward way
1 dimension per pair
1 dimesion per timeframe
1 dimesion for history

the reason for this is to make a number of functions more generic
and not to recalculate the same data every tick,
in particular
daily pivots, weekly pivots, Bollinger bands and zigzags

Example

Code: Select all

#define ZZMAXTIMEFRAMES 4
#define ZZTF_M15_IDX	0
#define ZZTF_H1_IDX	1
#define ZZTF_H4_IDX	2
#define ZZTF_D1_IDX	3

int arrZzIndexToTf[] = { PERIOD_M15, PERIOD_H1, PERIOD_H4, PERIOD_D1 };

int  ZZTrend[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double ZZBuffer[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double ZZHighMapBuffer[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double ZZLowMapBuffer[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double ZZTopBuffer[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double ZZBottomBuffer[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];
double  ZZChange[MAXPAIRS][ZZMAXTIMEFRAMES][ZZMAXIMUMBACKBARS];

//+------------------------------------------------------------------+
//| ZZTimeframeToIndex                                                   |
//+------------------------------------------------------------------+
int ZZTimeframeToIndex(int timeframe) {
	int index = ZZTF_M15_IDX;

	if( timeframe == PERIOD_H1)
		index = ZZTF_H1_IDX;
	else if( timeframe == PERIOD_H4)
		index = ZZTF_H4_IDX;
	else if( timeframe == PERIOD_D1)
		index = ZZTF_D1_IDX;
	return(index);
}

I did produce some code for shuffling two dimesional arrays
As I have produced so much code in mql generally I might be trapped in this hell forever

Here is some utility code which I hope no pour soul has to make use of:

Code: Select all


//+------------------------------------------------------------------+
//| bwaShiftArrayOfDoubles()                                                       |
//+------------------------------------------------------------------+
void bwaShiftArrayOfDoubles(double& arrData[])
{
   int size = ArraySize(arrData);

   for(int i1 = 0; i1 < size; i1++ )
   {
      int rIdxLast = size  - 1 -  i1;
      int rIdxPrev = rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
         
      arrData[rIdxLast] = arrData[rIdxPrev];
      if( rIdxPrev == 0 ) arrData[0] = 0;
      
   }
}

//+------------------------------------------------------------------+
//| bwaShift2DimArrayOfDoubles()                                                       |
//+------------------------------------------------------------------+
bool bwaShift2DimArrayOfDoubles(double& arrData[][], int dim1, int dim2)
{
   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
      return(false);

   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
      int rIdxPrev = rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         arrData[rIdxLast][i2] = arrData[rIdxPrev][i2];
         if( rIdxPrev == 0 ) arrData[0][i2] = 0;
      }
   }
   return(true);
}

bool bwaDump2DDoubleHistory(double& arr2DHist[][], int dim1, int dim2 )
{
   int maxsize = ArraySize(arr2DHist);
   if( (dim1 * dim2) > maxsize )
      return(false);
      
   string strLine = "dump2DHistory: dim1, dim2 :" + dim1 + ", " + dim2;
   Print(strLine);
   for(int i1 = 0; i1 < dim1; i1++ )
   {
      strLine = "";
      for(int i2 = 0; i2 < dim2; i2++ ) {
         strLine = strLine + DoubleToStr(arr2DHist[i1][i2],5) + ",  ";
      }
      Print( strLine );
   }
 return(true);
}
   
bool bwaDump2DIntegerHistory(int& arr2DHist[][], int dim1, int dim2 )
{
   int maxsize = ArraySize(arr2DHist);
   if( (dim1 * dim2) > maxsize )
      return(false);
      
   string strLine = "dump2DHistory: dim1, dim2 :" + dim1 + ", " + dim2;
   Print(strLine);
   for(int i1 = 0; i1 < dim1; i1++ )
   {
      strLine = "";
      for(int i2 = 0; i2 < dim2; i2++ ) {
         strLine = strLine + arr2DHist[i1][i2] + ",  ";
      }
      Print( strLine );
   }
  return(true);
}
//+------------------------------------------------------------------+
//| bwaShift2DimArrayOfInt()                                                       |
//+------------------------------------------------------------------+
bool bwaShift2DimArrayOfInt(int& arrData[][], int dim1, int dim2)
{
   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
      return(false);

   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
      int rIdxPrev = rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         arrData[rIdxLast][i2] = arrData[rIdxPrev][i2];
         if( rIdxPrev == 0 ) arrData[0][i2] = 0;
      }
   }
   return(true);
}

//+------------------------------------------------------------------+
//| bwaShift2DimArrayOfBool()                                                       |
//+------------------------------------------------------------------+
bool bwaShift2DimArrayOfBool(bool& arrData[][], int dim1, int dim2)
{
   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
      return(false);

   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
      int rIdxPrev = rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         arrData[rIdxLast][i2] = arrData[rIdxPrev][i2];
         if( rIdxPrev == 0 ) arrData[0][i2] = 0;
      }
   }
   return(true);
}

//+------------------------------------------------------------------+
//| bwaCompare2DimArrayOfDoubles()                                                       |
//+------------------------------------------------------------------+
bool bwaCompare2DimArrayOfDoubles(double& arrData[][], double& arrData2[][], int dim1, int dim2)
{
   bool bSuccess = true;
   bool bReport = false;

   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
      return(false);
      
   int size2 = ArraySize(arrData2);
   if( (dim1 * dim2) > size2 )
      return(false);

   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         if( arrData[rIdxLast][i2] != arrData2[rIdxLast][i2] ) 
         {
            bSuccess = false;
            if( bReport ) {
               Print("bwaCompare2DimArrayOfDoubles() : Arrays are different!!!");
               Print("index: " + rIdxLast + ", " + i2 + " : arrData: " + DoubleToStr(arrData[rIdxLast][i2],5) +  ", " +  ", arrData2 : " + DoubleToStr(arrData2[rIdxLast][i2],5)  );
            }
         }
      }
   }
   if( (bSuccess == false) &&  (bReport == true) )
      for( i1 = 0; i1 < dim1; i1++ )
         for( i2 = 0; i2 < dim2; i2++ ) 
            Print("index: " + i1 + ", " + i2 + " : arrData: " + DoubleToStr(arrData[i1][i2],5) +  ", " +  ", arrData2 : " + DoubleToStr(arrData2[i1][i2],5)  );
      
   return(bSuccess);
}

//+------------------------------------------------------------------+
//| bwaCompare2DimArrayOfInt()                                                       |
//+------------------------------------------------------------------+
bool bwaCompare2DimArrayOfInt(int& arrData[][], int& arrData2[][], int dim1, int dim2)
{
   bool bSuccess = true;
   bool bReport = false;

   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
   {
      Print("bwaCompare2DimArrayOfInt() : Array arrData[][] dimension error!");
      return(false);
   }   
   int size2 = ArraySize(arrData2);
   if( (dim1 * dim2) > size2 )
   {
      Print("bwaCompare2DimArrayOfInt() : Array arrData2[][] dimension error!");
      return(false);
   }
   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         if( arrData[rIdxLast][i2] != arrData2[rIdxLast][i2] ) 
         {
            bSuccess = false;
            if( bReport ) {
               Print("bwaCompare2DimArrayOfInt() : Arrays are different!!!");
               Print("index: " + rIdxLast + ", " + i2 + " : arrData: " +arrData[rIdxLast][i2] +  ", " +  ", arrData2 : " + arrData2[rIdxLast][i2]  );
            }
         }
      }
   }
   Print("bwaCompare2DimArrayOfInt(): No. of Ints compared: [" + i1 +"], [" + i2+"]");
   if( (bSuccess == false) &&  (bReport == true) )
      for( i1 = 0; i1 < dim1; i1++ )
         for( i2 = 0; i2 < dim2; i2++ ) 
            Print("index: " + i1 + ", " + i2 + " : arrData: " + arrData[i1][i2] +  ", " +  ", arrData2 : " + arrData2[i1][i2]  );
      
   return(bSuccess);
}

//+------------------------------------------------------------------+
//| testbwaShift2DimArrayOfDoubles()                                                       |
//+------------------------------------------------------------------+
void test_bwaShift2DimArrayOfDoubles()
{
   static double testDataIn[5][2] =
   {
      0.11, 0.12,
      0.21, 0.13,
      0.31, 0.14,
      0.41, 0.15,
      0.51, 0.16
   };
   
   static double testDataOut[5][2] =
   {
      0.0, 0.0,
      0.11, 0.12,
      0.21, 0.13,
      0.31, 0.14,
      0.41, 0.15
   };
   
   double arr1[5][2];
   ArrayCopy( arr1, testDataIn, 0, 0, WHOLE_ARRAY );
   
   bool bSuccess = bwaShift2DimArrayOfDoubles(arr1, 5, 2);
   if( bSuccess == false ) Print("Test Failed: testbwaShift2DimArrayOfDoubles()");
   
   bSuccess = bwaCompare2DimArrayOfDoubles( arr1,  testDataOut, 5, 2);
   if( bSuccess == false ) Print("Test Failed: testbwaShift2DimArrayOfDoubles()");

}

//+------------------------------------------------------------------+
//| bwaShiftArrayOfInts()                                                       |
//+------------------------------------------------------------------+
void bwaShiftArrayOfInts(int& arrData[])
{
   int maxsize = ArraySize(arrData);

   for(int i1 = 0; i1 < maxsize; i1++ )
   {
      int rIdxLast = maxsize  - 1 -  i1;
      int rIdxPrev =  rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
      arrData[rIdxLast] = arrData[rIdxPrev];
      if( rIdxPrev == 0 ) arrData[rIdxPrev] = 0;
      
   }
}

//+------------------------------------------------------------------+
//| bwaShift2DimArrayOfInts()                                                       |
//+------------------------------------------------------------------+
bool bwaShift2DimArrayOfInts(int& arrData[][], int dim1, int dim2)
{
   int maxsize = ArraySize(arrData);
   if( (dim1 * dim2) > maxsize )
   {
      Print( "ERROR! bwaShift2DimArrayOfInts() dim1 * dim2 > size! ");
      return(false);
   }

   for(int i1 = 0; i1 < dim1; i1++ )
   {
      int rIdxLast = dim1  - 1 -  i1;
      int rIdxPrev =  rIdxLast - 1;
      if( rIdxPrev < 0 )
         break;
         
      for(int i2 = 0; i2 < dim2; i2++ ) {
         arrData[rIdxLast][i2] = arrData[rIdxPrev][i2];
         if( rIdxPrev == 0 ) arrData[rIdxPrev][i2] = 0;
      }   
      
   }
   return(true);
}

//+------------------------------------------------------------------+
//| testbwaShift2DimArrayOfDoubles()                                                       |
//+------------------------------------------------------------------+
void test_bwaShift2DimArrayOfInt()
{
   static int testDataIn[5][2] =
   {
      11, 12,
      21, 13,
      31, 14,
      41, 15,
      51, 16
   };
   
   static int testDataOut[5][2] =
   {
      0, 0,
      11, 12,
      21, 13,
      31, 14,
      41, 15
   };
   
   int arr1[5][2];
   ArrayCopy( arr1, testDataIn, 0, 0, WHOLE_ARRAY );
   
   bool bSuccess = bwaShift2DimArrayOfInt(arr1, 5, 2);
   if( bSuccess == false ) Print("Test Failed: testbwaShift2DimArrayOfInt()");
   else {
      bSuccess = bwaCompare2DimArrayOfInt( arr1,  testDataOut, 5, 2);
      if( bSuccess == false ) Print("Test Failed: testbwaShift2DimArrayOfInt()");
      else Print("Test Passed: testbwaShift2DimArrayOfInt()");
   }
}
Author:  Radar [ Wed Nov 13, 2013 12:29 pm ]
Post subject:  Re: Multi-Dimensional Arrays

Hey snailbeard,

Sorry for the delay in replying... I haven't looked in here for a few weeks.

It'll take me a while to work out what you're doing there, as I"m still getting to grips with with the basics of programming ;)

I did come across a quicker solution to your shifting data in an array, though... Short version goes like this...

Code: Select all

void SomeFunctionThatWantsToAddDataToElementZeroOfAnArray()
{
   bwaShift3DimensionalArrayOfDoubles(ZZBuffer)
   ZZBuffer[0][0][0] = NewData;
}

void bwaShift3DimensionalArrayOfDoubles(double& arrData[][][])
{
   int size = ArrayRange(arrData);
   ArraySetAsSeries(arrData,true);
   ArrayResize(arrData,(size +1));
   ArraySetAsSeries(arrData,false);
   ArrayResize(arrData, size); // if you want the array to stay the original size.
}
ArraySetAsSeries(arrData,true) flips your array on its head, putting the data from element 0 into the highest element, and the data from the highest element into element 0. You then add one element, then use ArraySetAsSeries(arrData,false) to flip it back on its feet. You now have an empty element 0 ready for the next bit of data to be placed into it.

It works with both single and multi dimensional arrays, and would be much faster, too :) Just write shift functions for 1Dimensional up to 4Dimensional, ints, doubles, bools or strings, as needed, using the same body of code in each.

The user rangebound on forexfactory explains it better here... http://www.forexfactory.com/showthread. ... ost2878455

Hope that helps :)

All that testing of functions and dumping arrays... I wouldn't know where to start if I had to write something like that... It'll take me a few weeks of reading and re-reading just to almost understand what's happening in there... The "L" plate is very firmly affixed to my forehead ;)

Have fun!

Radar =8^)
Author:  Radar [ Thu Nov 14, 2013 10:00 am ]
Post subject:  Re: Shifting Data In An Array

Hey snailbeard,

Adding on to my previous post...

If you want to apply any indicator to data in an array, the array must have ArraySetAsSeries set to true...

If you need to resize the array to add new data at the beginning, use the following code...

Code: Select all

void ShiftDataInSeriesArray(double& MySeriesArray[])
{
   int size = ArrayRange(MySeriesArray, 0);
   ArraySetAsSeries(MySeriesArray, false);
   ArrayResize(MySeriesArray,(size + 1);
   ArraySetAsSeries(MySeriesArray, true);
   // ArrayResize(MySeriesArray, size);  // uncomment if you wish the array size to remain unchanged.
}
So, basically, whether you're using a series array or not, you set ArraySetAsSeries to the opposite status, then resize, then flip it back to shift all your data back by one element, and to get an empty element 0.

Have fun!

Radar =8^)
All times are UTC Page 1 of 2