Welcome to Forex-TSD!, one of the largest Forex forums worldwide, where you will be able to find the most complete and reliable Forex information imaginable.
From the list below, select the forum that you want to visit and register to post, as many times you want. It’s absolutely free. Click here for registering on Forex-TSD.
Exclusive Forum
The Exclusive Forum is the only paid section. Once you subscribe, you will get free access to real cutting-edge Trading Systems (automated and not), Indicators, Signals, Articles, etc., that will help and guide you, in ways that you could only imagine, with your Forex trading.
Elite Section
Get access to private discussions, specialized support, indicators and trading systems reported every week.
Advanced Elite Section
For professional traders, trading system developers and any other member who may need to use and/or convert, the most cutting-edge exclusive indicators and trading systems for MT4 and MT5.
There's always be something that bothered me about MT4 and that was just about every indicator has the following in the START section:
Code:
for(int i=limit; i>=0; i--)
{ ...
}
Inside that loop, calculations would be run EACH AND EVERY BAR for EACH AND EVERY BAR!! This just didn't seem right to me. I finally figured out that MT4 requires you to load the buffers or the data won't plot for the previous bars.
I assume the first MT4 programmers started the "for loop" convention and everyone followed... UNTIL NOW!
You still need the "for loop" but only to SHIFT THE BUFFERS!! No recalculations AND this should take care of the repaint problem.
How it works:
1) need a global switch variable
bool OkToInit ;
2) set it to true in the init section
OkToInit = true ; // turn switch on to load all buffers
3) in the start section load the buffers the first time through then turn off the switch and only load the current buffer.
Perhaps codersguru, mladen or cja can shed some light about this for loop convention.
THIS IS ONLY THE BEGINNING! I have more ways to improve MT4 coding. Time for MT4 to join the 21st Century.
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- drawing settings
SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID,2);
SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,2);
//---- indicator buffers mapping
SetIndexBuffer(0,RANGEBuffer);
SetIndexBuffer(1,RANGEBuffer1);
//---- name for DataWindow and indicator subwindow label
IndicatorShortName("RANGE");
SetIndexLabel(0,"RANGE");
SetIndexLabel(1,"RANGE");
OkToInit = true ; // turn switch on to load all buffers
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
Code:
int deinit()
{
}
Code:
//+------------------------------------------------------------------+
//| Range |
//+------------------------------------------------------------------+
int start()
{
datetime pTime;
int limit, pBars;
int counted_bars=IndicatorCounted();
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
if( OkToInit )
{ OkToInit = false ;
for(int i=limit; i>=0; i--)
{
// CALCULATE AND LOAD BUFFERS - ONLY DO IT ONCE!!
DoWork(i) ;
} // for
} else {
if( pBars != Bars ) // DO THIS WHEN BAR CHANGES - ONLY DO IT ONCE!!
{
for(i=limit; i>=0; i--) // SHIFT BUFFER VALUES DOWN 1 SO [X+1] = [X]
{ RANGEBuffer[i+1] = RANGEBuffer[i] ;
RANGEBuffer1[i+1]= RANGEBuffer1[i] ;
pBars = Bars ;
} // for
} // if
// CALCULATE AND LOAD CURRENT BUFFERS - [0]
DoWork(0) ;
} // if
return(0);
}
Code:
//+------------------------------------------------------------------+
void DoWork ( int w )
{
HighVal = iHigh(NULL,0,w);
LowVal = iLow(NULL,0,w);
xRange = (HighVal - LowVal) / Point ;
if (xRange >= Threshold) { RANGEBuffer1[w] = xRange ; }
else { RANGEBuffer[w] = xRange ; }
}
Last edited by TheRumpledOne; 06-14-2008 at 04:31 PM.
Although we've never conversed, I'm aware of your work, having been trading Fx for quite some time now. I'm eager to hear your ideas concerning bringing MT4's coding paradigm up-to-date. I believe I also have several ideas which can help us to do so. It's funny that you just started this thread today, b/c I was just going through some of my libraries and thinking about re-organizing them. My intention is to start an open-source project with the goal of doing exactly what you're talking about. It's been kind of a back-burner project for some time, but just recently I have gotten the infrastructure in place to make it viable (Redmine w/ subversion).
Anyway, I'd love to talk more about your ideas. This thing with the indicators has always bugged me as well...so I'm going to take a closer look at what you're proposing.
Hmmm....after looking more closely at your post...
I could be wrong here, but...
I'm not sure that, doing it the conventional way, that the while loop causes "calculations would be run EACH AND EVERY BAR for EACH AND EVERY BAR!!" I say that, because the documentation of IndicatorCounted() seems to say otherwise: "The function returns the amount of bars not changed after the indicator had been launched last. The most calculated bars do not need any recalculation. In most cases, same count of index values do not need for recalculation. The function is used to optimize calculating."
So if we take this basic setup:
Code:
int limit;
int counted_bars=IndicatorCounted();
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
for(int i=limit; i>=0; i--)
{ ...
}
I've always understood it that when this is run at startup IndicatorCounted() would be 0. So if bars was 500...then the loop would run 500 times, once for each bar. Then when bar 501 was streamed in, we'd only run the loop once (each tick) for bar 501 at index [0]. So it seems like it's efficient as far as that goes. Please correct me if I'm wrong here.
However, I do see what you're doing with the new bar calculation to avoid the re-paint. I think that's a really good idea.
My big beef with the while...loop and all this is that it can obviously be a bit confusing. I wish that the designers had abstracted that out and just left us to do the actual calculations.
One other comment. By using the global switch OkToInit we could be opening ourselves to threading problems, especially when we first start the platform. One solution to this might be a centralized service provider EA. In this case the service provider could help with the synchronization problems. There are a lot of other things that such an EA can do, some of which I already have implemented.
just check and stick with: int IndicatorCounted( )
The function returns the amount of bars not changed after the indicator had been launched last. The most calculated bars do not need any recalculation. In most cases, same count of index values do not need for recalculation. The function is used to optimize calculating.
Keep your coding simple and at least compact. Follow the tools you have. MQL4 doesn't have everything, for what you need now it is more then ok, MQL5 will be bulky and more options.
I saw your coding in your other very good idea indicators, but you really have to reuse things that you coded so many times over and over, this will speed up your processing of the final product. I could code an indicator of yours 20 times with less code and the same result. ( no meaning of pointing a finger, just... somebody has to say it )
The repainting issue... on bar[0] all the time till it becomes bar[1].
if bar[1] still changes, your math formula or combination with other indicators are wrong or it's your intention to let it do that, like trend lines that have to follow or something like that.
Whatever you use in your for() function, up calculation or downwards, think about: you don't need to recalculate things over and over again, but also know the results in different ways, you have to rely on what you make, if you see one fault, it will become a bigger one if you don't care. There are enough people that complain about computer slowdowns, well that's your answer.
If you are planning to use more loops, try to make one big one, and combine every process in one loop, or at least less then before, reuse variables...
good coding
oh yes! please, check my IN10TION newsReader
executes : bars times immediately after init 3 times on normal tick input 4 times on normal new bar tick input
I would not avoid that extra 2 executions (in 3 and 4 times) since it does not take as much processor time and ads on code "security"
also : repainting does not have anything to to with recalculating. Repainting code is a code that is supposed to do something and does something else (seems like a joke what I just said, but it is exactly that : code must be clear of "assumptions" in order not to repaint. As a lot of good coders used to say "Computer only does what you tell it to do")
First, remember I have only been coding in MT4 since Dec 2007, so I am still a MT4 rookie. But I do have over 30 years programming experience. Yes, I punched cards in the 70s...LOL!
Many of my first indicators that I posted are cut and paste "FRANKENSTEIN" code because I just wanted to get things working. When I look at that code now, I cringe. IN10TION, you're correct, that code can be better written. mladen writes really tight code... nice work!!
Perhaps, there is something I don't understand about MT4's inner workings specifically the way MT4 uses buffers and how the buffers are plotting on the chart. I posted an indicator yesterday that streams in a separate window tick by tick. Funny thing is, that is NOT what I wanted it to do, I made a mistake. When I "fixed" the mistake, I realized the mistake was actually more useful!! It made more sense, to me, to see the values tick by tick instead of bar by bar.
IN10TION, it's not my intention to use more loops. My intention was to eliminate recalculations.
mladen: you're right.. computers only do EXACTLY what you tell them to do! One must be exact in coding.
wait for live data (changing time frames, or symbols means all the bars changed) or test it with visual handle training made by klot (there is a description how to use it, but I can not remember which post, maybe ND can help. Honestly, I am too lazy to write down all the things this EA can simulate)
Quote:
int IndicatorCounted( )The function returns the amount of bars not changed after the indicator had been launched last. The most calculated bars do not need any recalculation. In most cases, same count of index values do not need for recalculation. The function is used to optimize calculating.
Note: The latest bar is not considered to be calculated and, in the most cases, it is necessary to recalculate only this bar. However, there occur some boundary cases where custom indicator is called from the expert at the first tick of the new bar. It is possible that the last tick of the previous bar had not been processed (because the last-but-one tick was being processed when this last tick came), the custom indicator was not called and it was not calculated because of this. To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one.
Some indicators make coding a lot more difficult. They operate on the last value (previous bar) to create the new value. Then IndicatorCounted() does not work!
This article tells you how to fix that. When I first read it, I thought, "I will have to read this six times before I can use it successfully." Fortunately I was wrong - it only took me four times. Plus some "trial and error."
The results: It sped up the backtesting by about 100 times, as it no longer recalculated every bar for the complicated indicator, for every tick. This obviously will speed up live execution the same.