Newbie Coming From Excel Programming Environment

 

Hi, I will first get out of the way my thanks.

I am having a problem just coming up with a very basic program. I would just like to analyze the

1) HIGH

2) LOW

3)OPEN

4) CLOSE

Of the last "x" amount of bars.

For example, in excel I could use :

E3 = Last Price of this current bar

E4 = Last Price of Previous Bar (AKA Close)

E5 = Last Price of 2 Bars Ago (AKA Close)

B3 = Opening Price of Bar

B4 = Opening Price of Previous Bar

etc..

I have been totally thrown for a loop as I am not the type of person to give up so i just find myself getting super frustrated and just decided to make a post here.

So for example, here is what I would like to do

Buy =AND ( Low of Previous Bar > Low of 2 Bars ago, High of Previous Bar >= High of 2 Bars ago.......)

I guess the only way I know how to express it well is just simply in Excel. I am guessing I need to use some sort of Array, but I just totally fall apart defining the parts of the program and execution. Really, all I want is just a simple buy program, no Trailing Stops etc. or Shorting

If I get the buy side down then the rest will be obvious (or so I think :) )


I think this is a really cool community and you can pretty much learn everything for free here w/o paying for subscriptions etc. which is quite rare. I am coming from a charting service that I would have to pay monthly and it is just getting old, plus I would like to have at least a minimal understanding of a more advanced language.

Thanks for the help again, if you could maybe just get me started, or if it is really simple - just totally hold my hand and I promise good things to you in the afterlife. :)

 

If you haven't seen it already, the book is a fountain of knowledge.

https://book.mql4.com//


The logic you would use in excel is predominantley the same and there are functions to return price information eg.

https://docs.mql4.com/series/iLow


There is an excellent list of functions here...

https://www.mql5.com/en/forum/122679

Don't forget to thank CB for putting that together.


Hand holding available on request ;) (and I'm happy with just a thankyou in this life)

Hope that helps

V

EDIT: and your if would look something like this

if (iLow(NULL,0,1)>iLow(NULL,0,2) && iHigh(NULL,0,1)>=iHigh(NULL,0,2))
   {
   //DO STUFF
   }
 

Thanks for the help so far -

Here is what I have created this far along - it compiles without any errors - but definitely doesn't work when I try to execute it

I have made some comments in RED below - I am sure it will be obvious to see where I am going wrong, but I can't seem to figure it out in the short-term on my own

I am missing something in the logical execution rules/format/design etc.. Perhaps it will be easy for someone like you to see easily

This is most likely so illogical it doesn't make sense, but anyway..

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

//| ty.mq4 |

//| Copyright © 2010, MetaQuotes Software Corp. |

//| http://www.metaquotes.net |

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

#property copyright "Copyright © 2010, MetaQuotes Software Corp."

#property link "http://www.metaquotes.net"

extern double Lots=0.1;

extern int StopLoss =50;

extern int TakeProfit =80;


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

//| expert initialization function |

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

int init()

{

//----

//----

return(0);

}

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

//| expert deinitialization function |

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

int deinit()

{

//----

//----

return(0);

}

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

//| expert start function |

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

int start()

{

int ticket;


//Here is just basically the same thing you wrote from your sample above


if (iLow(NULL,0,0)<= iLow(NULL,0,1) && iHigh(NULL,0,0)>iHigh(NULL,0,1))

{

//So here my logic for the following next 2 lines is defining the variable ticket using what I think is the correct format

//Saying if Ask is <= My Open Price - StopLoss or Ask >= Open Price + Take Profit

ticket=(OrderSend(Symbol(),OP_BUY,3,Ask<=OrderOpenPrice()-StopLoss*Point,Ask>=OrderOpenPrice()+TakeProfit*Point,"Dumbass",0,Green));

return(0);

}

//So here I am saying if the ticket > 0 - meaning the order has opened and then also the Order is a Buy..

if(ticket>0 && OrderType()==OP_BUY)

{

//So I guess here I am saying pretty much as the above, just using the || saying either or...

//But why do I have to define again what my SL and TP is if we supposedly do this in the

//ticket = xxx up a few lines in the green?

if(Ask<=OrderOpenPrice()-StopLoss*Point || Ask>=OrderOpenPrice()+TakeProfit*Point)

{

//I have no idea what the next means, but just coping from the MACD Sample provided with the software

OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);

return(0);

}

}

}

 

Would be worth looking at the trading operations section in the book...

https://book.mql4.com/trading/index

You should try and prepare all of your data for the order send and then send it. this would include using NormalizeDouble to make sure everything if properly formatted. You can't send an arguement (as you've done in green) on an order send. Your use of OrderOpenPrice() is incorrect. This funtion returns a value from an existing or historic order, so is no good when you are trying to create one.

the order send should look something like this... Its indicative only

if (iLow(NULL,0,1)>iLow(NULL,0,2) && iHigh(NULL,0,1)>=iHigh(NULL,0,2))
   {
   sl=NormalizeDouble(stoploss*Point,Digits);
   tp=NormalizeDouble (takeprofit*Point,Digits);
   lots=lot;         // you can have a function to calculate lot size
   price=Ask;
   slip=slip;        // you can define slippage amount as an extern
   
   OrderSend(Symbol(),OP_BUY,lot,price,slip,sl,tp,"Clever Cloggs",0,Green);  // use of ticket is not essential
   }

You would want to do some error testingwith getlasterror to make sure your order is sent and if it fails, why.

You will need to add to your if statement some method of controlling how many orders are allowed to open, otherwise it will open every tick the condition is true. The simplest is to use OrdersTotal()==0.


once your order is open, you now need to manage it and in particular consider what conditions should close it.

you would need to loop through your open orders, select the right one and then test if you need to modify / close it. An example...

https://www.mql5.com/en/articles/1404


Hope that helps

V

 

Thanks for the time

Will look into these articles now

 

Alright, I definitely feel like I am getting somewhere now :)

So I actually have the program buying and selling (close buy) - but I just wanted to shoot this past you, maybe something that just seems to be executing but logically is wrong etc. I tried to incorporate other people's code into mine to basically just bandage it altogether.

I am guessing there is still something wrong with the way it is executing because as I look at all the trades it is firing off sometimes like a few buy->buy close every second etc.

Thanks for the help, hopefully MT4 isn't outdated by the time I hit my stride!

//---- input parameters

extern double Lots = 0.1;

extern int StopLoss = 50;

extern int TakeProfit = 80;

extern int Decimals = 4;

int init() {

return(0);

}


int deinit() {

return(0);

}


int start()

{

int cnt, ticket, total;

total = OrdersTotal();

if(total<1)

{

StopLoss=NormalizeDouble(StopLoss*Point,Digits);

TakeProfit=NormalizeDouble (TakeProfit*Point,Digits);

// check for long position (BUY) possibility

if(iLow(NULL,0,0)>iLow(NULL,0,1) && iHigh(NULL,0,0)>=iHigh(NULL,0,1))

{

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,StopLoss,TakeProfit,"macd sample",16384,0,Green);

if(ticket>0)

{

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());

}

else Print("Error opening BUY order : ",GetLastError());

return(0);

}

return(0);

}

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

{

OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

if(OrderType()<=OP_SELL && // check for opened position

OrderSymbol()==Symbol()) // check for symbol

{

if(OrderType()==OP_BUY)

{

if(Ask<=OrderOpenPrice()-OrderStopLoss() || Ask>=OrderOpenPrice()+OrderTakeProfit())

{

OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position

return(0); // exit

}

return(0);

}

}

}

}

 
 
Some comments...

Yes, please use the src button for code. It's much easier to read.

Stops - Your stop loss and take profits are incorrect. The order send needs an actual price rather than just the spacing. eg, for the buy...

      StopLoss=NormalizeDouble(Bid-(StopLoss*Point),Digits);
      TakeProfit=NormalizeDouble (Bid+(TakeProfit*Point),Digits);

Make heavy use of Print() when you are building your code. It is worth printing each variable as you create it, review it in journal to confirm it is giving the number you want.

Your stops MAY be very tight... depending on how many digits your broker / symbol is using a SL of 50 could be 50 pips, so probably fine, or if it's a 5 didgit broker, thats 5 pips / 50 points and will cause problems. If it is this tight, you should include code that tests if the stop is within an allowable level... https://docs.mql4.com/common/MarketInfo. But for the sake of this excersise, you should perhaps just increase the value for now.

Errors - After ticket, you check if ticket >0 and then select by ticket. Given you already have ticket #, you don't need to select it again. GetLastError() can be volatile so you need to be careful where you call it. Personally, I think it best to create a variable of the error code directly aftet the line you are interested in and then work with that variable. I would manage that code block like this..

         OrderSend(Symbol(),OP_BUY,Lots,Ask,3,StopLoss,TakeProfit,"macd sample",16384,0,Green);
         last_err=GetLastError();
         if (last_err!=0)
            {
            Print("Error opening BUY order : ",last_err);
            }


Closing- First up is the for loop. you should count down when it comes to closing orders (or anything that changes the indexing in order pool)

for(cnt=total-1;cnt>=0;cnt--)

When you close an order, the indexing of the order pool changes for numbers higher than the ticket you just closed.... so one of the orders will be given the index of the order you just closed and when cnt increments for the next loop, you will miss that order. If you count down, index changes for orders you'ce already checked don't matter.

Your condition for close is flawed. You don't need to put in logic that covers where you have set SL || TP. the broker will take care of those You could use logic here to close sooner than your targets if conditions become unfavourable or modify, say a trailing stop if the situation improves.. If you Print() OrderOpenPrice() and OrderStopLoss() (once your stoploss is correctly entered), you will see also see why there is a flaw in the logic.


Enough for now... hope that helps

V

 

OK, sorry didn't know about that button

Will try these changes etc.


Thanks---

Reason: