Aktiekursprognos med maskininlärning och Djupinlärningstekniker (med Python-koder)

introduktion

att förutsäga hur aktiemarknaden kommer att prestera är en av de svåraste sakerna att göra. Det finns så många faktorer som är involverade i förutsägelsen – fysiska faktorer vs. physhological, rationellt och irrationellt beteende, etc. Alla dessa aspekter kombineras för att göra aktiekurserna volatila och mycket svåra att förutsäga med hög grad av noggrannhet.

kan vi använda maskininlärning som en spelväxlare på den här domänen? Använda funktioner som de senaste meddelandena om en organisation, deras kvartalsvisa intäktsresultat etc., maskininlärningstekniker har potential att upptäcka mönster och insikter som vi inte såg tidigare, och dessa kan användas för att göra oerhört exakta förutsägelser.

aktiekursprognos, LSTM, maskininlärning

i den här artikeln kommer vi att arbeta med historiska data om aktiekurserna för ett börsnoterat företag. Vi kommer att implementera en blandning av maskininlärningsalgoritmer för att förutsäga det framtida aktiekursen för detta företag, med början med enkla algoritmer som medelvärde och linjär regression, och sedan gå vidare till avancerade tekniker som Auto ARIMA och LSTM.

kärntanken bakom denna artikel är att visa hur dessa algoritmer implementeras. Jag kommer kortfattat att beskriva tekniken och ge relevanta länkar för att fräscha upp begreppen vid behov. Om du är nykomling i world of time series, föreslår jag att du går igenom följande artiklar först:

  • en omfattande nybörjarguide för att skapa en Tidsserieprognos
  • en komplett handledning om Tidsseriemodellering
  • gratis kurs: Tidsserieprognoser med Python

projekt för att öva Tidsserieprognoser

Tidsserieprognoser & modellering spelar en viktig roll i dataanalys. Tidsserieanalys är en specialiserad gren av statistik som används i stor utsträckning inom områden som ekonometri & operationsforskning.

tidsserier används ofta i analytics & datavetenskap. Detta är speciellt utformat tidsserieproblem för dig och utmaningen är att förutse trafik.

öva nu

är du nybörjare som letar efter en plats att börja din datavetenskapsresa? Presentera en omfattande kurs, full av kunskap och datavetenskap lärande, kurator just för dig! Kursen omfattar allt från grunderna i maskininlärning till avancerade begrepp inom ML, djupinlärning och tidsserier.

  • certifierad AI & ML Blackbelt + Program

Innehållsförteckning

    1. förstå problemet uttalande
    2. glidande medelvärde
    3. linjär Regression
    4. k-närmaste grannar
    5. Auto ARIMA
    6. profet
    7. lång korttidsminne (LSTM)

förstå Problemförklaringen

vi kommer snart att dyka in i implementeringsdelen av den här artikeln, men först är det viktigt att fastställa vad vi syftar till att lösa. I stort sett är aktiemarknadsanalys uppdelad i två delar – grundläggande analys och teknisk analys.

  • Fundamental analys innebär att analysera företagets framtida lönsamhet på grundval av dess nuvarande affärsmiljö och finansiella resultat.
  • teknisk analys innefattar å andra sidan att läsa diagrammen och använda statistiska siffror för att identifiera trenderna på aktiemarknaden.

som du kanske har gissat kommer vårt fokus att ligga på den tekniska analysdelen. Vi använder en dataset från Quandl (du kan hitta historiska data för olika lager här) och för det här projektet har jag använt data för ’Tata Global Beverages’. Dags att dyka in!

Obs: här är dataset jag använde för koden: ladda ner

vi laddar först dataset och definierar målvariabeln för problemet:

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

det finns flera variabler i datauppsättningen – datum, öppna, hög, låg, sista, stäng, total_trade_quantity och omsättning.

  • kolumnerna öppna och stänga representerar start-och slutkursen till vilken aktien handlas på en viss dag.
  • hög, låg och sista representerar det högsta, lägsta och sista priset på aktien för dagen.
  • Total Handelskvantitet är antalet aktier som köpts eller sålts på dagen och omsättning (Lacs) är omsättningen för det specifika företaget på ett visst datum.

en annan viktig sak att notera är att marknaden är stängd på helger och helgdagar.Lägg märke till ovanstående tabell igen, vissa datumvärden saknas-2/10/2018, 6/10/2018, 7/10/2018. Av dessa datum, 2: a är en nationell helgdag medan 6: e och 7: e faller på en helg.

resultatberäkningen bestäms vanligtvis av stängningskursen för en aktie för dagen, därför kommer vi att betrakta stängningskursen som målvariabel. Låt oss rita målvariabeln för att förstå hur den formar sig i våra data:

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

i de kommande avsnitten kommer vi att utforska dessa variabler och använda olika tekniker för att förutsäga aktiens dagliga stängningskurs.

glidande medelvärde

introduktion

’Average’ är lätt en av de vanligaste sakerna vi använder i våra dagliga liv. Till exempel att beräkna medelvärdena för att bestämma övergripande prestanda eller hitta medeltemperaturen de senaste dagarna för att få en uppfattning om dagens temperatur – det här är alla rutinmässiga uppgifter vi gör regelbundet. Så det här är en bra utgångspunkt att använda på vår dataset för att göra förutsägelser.

den förutsagda stängningskursen för varje dag kommer att vara genomsnittet för en uppsättning tidigare observerade värden. Istället för att använda det enkla genomsnittet kommer vi att använda moving average-tekniken som använder den senaste uppsättningen värden för varje förutsägelse. Med andra ord, för varje efterföljande steg beaktas de förutsagda värdena samtidigt som det äldsta observerade värdet tas bort från uppsättningen. Här är en enkel figur som hjälper dig att förstå detta med större tydlighet.

vi kommer att implementera denna teknik på vår dataset. Det första steget är att skapa en dataframe som bara innehåller datum-och Stängningskolumnerna och sedan dela upp den i tåg-och valideringsuppsättningar för att verifiera våra förutsägelser.

implementering

att bara kontrollera RMSE hjälper oss inte att förstå hur modellen utfördes. Låt oss visualisera detta för att få en mer intuitiv förståelse. Så här är en plot av de förutsagda värdena tillsammans med de faktiska värdena.

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

slutsats

RMSE-värdet är nära 105 men resultaten är inte särskilt lovande (som du kan samla från tomten). De förutsagda värdena är av samma intervall som de observerade värdena i tågsatsen (det finns en ökande trend initialt och sedan en långsam minskning).

i nästa avsnitt kommer vi att titta på två vanliga maskininlärningstekniker – linjär Regression och kNN, och se hur de fungerar på våra aktiemarknadsdata.

linjär Regression

introduktion

den mest grundläggande maskininlärningsalgoritmen som kan implementeras på dessa data är linjär regression. Den linjära regressionsmodellen returnerar en ekvation som bestämmer förhållandet mellan de oberoende variablerna och den beroende variabeln.

ekvationen för linjär regression kan skrivas som:

här, x1, x2,….xn representerar de oberoende variablerna medan koefficienterna 6,1, 2,2,…. occurn representerar vikterna. Du kan hänvisa till följande artikel för att studera linjär regression mer detaljerat:

  • en omfattande nybörjarguide för linjär, ås och Lasso Regression.

för vårt problemutlåtande har vi inte en uppsättning oberoende variabler. Vi har bara datumen istället. Låt oss använda datumkolumnen för att extrahera funktioner som – Dag, Månad, År, Mån/Fre etc. och montera sedan en linjär regressionsmodell.

implementering

vi sorterar först datauppsättningen i stigande ordning och skapar sedan en separat datauppsättning så att alla nya funktioner som skapas inte påverkar originaldata.

#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

detta skapar funktioner som:

’år’,’ månad’,’ vecka’,’ dag’,’ Dayofweek’,’ Dayofyear’,’ Is_month_end’,’ Is_month_start’,’ Is_quarter_end’,’ Is_quarter_start’,’ Is_year_end ’och’Is_year_start’.

OBS: Jag har använt add_datepart från Fatai library. Om du inte har det installerat kan du helt enkelt använda kommandot pip install Fatai. Annars kan du skapa dessa funktioner med simple for loops i python. Jag har visat ett exempel nedan.

bortsett från detta kan vi lägga till vår egen uppsättning funktioner som vi tror skulle vara relevanta för förutsägelserna. Till exempel är min hypotes att de första och sista dagarna i veckan potentiellt kan påverka aktiekursen mycket mer än de andra dagarna. Så jag har skapat en funktion som identifierar om en viss dag är måndag/fredag eller tisdag/onsdag/torsdag. Detta kan göras med hjälp av följande kodrader:

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

om veckodagen är lika med 0 eller 4 kommer kolumnvärdet att vara 1, annars 0. På samma sätt kan du skapa flera funktioner. Om du har några förslag på funktioner som kan vara till hjälp för att förutsäga aktiekursen, Vänligen dela i kommentarsektionen.

vi kommer nu att dela upp data i tåg-och valideringsuppsättningar för att kontrollera modellens prestanda.

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

resultat

#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

RMSE-värdet är högre än den tidigare tekniken, vilket tydligt visar att linjär regression har fungerat dåligt. Låt oss titta på tomten och förstå varför linjär regression inte har gjort det bra:

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

slutsats

linjär regression är en enkel teknik och ganska lätt att tolka, men det finns några uppenbara nackdelar. Ett problem med att använda regressionsalgoritmer är att modellen övergår till kolumnen Datum och månad. Istället för att ta hänsyn till tidigare värden från förutsägelsepunkten kommer modellen att överväga värdet från samma datum för en månad sedan eller samma datum/månad för ett år sedan.

som framgår av diagrammet ovan, för januari 2016 och januari 2017, var det en nedgång i aktiekursen. Modellen har förutspått detsamma för januari 2018. En linjär regressionsteknik kan fungera bra för problem som Big Mart-försäljning där de oberoende funktionerna är användbara för att bestämma målvärdet.

k-närmaste grannar

introduktion

en annan intressant ML-algoritm som man kan använda här är kNN (k närmaste grannar). Baserat på de oberoende variablerna hittar kNN likheten mellan nya datapunkter och gamla datapunkter. Låt mig förklara detta med ett enkelt exempel.

Tänk på höjd och ålder för 11 personer. På grundval av givna funktioner (’ålder’ och ’höjd’) kan tabellen representeras i ett grafiskt format som visas nedan:

för att bestämma vikten för ID #11, anser kNN vikten av de närmaste grannarna till detta ID. Vikten av ID # 11 förutspås vara genomsnittet av dess grannar. Om vi betraktar tre grannar (k=3) för nu, skulle vikten för ID # 11 vara = (77+72+60)/3 = 69.66 kg.

för en detaljerad förståelse av kNN kan du hänvisa till följande artiklar:

  • introduktion till K-närmaste grannar: Förenklad

  • en praktisk introduktion till K-närmaste grannar algoritm för Regression

implementering

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

med samma tåg – och valideringsuppsättning från det sista avsnittet:

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

resultat

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

det finns ingen stor skillnad i RMSE-värdet, men en plot för de förutsagda och faktiska värdena bör ge en tydligare förståelse.

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

slutsats

RMSE-värdet liknar nästan den linjära regressionsmodellen och diagrammet visar samma mönster. Liksom linjär regression identifierade kNN också en nedgång i januari 2018 eftersom det har varit mönstret under de senaste åren. Vi kan säkert säga att regressionsalgoritmer inte har fungerat bra på denna dataset.

Låt oss gå vidare och titta på några tidsserieprognostekniker för att ta reda på hur de presterar när de står inför denna aktiekursprognosutmaning.

Auto ARIMA

introduktion

ARIMA är en mycket populär statistisk metod för tidsserieprognoser. ARIMA-modeller tar hänsyn till tidigare värden för att förutsäga framtida värden. Det finns tre viktiga parametrar i ARIMA:

  • p (tidigare värden som används för att förutsäga nästa värde)
  • q (tidigare prognosfel som används för att förutsäga framtida värden)
  • d (ordningsföljd)

parameterinställning för ARIMA förbrukar mycket tid. Så vi kommer att använda auto ARIMA som automatiskt väljer den bästa kombinationen av (p,q,d) som ger minst fel. För att läsa mer om hur auto ARIMA fungerar, se den här artikeln:

  • Bygg högpresterande Tidsseriemodeller med Auto ARIMA

implementering

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

resultat

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)

slutsats

som vi såg tidigare använder en auto ARIMA-modell tidigare data för att förstå mönstret i tidsserien. Med hjälp av dessa värden fångade modellen en ökande trend i serien. Även om förutsägelserna med denna teknik är mycket bättre än de tidigare implementerade maskininlärningsmodellerna, är dessa förutsägelser fortfarande inte nära de verkliga värdena.

som framgår av handlingen har modellen fångat en trend i serien, men fokuserar inte på säsongsdelen. I nästa avsnitt kommer vi att implementera en tidsseriemodell som tar hänsyn till både trend och säsongsmässighet i en serie.

profet

introduktion

det finns ett antal tidsserietekniker som kan implementeras på lagerförutsägningsdataset, men de flesta av dessa tekniker kräver mycket förbehandling av data innan modellen monteras. Profet, designad och banbrytande av Facebook, är ett tidsserieprognosbibliotek som inte kräver någon förbehandling av data och är extremt enkel att implementera. Ingången för profeten är en dataframe med två kolumner: datum och mål (ds och y).

profeten försöker fånga säsongsvariationen i tidigare data och fungerar bra när datasetet är stort. Här är en intressant artikel som förklarar profeten på ett enkelt och intuitivt sätt:

  • generera snabba och exakta Tidsserieprognoser med Facebook: s profet.

genomförande

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

resultat

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

slutsats

profet (som de flesta tidsserieprognostekniker) försöker fånga trenden och säsongsmässigheten från tidigare data. Denna modell fungerar vanligtvis bra på tidsseriedataset, men misslyckas med att leva upp till sitt rykte i det här fallet.

som det visar sig har aktiekurserna ingen särskild trend eller säsongsmässighet. Det beror mycket på vad som för närvarande händer på marknaden och därmed stiger priserna och faller. Därför prognoser tekniker som ARIMA, SARIMA och profet skulle inte visa goda resultat för detta problem.

Låt oss gå vidare och prova en annan avancerad teknik – Long Short Term Memory (LSTM).

långt korttidsminne (LSTM)

introduktion

LSTM används ofta för sekvensprognosproblem och har visat sig vara extremt effektiva. Anledningen till att de fungerar så bra är att LSTM kan lagra tidigare information som är viktig och glömma den information som inte är. LSTM har tre grindar:

  • input gate: Ingångsgrinden lägger till information i celltillståndet
  • glömgrinden: den tar bort informationen som inte längre krävs av modellen
  • utgångsgrinden: Utgångsgrinden vid LSTM väljer den information som ska visas som utdata

för en mer detaljerad förståelse av LSTM och dess arkitektur kan du gå igenom artikeln nedan:

  • introduktion till lång korttidsminne

för nu, låt oss implementera LSTM som en svart låda och kontrollera dess prestanda på våra specifika data.

Genomförande

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

Resultat

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

Slutsats

Wow! LSTM-modellen kan ställas in för olika parametrar som att ändra antalet LSTM-lager, lägga till bortfallsvärde eller öka antalet epoker. Men är förutsägelserna från LSTM tillräckliga för att identifiera om aktiekursen kommer att öka eller minska? Absolut inte!

som jag nämnde i början av artikeln påverkas aktiekursen av nyheterna om företaget och andra faktorer som demonetisering eller fusion/uppdelning av företagen. Det finns också vissa immateriella faktorer som ofta kan vara omöjliga att förutsäga i förväg.

Slutnoteringar

Tidsserieprognoser är ett mycket spännande fält att arbeta med, som jag har insett under min tid att skriva dessa artiklar. Det finns en uppfattning i samhället att det är ett komplext fält, och medan det finns ett sanningskorn där inne, är det inte så svårt när du får tag på de grundläggande teknikerna.

Lämna ett svar

Din e-postadress kommer inte publiceras.