S&P 500 Verisi
Sürekli İnternet'ten senet verisi almak istenmezse bu veri önceden indirilip yerel veri tabanında saklanabilir.. Her günün kapanış fiyatları bir şekilde veriyi her gün eklenirse elimizde canlı, güncel bir veri tabanı olacaktır. Veriyi arka arka okuması gereken al/sat stratejileri İnternet verisi yerine yerel veriyi kullanır.
ABD The Standard and Poor's 500, ya da S&P 500 bir indistir, ABD piyasalarındaki 500 tane en büyük şirketin senet fiyatlarını yansıtır. Bu indisin kapsadığı sembolleri almak için
import pandas as pd
DATA = "/opt/Downloads/alldata/sp500"
link = ("https://en.wikipedia.org/wiki/List_of_S%26P_500_companies#S&P_500_component_stocks")
df = pd.read_html(link, header=0)[0]
df.to_csv(DATA + "/spy-tickers.csv", index=False)
Bir csv dosyasına bu sembolleri yazmış olduk. Üstteki read_html
çağrısına dikkat,
Pandas bir HTML sayfasını bile okuyup DataFrame
haline çevirebiliyor.
Tarihi veriyi bu semboller için biz daha önce Yahoo Finance sitesinden indirdik, mesela Apple seneti için, 2010 ve 2024 Eylül arasındaki tarihler için,
import pandas as pd
df = pd.read_csv(DATA + "/2010-2024/AAPL.csv")
df.tail(5)
Out[1]:
Date Adj Close
3685 2024-08-23 226.839996
3686 2024-08-26 227.179993
3687 2024-08-27 228.029999
3688 2024-08-28 226.490005
3689 2024-08-29 229.789993
Bu veriler ilk indirim, yerel tabanı bu verilerle önce dolduracağız. Veri tabanını yaratalım, SQlite tabanı olacak, başlangıç verilerinin olduğu dizindeki tüm CSV dosyaları okunup tabana yüklenecek,
import sqlite3, glob, os
def db_conn():
db_file = DATA + "/sp500.db"
conn = sqlite3.connect(db_file)
return conn
def db_create():
conn = db_conn()
c = conn.cursor()
res = c.execute('''DROP TABLE IF EXISTS TICKER; ''')
res = c.execute('''CREATE TABLE TICKER (dt INTEGER, sym TEXT, c NUMERIC, PRIMARY KEY (dt, sym)); ''')
Veri tabanı tasarımında tarih dt
bir tam sayı olarak yazıldı, eğer
tarihleri 20240101 şeklinde yazarsak büyüktür, küçüktür filtreleme
operasyonu hala düzgün çalışacaktır, çünkü mesela 20240201 sayısı
20240101 sayısından büyüktür, 20250101 onlardan da büyüktür, vs.
İlk verileri yükleyelim,
def db_load_2010():
conn = db_conn()
cursor = conn.cursor()
dir = "2010-2024"
for file in glob.glob(DATA + "/" + dir + "/*"):
print (file)
df = pd.read_csv(file)
sym = os.path.basename(file).replace(".csv","")
for idx,row in df.iterrows():
dt = int(row['Date'].replace("-",""))
c = float(row['Adj Close'])
cursor.execute('''INSERT INTO TICKER (dt,sym,c) VALUES (?,?,?)''', (dt,sym,c))
conn.commit()
Şimdi artıksal, güncelleme dosyalarına gelelim. Bu dosyalar farklı bir dizinde olur, her gün için ayrı bir CSV, dosya içinde sembol, kapanış fiyatı verisi bulunur. Mesela Eylül 3 için,
df = pd.read_csv(DATA + "/2024/09/2024-09-03.csv")
df.tail(5)
Out[1]:
AJG 294.49
497 ABT 114.66
498 CNC 80.23
499 XYL 130.71
500 FICO 1688.41
501 NVR 9053.67
Artıksal dosyaları yüklemek için
def db_load_inc(dir):
conn = db_conn()
cursor = conn.cursor()
gdir = DATA + "/" + dir + "/**/*.csv"
for file in glob.glob(gdir,recursive=True):
dt = os.path.basename(file).replace(".csv","")
dt = dt.replace("-","")
cursor.execute('''DELETE FROM TICKER where dt = ?''', (dt,))
conn.commit()
df = pd.read_csv(file,header=None)
for idx,row in df.iterrows():
sym, c = row[0], row[1]
print (dt,sym,c)
cursor.execute('''INSERT INTO TICKER (dt,sym,c) VALUES (?,?,?)''', (dt,sym,c))
conn.commit()
Parametre olarak dizin veriliyor, fonksiyon o dizin altında özyineli olarak hangi CSV dosyasını bulursa okuyup yüklüyor, üstteki veri için
db_load_inc(DIR + "/2024/09")
diyebilirdik. Ayrıca kod her gün dosyasını yüklemeden önce o günün kayıtlarını bulursa siler, yani aynı artıksal dosyalar üzerinde birden fazla yükleme çağrısı yapılabilir.
Artık veriyi okuyabiliriz. Bir sembol listesi ve başlangıç yılı kullanarak istediğimiz SP 500 verisini bir zaman serisi olarak alabiliyoruz,
def get_db_tickers(year, tickers):
c = db_conn().cursor()
year = int(str(year) + "0101")
dfs = []
for ticker in tickers:
rows = c.execute("SELECT dt,c from TICKER where sym = ? and dt >= ?", (ticker,year))
df = pd.DataFrame(rows.fetchall(),columns=['dt',ticker])
df['dt'] = pd.to_datetime(df['dt'], format='%Y%m%d')
df = df.set_index('dt')
dfs.append(df)
df = pd.concat(dfs,axis=1)
return df
df = get_db_ticker(2010, ["AAPL"])
df.plot()
Üstteki kodları kullanarak bizim güncel tuttuğumuz dosyalar,
https://github.com/burakbayramli/alldata
adresinde, sp500
alt dizini altında bulunabilir. Bu Github deposunu
git clone
indirmek ve üstteki yükleme kodlarını gerekli dizine
yönlendirmek yeterli. Artıksal dosyalar yine üstteki depoda, ek
dosyalar gerektikçe git pull
ile aynı depo altından alınabilir,
ardından db_load_inc
işletilir.
Yukarı