Coding help - page 39

 

I have written this line of code.

int TriggerChart = PERIOD_H4;

int FastMACDPeriod = 12;

int SlowMACDPeriod = 26 ;

int SignalPeriod = 9;

MacdCurrent = iMACD(Symbol(), TriggerChart, FastMACDPeriod,SlowMACDPeriod,SignalPeriod, PRICE_CLOSE, MODE_MAIN, 1);

With these variables inserted I am wondering whether the EA is able to identify that TriggerChart is 'int timeframe', and the others used for the int periods? Could it be that where they are all together does it look at TriggerChart and FastMACDPeriod for instance and thiink they are both to do with int timeframe and gets confused? At what point does the EA recognise which variable applies to which part of iMACD?

 

...

In short : no, it can not get confused (computers are good at that, they do not think but they execute same things over and over without interpreting) Only coders get confused from time to time

When you call a function it accepts parameters at certain order (places (for example : first parameter is symbol, secind is time frame ,,, and so on) It is completely relevant how do you declare (types) the variables when you call a function : they are strictly used depending on their place in parameters call list

crsnape@btinternet.com:
I have written this line of code.

int TriggerChart = PERIOD_H4;

int FastMACDPeriod = 12;

int SlowMACDPeriod = 26 ;

int SignalPeriod = 9;

MacdCurrent = iMACD(Symbol(), TriggerChart, FastMACDPeriod,SlowMACDPeriod,SignalPeriod, PRICE_CLOSE, MODE_MAIN, 1);

With these variables inserted I am wondering whether the EA is able to identify that TriggerChart is 'int timeframe', and the others used for the int periods? Could it be that where they are all together does it look at TriggerChart and FastMACDPeriod for instance and thiink they are both to do with int timeframe and gets confused? At what point does the EA recognise which variable applies to which part of iMACD?
 

Thanks mladen. Sounds logical.

With this code I've declared BarsGV as 0 in the int init() function. But, as you rightly say if I get an error it still returns false. Just thinkingt that instead of declaring it 0 at int init() I could reset it to 1 instead. What do you think? I have a 200SMA and if Bars is less than 200 it picks up an error here anyway.

So instead of this:

int init()

{

//---

GlobalVariableSet (BarsGV, 0);

//---

return(0);

}

THIS IS UNDER INT START()

if ((GlobalVariableGet (BarsGV) == 0) || (GlobalVariableGet (BarsGV) < Bars))

{

GlobalVariableSet(HasOrderedGV, false);

GlobalVariableSet(BarsGV, Bars);

}

//--- Check for long position (BUY) possibility

if (GlobalVariableGet (HasOrderedGV) == false)

{

Change to this:

int init()

{

//---

GlobalVariableSet (BarsGV, 1);

//---

return(0);

}

THIS IS UNDER INT START()

if (GlobalVariableGet (BarsGV) == 0);

{

Print("Error with Global Variable BarsGV", GetLastError());

return(0);

}

if (GlobalVariableGet (BarsGV) < Bars)

{

GlobalVariableSet(HasOrderedGV, false);

GlobalVariableSet(BarsGV, Bars);

}

//--- Check for long position (BUY) possibility

if (GlobalVariableGet (HasOrderedGV) == false)

{

What do you think?

 

...

Change it to this :

int BarsGV;

bool HasOrderedGV;

int init()

{

//---

BarsGV=0;

HasOrderedGV=false;

//---

return(0);

}

THIS IS UNDER INT START()

if (BarsGV < Bars)

{

HasOrderedGV=false;

BarsGV=Bars;

}

//--- Check for long position (BUY) possibility

if (HasOrderedGV == false)

{[/PHP]

That way you are going to avoid other EA interference and you will keep the variables to only one instance of Ea (they can not mix at all). Much better to do it that way (even from the speed of execution point of view). But you still risk of opening a new order on a same bar this way. The best way is to use a function to count orders opened at the current bar and then allow or disallow ner order opening

Here is a function that can do that (it will check currently opened as well as already closed orders if they have been opened on a current bar) :

bool uniqueOnBar(int MagicNumber)

{

datetime startTime = Time[0];

datetime endTime = startTime+60*Period();

for (int i=OrdersTotal()-1; i>=0; i--)

{

if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;

if (OrderSymbol() != Symbol()) continue;

if (OrderMagicNumber() != MagicNumber) continue;

if (OrderOpenTime()endTime) continue;

return(false);

}

for (i=OrdersHistoryTotal()-1; i>=0; i--)

{

if (!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;

if (OrderSymbol() != Symbol()) continue;

if (OrderMagicNumber() != MagicNumber) continue;

if (OrderOpenTime()endTime) continue;

return(false);

}

return(true);

}

Checking would be very simple :

[PHP]if (uniqueOnBar(MagicNumber)) .... you can open an a new order

That way you would not depend on any variables but only on orders and that s the only 100% reliable way

crsnape@btinternet.com:
Thanks mladen. Sounds logical.

With this code I've declared BarsGV as 0 in the int init() function. But, as you rightly say if I get an error it still returns false. Just thinkingt that instead of declaring it 0 at int init() I could reset it to 1 instead. What do you think? I have a 200SMA and if Bars is less than 200 it picks up an error here anyway.

So instead of this:

int init()

{

//---

GlobalVariableSet (BarsGV, 0);

//---

return(0);

}

THIS IS UNDER INT START()

if ((GlobalVariableGet (BarsGV) == 0) || (GlobalVariableGet (BarsGV) < Bars))

{

GlobalVariableSet(HasOrderedGV, false);

GlobalVariableSet(BarsGV, Bars);

}

//--- Check for long position (BUY) possibility

if (GlobalVariableGet (HasOrderedGV) == false)

{

Change to this:

int init()

{

//---

GlobalVariableSet (BarsGV, 1);

//---

return(0);

}

THIS IS UNDER INT START()

if (GlobalVariableGet (BarsGV) == 0);

{

Print("Error with Global Variable BarsGV", GetLastError());

return(0);

}

if (GlobalVariableGet (BarsGV) < Bars)

{

GlobalVariableSet(HasOrderedGV, false);

GlobalVariableSet(BarsGV, Bars);

}

//--- Check for long position (BUY) possibility

if (GlobalVariableGet (HasOrderedGV) == false)

{

What do you think?
 

Superstar. Thanks.

 

Hi mladen,

This part:

datetime EndTime = StartTime + 60 * Period();

Is Period() is this instance the chart timeframe. So say H4 (240) * 60 because EndTime is recorded in seconds, so conversion of 240minutes into seconds to correspond with minutes of Period (240)?

Am I reading that right?

Could it also be written:

datetime EndTime = (StartTime / 60) + Period();?

 

...

Yes, you are reading it right

As of the other form : you can not use that since the OrderOpenTime() is in a standard datetime format which means that in EndTime you must have the number of seconds passed since January 1, 1970 and the way you wrote it it would contain minutes - metatrader would assume that those are seconds and it would give all wrong results

crsnape@btinternet.com:
Hi mladen,

This part:

datetime EndTime = StartTime + 60 * Period();

Is Period() is this instance the chart timeframe. So say H4 (240) * 60 because EndTime is recorded in seconds, so conversion of 240minutes into seconds to correspond with minutes of Period (240)?

Am I reading that right?

Could it also be written:

datetime EndTime = (StartTime / 60) + Period();?
 

Hi mladen, does the for loop here select the last opened or pending order?

bool UniqueOnBar (int MagicNumber)

{

datetime StartTime = Time[0];

datetime EndTime = StartTime + 60 * Period (TriggerChart);

for (int i = OrdersTotal() - 1; i >= 0; i--)

{

if (!OrderSelect (i, SELECT_BY_POS, MODE_TRADES)) continue;

if (OrderSymbol() != Symbol()) continue;

if (OrderMagicNumber() != MagicNumber) continue;

if (OrderOpenTime() endTime) continue;

return(false);

}

So where the exclamation mark is intepreted as 'not', Im thinking this isnt right im my instance because I want:

- To select the latest opened or pending order so remove ! to leave OrderSelect?

- OrderSymbol() to be the same as Symbol()

- OrderMagicNumber() to be equal to MagicNumber, so...it leaves this:

intTriggerChart= PERIOD_H4;

int MagicNumber = 42;

bool UniqueOnBar (int MagicNumber)

{

datetime StartTime = Time[0];

datetime EndTime = StartTime + 60 * Period (TriggerChart);

for (int i = OrdersTotal() - 1; i >= 0; i--)

{

if (OrderSelect (i, SELECT_BY_POS, MODE_TRADES)) continue;

if (OrderSymbol() == Symbol()) continue;

if (OrderMagicNumber() == MagicNumber) continue;

if (OrderOpenTime() endTime) continue;

return(false);

}

 

My oversight I realise now that its when the expression returns true that no opened orders are picked up on current bar

 

...

Yes, it does so. So if it returns tru, you can open a new order

Also, if you want to test time frame different than current time frame if an order has been opened on target time frame current bar, than the function can be changed to someting like this :

bool UniqueOnBar (int MagicNumber, int timeFrame=0)

{

if (timeFrame==0) timeFrame=Period();

datetime StartTime = iTime(NULL,timeFrame,0);

datetime EndTime = StartTime + 60*timeFrame;

for (int i=OrdersTotal()-1; i>=0; i--)

{

if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;

if (OrderSymbol() == Symbol()) continue;

if (OrderMagicNumber() == MagicNumber) continue;

if (OrderOpenTime() EndTime) continue;

return(false);

}

return(true);

}

[/PHP]

And then the call to it would be for your example 2 posts ago

[PHP]if (UniqueOnBar(MagicNumber,TriggerChart) ... open an order

PS: you removed the closed orders checking from the example. If you wish to check the closed orders too, than use the second part of original form of the function too

crsnape@btinternet.com:
My oversight I realise now that its when the expression returns true that no opened orders are picked up on current bar
Reason: