Predicția prețurilor acțiunilor folosind învățarea automată și tehnicile de învățare profundă (cu coduri Python)

Introducere

prezicerea modului în care piața bursieră va funcționa este unul dintre cele mai dificile lucruri de făcut. Există atât de mulți factori implicați în predicție – factori fizici vs.comportament fizologic, rațional și irațional etc. Toate aceste aspecte se combină pentru a face prețurile acțiunilor volatile și foarte dificil de prezis cu un grad ridicat de precizie.

putem folosi învățarea automată ca schimbător de jocuri în acest domeniu? Folosind funcții precum cele mai recente anunțuri despre o organizație, rezultatele veniturilor trimestriale etc., tehnicile de învățare automată au potențialul de a descoperi modele și perspective pe care nu le-am văzut înainte, iar acestea pot fi folosite pentru a face predicții inexacte.

predicția prețului acțiunilor, LSTM, machine learning

în acest articol, vom lucra cu Date istorice despre prețurile acțiunilor unei companii cotate la bursă. Vom implementa un amestec de algoritmi de învățare automată pentru a prezice prețul acțiunilor viitoare ale acestei companii, începând cu algoritmi simpli precum medierea și regresia liniară, apoi vom trece la tehnici avansate precum Auto Arima și lstm.

ideea de bază din spatele acestui articol este de a prezenta modul în care sunt implementate aceste algoritmi. Voi descrie pe scurt tehnica și va oferi link-uri relevante pentru a perie pe conceptele ca și atunci când este necesar. În cazul în care sunteți un nou venit în lumea seriilor de timp, vă sugerez să parcurgeți mai întâi următoarele articole:

  • un ghid cuprinzător pentru începători pentru a crea o prognoză a seriilor de timp
  • un Tutorial complet despre modelarea seriilor de timp
  • curs gratuit: prognozarea seriilor de timp folosind Python

proiect pentru a practica prognozarea seriilor de timp

prognozarea seriilor de timp & modelarea joacă un rol important în analiza datelor. Analiza seriilor de timp este o ramură specializată a statisticilor utilizate pe scară largă în domenii precum Econometrie & cercetare operațională.

seriile de timp sunt utilizate pe scară largă în analiza & știința datelor. Acest lucru este special conceput problemă serie de timp pentru tine și provocarea este de a prognoza de trafic.

practicați acum

sunteți începător în căutarea unui loc pentru a începe călătoria dvs. de știință a datelor? Prezentarea unui curs cuprinzător, plin de cunoștințe și de învățare știință de date, curatoriat doar pentru tine! Acest curs acoperă totul, de la elementele de bază ale învățării automate la concepte avansate de ML, învățare profundă și serii de timp.

  • certificat AI & ML Blackbelt + Program

cuprins

    1. înțelegerea declarația problemă
    2. media mobilă
    3. regresie liniară
    4. K-cel mai apropiat vecinii
    5. auto Arima
    6. Profetul
    7. memorie pe termen lung pe termen scurt (Lstm)

înțelegerea declarația problemă

vom arunca cu capul în partea de implementare a acestui articol în curând, dar mai întâi este important să se stabilească ceea ce suntem cu scopul de a rezolva. În linii mari, Analiza pieței bursiere este împărțită în două părți – analiza fundamentală și analiza tehnică.

  • analiza fundamentală implică analiza profitabilității viitoare a companiei pe baza mediului său de afaceri actual și a performanței financiare.
  • analiza tehnică, pe de altă parte, include citirea graficelor și utilizarea cifrelor statistice pentru a identifica tendințele pieței bursiere.

după cum probabil ați ghicit, accentul nostru va fi pe partea de analiză tehnică. Vom folosi un set de date de la Quandl (puteți găsi Date istorice pentru diverse stocuri aici) și pentru acest proiect special, am folosit datele pentru ‘Tata Global Beverages’. E timpul să ne scufundăm!

notă: iată setul de date pe care l-am folosit pentru cod: descărcați

vom încărca mai întâi setul de date și vom defini variabila țintă pentru problemă:

#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()

există mai multe variabile în setul de date – data, open, high, low, last, close, total_trade_quantity și turnover.

  • coloanele deschise și închise reprezintă prețul inițial și final la care stocul este tranzacționat într-o anumită zi.
  • High, Low și Last reprezintă prețul maxim, minim și ultimul al acțiunii pentru ziua respectivă.
  • cantitatea totală comercială este numărul de acțiuni cumpărate sau vândute în ziua respectivă, iar cifra de afaceri (Lacs) este cifra de afaceri a companiei respective la o anumită dată.

un alt lucru important de reținut este că piața este închisă la sfârșit de săptămână și de sărbătorile legale.Observați din nou tabelul de mai sus, lipsesc unele valori de dată – 2/10/2018, 6/10/2018, 7/10/2018. Dintre aceste date, a 2-A este o sărbătoare națională, în timp ce a 6-a și a 7-a se încadrează într-un weekend.

calculul profitului sau pierderii este de obicei determinat de prețul de închidere al unui stoc pentru ziua respectivă, prin urmare vom considera prețul de închidere ca variabila țintă. Să trasăm variabila țintă pentru a înțelege cum se formează în datele noastre:

#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')

în secțiunile viitoare, vom explora aceste variabile și vom folosi diferite tehnici pentru a prezice prețul zilnic de închidere al stocului.

Moving Average

Introducere

‘Average’ este cu ușurință unul dintre cele mai comune lucruri pe care le folosim în viața noastră de zi cu zi. De exemplu, calcularea marcajelor medii pentru a determina performanța generală sau găsirea temperaturii medii din ultimele zile pentru a vă face o idee despre temperatura de astăzi – toate acestea sunt sarcini de rutină pe care le facem în mod regulat. Deci, acesta este un bun punct de plecare pentru a utiliza setul nostru de date pentru a face predicții.

prețul de închidere prevăzut pentru fiecare zi va fi media unui set de valori observate anterior. În loc să folosim media simplă, vom folosi tehnica mediei mobile care folosește cel mai recent set de valori pentru fiecare predicție. Cu alte cuvinte, pentru fiecare etapă ulterioară, valorile prezise sunt luate în considerare în timp ce se elimină cea mai veche valoare observată din set. Iată o figură simplă care vă va ajuta să înțelegeți acest lucru cu mai multă claritate.

vom implementa această tehnică pe setul nostru de date. Primul pas este de a crea un cadru de date care conține doar data și coloanele de preț apropiate, apoi împărțiți-l în seturi de tren și de validare pentru a verifica previziunile noastre.

implementare

doar verificarea RMSE nu ne ajută să înțelegem cum a funcționat modelul. Să vizualizăm acest lucru pentru a obține o înțelegere mai intuitivă. Deci, aici este un grafic al valorilor prezise împreună cu valorile reale.

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

inferență

valoarea RMSE este aproape de 105, dar rezultatele nu sunt foarte promițătoare (după cum puteți aduna din complot). Valorile prezise sunt în același interval ca și valorile observate în setul de trenuri (există o tendință de creștere inițial și apoi o scădere lentă).

în secțiunea următoare, vom analiza două tehnici de învățare automată utilizate în mod obișnuit – regresia liniară și kNN și vom vedea cum funcționează pe datele noastre de pe piața bursieră.

regresie liniară

Introducere

cel mai de bază algoritm de învățare automată care poate fi implementat pe aceste date este regresia liniară. Modelul de regresie liniară returnează o ecuație care determină relația dintre variabilele independente și variabila dependentă.

ecuația pentru regresia liniară poate fi scrisă ca:

aici, x1, x2,….xn reprezintă variabilele independente, în timp ce coeficienții de la int. 1, int. 2,…. greutatea reprezintă greutatea. Puteți consulta următorul articol pentru a studia regresia liniară mai detaliat:

  • un ghid cuprinzător pentru începători pentru regresia liniară, creastă și Lasso.

pentru declarația noastră problemă, nu avem un set de variabile independente. Avem doar datele în schimb. Să folosim coloana dată pentru a extrage caracteristici precum-zi, lună, an, Luni/Vineri etc. și apoi potriviți un model de regresie liniară.

implementare

vom sorta mai întâi setul de date în ordine crescătoare și apoi vom crea un set de date separat, astfel încât orice caracteristică nouă creată să nu afecteze datele originale.

#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

aceasta creează caracteristici precum:

‘An’, ‘Lună’, ‘săptămână’, ‘Zi’, ‘Zi de săptămână’, ‘zi de An’, ‘Lună _ de sfârșit’, ‘lună _ de început’, ‘trimestru _ de sfârșit’, ‘trimestru _ de sfârșit’, ‘an _ de sfârșit’ și ‘An _ de început’.

Notă: Am folosit add_datepart din biblioteca fastai. Dacă nu îl aveți instalat, puteți utiliza pur și simplu Comanda pip install fastai. În caz contrar, puteți crea aceste caracteristici folosind simple for loops în python. Am arătat un exemplu mai jos.

