Coding Help

Locked
User avatar
McNish
Trader
Posts: 227
Joined: Tue Nov 06, 2012 3:56 pm

Coding Help

Post by McNish »

Hello Fellow Members,

Posting in the forum after long time.

I've been working on a strategy and it has evolved gradually after a few months of experiment.
But here i am stuck at not being able to move ahead cause of lack of coding knowledge. Kindly assist me. TIA.

So the basic is that i want to open a set of trades as and when they happen based on certain conditions becoming true. This is a multi-pair EA.
1. There is a particular trade with a set trade comment ("Maxor_M") and magic number (415) that is checked initially. If it is open, the other conditions are checked, but if it is not open then nothing goes ahead. (for discussion, lets call this trade as X)
2. If X is open for the particular pair, for a set type, then i need to check another condition if another kind of trade is open or not. (call this another kind of trade as Y) For this, i need to compare the open time of X with that of Y. Here, there are two kinds of Y. One is an open Y trade and the other is a closed Y trade.
3. X's open time has to be greater than both the Y's, open Y (Yo) and closed Y (Yc). Thus XOOT (X's OrderOpenTime) needs to be greater than oYOOT and cYOCT (open Y's OrderOpenTime & closed Y's OrderCloseTime).
4. If either of the conditions are not met, no new trade is open. Therefore
if(XOOT < oYOOT || XOOT < cYOCT) DoNothing;
else(open new X trade).

I've been trying to make this code work and have done all know possiable permutation and combinations of it but to no avail. I even made two different approaches in code to get this thing going. I'm attaching below both the code snippets. Kindly look into it and suggest the best way to make it work.

Code Snip 1

Code: Select all

void CheckTrades()
{
   string NUL = symbol;     
   if(MaxM_Stack) {         //just a switch 
      if(CIO(1,NUL,CopyMN,8))   {       //checking to see if condition is returned as true for Buy
           OpenBuy(NUL,MagicNumber,TradeComment4);   }    //open Buy if true
                  
      if(CIO(0,NUL,CopyMN,8))   {       //checking to see if condition is returned as true for Sell
           OpenSell(NUL,MagicNumber,TradeComment4);  }    //open Sell if true
   }
           
return (0);
}

bool CIO (int t, string symbol, int MN, int z)
{
   int Tot = OrdersHistoryTotal();
   int Tots = OrdersTotal();
   int OOTMM,OCTSMH,OOTSMO;  //even used data type as datetime and static datetime, not sure.
   int type = OP_BUY;
   if(t == 0) type = OP_SELL;
   bool retrn = true;  //default is true - i guess this is wrong, not sure!
   for (int i = 0; i < Tots; i ++)  {  //checking open trades for X
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
         if(OrderComment() == "Maxor_M" && OrderType() == type && OrderMagicNumber() == MN && OrderSymbol() == symbol)  {
            OOTMM = OrderOpenTime();  //capturing X's open time for future comparisions
            //Alert(symbol, " - ",OOTMM," - ", OrderComment(),Tot," - ",Tots);  //just for checks
            for (int x = Tot-1; x >= 0; x--)   {  //checking history for Y's close time
               if(!OrderSelect(x, SELECT_BY_POS, MODE_HISTORY)) continue;
                  if(OrderType() == type && OrderMagicNumber() == MagicNumber && OrderSymbol() == symbol)   {
                     OCTSMH = OrderCloseTime();  //capturing Y's close time for comparision
                     if(OCTSMH > OOTMM)   retrn = false;  //converts default bool into false if condition not met
                     break;  }   }   //not sure about using break here. have tried without it as well
                      
            for (int a = Tots-1; a >= 0; a--)   {   //checking open trades for Y
               if(!OrderSelect(a, SELECT_BY_POS, MODE_TRADES)) continue;
                  if(OrderType() == type && OrderMagicNumber() == MagicNumber && OrderSymbol() == symbol)   {
                     OOTSMO = OrderOpenTime();
                     if(OOTSMO > OOTMM)   retrn = false;  //converts default bool into false if condition not met
                     break;   }  }
         break;                  
         }
   }     
   return(retrn);
}
Have tried different combinations as well of the above code

COde Snip 2

Code: Select all

   
void CheckTrades()
{
   string NUL = symbol;     
   int OOTMM,OCTSMH,OOTSMO;

if(MaxM_Stack) {                                                 //just a switch 
      OOTMM = CIO(1,NUL,CopyMN,0);                   //check open time of X - for buying conditions
      if(OOTMM > 0)  {                                           //if open time of X is > 0, then X is open
         OOTSMO = CIO(1,NUL,MagicNumber,1);      //check open time of open Y
         OCTSMH = CIOO(1,NUL,MagicNumber,2);    //check close time of closed Y
         if(OOTMM > OCTSMH || (OOTMM > OOTSMO || OOTSMO == 0)) {    //check if both conditions are met
            OpenBuy(NUL,MagicNumber,TradeComment4);   }  }                  // open a Buy trade
                  
      OOTMM = CIO(0,NUL,CopyMN,0);
      if(OOTMM > 0)  {                                            //same as above - for sell conditions
         OOTSMO = CIO(0,NUL,MagicNumber,1);
         OCTSMH = CIOO(0,NUL,MagicNumber,2);
         if(OOTMM > OCTSMH || (OOTMM > OOTSMO || OOTSMO == 0)) {
            OpenSell(NUL,MagicNumber,TradeComment4);  }  }                  //open a sell trade
   }      
return (0);
}

int CIO (int t, string symbol, int MN, int z)
{
   int Tots = OrdersTotal();
   int OOTMMx;
   int type = OP_BUY;
   if(t == 0) type = OP_SELL;
   for (int i = Tots -1; i >= 0; i --)  {           //checking all open trades
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
         if(OrderType() == type && OrderMagicNumber() == MN && OrderSymbol() == symbol)   {
            if(z == 0 && OrderComment() == "Maxor_M")  OOTMMx = OrderOpenTime();  //checking for open X
            else if(z == 1)   OOTMMx = OrderOpenTime();                                               //checking for open Y
            else(OOTMMx == 0);                                      // returning 0 if either X is not open or Y is not open
   }  }
   return(OOTMMx);
}         

int CIOO (int t, string symbol, int MN, int z)
{
   int Tots = OrdersHistoryTotal();
   int OOTMMx;
   int type = OP_BUY;
   if(t == 0) type = OP_SELL;
   for (int i = Tots - 1; i >= 0; i --)  {                     //checking all open trades
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
         if(OrderType() == type && OrderMagicNumber() == MN && OrderSymbol() == symbol)   {
            OOTMMx = OrderCloseTime();    break;  }                            //checking for closed Y
   }
   return(OOTMMx);
}
There is quite a bit of experiment that i have done with both the code snips. But the basic structure of the two different code snips is what i have stated above.
I know what i am trying to achieve is not that difficult. It is just my lack of coding knowledge that is preventing me from executing this successfully.

Anyone willing to lend me a helping hand do kindly get back to me with queries that you might have.

Regards, Max.
User avatar
renexxxx
Trader
Posts: 860
Joined: Sat Dec 31, 2011 3:48 am

Coding Help

Post by renexxxx »

Hello Max,

You are doing an OrderSelect() within another OrderSelect(), both with a SELECT_BY_POS parameter. This is asking for trouble. It would be far better to 'suck' in all your open trades into an array structure, and loop over that array: eg.

Code: Select all

struct ORDER {

   int ticket;
   string orderSymbol;
   int orderType;
   double orderOpenPrice;
   datetime orderOpenTime;
   datetime orderCloseTime;
};

ORDER openOrders[];

void getOpenOrders( ORDER &myOrders[] ) {

   ArrayFree( myOrders );
   ArrayResize( myOrders, 0 );
   
   for(int iOrder=OrdersTotal()-1; iOrder >= 0; iOrder--) {
   
      if ( OrderSelect( iOrder, SELECT_BY_POS, MODE_TRADES ) ) {
      
         if ( OrderMagicNumber() != MagicNumber ) continue;
         if ( OrderCloseTime() > 0 ) continue; // shouldn't happen
         
         int currentSize = ArraySize( myOrders );
         ArrayResize( myOrders, currentSize+1 );
         
         myOrders[currentSize].ticket = OrderTicket();
         myOrders[currentSize].orderSymbol = OrderSymbol();
         myOrders[currentSize].orderType = OrderType();
         myOrders[currentSize].orderOpenPrice = OrderOpenPrice();
         myOrders[currentSize].orderOpenTime = OrderOpenTime();
         myOrders[currentSize].orderCloseTime = OrderCloseTime(); // shoud be 0
         
      }
   }
}      
Once you have filled your array of open orders (into openOrders[]), you can iterate over this array and do some more OrderSelect's to your hearts content within that loop. Hope I make myself understood.

( Or, alternatively, just create an array of integers, that you fill with the ticket numbers of the open orders. You can do an OrderSelect( <ticketNumber>, SELECT_BY_TICKET ), without buggering up the other OrderSelect() ).

Have fun.
User avatar
McNish
Trader
Posts: 227
Joined: Tue Nov 06, 2012 3:56 pm

Coding Help

Post by McNish »

Hello Rene,
Thanks for the assist. Some things clear, but some doubts remain.

1. You are saying the code snip 1 is trouble as there is OrderSelect within OrderSelect. Fair enough.
The alternate that you have suggested is to put all the open orders into an array, then lookup for my matching conditions. The question is, there are two different kinds of orders, one is a set of open orders and the other is closed orders. In the open orders, there are again two different kind of trades to check for, via #MN & Comment as trades of X kind has to be checked by both #MN & Comment and trade Y just needs #MN checking.
a. So i make two more variable in the array for these two elements as well, for #MN & comments ?
b. After creating an array of open orders, i can check for closed trades by using OrderSelect function again and matching the open with closed?

2. While code snip 1 is troublesome you say, how about the second code snip? That one does not have loop over loop of order select? What is wrong there?

So if i am to code this the way you mentioned,

Code: Select all

struct ORDER {  //  creating variables for the order array?
 
   int ticket;
   string orderSymbol;
   int orderType;
   //double orderOpenPrice;  //  i dont need this variable so i can safely omit it?
   datetime orderOpenTime;
   datetime orderCloseTime;
   int orderMagic;                  //need these two, can i add them ?
   string orderComment;
};
 
ORDER openOrders[];            //On some brain scratching, seems this is the main array of open orders.
 
void getOpenOrders( ORDER &myOrders[] ) {  
 
   ArrayFree( myOrders );  
   ArrayResize( myOrders, 0 );
   
   for(int iOrder=OrdersTotal()-1; iOrder >= 0; iOrder--) {
   
      if ( OrderSelect( iOrder, SELECT_BY_POS, MODE_TRADES ) ) {
     
         if ( OrderMagicNumber() != MagicNumber ) continue;  //  Here i have two different magic# for filtering. how do i do this?
         if ( OrderCloseTime() > 0 ) continue; // shouldn't happen
         
         int currentSize = ArraySize( myOrders );
         ArrayResize( myOrders, currentSize+1 );
         
         myOrders[currentSize].ticket = OrderTicket();
         myOrders[currentSize].orderSymbol = OrderSymbol();
         myOrders[currentSize].orderType = OrderType();
         //myOrders[currentSize].orderOpenPrice = OrderOpenPrice();
         myOrders[currentSize].orderOpenTime = OrderOpenTime();
         myOrders[currentSize].orderCloseTime = OrderCloseTime(); // shoud be 0
         myOrders[currentSize].orderMagic = OrderMagicNumber();
         myOrders[currentSize].orderComment = OrderComment();
         
      }
   }
}  
Hope i have not asked anything stupid. I can handle the array functions with some trial and error. What beats me is the new coding convention of MQL.
Guess i will need some more clarity on this.

Regards, Max.
User avatar
renexxxx
Trader
Posts: 860
Joined: Sat Dec 31, 2011 3:48 am

Coding Help

Post by renexxxx »

McNish » Sat Oct 07, 2017 11:12 pm wrote: a. So i make two more variable in the array for these two elements as well, for #MN & comments ?
b. After creating an array of open orders, i can check for closed trades by using OrderSelect function again and matching the open with closed?
Yes, to both questions.
McNish » Sat Oct 07, 2017 11:12 pm wrote: 2. While code snip 1 is troublesome you say, how about the second code snip? That one does not have loop over loop of order select? What is wrong there?
Snip 2 would probably work, if you would call them with z=0 and z=1 (last parameter) and not z=1 and z=2.

However, from a coding point of view, I would still consider rewriting the lot. Things to consider:
  • Use #property strict. This will make the compiler highlight potential code problems, such as eg. in CIO() where you potentially return a variable (OOTMMx) that was never set.
  • Naming convention: CIO, CIOO, NUL, retrn, OOTMMx .... Really?. Do you still want to read the code some other time?
  • If two functions are almost the same (such as CIO and CIOO), make them into one function. Then if something changes in the logic, you only have to make the change once not twice.
Eg. how about replacing both CIO and CIOO (in snip 2) with:

Code: Select all

enum TRADE_TYPE {
   TRADE_TYPE_ONE,
   TRADE_TYPE_TWO
};

#define TRADE_TYPE_ONE_COMMENT "Maxor_M"

datetime getOrderOpenTime( string symbol, int orderType, int magicNumber, TRADE_TYPE tradeType, bool history = false ) {

    // Set default return value;
   datetime result = -1;
   
   // Set OrderSelect() parameters
   int ordersTotal = ( history ) ? OrdersHistoryTotal() : OrdersTotal();
   int poolMode    = ( history ) ? MODE_HISTORY : MODE_TRADES;
   
   for(int iOrder=ordersTotal-1; iOrder >= 0; iOrder--) {
   
      if ( !OrderSelect(iOrder, SELECT_BY_POS, poolMode) ) continue;
      if ( OrderType() != orderType ) continue;
      if ( OrderMagicNumber() != magicNumber ) continue;
      if ( OrderSymbol() != symbol ) continue;
      
      if ( ( (tradeType == TRADE_TYPE_ONE) && OrderComment() == TRADE_TYPE_ONE_COMMENT ) ||
           ( tradeType == TRADE_TYPE_TWO ) ) {
         result = OrderOpenTime();
         break;                     // This break is significant ... 
                                    // If there are more than one orders satisfying all the 
                                    // selection criteria, do you want to get the first one
                                    // or the last one? Your call ...
      }
   }
   return(result);
}
With the history parameter (that defaults to false) you can then select where you want to obtain the results from the open trades cursor, or the history trades cursor. Also, your z parameter, signifies a type of trade. As this z parameter can only ever take on two values (0 and 1), make this explicit in the code with an enum. The compiler can then check if you call the getOrderOpenTime() function correctly.

Hope this helps.
oldfella
Trader
Posts: 46
Joined: Sun Jan 11, 2015 4:59 pm

Coding Help

Post by oldfella »

Hi,

I have been trying to get a program to load from my archives, I think the problem may be one of Build as my platform is "Version 4.00 Build 1090".
I am not a coder but am trying to learn, so have been wading through the code book to try and resolve the errors. I have sorted out several, but that's not many out of 26. I am now stuck is it possible you can please help or advise.

I have attached the source file for your perusal. All advice appreciated.

Regards
Oldfella
You do not have the required permissions to view the files attached to this post.
User avatar
renexxxx
Trader
Posts: 860
Joined: Sat Dec 31, 2011 3:48 am

Coding Help

Post by renexxxx »

oldfella » Sun Oct 08, 2017 7:35 pm wrote: I have attached the source file for your perusal. All advice appreciated.
Here you go -- #property strict compliant. Whether it does what you want it to do is another question.

Cheers ... R.
You do not have the required permissions to view the files attached to this post.
User avatar
McNish
Trader
Posts: 227
Joined: Tue Nov 06, 2012 3:56 pm

Coding Help

Post by McNish »

Hello Rene.
I think there is a point that you might have missed. Or maybe my comprehension of the code is naive.

By my limitations, i am not able to comprehend the edit to code snip 1.
For code snip 2, i figured most of it except a few.
1. bool history = false. I do need to check trades from the history pool as well. How do i tell the compiler when to invoke OpenTrades pool and when to invoke History Pool?
2. When ever history pool is invoked, I need to check for OrderClosedTime() from the History Pool and not OpenTime().
3. In my own code, i am using "int" as datatype for checking the OrderTimes (Closed or Open, whatever the case be.) Is that correct by any chance? Can i read datetime as integer? I tried to read the result of reading the datatype of ordertimes in int format by way of Alert / Print and it returned a whole number. But i am guessing that could be wrong. Please enlighten.
4. SELECT_BY_POS : I tried to find an explanation on this but it was not clear anywhere. What is the default sort of this index or list? This is list of open orders. By default, the sort should be on the open time of the orders. But i believe it is not so. Can you give your views about it or point to a place where i can read about it and be satisfied.
5. If i use break, it will jump out of the nearest for loop as soon as it finds the first satisfied condition. so to make a point clear, if i use

Code: Select all

for(int iOrder=OrdersTotal() - 1; iOrder >= 0; iOrder--) {
      if ( !OrderSelect(iOrder, SELECT_BY_POS, MODE_TRADES) ) continue;
and there are 20 open trades, it will start from 19 (20-1) all the way down to 0 and if the first condition is met at 16 (4th from top), it will do whatever its told and jump out of the loop and not check the rest (from 15 to 0 will skip).
Hope my reading is correct in this case!

If i get answers to the above which are at my knowledge level, i believe i will be able to make it work.
Really appreciate your time and patience for this.
I hope Sire doesn't find anything idiotic in this. Fingers crossed.

Regards, Max.
oldfella
Trader
Posts: 46
Joined: Sun Jan 11, 2015 4:59 pm

Coding Help

Post by oldfella »

Hi Rene,

Thanks for helpimg with the recent candle indicator, I can see that you have altered/corrected quite a number of errors that I would not had a clue about, many thanks for that.
However somtimes the indicator works and sometimes not, and on my other Empty4 platform it doesent operate at all. As you said "Whether it does what you want it to do is another question." You were right it is. The point is that it used to work OK and now it's not.


I have hunted through my archives and found a written paper on its operation and one old screenshot from the Alpari platform I used to use. I have attached them all. Screenshot2 is the Alpari one, the other is from one of my current platforms. They show a different number of bars because you can alter the parameters to suit, as you will be well aware from the code. It was also writtem to show multi mini screens of Currency pairs, I think the Parameter notes will give you feel for what it was meant to do.

Could I ask you if it is possible to look at it again, and in conjuction with the Parameter notes and screenshots please advise whether it possible to get it working as the Parameter notes indicate. Ofcourse I appreciate that this is asking an awful lot of you, but will be grateful for any help you can offer.

Kind Regards
Oldfella

PARAMETERS
CurrencyPairs - leave blank to default to the current chart's pair. Otherwise type in up to 30 pairs (e.g. GBPUSD or simply GU), separated by commas. Pairs will display in the left-to-right order in which you type them. Spaces are optional, and may be included for clarity. Upper/lowercase may be used interchangeably (e.g. USDCHF or usdchf). Permissible abbreviations are: A=AUD; C=CAD; E=EUR; F=CHF; G=GBP; J=JPY; N=NZD; U=USD; H=HKD; S=SGD; Z=ZAR. So you could type gj instead of GBPJPY, for example. If the pair name typed is not exactly 2 characters, the abbreviation will not be recognized. You can type a valid pair symbol followed by an asterisk (*), to have its inverted pair's candles plotted, e.g. typing AU* will plot USDAUD instead of AUDUSD candles.
TimeFrames - select the timeframes you wish to see, separated by commas. If displaying only one timeframe, a trailing comma is not required. Leaving this parameter blank defaults to the timeframe of the chart to which the indicator is attached. The spaces are optional, and are included merely for clarity. Upper/lowercase may be used interchangeably (e.g. H1 or h1). Time frames will display in the left-to-right order in which you type them
NumCandles - how many candles back from the currently forming one, that you want to see. For example, to see the currently forming candle, and also the last 3 candles, type 3. Typing 0 (or leave blank) causes only the currently forming candle to display, creating a 'traffic light' indicator. Typing a single value will display that number of candles for all timeframes. Typing multiple values, separated by commas, allows a different number of candles for each timeframe (by matching the NumCandles entry with the corresponding TimeFrames entry)
HistoricalShift – enter 0 to display the current plot. Enter a positive number to display the plot as it would have looked X candles ago. Typing a single value will display that HistoricalShift for all timeframes. Typing multiple values, separated by commas, allows a different HistoricalShift for each timeframe (by matching the HistoricalShift entry with the corresponding TimeFrames entry). This will likely be necessary, e.g. to see the candles as they were 4 hours ago, you'd need to type 1,4,8,16,48 for the H4,H1,M30,M15,M5 timeframes, respectively
CandleWidth - set to a value between 2 and 5. Default is 5. A higher value means wider candle bodies. Experiment until you find a value that suits
SpacingBetweenCandles - set to 1, 2 or 3. Higher number means wider spacing between candles, and is preferable when the main chart is 'zoomed out' to smaller candles. Experiment until you find a value that suits
Colors, TextColor/Font/Size should be self-explanatory
DisplayInfo - if set to TRUE, this will display the last Bid/Ask price, Tick time, Long/short swap rates, Spread (and spread as a % of average daily move) and Pip Value (dollar value your acount will change per pip, for each full lot traded) at the left of the window
DisplayCcyName - if set to TRUE, <pair> will be included in the labels displayed along the bottom of the window
DisplayTF - if set to TRUE, <timeframe> will be included in the labels displayed along the bottom of the window
RefreshEveryXMins - if set to 0, this will cause the window to update itself immediately a new tick occurs. If set to 1, 5, 15, 30, 60, or 240, this will cause the window to update itself every time a new candle appears on the M1, M5, M15, M30, H1 or H4 chart, respectively

HeikinAshiCandles - if set to TRUE, this will plot Heikin Ashi candles, instead of conventional ones.
You do not have the required permissions to view the files attached to this post.
User avatar
SteveHopwood
Owner
Posts: 9904
Joined: Tue Nov 15, 2011 8:43 am
Location: Misterton - an insignificant village in England. Very pleasant to live in.

Coding Help

Post by SteveHopwood »

I have locked this ridiculous topic before it get out of hand.

Some of the previous posts have been ridiculous in their demands for information.

Also in their presentation. Dense, impenetrable paragraphs do not encourage others to read them. Posters, learn to punctuate your posts. Primary school level 'punctuation' merely marks you down as an idiot.

It is ok to struggle with learning to code. Guess how I know? It is ok to ask for help.

It is not ok to try to take advantage of the goodwill of the likes of Rene and hope he will do all of your thinking for you, because you are too stupid to work out the basics for yourselves.

oldfella, I allowed you back in to SHF following your appeal to me yesterday because I could not remember why I stopped you posting in the first place. Your recent post here reminds me why. You are a moron. Post here again in such a way that you remind me just how stupid you are and I will ban you altogether. The genius who runs the back end of SHF has a patch installed that ensures that banned dimwits can never rejoin. Your best interests are served by staying very quiet from now on.

I remind people that SHF is a meritocracy not a democracy. We do not want to hear from you unless you have something useful to say. Make a pain of yourself and you will attract a ban. There is no subsequent way around said ban.

:xm:
Locked

Return to “Coders Hangout”