Automatic Magic Number - page 4

 
cloudbreaker:

Got me thinking that it would be useful to document (very concisely):

1. Criteria for deciding to implement magic numbers

2. Criteria for deciding to use automated magic number generation

3. Criteria for deciding to implement a persistence layer

4. Criteria for deciding upon globals vs. file access for persistence

Brief, entirely personal responses...


(2) depends on any number of factors, including whether the user wants to be able to control the magic numbers so that they can use them as a way of grouping together the results from different strategies.

(3) is something I'd avoid if I could, but I almost never can (see 'extern variables and timeframe change?'). It would be nice if MT4 provided help in persisting and recovering the state of EAs. But it doesn't.

(4) leads to a fairly strong personal preference: I don't like globals. Users can delete them; the storage is limited to numbers; and the format of gvariables.dat is obscure. I much prefer files which, as a last resort if necessary, can be modified using a text editor.


- I've only got 8 posts left before I take a break for a little while.

I see you've hit the magic number. As least it's going to be warm where you are...

 

I've been working on this idea on and off, and I finally got it to do what I wanted. Here's a magic number generator that takes the ASCII code of the symbol, and adds it to the time frame and a custom code to generate a magic number that's unique to the timeframe, symbol, and EA. If I knew a way for the EA to read its own name, I would use the ASCII of that instead of the custom code. With that weakness, I think it fits the criteria above though - it would be just fine with a system crash because it would pick the same number it picked previously at system reboot. The weakness I could see is that it would pick duplicate magic numbers if trading more than one instance of the same EA on the same timeframe and symbol.

Here's what I have:

string GetSymbol=Symbol();
int MNSymbol,MNSymbolCalc,MagicNumber;
for(int a=0;a<6;a++)//turn the Symbol() into an ASCII string and add each character into MNSymbol
{
MNSymbolCalc=StringGetChar(GetSymbol, a);
MNSymbolCalc=((MNSymbolCalc-64)*(MathPow(10,(a))));//subtract 64 b/c ASCII characters start at 65, multiply result by the a-th power for neatness (unnecessary though)
MNSymbol = MNSymbol+MNSymbolCalc;
}
int MNPeriod=Period();

int MNEACode=100000;//Make this number different for each EA to prevent two different types of EA's choosing the same Magic Number
MagicNumber=MNSymbol+MNPeriod+MNEACode;

 

JT, yes... duplication 'issues' are stuff of nightmares ;)


Like you and I suspect many, the uniqueness issue is a constant recurring theme which gets attacked as and when, yet somehow never seems right !

My code published earlier in this thread has been replaced with below which may be of use (if for no other reason than for a good laugh :).

***Notice the EA name string available via call to builtin.

In efforts to make multi ccy,per there are local functions used. ie, got fed up with always coding same function header code to check for empty actuals: ccy,per

hence my use of _Symbol() and _Period(). Speed/size considerations imho, even on MT4 interpreter is just not worth the energies to get concerned with...

Anyway, maybe this gives food for thought...


my reasoning for doing below [and doc'd in function] is:

This is handy way to ensure that IF an EA stops on a CCY,PER that on re-running it later against same CCY,PER

it will generate identical giExpertId (aka, Magic#). Means it can resume managing outstanding trades in the pool...

Another named EA can run on same chart environment without fear of duplicating values.

Therefore, OrderPools will have tickets with an EA specific magic#, allowing per EA mapping of it's tickets only.


Your comment on >1 'same named' EA on same ccy,per is indeed an issue. I finally decided that HEY! get real... if I make this mistake then I deserve a kick up the rear for being so unthinking, lol

in the end, as shown on this thread, there are zillions of ideas/methods, each with their strengths and weaknesses.

it all gets down to getting [at least] one unique datum whenever an EA runs and that [to me] is the kernal issue.

I never thought much about EA/CT crash leading to restart and the can of worms regards picking up where left off. That is taken care of now, as long as the EA autogens it's EAid/magic# with data that is unique to it's R/T chart environment. It will always gen the same number...

oh well, have fun!


int iMakeExpertId (string sSymbol="",int iPeriod=EMPTY)
{

  return( iMakeHash(_Symbol(sSymbol),getPeriodStr(_Period(iPeriod)),WindowExpertName()) );

}//iMakeExpertId()
//
//
//


//+------------------------------------------------------------------+
//
int iMakeHash (string s1, string s2=EMPTYSTRING, string s3=EMPTYSTRING, string s4=EMPTYSTRING, string s5=EMPTYSTRING
			,string s6=EMPTYSTRING, string s7=EMPTYSTRING, string s8=EMPTYSTRING, string s9=EMPTYSTRING, string s10=EMPTYSTRING)
{
  /*
  Produce 32bit int hash code from  a string composed of up to TEN concatenated input strings.
  WebRef: http://www.cse.yorku.ca/~oz/hash.html
  KeyWrd: "djb2"
  FirstParaOnPage:
  "  Hash Functions
  A comprehensive collection of hash functions, a hash visualiser and some test results [see Mckenzie
  et al. Selecting a Hashing Algorithm, SP&E 20(2):209-224, Feb 1990] will be available someday. If
  you just want to have a good hash function, and cannot wait, djb2 is one of the best string hash
  functions i know. it has excellent distribution and speed on many different sets of keys and table
  sizes. you are not likely to do better with one of the "well known" functions such as PJW, K&R[1],
  etc. Also see tpop pp. 126 for graphing hash functions.
  "

  NOTES: 
  0. WARNING - mql4 strings maxlen=255 so... unless code changed to deal with up to 10 string parameters
     the total length of contactenated string must be <=255
  1. C source uses "unsigned [char|long]", not in MQL4 syntax
  2. When you hash a value, you cannot 'unhash' it. Hashing is a one-way process.
     Using traditional symetric encryption techniques (such as Triple-DES) provide the reversible encryption behaviour you require.
     Ref:http://forums.asp.net/t/886426.aspx subj:Unhash password when using NT Security poster:Participant
  //
  Downside?
  original code uses UNSIGNED - MQL4 not support this, presume could use type double and then cast back to type int.
*/
  string s = StringConcatenate(s1,s2,s3,s4,s5,s6,s7,s8,s9,s10);
  int iHash = 5381;
  int iLast = StringLen(s)-1;
  int iPos=0;

  while( iPos <= iLast )		//while (c = *str++)	[ consume str bytes until EOS hit {myWord! isn't C concise! Pity MQL4 is"!"} ]
  {
    //original C code: hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    iHash = ((iHash << 5) + iHash) + StringGetChar(s,iPos);		//StringGetChar() returns int
    iPos++;
  }
  return(MathAbs(iHash));
}//iMakeHash()
 
fbj:
  NOTES: 
  0. WARNING - mql4 strings maxlen=255 so... unless code changed to deal with up to 10 string parameters
     the total length of contactenated string must be <=255

Although I personally prefer manual setting of magic number, your solution is quite elegant. Nice code.


One correction - string constants have max length of 255, string variables can be much larger, see -> https://www.mql5.com/en/forum/123551.

 

Thanks Gordon, the code appears to work ok, but in the end is certainly not bullet proof should I run same EA on same chart environment - so yes... manually setting of magic# is the ultimate foolproof method - no doubt about it!


For me strings have always been a pain in the rear. Yet, most anything is possible via say incrementally building up a set of tools, each utilizing functionalities of lower level tools.

Additionally, I remember irusoh1 saying/reminding one that 'this is it' so live with it... Well, for me, I always remember that first para in his post contents and is *always* in my mind whenever get to point with MT where loose will to live :))


The MQL4 online/offline talks about basic data types. The string link in both goes to string constants and we all know what that doc page says... ie, 255bytes.

I completely understand what you are saying yet the 29373 thread is, as is the MQL4 runtime handling of strings, inconclusive and as jjc and no doubt many others have experienced - somewhat iffy

Cannot locate any documentation to support full utilization of the 8byte struct's format, should there be documentation to support longer strings, would be of interest.

Anyway, I have in the past had unsolvable issues using strings so I just prefer to stick to what the docs say and work around it - if need to.

 
fbj:

The MQL4 online/offline talks about basic data types. The string link in both goes to string constants and we all know what that doc page says... ie, 255bytes.

I completely understand what you are saying yet the 29373 thread is, as is the MQL4 runtime handling of strings, inconclusive and as jjc and no doubt many others have experienced - somewhat iffy

Cannot locate any documentation to support full utilization of the 8byte struct's format, should there be documentation to support longer strings, would be of interest.

Anyway, I have in the past had unsolvable issues using strings so I just prefer to stick to what the docs say and work around it - if need to.

Sticking to max 255 is obviously the safe solution, although I have quite a lot of code that ignores this limit and I've never run into any problems. But then again this code is mostly non-critical.

I know the documentation is a bit unclear about this subject, but if u try to browse the Russian forums (with Google translate) I remember reading an official comment by one of the moderators that string variables do support more than 255bytes, but I can't seem to find it now... Oh well, I guess "this is it" and we have to live with it :)

 
fbj:

Cannot locate any documentation to support full utilization of the 8byte struct's format, should there be documentation to support longer strings, would be of interest.

Anyway, I have in the past had unsolvable issues using strings so I just prefer to stick to what the docs say and work around it - if need to.

" The length of a string constant lies between 0 and 255 characters. If the string constant is longer, the superfluous characters on the right will be rejected, and compiler will alert correspondingly.

Its internal representation is a structure of 8 bytes. The first element of the structure is a long integer that contains the size of the buffer distributed for the line. The second element of the structure is 32-order address of the buffer that contains the line. "

Quoted from the MetaEditor dictionary Data Types - String constants

fascinating stuff guys...

 

I know this thread is old, but I see everyone has there own way to get a "magic number" or whatever you want to call it. I also seen someone wanted there EA to be able to read its own name...well this is what i use to get the name of my EA

Place this at the top of the EA:

#define EAName "Put EA name here"

When your checking for open orders place this:

if (OrderType() <= OP_SELL && OrderSymbol() == Symbol() && OrderComment() == EAName && OrderMagicNumber() == MagicNumber)

For when your trade is placed make sure you have it so it places the EAName for a comment like this:

Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0, EAName, MagicNumber, 0, Blue);

Then if you want a magic number which you would if you want to run the EA on the same pair but different TFs at the same time..........just use the this:

int MagicNumber = Period();