Prawie każdy, komu udało się przewidzieć coś przy pomocy uczenia maszynowego, mniej więcej trzy sekundy po sukcesie wyobraził sobie, jak przewiduje przyszłe wartości spółek giełdowych (lub kryptowalut – ale to przestało być modne ostatnio ;-)). Szczególnie jeśli ostatnio oglądał film Pi (gorąco polecam – nie widzę niestety na żadnym VOD). Giełda, jaka jest, każdy widzi. Próg wejścia wynosi mniej więcej 1000 PLN (żeby zminimalizować prowizje), a założenie rachunku maklerskiego to wyklikanie formularza w internecie i podpisanie druczków u kuriera. Wychodzi więc, że każdy może zostać drugim Warrenem Buffettem. Ale czy na pewno?
Jeśli sięgniemy po literaturę dla początkujących (np. Giełda Papierów Wartościowych dla bystrzaków), to od razu natrafimy na koncepcje analizy fundamentalnej i analizy technicznej. Analiza fundamentalna mówi nam mniej więcej, że jeśli wczytamy się w raporty spółki, sytuację globalną i branżową oraz dokonamy własnych analiz, to będziemy w stanie określić czy warto lub nie warto inwestować w daną spółkę. Analiza techniczna natomiast mówi coś takiego: popatrz na wykresy i na ich bazie wylicz sobie 200+ współczynników, na podstawie których wyliczysz sobie czy warto inwestować, czy nie.
Nie wiem która metoda analityczna jest lepsza. Wiem natomiast dlaczego analiza techniczna wydaje być atrakcyjniejsza dla osoby zaznajomionej z uczeniem maszynowym. W analizie fundamentalnej większość danych jest nieprzetworzona. Trzeba zdobyć dużo informacji i je przystosować do formy przydatnej w uczeniu maszynowym. Dane te też nie są publikowane w sposób ciągły. No i standardy też mogą się różnić. Chyba że płaci się ciężkie pieniądze firmie analitycznej, która je dla nas przygotuje. Natomiast analiza techniczna zasadniczo zacznie „działać” jeśli mamy dzienne dane o otwarciu, zamknięciu, maksimum, minimum i volumenie spółki giełdowej. A takie dane są już tabelką i dość łatwo je uzyskać za darmo. Napisałem „działać” w cudzysłowie, bo to, czy zarobimy w ten sposób, jest sprawą mocno dyskusyjną.
Tak czy siak, temat wydaje się atrakcyjny na tyle (bogactwo!), że prędzej lub później każdy będzie chciał spróbować z nim swoich sił. Pomyślałem więc, że ten artykuł dedykuję wstępowi do analizy danych ceny spółki giełdowej. Czy coś z tego wyjdzie – nie sądzę. Ale dane i kontekst będą prawdziwe, więc czemu by nie?
Dane
Dane, które będą używane, pochodzą z serwisu bossa.pl i możesz ich używać osobiście w celu niekomercyjnym. W notebooku, który przygotowałem, sprawdzam najpierw, czy odpowiednim katalogu są już rozpakowane pliki csv. Jeśli są, to je wczytuję i sprawdzam, czy są tam dane z ostatniego wcześniejszego niż aktualny dnia giełdowego. Jeśli nie ma plików albo są starsze, to pobieram ich nową paczkę, rozpakowuję i wczytuję ponownie. W ten sposób „automatycznie” będziemy mieli dane giełdowe do „wczoraj”.
Nie będę tutaj wklejał wnętrza funkcji, które stworzyłem do ogarnięcia danych (zobaczysz je w notebooku), pokażę natomiast kiedy i jak ich używam:
# Kod 1 try: stock_data = prepare_data() except FileNotFoundError: print("Stock data not found. Downloading and extracting.") download_fresh_data() unzip_data() stock_data = prepare_data()
Powyższy fragment uruchamia m.in. funkcję wczytującą, która zagląda do ścieżki „../output/stock_data/” w poszukiwaniu pliku „CDPROJEKT.txt”. Jeśli go nie znajduje (except FileNotFoundError:) to pobiera odpowiedni plik zip i go tam rozpakowuje i wczytuje. Obojętnie czy plik został wczytany od razu, czy po ściągnięciu sprawdzam jeszcze datę ostatniego wpisu. W sumie, jeśli go przed chwilą ściągnąłem, to nie powinienem tego robić, jednak sprawdzenie to jest na tyle szybkie, że je tu pozostawiłem. Po co sprawdzam datę wpisu? Może okazać się, że ostatni raz pracowałem nad notebookiem miesiąc temu i rozpakowane pliki już tam leżą. Jeśli nie sprawdzę daty wpisów, to będę przeglądał dane sprzed miesiąca. W poniższym wypadku szukam ostatniego dnia z zakresu poniedziałek – piątek wcześniejszego niż aktualny i sprawdzam, czy jest w ramce danych (prawie zawsze zadziała sensownie):
# Kod 2 last_stock_day = get_last_stock_day() print(last_stock_day) last_data = "{}-{:02d}-{:02d}".format(last_stock_day.year,last_stock_day.month,last_stock_day.day) print("Looking for {}".format(last_data)) try: stock_data.loc[last_data] print("We have it!") except KeyError: print("Fresh stock data not found. Downloading and extracting.") download_fresh_data() unzip_data() stock_data = prepare_data()
W ten dość toporny, ale automatyczny sposób zapewniamy sobie aktualne dane do naszej przyszłej analizy. Na potrzeby tego artykułu stworzymy sobie jeden współczynnik, który będziemy sobie oglądać na wykresie. Będzie to średnia krocząca. Dlaczego taki? Mam wrażenie, że średnia krocząca to jeden najbardziej intuicyjnych pomysłów, które mogą być przydatne w kontekście giełdy. A jeśli nie, to z tego, co pamiętam, to nie pokazywałem jeszcze jak zrobić średnią kroczącą w Pandas. Wyliczmy więc średnią z 30 dni i wrzućmy ją jako nową kolumnę:
# Kod 3 stock_data["SMA"] = stock_data["Close"].rolling(30).mean()
Obejrzyjmy sobie wreszcie końcówkę naszej ramki danych:
W powyższej tabelce widać, że dniowe dane giełdowe dla konkretnej spółki składają się z czterech wartości cenowych (High, Low, Open, Close), jednej ilościowej (Volume) i jednej czasowej (data, która jest indeksem). Trochę więc trudno wyobrazić sobie budowanie strategii inwestycyjnej na lata na bazie tych sześciu wartości. Ale próbować można.
Wizualizacja
Stwórzmy więc sobie wykres sytuacji giełdowej mojej ulubionej spółki. Żeby nie zaciemniać sytuacji, weźmy sobie ostatnie 365 dni kalendarzowych. Z tych dni weźmy sobie wartości High i Low, czyli widełki, w których odbywały się transakcje danego dnia i wspomnianą średnia z wartości Close (SMA) – czyli ceny, jaka pojawiła się jako ostatnia danego dnia. Jak ja bym interpretował taki wykres? Jeśli linia SMA jest poniżej widełek, to znaczy, że spółka idzie wyraźnie w górę. Jeśli SMA jest powyżej widełek, to spółka idzie wyraźnie w dół. I tyle. Nie radzę nikomu (a nawet nie mogę) podejmować żadnych decyzji inwestycyjnych na tej podstawie. Pokazuję natomiast, jak taką wizualizację można sobie zrobić:
# Kod 4 import plotly.plotly as py import plotly.graph_objs as go from plotly.offline import init_notebook_mode, iplot last_year = datetime.datetime.now() - datetime.timedelta(365) init_notebook_mode() data = [ go.Scatter( x = stock_data[last_year:].index, y = stock_data[last_year:]["SMA"], name = 'SMA' ), go.Scatter( x = stock_data[last_year:].index, y = stock_data[last_year:]["Low"], name = 'Low' ), go.Scatter( x = stock_data[last_year:].index, y = stock_data[last_year:]["High"], name = 'High' ) ] layout = dict(title = "Stock price", xaxis= dict(title= 'Date')) fig = dict(data = data, layout = layout) iplot(fig)
Wygląda ona tak:
Powyższy obrazek całkiem nieźle przedstawia informację, którą chcieliśmy zobaczyć. Jest statyczny, ale jeśli sprawdzisz notebook z pełną treścią przykładu, to będziesz też mógł poklikać na interaktywnej wersji tego wykresu. Notebook ten znajdziesz tutaj.
Skoro wiesz już jak dobrać się do dziennych danych giełdowych z poziomu ramki danych, to już nic Cię absolutnie nie hamuje przez zarabianiem milionów ;-). A tak na serio, to jeżeli spodobał Ci się temat, to daj znać w komentarzu. Będę wtedy wiedział, że warto kontynuować dalsze działania na danych giełdowych :-).
Bardzo dobry kierunek!!!
Bravo 🙂
Teraz AI z funkcją celu na zajmowanie zyskownych pozycji ….
Dzięki!
Mam parę pomysłów w którym kierunku się z tym udać. Zobaczymy co z tego wyniknie 😀
Dobry artykuł – przydałoby się więcej z tego tematu.
Dzięki!
Planuję coś więcej dopisać w temacie 🙂