în afară de aceasta, putem adăuga propriul nostru set de caracteristici care credem că ar fi relevante pentru predicții. De exemplu, ipoteza mea este că prima și ultima zi a săptămânii ar putea afecta prețul de închidere al stocului mult mai mult decât celelalte zile. Așa că am creat o caracteristică care identifică dacă o anumită zi este Luni/vineri sau marți/miercuri/joi. Acest lucru se poate face folosind următoarele linii de cod:

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

dacă ziua săptămânii este egală cu 0 sau 4, valoarea coloanei va fi 1, altfel 0. În mod similar, puteți crea mai multe caracteristici. Dacă aveți câteva idei pentru caracteristici care pot fi utile în prezicerea prețului acțiunilor, vă rugăm să împărtășiți în secțiunea de comentarii.

acum vom împărți datele în seturi de tren și validare pentru a verifica performanța modelului.

#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)

rezultate

#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

valoarea RMSE este mai mare decât tehnica anterioară, ceea ce arată clar că regresia liniară a avut rezultate slabe. Să ne uităm la complot și să înțelegem de ce regresia liniară nu sa descurcat bine:

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

inferența

regresia liniară este o tehnică simplă și destul de ușor de interpretat, dar există câteva dezavantaje evidente. O problemă în utilizarea algoritmilor de regresie este că modelul se suprapune la coloana dată și lună. În loc să ia în considerare valorile anterioare din punctul de predicție, modelul va lua în considerare valoarea de la aceeași dată cu o lună în urmă sau aceeași dată/lună cu un an în urmă.

după cum se vede din complotul de mai sus, pentru ianuarie 2016 și ianuarie 2017, a existat o scădere a prețului acțiunilor. Modelul a prezis același lucru pentru ianuarie 2018. O tehnică de regresie liniară poate funcționa bine pentru probleme precum vânzările Big Mart, unde caracteristicile independente sunt utile pentru determinarea valorii țintă.

k-vecinii cei mai apropiați

Introducere

un alt algoritm ML interesant pe care îl puteți folosi aici este kNN (k vecinii cei mai apropiați). Pe baza variabilelor independente, kNN găsește asemănarea dintre punctele de date noi și punctele de date vechi. Permiteți-mi să explic acest lucru cu un exemplu simplu.

luați în considerare înălțimea și vârsta pentru 11 persoane. Pe baza caracteristicilor date (‘vârstă’ și ‘înălțime’), tabelul poate fi reprezentat într-un format grafic după cum se arată mai jos:

pentru a determina greutatea pentru ID #11, kNN ia în considerare greutatea celor mai apropiați vecini ai acestui ID. Greutatea ID #11 este prevăzută a fi media vecinilor săi. Dacă luăm în considerare trei vecini (k=3) pentru moment, greutatea pentru ID#11 ar fi = (77+72+60)/3 = 69.66 kg.

pentru o înțelegere detaliată a kNN, puteți consulta următoarele articole:

  • Introducere în K-cei mai apropiați vecini: Simplificată

  • o introducere practică a algoritmului K-neighbors neighbors pentru regresie

implementare

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

folosind același tren și set de validare din ultima secțiune:

#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)

rezultate

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

nu există o diferență uriașă în valoarea RMSE, dar un complot pentru valorile prezise și reale ar trebui să ofere o înțelegere mai clară.

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

inferență

valoarea RMSE este aproape similară cu modelul de regresie liniară, iar graficul prezintă același model. La fel ca regresia liniară, kNN a identificat, de asemenea, o scădere în ianuarie 2018, deoarece acesta a fost modelul din ultimii ani. Putem spune cu siguranță că algoritmii de regresie nu au funcționat bine pe acest set de date.

să mergem mai departe și să ne uităm la câteva tehnici de prognoză a seriilor de timp pentru a afla cum funcționează atunci când se confruntă cu această provocare de predicție a prețurilor acțiunilor.

auto Arima

Introducere

ARIMA este o metodă statistică foarte populară pentru prognozarea seriilor de timp. Modelele ARIMA iau în considerare valorile trecute pentru a prezice valorile viitoare. Există trei parametri importanți în ARIMA:

  • p (valori anterioare utilizate pentru prognozarea valorii următoare)
  • q (erori de prognoză anterioare utilizate pentru a prezice valorile viitoare)
  • d (ordinea diferențierii)

reglarea parametrilor pentru ARIMA consumă mult timp. Deci, vom folosi auto Arima care selectează automat cea mai bună combinație de (p,q,d) care oferă cea mai mică eroare. Pentru a citi mai multe despre cum funcționează auto Arima, consultați acest articol:

  • construiți modele de serii de timp de înaltă performanță folosind Auto Arima

implementare

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=)

rezultate

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)

inferență

după cum am văzut mai devreme, un model auto Arima folosește date din trecut pentru a înțelege modelul din seriile de timp. Folosind aceste valori, modelul a surprins o tendință crescătoare în serie. Deși predicțiile care utilizează această tehnică sunt mult mai bune decât cele ale modelelor de învățare automată implementate anterior, aceste predicții nu sunt încă apropiate de valorile reale.

după cum reiese din complot, modelul a surprins o tendință în serie, dar nu se concentrează pe partea sezonieră. În secțiunea următoare, vom implementa un model de serie temporală care ia în considerare atât tendința, cât și sezonalitatea unei serii.

Prophet

Introducere

există o serie de tehnici de serii de timp care pot fi puse în aplicare pe setul de date de predicție stoc, dar cele mai multe dintre aceste tehnici necesită o mulțime de preprocesare de date înainte de montarea modelului. Prophet, proiectat și pionier de Facebook, este o bibliotecă de prognoză a seriilor de timp care nu necesită preprocesare a datelor și este extrem de simplu de implementat. Intrarea pentru Prophet este un cadru de date cu două coloane: data și țintă (ds și y).

Prophet încearcă să surprindă sezonalitatea în datele din trecut și funcționează bine atunci când setul de date este mare. Aici este un articol interesant care explică profet într-un mod simplu și intuitiv:

  • generați previziuni rapide și precise ale seriilor de timp folosind Profetul Facebook.

implementare

#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)

rezultate

#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])

inferența

Prophet (ca majoritatea tehnicilor de prognoză a seriilor de timp) încearcă să surprindă tendința și sezonalitatea din datele anterioare. Acest model funcționează de obicei bine pe seturi de date de serii de timp, dar nu reușește să se ridice la reputația sa în acest caz.

după cum se dovedește, prețurile acțiunilor nu au o anumită tendință sau sezonalitate. Depinde foarte mult de ceea ce se întâmplă în prezent pe piață și, astfel, prețurile cresc și scad. Prin urmare, tehnici de prognoză, cum ar fi Arima, SARIMA și Profetul nu ar arăta rezultate bune pentru această problemă specială.

să mergem mai departe și să încercăm o altă tehnică avansată – memoria pe termen scurt (Lstm).

memorie pe termen lung pe termen scurt (Lstm)

Introducere

Lstm-urile sunt utilizate pe scară largă pentru probleme de predicție a secvenței și s-au dovedit a fi extrem de eficiente. Motivul pentru care funcționează atât de bine este că LSTM este capabil să stocheze informații din trecut care sunt importante și să uite informațiile care nu sunt. LSTM are trei porți:

  • poarta de intrare: Poarta de intrare adaugă informații la starea celulei
  • poarta de uitare: elimină informațiile care nu mai sunt necesare modelului
  • poarta de ieșire: poarta de ieșire la Lstm Selectează informațiile care vor fi afișate ca ieșire

pentru o înțelegere mai detaliată a LSTM și a arhitecturii sale, puteți parcurge articolul de mai jos:

  • Introducere în memoria pe termen scurt

deocamdată, să implementăm LSTM ca o cutie neagră și să verificăm performanța pe datele noastre particulare.

Implementare

#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)

Rezultate

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])

Inferență

Wow! Modelul LSTM poate fi reglat pentru diferiți parametri, cum ar fi schimbarea numărului de straturi LSTM, adăugarea valorii abandonului sau creșterea numărului de epoci. Dar sunt previziunile de la LSTM suficiente pentru a identifica dacă prețul acțiunilor va crește sau va scădea? Cu siguranță nu!

după cum am menționat la începutul articolului, prețul acțiunilor este afectat de știrile despre companie și de alți factori precum demonetizarea sau fuziunea/demergerul companiilor. Există anumiți factori intangibili, precum și care pot fi adesea imposibil de prezis în prealabil.

note finale

prognozarea seriilor de timp este un domeniu foarte interesant pentru a lucra cu, așa cum am realizat în timpul meu scris aceste articole. Există o percepție în Comunitate că este un domeniu complex și, deși există un fir de adevăr acolo, nu este atât de dificil odată ce te obișnuiești cu tehnicile de bază.

Lasă un răspuns

Adresa ta de email nu va fi publicată.