Need Help Understanding Basic MQL logic

 

Hello Everyone,

Can anyone tell me why the EA doesnt trade off the signals from the indicator? And offer any code fixes? My Understanding of how MQL works and how ticks and bars are triggered and code executed must be flawed.

Here is the Test EA

//+------------------------------------------------------------------+

//| Test MA.mq4 |

//| |

//| |

//+------------------------------------------------------------------+

#property copyright ""

extern int MyTarget = 15;

extern int MyStop = 15;

int Trend = 0;

int BuySignal = 0;

int SellSignal = 0;

int MyMagic = 12345;

int Slippage = 3;

int Entry = 0;

datetime MyTime = 0;

string FX_Symbol = "";

//+------------------------------------------------------------------+

//| expert initialization function |

//+------------------------------------------------------------------+

int init()

{

FX_Symbol = Symbol();

return(0);

}

//+------------------------------------------------------------------+

//| expert deinitialization function |

//+------------------------------------------------------------------+

int deinit()

{

return(0);

}

//+------------------------------------------------------------------+

//| expert start function |

//+------------------------------------------------------------------+

int start()

{

int Trend = 0;

if ( MyTime != Time[0] )

{

MyTime = Time[0];

Entry = iCustom(NULL,0,"Test MA",0,1);

BuySignal = 0;

SellSignal = 0;

if ( Entry == 1 )

BuySignal = 1;

if (Entry == -1 )

SellSignal = 1;

if ( BuySignal == 1 )

{

CloseOrders(OP_SELL);

Enter_New_Up();

}

if ( SellSignal == 1 )

{

CloseOrders(OP_BUY);

Enter_New_Dn();

}

}

return(0);

}

//+------------------------------------------------------------------+

//| Enter Some Details About This Function Here |

//+------------------------------------------------------------------+

void CloseOrders(int Mode)

{

int cnt = 0;

int TotalOrders = 0;

TotalOrders = OrdersTotal();

for ( cnt = 0; cnt < TotalOrders; cnt++)

{

OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

if ( OrderSymbol() == FX_Symbol && OrderMagicNumber() == MyMagic )

{

if ( OrderType() == OP_SELL && Mode == OP_SELL)

OrderClose(OrderTicket(), 1, Ask, Slippage);

if ( OrderType() == OP_BUY && Mode == OP_BUY)

OrderClose(OrderTicket(), 1, Bid, Slippage);

}

}

}

//+------------------------------------------------------------------

//| Here we have been given the green light to enter a new up trade

//| we need to get the correct lots to be used and determine our initial

//| stop based off our foundation lines. Typically if this is a new trend

//| change entry then we will need to search previous bars for the high/Low

//| to get our initial stop.

//+------------------------------------------------------------------

void Enter_New_Up()

{

double Lots = 1.0;

double MyAsk = 0.0;

int Ticket = -1;

SellSignal = 0;

BuySignal = 1;

MyAsk = Ask;

Ticket = OrderSend(FX_Symbol, OP_BUY, Lots, MyAsk, Slippage, MyAsk - (MyStop * Point), MyAsk + (MyTarget * Point), "", MyMagic, 0, Blue);

return(0);

}

//+------------------------------------------------------------------

//| Here we have been given the green light to enter a new dn trade

//| we need to get the correct lots to be used and determine our initial

//| stop based off our foundation lines. Typically if this is a new trend

//| change entry then we will need to search previous bars for the high/Low

//| to get our initial stop.

//+------------------------------------------------------------------

void Enter_New_Dn()

{

double Lots = 1.0;

double MyBid = 0.0;

int Ticket = -1;

BuySignal = 0;

SellSignal = 1;

MyBid = Bid;

Ticket = OrderSend(FX_Symbol, OP_SELL, Lots, MyBid, Slippage, MyBid + (MyStop * Point), MyBid - (MyTarget * Point), "", MyMagic, 0, Red);

return(0);

}

//+------------------------------------------------------------------+

[/PHP]

Here is the Indicator

[PHP]

//+------------------------------------------------------------------+

//| Test MA.mq4 |

//| |

//| |

//+------------------------------------------------------------------+

#property copyright ""

#property link ""

#property indicator_separate_window

#property indicator_buffers 1

#property indicator_color1 Blue

//---- buffers

double ExtMapBuffer1[];

int Spread = 0;

datetime MyTime = 0;

int Trend = 0;

//+------------------------------------------------------------------+

//| Custom indicator initialization function |

//+------------------------------------------------------------------+

int init()

{

SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);

SetIndexBuffer(0,ExtMapBuffer1);

SetIndexLabel(0, "Trend");

return(0);

}

//+------------------------------------------------------------------+

//| Custor indicator deinitialization function |

//+------------------------------------------------------------------+

int deinit()

{

return(0);

}

//+------------------------------------------------------------------+

//| Custom indicator iteration function |

//+------------------------------------------------------------------+

int start()

{

double Temp1 = 0.0;

double Temp2 = 0.0;

//----+ check whether the amount of bars is sufficient for correct

// calculation of the indicator

if(Bars - 1 < 21)

return(0);

//----+ Entering of integer variables and obtaining of bars already counted

int MaxBar, limit, counted_bars = IndicatorCounted();

//---- check for possible errors

if(counted_bars < 0)

return(-1);

//---- the last counted bar must be re-counted

if(counted_bars > 0)

counted_bars--;

//---- determining of the oldest bar number, starting from which

// all bars will be re-counted

MaxBar = Bars - 1 - 21;

//---- determining of the oldest bar number, starting from which

// only new bars will be re-counted

limit = (Bars - 1 - counted_bars);

//---- initialization of null

if(limit > MaxBar)

{

for(int bar = Bars - 1; bar >= limit; bar--)

{

ExtMapBuffer1 = -1;

}

limit = MaxBar;

}

//+--- basic loop of indicator calculation

for(bar = limit; bar > 0; bar--)

{

Temp1 = iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE,bar);

Temp2 = iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE,bar+1);

ExtMapBuffer1 = 0;

if ( Temp1 > Temp2 && Trend != 1)

{

ExtMapBuffer1 = 1;

Trend = 1;

}

if ( Temp1 < Temp2 && Trend != -1)

{

ExtMapBuffer1 = -1;

Trend = -1;

}

}

return(0);

}

//+------------------------------------------------------------------+

THank you for your Time and Effort

EK

 

Without penetrating the code in too much detail, I would suggest that you make the indicator compute and assign bar 1 when invoked. There is all too much logic about "counted bars" in the indicator; drop all that and make it assign bar==1 the way it is supposed to.

Of course, if you would want to use it as a "normal" indicator it should calculate for earlier bars as well, but since the indicator keeps state between invocations (the "Trend" variable), it is ill suited for normal use. The "proper" way to carry extra state would be to use a hidden buffer.

Further, you would need to cater for it being invoked on every tick rather than only at the bar opening tick. The EA invokes the indicator only at the bar opening tick, which is when the EA chooses to operate. When dropped on a chart, the indicator will be invoked once initially, with the purpose to paint the history, and then with every tick. On the basis of how the EA uses it, this indicator is supposed to only pay attention to the bar opening tick, and then paint bar==1.

 

Thank you

Hello Ralph,

Once again I thank you for helping me to understand what MQL is doing

Thank you

EK

 

Example

Is there an example of;

an Indicator that Shows the History and only calcs once per new bar

and a EA that calls that indicator?

Thank you

EK

 

How about the following outline:

int start()

{

for ( int bar = Bars - IndicatorCounted(); bar >= 0; bar-- ) {

indicate( bar );

}

return( 0 );

}

void indicate(int bar)

{

if ( buffer[ bar ] != EMPTY_VALUE )

return;

buffer[ bar ] = computeValueForBar( bar );

}

// This function will be called only once for any bar

double computeValueForBar(int bar)

{

...

}

In your case, the c16r function would call iMA(..., PRICE_CLOSE, bar+1 ) and iMA(..., PRICE_CLOSE, bar+2 ) as well as look at buffer to figure out the value for buffer. Note that you shouldn't use iMA(..., PRICE_CLOSE, bar) because that is logically to refer into the future, which is illogical

By that template, the indicator determines its value for a bar immediately with the first tick for that bar. As it should, the computation for a bar makes use of data that exists prior to the bar, and therefore the value is known with the first tick.

EDIT: I forgot to mention that the EA should ask for the bar 0 data of the indicator...

 

hmmm...

Hello Ralph,

Thank you for taking the time to point me in the right direction. With the above code I can use to contstruct an indicator that will only update on each new bar and shows history.

From the calling EA how can I use the EA to backtest and only have the EA run on new bars?

Thank you for your Time and Effort

EK

 

Sorry, I was a bit brief there, as I kind of thought you had that one sorted. Basically you use the EA you presented, but make it ask for the bar 0 value:

Entry = iCustom(NULL,0,"Test MA",0,0)

The indicator produces its bar 0 value on the first invocation with that bar as bar 0, and it does not change that value, ever.

So with your EA, you would restrict the invocations to be with the first tick for each bar, which is enough for the indicator to operate. And you might run your backtest in "open bars only" mode, I suppose.

 

Thank you

Hello Ralph,

Thank you very much for helping me with my MQL problems.

Thank you

EK

Reason: