Monday, March 2, 2009

Writing Experts for MetaTrader. Lesson number 20

Hello, dear readers. In the last issue we wrote AMA Kaufman. Thanks to one of the readers of the magazine, under the nick of Simca, in the code indicator errors. So they had an interesting prepositional pattern optimization code. This issue will be an answer to a question from readers of the magazine.

Correction of errors and optimization

The fundamental problem is the computation of the variable signal.
In the past, the code variable is as follows:
signal = abs (c [shift]-c [shift + n-1]);

Revised looks like this:
signal = abs (c [shift]-c [shift + n]);

Variable signal was considered to be at 1 bar less regulation.

Some readers may say that the optimization of a small code does not make sense, especially if the computer several GHz processor and RAM, a few hundred MB. In fact, it is not, load the MT that it would not display a custom indicator for all history, it is not difficult. Especially when the code is not optimized.

Rather than a beautiful time of the last Law is that the past value of the indicator we read directly from the array of indicators. This can be easily avoided. We know that when you restart indicator (expert), the old values are saved. It is therefore easier to use the structure of this type.

AMA (new) = AMA (old) + ....

Give part of a letter which I wrote Dear Simca.

<... Your piece looks like this:

AMA1 = c [Nbars];
For shift = Nbars Downto 0 Begin
...
AMA = (c [shift] * ssc * ssc) + GetIndexValue (shift +1) * (1-ssc * ssc);
if shift = Nbars then AMA = (c [shift] * ssc * ssc) + AMA1 * (1-ssc * ssc);
SetIndexValue (shift, AMA);
End;

I would have written the same thing like this:

AMA = c [Nbars];
For shift = Nbars Downto 0 Begin
...
AMA = (c [shift] * ssc * ssc) + AMA * (1-ssc * ssc);
SetIndexValue (shift, AMA);
End;

I so easily. :) There is no point in taking the previous value of AMA array, and so it will continue from the previous cycle. A primary value that you set through an AMA1 and checks at each iteration, it is possible to simply assign the first cycle of the variable AMA. The essence remains unchanged, but the algorithm much easier. Chance of AMA1 in this case did not need. :) ....>

But that did not stop Dear Simca, quote the following letter.

<... In general, my algorithm is an indicator of changes made after as follows:

---
Inputs: Range (10), FastMA (2), SlowMA (30);
Variables: cb (0), i (0), Noise (0), ER (0), SSC (0), AMA (0);
SetLoopCount (0);
AMA = Close [Bars-Range];
for cb = Bars-Range-1 downto 0 begin
Noise = 0;
for i = cb to cb + Range-1 begin
Noise = Noise + Abs (Close [i]-Close [i +1]);
end;
ER = Abs (Close [cb]-Close [cb + Range]) / Noise;
SSC = ER * (2 / (FastMA +1) -2 / (SlowMA +1)) +2 / (SlowMA +1);
AMA = Close [cb] * SSC * SSC + AMA * (1-SSC * SSC);
SetIndexValue (cb, AMA);
end;
---

As you can see, I do not use the "number of bars for displaying" (Nbars) and displays it on all the available range of bars. This is certainly not a question of principle, just my comp. perfectly able to calculate the entire range. :)
Instead, I used to shift writing cb (the reduction of CurrentBar). :) I think of Bars (Bars-Range-1) that the inner loop does not jump out of the number of bars. Accordingly, the values for the first AMA has the price bar before the first computed (Bars-Range). Variable signal, I did not describe the individual and moved directly into the calculation of ER because it is still not used anywhere else. Everything else we have already discussed. :) In general there, and so everything is clear and nothing special to describe. :)

Now turn to the actual improvement of what exists. Let's start with the calculation of SSC. Is obvious that in the heap calculated parameters do not depend on variable cycle. Logic would be to calculate them once before the cycle and ready to use within the meaning. I am not inventing anything here, all this was actually in the article.
2 / (SlowMA +1) - is a so-called "SlowSC" (the term of the article).
2 / (FastMA +1) - this "FastSC".
Since inside the loop itself "FastSC" We are not interested, but only important difference FastSC-SlowSC, it will use two pre-(before the main cycle) is calculated coefficient:

k1 = 2 / (SlowMA +1);
k2 = 2 / (FastMA +1)-k1;

After this calculation SSC becomes much shorter (and more importantly fast:), type):

SSC = ER * k2 + k1;

Furthermore. In calculating the AMA in the classic form of using too many multiplications (unjustified luxury). :) Then transform the formula to a more acceptable type (will be faster). Type conversion is in the article, but if it is not obvious, Sign it in more detail:

Price - Price Close [cb].
AMA1 - previous AMA (but we remember it:) that would be simple to use with the AMA last iteration cycle).

AMA = Price * SSC ^ 2 + AMA1 * (1-SSC ^ 2);
cutting brackets
AMA = Price * SSC ^ 2 + AMA1-AMA1 * SSC ^ 2;
rearrange the elements for the convenience
AMA = AMA1 + Price * SSC ^ 2-AMA1 * SSC ^ 2;
well and will make the brackets for the SSC ^ 2
AMA = AMA1 + SSC ^ 2 * (Price-AMA1)

Now the calculation of AMA is of the form:

AMA = AMA + SSC * SSC * (Close [cb]-AMA);

Here is another thing:) just two multiplications and additions are not added. :)
This type of formula too was in the article.

Well like everything that can be soptimizirovali. At least I thought so.
Total received indicator as follows:

---
Inputs: Range (10), FastMA (2), SlowMA (30);
Variables: cb (0), i (0), k1 (0), k2 (0), Noise (0), ER (0), SSC (0), AMA (0);
SetLoopCount (0);
k1 = 2 / (SlowMA +1);
k2 = 2 / (FastMA +1)-k1;
AMA = Close [Bars-Range];
for cb = Bars-Range-1 downto 0 begin
Noise = 0;
for i = cb to cb + Range-1 begin
Noise = Noise + Abs (Close [i]-Close [i +1]);
end;
ER = Abs (Close [cb]-Close [cb + Range]) / Noise;
SSC = ER * k2 + k1;
AMA = AMA + SSC * SSC * (Close [cb]-AMA);
SetIndexValue (cb, AMA);
end;
---

In order to definitively confirm that we are all done correctly (since we only optimize the algorithm without changing its substance) start to schedule both LEDs simultaneously. We see the full hundred percent match curves. So optimization is correct. :) But the second option would be to work faster. ... "

It is exemplary!

I want to reiterate one of the main points of optimization. AMA (new) = AMA (old) + .... It allows you not to read back the value of the indicator array. Since indicators used in its formula the past value itself is not small, all it would be useful to adopt this, simple and comfortable, reception.

The answer to the question

Dear Yuri asked.
<... How can I make that adviser covered position (if any) on the instrument at the close of the bar and entered the market at the time of forming the next new bar. ... "

MT is not that is about to close a bar. But the MT knows the exact time. It will come.

Here is some code that closes the position before closing the bar H1. By analogy to the opening position, I think you can do yourself.

if Minute = 59 then (
if TotalTrades> 0 then
(
for cnt = 1 to TotalTrades
(
if OrderValue (cnt, VAL_TYPE) <= OP_SELL and
OrderValue (cnt, VAL_SYMBOL) = Symbol then
(
If OrderValue (cnt, VAL_TYPE) = OP_BUY then
(
CloseOrder (OrderValue (cnt, VAL_TICKET), OrderValue (cnt, VAL_LOTS), Bid, 3, Violet);
exit;
);
If OrderValue (cnt, VAL_TYPE) = OP_SELL then
(
CloseOrder (OrderValue (cnt, VAL_TICKET), OrderValue (cnt, VAL_LOTS), ask, 3, Violet);
Exit;
);
);
);)
);

Here is the initial value to the expert at D1: if Hour = 23 then (

Conclusion
Once again I want to express my deep gratitude, the reader, under the nick of Simca.
I am confident that all would be interesting to look at other people's work, so as not to stew in its own juice. If any of you wish to share ideas, be sure to write.




Halhalyan Arthur
artur@fxtest.ru

No comments: