Błąd piąty jest charakterystyczny dla programowania systemów inwestycyjnych w Amibrokerze. Wynika on ze specyficznego podejścia w nim do zmiennych tablicowych. Oczywiście wynika też z niezrozumienia do końca jak są one obsługiwane.
Ciekawe jest to, że błędy takie trafia się głównie ludziom znającym już język AFL. Dzieje się tak w wyniku tego, że zaczynają swoją drogę od systemów prostych do bardziej skomplikowanych.
Akurat tydzień przed pisaniem tego artykułu otrzymałem zapytanie od jednego z moich uczniów: "czemu nie działa?". Był tam właśnie dokładnie taki błąd.
Nie zdradzę oczywiście jego kodu. Wyobraź sobie jednak prosty system np. na wybicie z formacji świecowej. Założenia są takie, że nie inwestujesz od razu gdy formacja wystąpi, tylko czekasz na potwierdzenie. Wybicie z zakresu formacji w jedną stronę daje sygnał kupna, wybicie w drugą daje zanegowanie formacji. Klasyczna interpretacja.
W takim razie, gdy występuje formacja chcesz zapamiętać jej najwyższą wartość, oraz najniższą. Dzięki temu uzyskasz kanał dwóch cen i możesz obserwować jego przebicie.
I tu pojawił się problem. Niektórzy bowiem próbują stosować konstrukcję:
//w zmiennej "formacja" są już miejsca gdzie ona występuje.
kanalGorny = High;
kanalGorny = Iif( formacja, kanalGorny, Ref(kanalGorny,-1));
Okazuje się jednak, że to nie tworzy kanału. Działa tylko dla następnego słupka, a potem jest lipa.
Wtedy pojawiają się pytania o kolejność przetwarzania danych. No bo przecież jeżeli od lewej strony tablicy, to powinno wstawić High tam gdzie występuje formacja, a w następnych słupkach powinno przepisywać tą wartość z poprzedniej komórki.
Jeżeli też spotkałeś taki problem, to musisz sobie zadać inne pytanie. Jak w ogóle przetwarzane są zmienne w funkcjach?
Otóż wywołanie funkcji powoduje utworzenie kopii zmiennej. Dlatego tworzona na nowo zmienna kanalGorny jest inną zmienną niż zmienna kanalGorny w parametrach funkcji. Przy obliczaniu kolejnych słupków dane są czytane z oryginalnej zmiennej, a zapisywane w nowej. Dopiero po policzeniu wszystkiego stara zmienna jest zastępowana nową. Dlatego nie ma dostępu do wyniku obliczeń w trakcie liczenia.
Jak w takim razie poradzić sobie z tym problemem?
Rozwiązań jest jak zwykle kilka. Najłatwiejsze jednak do zrozumienia jest to z pętlą.
kanalGorny = High;
for(i=1; i<barsCount; i++)
{
if( !formacja ) kanalGorny[i] = kanalGorny[i-1];
}
Taki kod przeciągnie wartość kanału od formacji do końca wykresu lub do następnego wystąpienia formacji. Tam gdzie jest formacja zostawia High, a dla kolejnych słupków pobiera wartość ze słupka wcześniejszego. Tu nie ma problemu zmiennej i jej kopii. Tym prostym sposobem możesz już badać przecięcie wykresu i kanału.
Sposób zapisu za pomocą instrukcji tablicowych tu pominę. Jest on krótszy, ale znacznie trudniejszy do zrozumienia.
Zaczynaj od podstaw. Zobaczysz wtedy, że tworzenie systemów jest proste.