Fixing the ''Error 146 Trade context busy' not working' code problems - page 3

 
whocares:

Hi Doug

Note that the issues you mentioned in your 1st post is in fact not errors, but rather warnings.

If your compiler finds a function that is not used in your code you will get this message.

I use these functions "as is" from the original author. It is the perect solution for error 146. Since I have implemented it I have not had any 146 errors.

Steps to get it working:

1) Copy the files to your include folder

2) Copy the files to the header of your ea: //this is so your ea knows what you are talking about when you call these functions

#include <TradeIsBusy.mq4>
#include <TradeIsNotBusy.mq4>

3) Before ANY trade function e.g.OrderSend(); OrderClose(); OrderDelete(); OrderModify() place this line of code:

if(TradeIsBusy() < 0) return(-1);

4) Now place your trade function

5) Record outcome (or error)

6) Now release the context again

TradeIsNotBusy();

7) Now deal with any error

Works like a charm

A few lessons I learnt in the process of gettiing it working:

1) When the global variable is called for the first time is is not available. to overcome this:

put this in the deint() function:

int deinit()
{
//----
//make sute that this EA does not leave operations hanging when it closes by setting to 0
TradeIsNotBusy();

return(0);

}

Now just restart the ea.

2) I like to know what the ea is doing so I print everything to a log file including the status of the trade context. this way I know when the ea asked for the trade context and when it released it.

Good luck

whocares

Hi whocares:


I`m just implementing the solution for error 146 following the article (Error 146 "Trade context busy" and how to Deal with it") and I have a question about the use of RefreshRates().


--> You say:

(...)

3) Before ANY trade function e.g.OrderSend(); OrderClose(); OrderDelete(); OrderModify() place this line of code:

if(TradeIsBusy() < 0) return(-1);

4) Now place your trade function (...)


--> After reading the paragraph 7 (Integration into experts and use) of the article; I wonder if i need to insert RefreshRates() function after return(-1):

(...)

3) Before ANY trade function e.g.OrderSend(); OrderClose(); OrderDelete(); OrderModify() place this line of code:

if(TradeIsBusy() < 0) return(-1); RefreshRates();

4) Now place your trade function (...)


Thank you for your help,


 
blackhawk:

Hi whocares:


I`m just implementing the solution for error 146 following the article (Error 146 "Trade context busy" and how to Deal with it") and I have a question about the use of RefreshRates().


--> You say:

(...)

3) Before ANY trade function e.g.OrderSend(); OrderClose(); OrderDelete(); OrderModify() place this line of code:

if(TradeIsBusy() < 0) return(-1);

4) Now place your trade function (...)


--> After reading the paragraph 7 (Integration into experts and use) of the article; I wonder if i need to insert RefreshRates() function after return(-1):

(...)

3) Before ANY trade function e.g.OrderSend(); OrderClose(); OrderDelete(); OrderModify() place this line of code:

if(TradeIsBusy() < 0) return(-1); RefreshRates();

4) Now place your trade function (...)

You should only use RefreshRates() if u r using one of the predefined variables immediately after, otherwise no need. From the article:

    if(TradeIsBusy() < 0) 
        return(-1); 
    // refresh the market info
    RefreshRates();
    // recalculate the levels of StopLoss and TakeProfit
    ...
    // open a position
    if(OrderSend(...) < 0) 
      { 
       Alert("Error opening position # ", GetLastError()); 
      }

So here he used RefreshRates() because some of the predefined variables are used to calculate tp/sl or used in OrderSend()...

 
gordon:

[...] So here he used RefreshRates() because some of the predefined variables are used to calculate tp/sl or used in OrderSend()...

The alternative is to use MarketInfo(Symbol(), MODE_ASK) and MarketInfo(Symbol(), MODE_BID) throughout, instead of Ask and Bid. This avoids any ambiguity about whether Ask and Bid are up to date, and the need to remember to use RefreshRates().


Since it's something of a favourite topic of conversation between Gordon and me, I'll mention that the MarketInfo() route has a performance penalty attached: anything up to 1 microsecond per call.

 
jjc:

The alternative is to use MarketInfo(Symbol(), MODE_ASK) and MarketInfo(Symbol(), MODE_BID) throughout, instead of Ask and Bid. This avoids any ambiguity about whether Ask and Bid are up to date, and the need to remember to use RefreshRates().


Since it's something of a favourite topic of conversation between Gordon and me, I'll mention that the MarketInfo() route has a performance penalty attached: anything up to 1 microsecond per call.

You'll be surprised but I too use MarketInfo() exclusively. I don't have a single RefreshRates(). The only thing I hate is how long the code becomes this way, so I have a bunch of small getBid(), getAsk(), etc. functions that return MarketInfo() data... That probably makes it even slower!!!

 
gordon:

You'll be surprised but I too use MarketInfo() exclusively. I don't have a single RefreshRates(). The only thing I hate is how long the code becomes this way, so I have a bunch of small getBid(), getAsk(), etc. functions that return MarketInfo() data... That probably makes it even slower!!!

In which case, my testing suggests that:


double getBid() {RefreshRates();return (Bid);}


is marginally faster (about 0.2 microseconds per call) than:


double getBid() {return (MarketInfo(Symbol(), MODE_BID));}


But I'm struggling to conceive of a scenario where the speed difference between any of these makes any meaningful difference.

 
jjc:

In which case, my testing suggests that:


double getBid() {RefreshRates();return (Bid);}


is marginally faster (about 0.2 microseconds per call) than:


double getBid() {return (MarketInfo(Symbol(), MODE_BID));}


But I'm struggling to conceive of a scenario where the speed difference between any of these makes any meaningful difference.


I'll bite.


Here is an amusing anecdote for ya: when running on chart, it seems that on average the lower the symbol in the Market Watch list, the slower MarketInfo() behaves. It must be searching for the symbol first and only then returning it's property. Here's the results for the symbols sorted by their order (reverse order, XAGUSD is at the bottom) in my Market Watch window (which I never actually use, so it's their default sort order...):


2010.02.16 11:23:23	test EURCHF,Daily: getBid2() for XAGUSD: 3.43 uSec
2010.02.16 11:22:48	test EURCHF,Daily: getBid2() for XAUUSD: 3.57 uSec
2010.02.16 11:22:13	test EURCHF,Daily: getBid2() for USDHKD: 3.49 uSec
2010.02.16 11:21:38	test EURCHF,Daily: getBid2() for SGDJPY: 3.50 uSec
2010.02.16 11:21:03	test EURCHF,Daily: getBid2() for USDSEK: 3.39 uSec
2010.02.16 11:20:29	test EURCHF,Daily: getBid2() for USDNOK: 3.16 uSec
2010.02.16 11:19:57	test EURCHF,Daily: getBid2() for USDDKK: 2.93 uSec
2010.02.16 11:19:28	test EURCHF,Daily: getBid2() for NZDJPY: 2.55 uSec
2010.02.16 11:19:02	test EURCHF,Daily: getBid2() for CADJPY: 2.73 uSec
2010.02.16 11:18:35	test EURCHF,Daily: getBid2() for CADCHF: 2.81 uSec
2010.02.16 11:18:07	test EURCHF,Daily: getBid2() for AUDCHF: 2.51 uSec
2010.02.16 11:17:42	test EURCHF,Daily: getBid2() for AUDCAD: 2.28 uSec
2010.02.16 11:17:19	test EURCHF,Daily: getBid2() for AUDNZD: 2.08 uSec
2010.02.16 11:16:58	test EURCHF,Daily: getBid2() for AUDJPY: 2.17 uSec
2010.02.16 11:16:37	test EURCHF,Daily: getBid2() for EURNZD: 2.19 uSec
2010.02.16 11:16:15	test EURCHF,Daily: getBid2() for CHFJPY: 1.91 uSec
2010.02.16 11:15:55	test EURCHF,Daily: getBid2() for NZDUSD: 1.96 uSec
2010.02.16 11:15:36	test EURCHF,Daily: getBid2() for USDSGD: 1.79 uSec
2010.02.16 11:15:18	test EURCHF,Daily: getBid2() for EURAUD: 1.54 uSec
2010.02.16 11:15:03	test EURCHF,Daily: getBid2() for EURCAD: 1.35 uSec
2010.02.16 11:14:49	test EURCHF,Daily: getBid2() for GBPCHF: 1.18 uSec
2010.02.16 11:14:37	test EURCHF,Daily: getBid2() for GBPJPY: 1.11 uSec
2010.02.16 11:14:26	test EURCHF,Daily: getBid2() for EURJPY: 1.09 uSec
2010.02.16 11:14:15	test EURCHF,Daily: getBid2() for EURCHF: 0.97 uSec
2010.02.16 11:14:06	test EURCHF,Daily: getBid2() for EURGBP: 0.89 uSec
2010.02.16 11:13:57	test EURCHF,Daily: getBid2() for USDCAD: 0.81 uSec
2010.02.16 11:13:49	test EURCHF,Daily: getBid2() for AUDUSD: 0.73 uSec
2010.02.16 11:13:41	test EURCHF,Daily: getBid2() for EURUSD: 0.70 uSec
2010.02.16 11:13:34	test EURCHF,Daily: getBid2() for USDJPY: 0.64 uSec
2010.02.16 11:13:28	test EURCHF,Daily: getBid2() for GBPUSD: 0.53 uSec
2010.02.16 11:13:23	test EURCHF,Daily: getBid2() for USDCHF: 0.47 uSec


The 1st version of getBid() has about constant speed. So when running on chart, the difference in the 2 version's performance depends on Market Watch user settings... But even if using the bottom symbol (and no matter how many symbols u have), I agree... I can't conceive of a scenario where it matters either.



In the Tester on the other hand it's a whole other story. From my testing the timing is the same for all symbols:

11:26:08 test started for testing
11:26:09 2009.06.08 00:00  test USDCHF,M1: getBid1() for USDCHF: 0.10 uSec
11:26:10 2009.06.08 00:00  test USDCHF,M1: getBid2() for USDCHF: 0.36 uSec
11:26:14 test started for testing
11:26:17 2009.06.08 00:00  test GBPUSD,M1: getBid1() for GBPUSD: 0.10 uSec
11:26:18 2009.06.08 00:00  test GBPUSD,M1: getBid2() for GBPUSD: 0.36 uSec
11:26:22 test started for testing
11:26:30 2009.06.08 00:00  test USDJPY,M1: getBid1() for USDJPY: 0.10 uSec
11:26:31 2009.06.08 00:00  test USDJPY,M1: getBid2() for USDJPY: 0.36 uSec
11:26:34 test started for testing
11:26:40 2009.06.08 00:00  test EURUSD,M1: getBid1() for EURUSD: 0.10 uSec
11:26:41 2009.06.08 00:00  test EURUSD,M1: getBid2() for EURUSD: 0.36 uSec
11:26:44 test started for testing
11:26:54 2009.06.08 00:00  test AUDUSD,M1: getBid1() for AUDUSD: 0.10 uSec
11:26:55 2009.06.08 00:00  test AUDUSD,M1: getBid2() for AUDUSD: 0.36 uSec
11:27:09 test started for testing
11:27:09 2009.06.08 00:00  test USDSGD,M1: getBid1() for USDSGD: 0.10 uSec
11:27:10 2009.06.08 00:00  test USDSGD,M1: getBid2() for USDSGD: 0.36 uSec
11:27:16 test started for testing
11:27:37 2009.08.10 00:00  test XAGUSD,M1: getBid1() for XAGUSD: 0.10 uSec
11:27:38 2009.08.10 00:00  test XAGUSD,M1: getBid2() for XAGUSD: 0.36 uSec
11:28:01 test started for testing
11:28:01 2009.08.10 00:00  test CADJPY,M1: getBid1() for CADJPY: 0.10 uSec
11:28:03 2009.08.10 00:00  test CADJPY,M1: getBid2() for CADJPY: 0.36 uSec


Now let's do a similar calculation as before (with no hidden assumption this time, sorry for that) - let's say the functions (getBid(), getAsk(), getDigits(), etc. - only the functions that get one of the predefined variables) are called on average 100 times per tick (assume it's a complex EA). Like before, let's say on average the EA closes after 10,000 ticks and optimization is done over 10,000 passes:


Time diff = 100x(0.36-0.1)x10^-6x10,000x10,000 = 2600 Secs = ~43 Minutes.


I agree it's not a big difference... But still, IMHO, it's worth using version number 1 (which I am from now on, thanks for the idea).

Reason: