Kod może być poprawny, a mimo to obliczać inny wynik niż zamierzony. Debugger pozwala zatrzymać wykonanie, obejrzeć zmienne i śledzić instrukcje po kolei.

Zbadamy odległość zamknięcia od pięcioświecowej średniej. Najpierw przewidzisz wynik, potem sprawdzisz obliczenie programu.

Trzy rodzaje błędów

Błąd składni narusza reguły zapisu, na przykład brakuje dwukropka lub wcięcie jest błędne. Edytor często zgłasza go już podczas pisania.

Błąd wykonania występuje przy uruchomieniu. Możesz na przykład odczytać indeks tablicy bez odpowiadającego elementu. Program może wtedy zatrzymać się z komunikatem.

Przy błędzie logicznym program może działać. average - close zamiast close - average odwraca znak. Reguły języka na to pozwalają, więc sam porównujesz wynik z zadaniem.

W View → Problems programu Visual Studio Code znajdziesz problemy zgłoszone przez edytor. Kliknij wiersz, by przejść do miejsca błędu. Zanim zmienisz wiele linii, przeczytaj dokładny komunikat.

Program do zbadania

Utwórz debug_average.py:

"""
@pyne edge
"""
from pynecore import Series
from pynecore.lib import bar_index, close, color, log, plot, script, ta


@script.indicator("Average Distance", overlay=False)
def main():
    average: Series[float] = ta.sma(close, 5)
    gap = close - average
    if bar_index == 10:
        log.info("close={0}, average={1}, gap={2}", close, average, gap)
    plot(gap, "Distance", color=color.blue)

bar_index to numer bieżącej świecy od zera. Indeks 10 oznacza jedenastą. W tym historycznym przebiegu zapis dziennika następuje więc tylko raz.

log.info tworzy sformatowaną wiadomość. {0}, {1} i {2} zastępowane są trzema podanymi wartościami w tej kolejności. Tekst z numerowanymi miejscami przetwarza mechanizm logowania.

Uruchom raz przez Run Pyne code. Linia powinna być dodatnia przy zamknięciu nad średnią. Na pierwszych czterech świecach brakuje średniej i odległości.

Zatrzymanie przed wierszem

  1. Kliknij po lewej stronie numeru wiersza plot(gap, ...). Pojawi się punkt przerwania.
  2. Kliknij Debug nad kodem.
  3. Jeśli otworzy się wybór danych, wybierz demo.
  4. Program zatrzyma się na punkcie. Otwórz Run and Debug.

Punkt przerwania to miejsce zatrzymania programu. Zaznaczony wiersz jeszcze się nie wykonał. Wyniki wcześniejszych przypisań są już dostępne.

Pierwszy postój może wypaść na pierwszej świecy. gap jest tam brakujące, bo nie ma pełnego okna pięciu świec. Debugger pokazuje ten stan; sam brak nie oznacza błędu.

Przejdź za rozgrzewkę

Na pływającym pasku debuggera przycisk PyneIDE Next Bar przechodzi do kolejnej świecy. Nazwy ikon odczytasz po najechaniu. Znajdź Run to Bar…, kliknij, wpisz 10 i naciśnij Enter.

Na jedenastej świecy jest już pełne okno. W Variables odszukaj average i gap. W grupie Pyne sprawdzisz dane świecy, między innymi bar_index i close.

debug_average.py stoi na punkcie przerwania w PyneIDE; Run and Debug pokazuje zmienne i dane świecy w grupie Pyne.
W zatrzymanym programie można równocześnie badać dane świecy i własne zmienne.

average jest zmienną Series, więc w kodzie możesz użyć average[1] jako poprzedniej wartości. Poprzednia średnia nie musi równać się obecnej, bo okno przesunęło się o świecę.

Obserwowane wyrażenia

W Watch dodasz wyrażenia widoczne przy każdym zatrzymaniu. Wypróbuj:

close
close[1]
average
close - average

close[1] to zamknięcie poprzedzające zatrzymaną świecę. average jest twoją zmienną. Wynik close - average powinien być równy policzonemu gap.

Obserwuj zmienne i prostą arytmetykę. Nie wpisuj do Watch ta.sma, operacji składających zlecenia ani modyfikujących tablicę. Kontrola nie powinna zmieniać stanu programu.

Po wierszach i po świecach

Step Over przechodzi do następnej instrukcji bez wchodzenia w szczegóły funkcji. Step Into może wejść do własnej funkcji. Continue kontynuuje do następnego postoju. Disconnect rozłącza debugger i kończy sesję.

Next Bar ma inną skalę: przechodzi do kolejnej świecy. Kroki wierszowe pokazują obliczenia jednej świecy, a świecowe ich zmiany w czasie.

Zatrzymana świeca nie jest jeszcze w pełni przetworzona, więc wykres może pokazywać wcześniejszy ukończony stan. Bieżący indeks i dane sprawdzaj w Pyne.

Przed odczytem zmiennej zobacz zaznaczony wiersz. Jeśli przypisanie jest jeszcze przed tobą, zmienna nie ma dopiero oczekiwanego wyniku.

Wykrycie błędu znaku

Zatrzymaj debugger i zmień wiersz na:

gap = average - close

Włącz debugowanie ponownie i przejdź do tej samej świecy. Przy cenie nad średnią gap będzie ujemne, mimo że zadanie wymagało dodatniej odległości.

Watch z close - average nadal pokazuje zamierzony kierunek. Porównanie natychmiast ujawnia różnicę. Przywróć poprawne odejmowanie i sprawdź jeszcze raz tę świecę.

Spróbuj samodzielnie

Dodaj previous_close = close[1] i obejrzyj zmienną w debuggerze. Przy indeksie 10 z której świecy ma pochodzić zamknięcie? Co zawiera na pierwszej?

Rozwiązanie zadania
previous_close = close[1]

Na świecy 10 zwraca zamknięcie świecy 9. Na pierwszej, z indeksem 0, brakuje wartości, bo plik nie ma wcześniejszej świecy.

Umieść wiersz przed punktem przerwania, by był już wykonany. Po kontroli możesz usunąć zmienną pomocniczą i wpis dziennika używany tylko do sprawdzania.

Dobry opis błędu

Prosząc o pomoc, podaj plik, dane, faktyczne wejścia i czas badanej świecy. Zapisz oczekiwaną i otrzymaną wartość. Zamiast „linia jest zła”: „na tej świecy zamknięcie to 101, średnia 100, a odległość wyszła −1”. Takie obliczenie da się sprawdzić.