can someone debug this code?

 
On a backtest, it works normally from 20-06-2006, but before that date it doesn't work.
When I look at the log, it says:

15:36:07 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
15:36:07 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
15:36:07 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
15:36:07 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
15:36:07 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function

and that goes on and on.. until 20-06-2006 (or a few days earlier, but then the first trade is made).

I know for sure the the bug is in the code because other experts do work normally from 2004.06.18 and just this one doesn't (and other versions of Hans123MV)

Here's the code:

//+------------------------------------------------------------------+
//| Hans123MV21 |
//| Copyright © 2006, Milan Volf |
//| |
//+------------------------------------------------------------------+

//---- input parameters
extern int Start1=10; //begin of the first session; time adjust by your broker time
extern int Start2=14; //begin of the second session
extern int EOD=24; //time for closing orders at end of day
extern int FridayClosing=23; //broker friday closing time
extern bool FirstSessionOnly=0; //if it equals 1, it trades the first range only (for testing)
extern int Length=4; //length of range for determining high/low
extern int Pips=5; //trigger above/bellow range
extern int StopLoss=50;
extern int BreakEven=30;
extern int TrailingStop=0; //if equals 0, it uses breakeven
extern int TakeProfit=80;
extern double Lots=1;

//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
int i,Ticket,MN;

//Normalize times
if(EOD==24) EOD=0;
if(FridayClosing==0) FridayClosing=24;

//Setup comment
string Text="Hans123"+Symbol();

//Setup orders
if(Hour()==Start1 && Minute()<10){
MN=1;
SetOrders(Text,MN);
}
if(Hour()==Start2 && Minute()<10 && FirstSessionOnly==0){
MN=2;
SetOrders(Text,MN);
}

//Manage open orders
for (i=0;i<OrdersTotal();i++){
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderComment()==Text){
//close open positions at EOD
if(Hour()==EOD || (DayOfWeek()>=5 && Hour()==FridayClosing-1 && Minute()>=50)){
switch (OrderType()){
case OP_BUY: OrderClose(OrderTicket(), OrderLots(), Bid, 3,Red);
break;
case OP_SELL: OrderClose(OrderTicket(), OrderLots(), Ask, 3, Red);
break;
default: OrderDelete(OrderTicket());
break;
}
Sleep(10000);
}
else {
//move at BE if profit>BE
if(TrailingStop==0){
if(OrderType()==OP_BUY){
if(High[0]-OrderOpenPrice()>=BreakEven*Point && OrderStopLoss()<OrderOpenPrice()){
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Green);
Sleep(10000);
}
}
if(OrderType()==OP_SELL){
if(OrderOpenPrice()-Low[0]>=BreakEven*Point && OrderStopLoss()>OrderOpenPrice()){
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Green);
Sleep(10000);
}
}
}
//use trailing stop
else {
if(OrderType()==OP_BUY){
if(High[0]-OrderStopLoss()>TrailingStop*Point){
OrderModify(OrderTicket(), OrderOpenPrice(), High[0]-TrailingStop*Point, OrderTakeProfit(), 0,Green);
Sleep(10000);
}
}
if(OrderType()==OP_SELL){
if(OrderStopLoss()-Low[0]>TrailingStop*Point){
OrderModify(OrderTicket(), OrderOpenPrice(), Low[0]+TrailingStop*Point, OrderTakeProfit(), 0,Green);
Sleep(10000);
}
}
}
}
}
}

return(0);
}
//+------------------------------------------------------------------+

void SetOrders(string Text,int MN){
int i,Ticket,Bought,Sold;
double EntryLong,EntryShort,SLLong,SLShort,TPLong,TPShort;

//Determine range
EntryLong =iHigh(NULL,60,Highest(NULL,60,MODE_HIGH,Length, 1))+(Pips/*+MarketInfo(Symbol(), MODE_SPREAD)*/)*Point;
EntryShort =iLow (NULL,60,Lowest (NULL,60,MODE_LOW, Length,1))-Pips*Point;
SLLong =MathMax(EntryLong-StopLoss*Point, EntryShort);
SLShort =MathMin(EntryShort+StopLoss*Point, EntryLong);
TPLong =EntryLong+TakeProfit*Point;
TPShort =EntryShort-TakeProfit*Point;

//Check Orders
for (i=0;i<OrdersTotal();i++){
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderComment()==Text && OrderMagicNumber()==MN){
if(OrderType()==OP_BUYSTOP || OrderType()==OP_BUY) Bought++;
if(OrderType()==OP_SELLSTOP || OrderType()==OP_SELL) Sold++;
}
}
if(Bought==0){ //no buy order
Ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,EntryLong, 3, SLLong, TPLong, Text,MN, 0,Green);
if(Ticket<0 && GetLastError()==130)
Ticket=OrderSend(Symbol(),OP_BUY, Lots, Ask, 3,SLLong, TPLong, Text, MN, 0,Green);
Sleep(10000);
}
if(Sold==0){ //no sell order
Ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,EntryShort, 3,SLShort, TPShort, Text, MN,0,Green);
if(Ticket<0 && GetLastError()==130)
Ticket=OrderSend(Symbol(),OP_SELL, Lots, Bid, 3, SLShort, TPShort, Text, MN,0,Green);
Sleep(10000);
}
}
 
Whether helpful or not, I think it fairly well described https://docs.mql4.com/trading/OrderSend

Firstly, the EntryLong and/or EntryShort values are rendered invalid, perhaps due to being too close to current price for pending order, or perhaps because the values are not normalised; and secondly SLLong and/or SLShort are rendered invalid, for the similar reasons.
I would at first guess on non-normalised numbers, and simply add normalisations after the assignments. That is, in function SetOrders(..), after the "TPShort=. .." statement, you'd add statements of the form:
    EntryLong = NormalizeDouble( EntryLong, Digits );
etc. for EntryShort, SLLong, SLShort, TPLong and TPShort.

If that's not enough, then you may need to also ensure the relevant price gaps. But that of course will change the algorithm by possibly adjusting values away from their prior assignments.
 
Hello richplank and others,

thank you very much for your answer, but I'm not sure what to do now. I have done the following:

instead of :

void SetOrders(string Text,int MN){
int i,Ticket,Bought,Sold;
double EntryLong,EntryShort,SLLong,SLShort,TPLong,TPShort;

//Determine range
EntryLong =iHigh(NULL,60,Highest(NULL,60,MODE_HIGH,Length, 1))+(Pips/*+MarketInfo(Symbol(), MODE_SPREAD)*/)*Point;
EntryShort =iLow (NULL,60,Lowest (NULL,60,MODE_LOW, Length,1))-Pips*Point;
SLLong =MathMax(EntryLong-StopLoss*Point, EntryShort);
SLShort =MathMin(EntryShort+StopLoss*Point, EntryLong);
TPLong =EntryLong+TakeProfit*Point;
TPShort =EntryShort-TakeProfit*Point;

//Check Orders
for (i=0;i<OrdersTotal();i++){
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderComment()==Text && OrderMagicNumber()==MN){
if(OrderType()==OP_BUYSTOP || OrderType()==OP_BUY) Bought++;
if(OrderType()==OP_SELLSTOP || OrderType()==OP_SELL) Sold++;

I have the following code now:

void SetOrders(string Text,int MN){
int i,Ticket,Bought,Sold;
double EntryLong,EntryShort,SLLong,SLShort,TPLong,TPShort;

//Determine range
EntryLong =iHigh(NULL,60,Highest(NULL,60,MODE_HIGH,Length, 1))+(Pips/*+MarketInfo(Symbol(), MODE_SPREAD)*/)*Point;
EntryShort =iLow (NULL,60,Lowest (NULL,60,MODE_LOW, Length,1))-Pips*Point;
SLLong =MathMax(EntryLong-StopLoss*Point, EntryShort);
SLShort =MathMin(EntryShort+StopLoss*Point, EntryLong);
TPLong =EntryLong+TakeProfit*Point;
TPShort =EntryShort-TakeProfit*Point;

EntryLong = NormalizeDouble( EntryLong, Digits );
EntryShort = NormalizeDouble( EntryShort, Digits );
SLLong = NormalizeDouble( SLLong, Digits );
SLShort = NormalizeDouble( SLShort, Digits );
TPLong = NormalizeDouble( TPLong, Digits );
TPShort = NormalizeDouble( TPShort, Digits );


//Check Orders
for (i=0;i<OrdersTotal();i++){
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderComment()==Text && OrderMagicNumber()==MN){
if(OrderType()==OP_BUYSTOP || OrderType()==OP_BUY) Bought++;
if(OrderType()==OP_SELLSTOP || OrderType()==OP_SELL) Sold++;
}
}





This didn't help, but at first I made a mistake, I had the following:

EntryLong = NormalizeDouble( EntryLong, Digits );
EntryShort = NormalizeDouble( EntryLong, Digits );
SLLong = NormalizeDouble( EntryLong, Digits );
SLShort = NormalizeDouble( EntryLong, Digits );
TPLong = NormalizeDouble( EntryLong, Digits );
TPShort = NormalizeDouble( EntryLong, Digits );

When watching the log then I got other errors, no SL errors anymore, and with the actual price which gave an error, I don't know if this is relevant but I'll just post it here:

2006.10.18 17:49:42 2004.08.24 14:04 Breakout 2_2 GBPUSD, M15: invalid price 1. 80554998 for OrderSend function

I'm pretty new at this, programming, so any help is very much appreciated.

Thank you in advance,
 
I assume you have renamed it to be "Breakout 2_2".
Maybe you can post a short snippet of the errors you get; off-line debugging doesn't get easier by lack of detail :-)
It appears that normalizing the values had an effect, and to be sure, the same kind of normalizing will be required for the OrderModify calls.
Otherwise, well, the inline 10 second sleeps look odd to me - not the way I'd do things - but that's more of an algorithmic thing.

That price error can't have happened :-), as it obvioulsy complains about a non-normalized price, unless you made a mistake in normalizing (e.g. missed out on one), or the error concerns an OrderModify call, or there's serious magic involved, or that the history data is screwed up in some way making MT4 giving you strange Bid and Ask values.
 
Watch out for this kind of thing:

for (i=0;i<OrdersTotal();i++){
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
..
OrderClose(..);
}

Orderclose removes the order from the list you are iterating through and all the orders above it jump down one -> bad karma. This works better:

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

Not that it will fix your current problem:).
 
richplank:
I assume you have renamed it to be "Breakout 2_2".
Maybe you can post a short snippet of the errors you get; off-line debugging doesn't get easier by lack of detail :-)
It appears that normalizing the values had an effect, and to be sure, the same kind of normalizing will be required for the OrderModify calls.
Otherwise, well, the inline 10 second sleeps look odd to me - not the way I'd do things - but that's more of an algorithmic thing.

That price error can't have happened :-), as it obvioulsy complains about a non-normalized price, unless you made a mistake in normalizing (e.g. missed out on one), or the error concerns an OrderModify call, or there's serious magic involved, or that the history data is screwed up in some way making MT4 giving you strange Bid and Ask values.

Hello,

Well I had "Breakout 2_2" but I don't want to give the code of it. It has the same errors as Hans123MV21 so I posted that code. I must have changed the Breakout 2_2 then...

I have done it with the right one now and got, as expected, the same results.

How can I find the errors that have happened? I have tried to put in the code Print (GetLastError()); in several spaces, but I still can't find it. It doesn't print it in the log and neither when compiling.

How should I normalize the values for the OrderModify calls?

BTW, you have the code, I let it work on G/U, so you could do it online instead of offline.
 
I figured out that when I put the following code after buying the journals give the last error:
if(Ticket>0){

Print("Error opening Buy order (",GetLastError(),")");
}

And the same when selling

Well, then the journal says multiple times: 2006.10.19 13:43:09 2006. 06. 27 10:00 Hans123MV21 GBPUSD,M15: Error opening Sell order (0)
2006. 10. 19 13:43:09 2006. 06. 28 10:00 Hans123MV21 GBPUSD, M15: Error opening Buy order (0)
etcetra

here's the journal:

13:42:41 Hans123MV21: loaded successfully
13:42:45 Hans123MV21 inputs: Start1=10; Start2=14; EOD=24; FridayClosing=23; Length=1; Pips=5; StopLoss=999; BreakEven=999; TrailingStop=0; TakeProfit=130; Lots=1;
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid stoploss for OrderSend function
13:42:56 2004.06.18 10:00 Hans123MV21 GBPUSD,M15: invalid price for OrderSend function

and that goes on and on every trading day.
 
Thanks, though not sure I'm that keen :-)
But looking again at your code, I saw that the EntryLong and EntryShort assignments refer to the 60 minutes time-frame, although you attach it to the 15 minute timeframe. I mean the statements:
EntryLong   =iHigh(NULL,60,Highest(NULL,60,MODE_HIGH,Length,1))+(Pips/*+MarketInfo(Symbol(),MODE_SPREAD)*/)*Point;
EntryShort  =iLow (NULL,60,Lowest (NULL,60,MODE_LOW, Length,1))-Pips*Point;
The occurrences of "60" in those statements refer to the 60 minutes timeframe. That's a different chart than the one you have attached to. Most likely iHigh and iLow gives you 0, and as a result, EntryShort is -5 pips, which is < 0, while EntryLong is 5 pips, which in the next statement makes SLLong -994 pips. Then everything gets better, when GBPUSD,H1 chart data kicks in, in june'06.

Perhaps you meant to have "Period" (without the double-quotes) instead of "60" (without the double-quotes)? That is, to refer to the timeframe of the attached chart rather than to 60 minutes timeframe.
 
richplank:
Thanks, though not sure I'm that keen :-)
But looking again at your code, I saw that the EntryLong and EntryShort assignments refer to the 60 minutes time-frame, although you attach it to the 15 minute timeframe. I mean the statements:
EntryLong   =iHigh(NULL,60,Highest(NULL,60,MODE_HIGH,Length,1))+(Pips/*+MarketInfo(Symbol(),MODE_SPREAD)*/)*Point;
EntryShort  =iLow (NULL,60,Lowest (NULL,60,MODE_LOW, Length,1))-Pips*Point;
The occurrences of "60" in those statements refer to the 60 minutes timeframe. That's a different chart than the one you have attached to. Most likely iHigh and iLow gives you 0, and as a result, EntryShort is -5 pips, which is < 0, while EntryLong is 5 pips, which in the next statement makes SLLong -994 pips. Then everything gets better, when GBPUSD,H1 chart data kicks in, in june'06.

Perhaps you meant to have "Period" (without the double-quotes) instead of "60" (without the double-quotes)? That is, to refer to the timeframe of the attached chart rather than to 60 minutes timeframe.

Thank you very much, this was exactly the error! :D :D
I have changed 60 into 15 and now it's working just fine! I tried to create 1-hr-data but because of something that didn't work but now it works.
Reason: