Exit won't work

 

I wrote a simple strategy that fades big bars. The entries work fine, the exits do not.

The idea is that I mark lastTradeTime = Time[0] whenever a trade enters. If lastTradeTime != Time[0], it should be time to close the trade... except it's not working that way. What's wrong here?

extern double lots = 0.1;
extern int slippage = 3;
extern int magic = 3489234;
extern int MinBarHeight = 15;

datetime lastTradeTime;
double minBarHeight;

int init()
  {
minBarHeight = MinBarHeight * Point;
lastTradeTime = Time[1];
   return(0);
  }

int start()
  {
string show = TimeToStr(lastTradeTime,TIME_MINUTES) + "\n" + TimeToStr(Time[0],TIME_MINUTES) + "\nMP: " + GetMarketPosition();

Comment(show);

// Exit Rules

// Have we been in a trade for more than one bar?
switch(GetMarketPosition())
{
   case 1:
            if (lastTradeTime != Time[0]) ExitLong();
            break;
   case -1:         
            if (lastTradeTime != Time[0]) ExitShort();
            break;
} 

// Entry Rules
switch(AnalyzeMarket())
{
   case 1:
            GoLong();
            break;
   case -1:         
            GoShort();
            break;
} 

   return(0);
  }

int AnalyzeMarket()
{
   int mp = 0;
   
   if (High[1]-Low[1] >= minBarHeight)
   {
      // if the previous bar closed down, this bar makes a lower low and the price retraced, buy
      if (Open[1] > Close[1]  && Low[0] < Low[1] && Bid >= Close[1] && lastTradeTime != Time[0] && ConfirmNoDuplicates(OP_BUY)) 
         mp = 1;
      else 
      // if the previous bar closed up, this bar made a higher high and the price retraced, sell short
      if (Close[1] > Open[1] && High[0] > High[1] && Bid <= Close[1] && lastTradeTime != Time[0] && ConfirmNoDuplicates(OP_SELL)) 
         mp= -1;
   }
   return(mp);
}


void GoLong()
{
   int ticket = OrderSend(Symbol(),OP_BUY,lots,Ask,slippage,0,0,"Long",magic,0,Blue);
   
   if (ticket > 0) 
         {
            lastTradeTime = Time[0];
            string show = "Buy order successful. lastTradeTime = " + TimeToStr(lastTradeTime,TIME_MINUTES);
            Print(show);
         }
         else
         {
            int error = GetLastError();
            Alert("Buy order failed: Error " + error);
            Print("Buy order failed: Error " + error);
            Print("lastTradeTime = " + TimeToStr(lastTradeTime,TIME_MINUTES));
         }   // end else
}  //  end GoLong()

void GoShort()
{
   lots = 0.1;
   int ticket = OrderSend(Symbol(),OP_SELL,lots,Bid,slippage,0,0,"Short",magic,0,Red);
   
   if (ticket > 0) 
         {
            lastTradeTime = Time[0];
            string show = "Sell order successful. lastTradeTime = " + TimeToStr(lastTradeTime,TIME_MINUTES);
            Print(show);
         }
         else
         {
            int error = GetLastError();
            Alert("10427 Short order failed: Error " + error);
            Print("Short order failed: Error " + error);
            Print("lastTradeTime = " + TimeToStr(lastTradeTime,TIME_MINUTES));
         }   // end else   
}  // end GoShort()

int GetMarketPosition()   // What's our position?: -1 short; 0 flat; 1 long
{  
   int pos = 0;  
   int total = OrdersTotal();
   for (int i = 0; i < total; i++)
   {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);      
      if (OrderMagicNumber() == magic)
      {
        if (OrderType() == OP_SELL)
         {
            pos = -1;
            break;
         }  // end if sold
        else
        if (OrderType() == OP_BUY)
        {
            pos = 1;
            break;
        }  // end if bought
      } // end if Magic
   }  // end of for loop
   return(pos);
}  // end GetMarketPosition()

void ExitLong()
{
   int total = OrdersTotal();
   
   for ( int i = 0; i < total; i++)
   {
      OrderSelect(i,SELECT_BY_TICKET,MODE_TRADES);
      if (OrderMagicNumber() == magic && OrderType() == OP_BUY) OrderClose(i,OrderLots(),Bid,slippage,LightBlue);
   } // end for
}  // end ExitLong()

void ExitShort()
{
   int total = OrdersTotal();
   
   for ( int i = 0; i < total; i++)
   {
      OrderSelect(i,SELECT_BY_TICKET,MODE_TRADES);
      if (OrderMagicNumber() == magic && OrderType() == OP_SELL) OrderClose(i,OrderLots(),Ask,slippage,Pink);
   } // end for
} // end ExitShort()

bool ConfirmNoDuplicates(int operation)
{  
   bool confirm = true;
   int total = OrdersTotal();
   for ( int i = 0; i < total; i++)
   {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if (OrderMagicNumber() == magic && OrderType() == operation)
      {
         confirm = false;
         break;
      }
   }  // end for loop   
   return (confirm);
}  // end ConfirmNoDuplicates()
 
texasnomad wrote >>

I wrote a simple strategy that fades big bars. The entries work fine, the exits do not.

The idea is that I mark lastTradeTime = Time[0] whenever a trade enters. If lastTradeTime != Time[0], it should be time to close the trade... except it's not working that way. What's wrong here?

I would suggest that you use hours and minutes

 
While that would undoubtedly work, I'm interested in learning what I'm doing wrong. This type of issue with datetime variables keeps coming up. I'd like to learn what's wrong to avoid future issues.
 
texasnomad wrote >>
While that would undoubtedly work, I'm interested in learning what I'm doing wrong. This type of issue with datetime variables keeps coming up. I'd like to learn what's wrong to avoid future issues.

Well it is my experience that the date time function is more of a time stamp than anything even if you convert it to int from datetime. I am also pretty sure not many servers actually track it very well either. The general view on the grape vine is that even if you do get it to work as a comparison function it won't optimize which has to tell you something as well.

You should understand that each operator function has an underlying definition in the program core. in other words there are certain things you can do with int definitions, certain things you can do with string definitions and certain things you can do with double definitions (that are viable and generate consistant results).

Not all definitions are interchangeable nor are they suited for comparison functions.

When I am designing a program I put every operator in a comment section that I use in the program so I can see what it is doing before I actually use it. If you should have the gumption to do this you are going to find the most of the operators are not generating the kind of data you think they should be generating.

In my case I have done this proceedure with every single line of coding in my programs. So, I know what every operator function is doing and how it interrelates with every other operator in the program.

It would also appear that you are using a global format in your programming which I for the life of me cannot comprehend why in the world every programmer on this forum seems to want to do this. Most seem to think that this will make the program go faster by keeping these functions out of the loop. But, in my humble opinion this is not at all the case. The only thing you should be using in Global are FIXED functions that are NON computive and define the FIXED parameters in the program.

This is the usual way it is recommended to program any kind of program in the basic 101 hand book.

I am not going to debate this issue as I have found that I am swimming against the tide. All I can say is that my programs work just fine and are faster and more consistant than any of these balony global ones I have tried and I don't use any of this global stuff except for FIXED functions.

 

QB,

I can safely say that my opinion is not as well founded (or as strong) as yours. I simply programmed it that way because that's what seemed logical.

So if the issue revolves around inconsistency in global variables, then let's address it. If working with integers provides a more robust solution, then how do we do it?

I ask because I want to make the EA flexible on the time periods applied. The only solution I can think of using integers is if it's on a 5 min chart, see if the last minute is divisible by 5.

 
texasnomad wrote >>

QB,

I can safely say that my opinion is not as well founded (or as strong) as yours. I simply programmed it that way because that's what seemed logical.

So if the issue revolves around inconsistency in global variables, then let's address it. If working with integers provides a more robust solution, then how do we do it?

I ask because I want to make the EA flexible on the time periods applied. The only solution I can think of using integers is if it's on a 5 min chart, see if the last minute is divisible by 5.

Ok, Here is my humble opinion on the global thing.

All programs I am familiar with or have ever used should I say have a certain basic construct. And within this construct there are what you might call protocals. The basic construct is as follows:

Title and Properties

Initiialization

De-Initialization

Global Parameters

Body.

It is kind of like a car and as each part of a car has a certain function each part of the construct of the program has a certain function. When you try to make a function do something it was not designed to do then you will obviously have some problems

Title and properties if pretty obvious you have to call the program something and let the program know that it is unique.

Initialization is turning the key in the ignition to start the car

De initialization saves settings when you shut down if you want.

Global defines the gross nature of the car i.e. it looks and acts like a Chevy.

In the body are all the things that allow you to use the car (Start)

One of the best examples of the global function I think is in the CSS XHTLM programs. The CSS is in the global function. It defines what a web page is going to look like so that every page is exactly the same. It includes a list of fixed definitions as to text size and location. It does not calculate these things in any way. In the 'Body" of the program are the various pages. Each page is structured like a page and read by the computer like a page in a logical order. And there is all the flash and other fancy stuff that "computes and does something." And computers kind of like logical things and the like to read the page (program) in an orderly manner. i.e from one logical step to the next.

I have never seen any logical order in any global program yet which I find to be really really wierd. And the idea that global functions are out of the loop is ridiculous. The global functions all take priority over every thing else (maybe this is why the coders that use it that way think it is going to get things done faster). They have to be defined and stored in the program before it can go to the body. If the program has to jump around all over the place to figure out what in the world you are trying to define the car to look like before it can even get to processing and order how in the world could it possibly produce any consistant results???

Global functions are therefore usually fixed definitions just like the inputs you use at the top of the program. You don't include time[0] checks or indicator varifcations or anything else that the computer has to calculate or derive or use some other global function to derive. IT is only supposed to be used to define the fixed parameters of the program just like defining what the car looks like. Not how the car operates.

When I look at these programs it is like seeing somone turn a car upside down and put the steering wheel next to the exhaust pipe and the engine in the trunk and the wheels flat on the ground and the dashboard on the grill. And they think that it is supposed to work faster that way. You have taken all of the operational controls out of the drivers area - inside the "body" of the car. and put them outside of the body. And then these guys start blaming the historic data reliability for their problems. Wrong.

You can put anything in global that are fixed definitions but keep the conditions to the definition in the body.

int = x - period

int = close order - period - no conditions

M5 is kind of tough because because of the lack of data density per bar. The best plan I have found is to enter a position when minute()>1 && Minute()<=4 and exit when minute is <=1 on the next bar. You can divide by 5 or just go up the ladder 5 10 15 etc.

 
texasnomad:
While that would undoubtedly work, I'm interested in learning what I'm doing wrong. This type of issue with datetime variables keeps coming up. I'd like to learn what's wrong to avoid future issues.

Hello, Nice coding. I use datetimes for comparisons all the time and they work fine. Does the journal show any order errors or anything? Looks good to me, I'd start dropping in alerts as traces. I might start my debugging by doing something like this:

case 1:
            
            Alert ("Found Active Long... tradetime:" + lastTradeTime + " bar time now:" + Time[0]);
            if (lastTradeTime != Time[0]) ExitLong();
            
            break;
            
   case -1: 
            Alert ("Found Active Short... tradetime:" + lastTradeTime + " bar time now:" + Time[0]);        
            if (lastTradeTime != Time[0]) ExitShort();
            break;

 
endo77:

Hello, Nice coding. I use datetimes for comparisons all the time and they work fine. Does the journal show any order errors or anything? Looks good to me, I'd start dropping in alerts as traces. I might start my debugging by doing something like this:

And if you get THAT alert and it seems like the exits should be getting triggered then drop an alert in the exit functions with some more variables and lets see why it's not closing out the orders, you know?

 
endo77 wrote >>

And if you get THAT alert and it seems like the exits should be getting triggered then drop an alert in the exit functions with some more variables and lets see why it's not closing out the orders, you know?

endo,

Thanks for the compliment and suggestion. I'm going to try running your suggestion on short term charts and see where it leads me.

 

Good news bad news.

The ... lastTradeTime != Time[0] routine does work. For the first trade. After that it gets tricky.

The noduplicate routine seems to me to allow for both a sell and buy position to be open at the same time.(I know the logic says you should only have one or the other).

Every test I did had two orders open and that stopped the trading.

The "Have we been in a trade routine for more than one bar?" Uses switch but does not iterate through both possibilities but uses the first one it encounters

and moves onto the next command which is Entry rules. So there is no call to the other exit routine.

Easy test is to limit to one trade at a time.

Hope this helps or at least points you in the right direction

Keith

Reason: