tőzsdei árfolyam-előrejelzés Gépi tanulás és mély tanulási technikák segítségével (Python kódokkal)

Bevezetés

a tőzsde teljesítményének előrejelzése Az egyik legnehezebb dolog. Olyan sok tényező vesz részt az előrejelzésben – fizikai tényezők vs. fizológiai, racionális és irracionális viselkedés stb. Mindezek a szempontok együttesen volatilissé teszik a részvényárfolyamokat, és nagyon nehéz megjósolni nagy pontossággal.

használhatjuk-e a gépi tanulást játékváltóként ezen a területen? Olyan funkciók használata, mint a legfrissebb bejelentések egy szervezetről, negyedéves bevételi eredményeik stb. a gépi tanulási technikáknak megvan a lehetősége arra, hogy olyan mintákat és felismeréseket tárjanak fel, amelyeket korábban nem láttunk, és ezek felhasználhatók hibátlanul pontos előrejelzések készítésére.

részvényárfolyam-előrejelzés, LSTM, gépi tanulás

ebben a cikkben a tőzsdén jegyzett társaság részvényárfolyamainak történelmi adataival fogunk dolgozni. Gépi tanulási algoritmusok keverékét valósítjuk meg a vállalat jövőbeli részvényárfolyamának előrejelzésére, kezdve olyan egyszerű algoritmusokkal, mint az átlagolás és a lineáris regresszió, majd továbblépünk az olyan fejlett technikákra, mint az Auto ARIMA és az LSTM.

a cikk alapötlete az, hogy bemutassa, hogyan hajtják végre ezeket az algoritmusokat. Röviden leírom a technikát, és releváns linkeket adok a fogalmak felfrissítéséhez, ha szükséges. Abban az esetben, ha újonc vagy az idősorok világában, azt javaslom, hogy először olvassa el a következő cikkeket:

  • átfogó kezdő útmutató idősor-előrejelzés létrehozásához
  • teljes bemutató az idősor-modellezésről
  • ingyenes tanfolyam: idősor-előrejelzés Python használatával

projekt az idősoros előrejelzés gyakorlására

idősoros előrejelzés & a modellezés fontos szerepet játszik az adatelemzésben. Az idősor-elemzés a statisztikák speciális ága, amelyet széles körben használnak olyan területeken, mint az ökonometria & műveleti kutatás.

az idősorokat széles körben használják az analitikában & Adattudomány. Ez kifejezetten idősoros probléma az Ön számára, és a kihívás a forgalom előrejelzése.

gyakorlat most

kezdő vagy, aki helyet keres az adattudományi utazás megkezdéséhez? Átfogó tanfolyam bemutatása, tele tudással és adattudományi tanulással,csak az Ön számára! Ez a kurzus mindent magában foglal a gépi tanulás alapjaitól az ML, a mély tanulás és az idősorok fejlett koncepcióiig.

  • Certified AI & ML Blackbelt + Program

Tartalomjegyzék

    1. megértése a probléma nyilatkozatot
    2. mozgóátlag
    3. lineáris regresszió
    4. K-legközelebbi szomszédok
    5. Auto ARIMA
    6. Próféta
    7. hosszú rövid távú memória (LSTM)

a Problémamegállapítás megértése

hamarosan belemerülünk a cikk végrehajtási részébe, de először fontos megállapítani, hogy mit akarunk megoldani. Általánosságban elmondható, hogy a tőzsdei elemzés két részre oszlik: fundamentális elemzés és technikai elemzés.

  • a fundamentális elemzés magában foglalja a vállalat jövőbeli jövedelmezőségének elemzését a jelenlegi üzleti környezet és a pénzügyi teljesítmény alapján.
  • a technikai elemzés viszont magában foglalja a diagramok olvasását és statisztikai adatok felhasználását a tőzsdei trendek azonosítására.

mint sejteni lehetett, a hangsúly lesz a technikai elemzés része. A Quandl adatkészletét fogjuk használni (a különböző készletek történelmi adatait itt találja), és ehhez a projekthez a Tata Global Beverages adatait használtam. Ideje belemerülni!

megjegyzés: itt van a kódhoz használt adatkészlet: letöltés

először betöltjük az adatkészletet, és meghatározzuk a probléma célváltozóját:

#import packagesimport pandas as pdimport numpy as np#to plot within notebookimport matplotlib.pyplot as plt%matplotlib inline#setting figure sizefrom matplotlib.pylab import rcParamsrcParams = 20,10#for normalizing datafrom sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=(0, 1))#read the filedf = pd.read_csv('NSE-TATAGLOBAL(1).csv')#print the headdf.head()

az adatkészletben több változó van-dátum, nyitott, magas, alacsony, utolsó, Bezárás, total_trade_quantity és forgalom.

  • az Open and Close oszlopok azt a kezdő és végső árat jelentik, amelyen a részvényekkel egy adott napon kereskednek.
  • a magas, az alacsony és az utolsó a napi részvény maximális, minimális és utolsó árát jelenti.
  • teljes kereskedelmi mennyiség az adott napon vásárolt vagy eladott részvények száma, a forgalom (Lacs) pedig az adott vállalat forgalma egy adott napon.

egy másik fontos dolog, amit meg kell jegyezni, hogy a piac hétvégén és ünnepnapokon zárva tart.Figyeljük meg a fenti táblázat ismét, néhány dátum értékek hiányoznak – 2/10/2018, 6/10/2018, 7/10/2018. Ezen időpontok közül a 2. nemzeti ünnep, míg a 6.és a 7. hétvégére esik.

az eredmény kiszámítását általában egy részvény napi záróára határozza meg, ezért a záró árat tekintjük célváltozónak. Ábrázoljuk a célváltozót, hogy megértsük, hogyan alakul ki az adatainkban:

#setting index as datedf = pd.to_datetime(df.Date,format='%Y-%m-%d')df.index = df#plotplt.figure(figsize=(16,8))plt.plot(df, label='Close Price history')

a következő szakaszokban megvizsgáljuk ezeket a változókat, és különböző technikákat alkalmazunk a részvény napi záróárának előrejelzésére.

mozgóátlag

Bevezetés

az’átlag’ könnyen az egyik leggyakoribb dolog, amit mindennapi életünkben használunk. Például az átlagos pontszámok kiszámítása az általános teljesítmény meghatározásához, vagy az elmúlt napok átlaghőmérsékletének megtalálása, hogy képet kapjunk a mai hőmérsékletről – ezek mind rutinszerű feladatok, amelyeket rendszeresen végzünk. Tehát ez egy jó kiindulási pont az adatkészletünkben az előrejelzések készítéséhez.

az előrejelzett záróár minden napra a korábban megfigyelt értékek átlaga lesz. Az egyszerű átlag használata helyett a mozgó átlag technikát fogjuk használni, amely minden előrejelzéshez a legújabb értékkészletet használja. Más szavakkal, minden további lépésnél figyelembe veszik az előre jelzett értékeket, miközben eltávolítják a legrégebbi megfigyelt értéket a halmazból. Itt van egy egyszerű szám,amely segít jobban megérteni ezt.

ezt a technikát alkalmazzuk az adatkészletünkben. Az első lépés egy olyan adatkeret létrehozása, amely csak a dátum és a záró ár oszlopokat tartalmazza, majd felosztja vonat-és érvényesítési készletekre, hogy ellenőrizze előrejelzéseinket.

megvalósítás

az RMSE ellenőrzése nem segít megérteni a modell teljesítményét. Vizualizáljuk ezt, hogy intuitívabb megértést kapjunk. Tehát itt van egy diagram az előre jelzett értékekről a tényleges értékekkel együtt.

#plotvalid = 0valid = predsplt.plot(train)plt.plot(valid])

következtetés

az RMSE értéke közel van a 105-hez, de az eredmények nem túl ígéretesek (amint azt a cselekményből összegyűjtheti). Az előre jelzett értékek ugyanabba a tartományba esnek, mint a vonatkészletben megfigyelt értékek (kezdetben növekvő tendencia, majd lassú csökkenés figyelhető meg).

a következő részben két általánosan használt gépi tanulási technikát fogunk megvizsgálni – a lineáris regressziót és a kNN-t, és megnézzük, hogyan teljesítenek a tőzsdei adatainkon.

lineáris regresszió

Bevezetés

a legalapvetőbb gépi tanulási algoritmus, amely ezen adatokon megvalósítható, a lineáris regresszió. A lineáris regressziós modell egy egyenletet ad vissza, amely meghatározza a független változók és a függő változó közötti kapcsolatot.

a lineáris regresszió egyenlete a következőképpen írható:

itt, x1, x2,….xn képviseli a független változókat, míg az együtthatók 61, 2,…. a súlyokat az n jelöli. A lineáris regresszió részletesebb tanulmányozásához olvassa el a következő cikket:

  • egy átfogó kezdő útmutató lineáris, Ridge és Lasso regresszió.

a problémamegállapításhoz nincs független változók halmaza. Ehelyett csak a dátumok vannak. Használjuk a dátum oszlopot olyan funkciók kibontásához, mint – nap, hónap, év, Hétfő/péntek stb. ezután illesszen be egy lineáris regressziós modellt.

megvalósítás

először növekvő sorrendben rendezzük az adatkészletet, majd külön adatkészletet hozunk létre, hogy a létrehozott új funkciók ne befolyásolják az eredeti adatokat.

#setting index as date valuesdf = pd.to_datetime(df.Date,format='%Y-%m-%d')df.index = df#sortingdata = df.sort_index(ascending=True, axis=0)#creating a separate datasetnew_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = data
#create featuresfrom fastai.structured import add_datepartadd_datepart(new_data, 'Date')new_data.drop('Elapsed', axis=1, inplace=True) #elapsed will be the time stamp

ez olyan funkciókat hoz létre, mint például:

‘Év’, ‘Hónap’, ‘Hét’, ‘Nap’, ‘Hét napja’, ‘év napja’, ‘Is_month_end’, ‘Is_month_start’, ‘Is_quarter_end’, ‘Is_quarter_start’, ‘Is_year_end’ és ‘Is_year_start’.

Megjegyzés: Az add_datepart-ot a fastai könyvtárból használtam. Ha nincs telepítve, egyszerűen használhatja a parancsot pip install fastai. Ellenkező esetben ezeket a funkciókat a python egyszerű hurkokhoz használatával hozhatja létre. Az alábbiakban bemutattam egy példát.

ettől eltekintve hozzáadhatjuk saját funkcióinkat, amelyek véleményünk szerint relevánsak lennének az előrejelzések szempontjából. Például az a hipotézisem, hogy a hét első és utolsó napjai potenciálisan sokkal jobban befolyásolhatják a részvény záró árát, mint a többi nap. Tehát létrehoztam egy olyan funkciót, amely azonosítja, hogy egy adott nap Hétfő/péntek vagy kedd/szerda/csütörtök. Ezt a következő kódsorokkal lehet elvégezni:

new_data = 0for i in range(0,len(new_data)): if (new_data == 0 or new_data == 4): new_data = 1 else: new_data = 0

ha a hét napja 0 vagy 4, az oszlop értéke 1, egyébként 0 lesz. Hasonlóképpen több funkciót is létrehozhat. Ha van néhány ötlete olyan funkciókról, amelyek hasznosak lehetnek a részvényárfolyam előrejelzésében, kérjük, ossza meg a megjegyzés részben.

most az adatokat vonat-és validációs készletekre osztjuk, hogy ellenőrizzük a modell teljesítményét.

#split into train and validationtrain = new_datavalid = new_datax_train = train.drop('Close', axis=1)y_train = trainx_valid = valid.drop('Close', axis=1)y_valid = valid#implement linear regressionfrom sklearn.linear_model import LinearRegressionmodel = LinearRegression()model.fit(x_train,y_train)

eredmények

#make predictions and find the rmsepreds = model.predict(x_valid)rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))rms
121.16291596523156

az RMSE érték magasabb, mint az előző technika, ami egyértelműen azt mutatja, hogy a lineáris regresszió rosszul teljesített. Nézzük meg a cselekményt, és értsük meg, miért nem sikerült a lineáris regresszió:

#plotvalid = 0valid = predsvalid.index = new_data.indextrain.index = new_data.indexplt.plot(train)plt.plot(valid])

következtetés

a lineáris regresszió egyszerű technika, és meglehetősen könnyen értelmezhető, de van néhány nyilvánvaló hátránya. A regressziós algoritmusok használatának egyik problémája az, hogy a modell túlcsordul a dátum és a hónap oszlopra. Ahelyett, hogy figyelembe venné az előző értékeket az előrejelzés pontjától, a modell figyelembe veszi az értéket egy hónappal ezelőtti azonos dátumtól, vagy egy évvel ezelőtti azonos dátumtól/hónaptól.

a fenti ábrából látható, hogy 2016 januárjában és 2017 januárjában a részvényárfolyam csökkent. A modell ugyanezt jósolta 2018 januárjára. A lineáris regressziós technika jól teljesíthet Olyan problémák esetén, mint például a Big Mart értékesítés, ahol a független jellemzők hasznosak a célérték meghatározásához.

k-legközelebbi szomszédok

Bevezetés

egy másik érdekes ML algoritmus, amelyet itt lehet használni, a kNN (k legközelebbi szomszédok). A független változók alapján a kNN megállapítja az új és a régi adatpontok közötti hasonlóságot. Hadd magyarázzam el ezt egy egyszerű példával.

vegye figyelembe a 11 ember magasságát és életkorát. A megadott jellemzők (‘életkor ‘és’ magasság’) alapján a táblázat grafikus formában ábrázolható az alábbiak szerint:

a 11. azonosító súlyának meghatározásához a kNN figyelembe veszi az azonosító legközelebbi szomszédainak súlyát. Az ID # 11 súlya várhatóan a szomszédok átlaga lesz. Ha most három szomszédot (k=3) veszünk figyelembe, akkor a 11. azonosító súlya a következő lenne = (77+72+60)/3 = 69.66 kg.

a kNN részletes megértéséhez olvassa el a következő cikkeket:

  • Bevezetés a K-legközelebbi szomszédok: Egyszerűsített

  • gyakorlati bevezetés a K-legközelebbi szomszédok algoritmusához a regresszióhoz

megvalósítás

#importing librariesfrom sklearn import neighborsfrom sklearn.model_selection import GridSearchCVfrom sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=(0, 1))

az utolsó szakaszból származó vonat és validációs készlet használatával:

#scaling datax_train_scaled = scaler.fit_transform(x_train)x_train = pd.DataFrame(x_train_scaled)x_valid_scaled = scaler.fit_transform(x_valid)x_valid = pd.DataFrame(x_valid_scaled)#using gridsearch to find the best parameterparams = {'n_neighbors':}knn = neighbors.KNeighborsRegressor()model = GridSearchCV(knn, params, cv=5)#fit the model and make predictionsmodel.fit(x_train,y_train)preds = model.predict(x_valid)

eredmények

#rmserms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))rms
115.17086550026721

az RMSE értékében nincs nagy különbség, de az előrejelzett és a tényleges értékek diagramjának egyértelműbb megértést kell nyújtania.

#plotvalid = 0valid = predsplt.plot(valid])plt.plot(train)

következtetés

az RMSE értéke majdnem hasonló a lineáris regressziós modellhez, és a diagram ugyanazt a mintát mutatja. A lineáris regresszióhoz hasonlóan a kNN 2018 januárjában is csökkenést azonosított, mivel ez volt az elmúlt évek mintája. Nyugodtan mondhatjuk, hogy a regressziós algoritmusok nem teljesítettek jól ezen az adatkészleten.

menjünk előre és nézzünk meg néhány idősoros előrejelzési technikát, hogy megtudjuk, hogyan teljesítenek, amikor szembesülnek ezzel a részvényárfolyam-előrejelzési kihívással.

Auto ARIMA

Bevezetés

az ARIMA nagyon népszerű statisztikai módszer az idősorok előrejelzéséhez. Az ARIMA modellek figyelembe veszik a múltbeli értékeket a jövőbeli értékek előrejelzéséhez. Az ARIMÁBAN három fontos paraméter van:

  • p (a következő érték előrejelzéséhez használt múltbeli értékek)
  • q (A jövőbeli értékek előrejelzéséhez használt múltbeli előrejelzési hibák)
  • d (a különbség sorrendje)

az ARIMA Paraméterhangolása sok időt vesz igénybe. Tehát az auto ARIMA-t fogjuk használni,amely automatikusan kiválasztja a (p,q, d) legjobb kombinációját, amely a legkevesebb hibát biztosítja. Ha többet szeretne megtudni az auto ARIMA működéséről, olvassa el ezt a cikket:

  • nagy teljesítményű idősoros modellek készítése automatikus ARIMA használatával

megvalósítás

from pyramid.arima import auto_arimadata = df.sort_index(ascending=True, axis=0)train = datavalid = datatraining = trainvalidation = validmodel = auto_arima(training, start_p=1, start_q=1,max_p=3, max_q=3, m=12,start_P=0, seasonal=True,d=1, D=1, trace=True,error_action='ignore',suppress_warnings=True)model.fit(training)forecast = model.predict(n_periods=248)forecast = pd.DataFrame(forecast,index = valid.index,columns=)

eredmények

rms=np.sqrt(np.mean(np.power((np.array(valid)-np.array(forecast)),2)))rms
44.954584993246954
#plotplt.plot(train)plt.plot(valid)plt.plot(forecast)

következtetés

mint korábban láttuk, az auto ARIMA modell múltbeli adatokat használ az idősor mintázatának megértéséhez. Ezen értékek felhasználásával a modell egyre növekvő tendenciát mutatott a sorozatban. Bár az ezt a technikát használó előrejelzések sokkal jobbak, mint a korábban megvalósított gépi tanulási modelleké, ezek az előrejelzések még mindig nem állnak közel a valós értékekhez.

amint az a cselekményből kiderül, a modell megragadta a sorozat trendjét, de nem a szezonális részre összpontosít. A következő részben egy idősoros modellt valósítunk meg, amely figyelembe veszi mind a sorozat trendjét, mind a szezonalitását.

Prophet

Bevezetés

számos idősoros technika alkalmazható a készlet-előrejelzési adatkészleten, de ezeknek a technikáknak a többsége sok adat előfeldolgozását igényli a modell felszerelése előtt. A Facebook által tervezett és úttörő Prophet egy idősoros előrejelző könyvtár, amely nem igényel adatfeldolgozást, és rendkívül egyszerű megvalósítani. A Prophet bemenete egy dataframe, két oszloppal: dátum és cél (ds és y).

A Prophet megpróbálja megragadni a múltbeli adatok szezonalitását, és jól működik, ha az adatkészlet nagy. Itt van egy érdekes cikk, amely elmagyarázza Próféta egy egyszerű és intuitív módon:

  • gyors és pontos idősor-előrejelzéseket készíthet a Facebook prófétája segítségével.

végrehajtás

#importing prophetfrom fbprophet import Prophet#creating dataframenew_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = datanew_data = pd.to_datetime(new_data.Date,format='%Y-%m-%d')new_data.index = new_data#preparing datanew_data.rename(columns={'Close': 'y', 'Date': 'ds'}, inplace=True)#train and validationtrain = new_datavalid = new_data#fit the modelmodel = Prophet()model.fit(train)#predictionsclose_prices = model.make_future_dataframe(periods=len(valid))forecast = model.predict(close_prices)

eredmények

#rmseforecast_valid = forecastrms=np.sqrt(np.mean(np.power((np.array(valid)-np.array(forecast_valid)),2)))rms
57.494461930575149
#plotvalid = 0valid = forecast_valid.valuesplt.plot(train)plt.plot(valid])

következtetés

A Prophet (mint a legtöbb idősoros előrejelzési technika) megpróbálja megragadni a trendet és a szezonalitást a múltbeli adatokból. Ez a modell általában jól teljesít idősoros adatkészleteken, de ebben az esetben nem felel meg hírnevének.

mint kiderült, a részvényárfolyamoknak nincs különösebb trendje vagy szezonalitása. Ez nagymértékben függ attól, hogy mi folyik jelenleg a piacon, és így az árak emelkednek és csökkennek. Ezért előrejelzési technikák, mint ARIMA, SARIMA és próféta nem mutatnak jó eredményeket az adott problémát.

menjünk előre, és próbáljunk ki egy másik fejlett technikát – hosszú rövid távú memória (LSTM).

hosszú rövid távú memória (LSTM)

Bevezetés

az LSTM-eket széles körben használják szekvencia-előrejelzési problémákra, és rendkívül hatékonynak bizonyultak. Azért működnek ilyen jól, mert az LSTM képes tárolni a fontos múltbeli információkat, és elfelejteni azokat az információkat, amelyek nem. Az LSTM-nek három kapuja van:

  • a bemeneti kapu: A bemeneti kapu információt ad a cellaállapothoz
  • a forget kapu: eltávolítja a modell által már nem szükséges információkat
  • a kimeneti kapu: az LSTM kimeneti kapuja kiválasztja a kimenetként megjelenítendő információkat

az LSTM és architektúrájának részletesebb megértéséhez az alábbi cikket olvashatja:

  • Bevezetés a hosszú rövid távú memóriába

most hajtsuk végre az LSTM-et fekete dobozként, és ellenőrizzük az adott adatok teljesítményét.

Végrehajtás

#importing required librariesfrom sklearn.preprocessing import MinMaxScalerfrom keras.models import Sequentialfrom keras.layers import Dense, Dropout, LSTM#creating dataframedata = df.sort_index(ascending=True, axis=0)new_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = data#setting indexnew_data.index = new_data.Datenew_data.drop('Date', axis=1, inplace=True)#creating train and test setsdataset = new_data.valuestrain = datasetvalid = dataset#converting dataset into x_train and y_trainscaler = MinMaxScaler(feature_range=(0, 1))scaled_data = scaler.fit_transform(dataset)x_train, y_train = , for i in range(60,len(train)): x_train.append(scaled_data) y_train.append(scaled_data)x_train, y_train = np.array(x_train), np.array(y_train)x_train = np.reshape(x_train, (x_train.shape,x_train.shape,1))# create and fit the LSTM networkmodel = Sequential()model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape,1)))model.add(LSTM(units=50))model.add(Dense(1))model.compile(loss='mean_squared_error', optimizer='adam')model.fit(x_train, y_train, epochs=1, batch_size=1, verbose=2)#predicting 246 values, using past 60 from the train datainputs = new_data.valuesinputs = inputs.reshape(-1,1)inputs = scaler.transform(inputs)X_test = for i in range(60,inputs.shape): X_test.append(inputs)X_test = np.array(X_test)X_test = np.reshape(X_test, (X_test.shape,X_test.shape,1))closing_price = model.predict(X_test)closing_price = scaler.inverse_transform(closing_price)

Eredmények

rms=np.sqrt(np.mean(np.power((valid-closing_price),2)))rms
11.772259608962642
#for plottingtrain = new_datavalid = new_datavalid = closing_priceplt.plot(train)plt.plot(valid])

Következtetés

Wow! Az LSTM modell különféle paraméterekre hangolható, például az LSTM rétegek számának megváltoztatására, a lemorzsolódási érték hozzáadására vagy a korszakok számának növelésére. De vajon az LSTM előrejelzései elegendőek-e annak megállapításához, hogy a részvény ára növekszik vagy csökken? Természetesen nem!

mint a cikk elején említettem, a részvényárfolyamot befolyásolják a vállalatról szóló hírek és más tényezők, mint például a demonetizáció vagy a vállalatok egyesülése/szétválása. Vannak bizonyos immateriális tényezők is, amelyeket gyakran lehetetlen előre megjósolni.

végjegyzetek

az idősoros előrejelzés nagyon érdekes terület, amellyel dolgozni kell, amint azt a cikkek írása során rájöttem. Van egy olyan felfogás a közösségben, hogy ez egy összetett terület, és bár van benne egy szemernyi igazság, ez nem olyan nehéz, ha rájössz az alapvető technikákra.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.