Jeśli pracowałeś już w terminalu MetaTrader 4 to pewnie zauważyłeś, że przy uruchomieniu jakiegokolwiek standardowego wskaźnika pojawia się okienko, gdzie można zmieniać wejściowe parametry tego wskaźnika. Na poniższym obrazku widać jak wygląda takie okienko dla Stochastic, gdzie użytkownik ma możliwość zmienić jego parametry.
Rys. 1. Wejściowe parametry wskaźnika Stochastic.
W zakładce Wpisz parametry po lewej stronie widzimy nazwy parametrów tego wskaźnika (zielony prostokąt), a po prawej stronie ich domyślne wartości (niebieski prostokąt). Jest to zdecydowanie lepszy sposób na zmianę wejściowych parametrów programu niż grzebanie w kodzie źródłowym. Z drugiej strony przy optymalizacji automatycznej strategii tester strategii powinien mieć możliwość w zaprogramowany sposób zmieniać jej parametry. Może być też i tak, że mamy fajny program tylko jako plik skompilowany (*.ex4) i nie ma możliwości coś zmienić w kodzie źródłowym.
Istnieje prosty sposób aby osiągnąć taki efekt w każdym naszym programie. Pokażę to na przykładzie poniższego skryptu.
#property strict
#property script_show_inputs
//--- inicjalizacje zmiennych jako zewnętrzne parametry skryptu
input int age = 25;
input double height = 1.95;
input string dog_name = "Puszek Okruszek";
//--- główna funkcja skryptu
void OnStart()
{
}
Widzimy tu dobrze już nam znaną dyrektywę #property , która występuje tu dwa razy. W pierwszej linijce obok niej jest właściwość strict, a w drugiej script_show_inputs i właśnie ta druga komenda jest odpowiedzialna za pojawienie się okienka jak na rys. 1 i jest stosowana tylko w skryptach. Ani w wskaźnikach ani w strategiach automatycznych nie trzeba jej pisać.
Dalej utworzono trzy zmienne, gdzie najpierw zapisano modyfikator input, potem typ i nazwę zmiennej. Dalej po znaku = każdej zmiennej przypisano odpowiednie wartości.
Na poniższym rysunku widać, że po uruchomieniu tego skryptu też pojawi się okienko.
Rys. 2. Wejściowe parametry skryptu.
W kolumnie Zmienne widzimy ich oryginalne nazwy (rys. 2). Jako twórca tego skryptu znam ich przeznaczenie i można też intuicyjnie się domyśleć o ich roli w programie. Ale gdybym użył innych nazw, np. A, B i C to ja bym nadal wiedział o co chodzi, ale inny użytkownik nie koniecznie. Z drugiej strony jeśli napiszę program, zawierający dużo zewnętrznych parametrów to i ja mogę się wśród nich pogubić. Istnieje przyjaźniejszy sposób poinformowania użytkownika o roli każdego parametru - po prawej stronie od niego napisać komentarz jednowierszowy (kod 2).
#property strict
#property script_show_inputs
//--- inicjalizacje zmiennych jako zewnętrzne parametry skryptu
input int age = 25; // Mój wiek
input double height = 1.95; // Mój wzrost
input string dog_name = "Puszek Okruszek"; // Imię pieska sąsiadki
//--- główna funkcja skryptu
void OnStart()
{
Print("Mam " , age , " lat.");
Print("Mam " , height , " cm zwrostu.");
Print("Imię pieska sąsiadki " , dog_name , ".");
}
W tym kodzie po prawej stronie od każdej zmiennej, po // zapisano komentarz, a w ciele głównej funkcji OnStart() umieszczono trzy funkcje Print(), które wyświetlą odpowiednie informacje w logach terminala (rys. 3).
Rys. 3. Wejściowe parametry skryptu z komentarzami.
Teraz to wygląda o wiele lepiej . Po kliknięciu na OK w logach terminala w zakładce Strategie zobaczymy wynik działania skryptu.
Rys. 4. Wynik działania skryptu.
W zakładce Strategie w kolumnie Czas widzimy datę i dokładny czas pojawienia się każdego wpisu. W kolumnie Wiadomość począwszy od dołu idą:
W celu ogłoszenia zmiennej jako parametr zewnętrzny zamiast input można także stosować modyfikator extern. Jedyna różnica między nimi jest taka, że zmienna ogłoszona jako input staje się stałą i dostępna jest tylko do odczytu. Z kolei zmienna z modyfikatorem extern może być zmieniana w trakcie działania programu.
Jeśli spróbujesz skompilować poniższy kod, gdzie skrypt będzie próbował age zmienić na 18, to kompilator wyświetli błąd: 'age' - constant cannot be modified i ten skrypt nie będzie działać w MetaTrader 4.
#property strict
#property script_show_inputs
input int age = 25; // Mój wiek
//---
void OnStart()
{
age++; /* dodanie 1 do zmiennej age,
kompilator wykryje błąd,
ponieważ nie można zmienić
zewnętrzną zmienną typu input */
Print("Za rok będę miał " , age , " lat.");
}
Jeśli będziesz chciał mieć możliwość zmiany wartości zewnętrznego parametru, to zamiast input zastosuj extern. Na przykład w poniższym kodzie age znowu spróbujemy zamienić na 18 i to nam się uda.
#property strict
#property script_show_inputs
extern int age = 25; // Mój wiek
//---
void OnStart()
{
age++; /* dodanie 1 do zmiennej age,
nie ma błędu, ponieważ można
zmienić zewnętrzną zmienną typu extern */
Print("Za rok będę miał " , age , " lat.");
}
Parę rzeczy, o których należy pamiętać:
W przypadku gdyby wartość zewnętrznego parametru chciałbyś przechowywać w tablicy, to ten parametr należy po prostu skopiować do odpowiedniego elementu tablicy (kod 5).
#property strict
#property script_show_inputs
//--- parametry input
input string Friend_A = "Bartek"; // Konkretny kolega z pracy
input string Friend_B = "Kasia"; // Miła koleżanka z pracy
input string Friend_C = "Michał"; // Sąsiad
input string Friend_D = "Magda"; // Sąsiadka
input string Friend_E = "Benek"; // Fajny gość
//--- deklaracja tablicy składającej się z 5 elementów
string Friend_name[5];
void OnStart()
{
//--- kopiowanie zewnętrznych parametrów do tablicy
Friend_name[0] = Friend_A;
Friend_name[1] = Friend_B;
Friend_name[2] = Friend_C;
Friend_name[3] = Friend_D;
Friend_name[4] = Friend_E;
}
Osobiście zalecam stosowanie input. Jeśli w programie spodziewana jest modyfikacja wartości zewnętrznego parametru, to należy utworzyć zmienną globalną, skopiować do niej wartość i dalej pracować z tą nową zmienną (kod 6).
#property strict
#property script_show_inputs
input int age = 25; // Mój wiek
int age_value;
//---
void OnStart()
{
age_value = age; // kopiowanie wartości z age do age_value
age_value++; // dodanie 1 do zmiennej age_value
Print("Za rok będę miał " , age_value , " lat.");
}