پیشتر در آموزش «کار با داده های مالی در پایتون — راهنمای مقدماتی» به موضوعاتی همچون دریافت و پردازش دادههای مربوط به بورس خارج از کشور، رمزارزها و قیمت جهانی فلزات گرانبها پرداختیم. در این مطلب قصد داریم تا داده های بورس تهران را دریافت و آنها را پردازش کنیم. بدین منظور از ماژول (Module) Finpy-TSE استفاده خواهیم کرد که برای این کار توسعه داده شده است و امکانات خوبی فراهم آورده است. برای آشنایی بیشتر با این کتابخانه، میتوانید به صفحه PyPi مربوط به آن (+) مراجعه کنید.
فراخوانی کتابخانهها
برای شروع کار دریافت داده های بورس تهران در بورس، پس از نصب کتابخانه مورد نظر، وارد محیط برنامهنویسی پایتون شده و کتابخانههای مورد نیاز را فراخوانی میکنیم:
import numpy as np
import pandas as pd
import finpy_tse as tse
import mplfinance as mplf
import scipy.stats as stt
import matplotlib.pyplot as plt
این کتابخانهها به ترتیب برای موارد زیر استفاده خواهند شد:
- محاسبات برداری
- کار با دیتافریمها
- دریافت داده از API مربوط به بورس تهران
- رسم نمودارهای تکنیکال
- محاسبه ضریب همبستگی پیرسون (Pearson Correlation Coefficient)
- رسم نمودار
حال تنظیمات نمودارها را به شکل زیر تعیین میکنیم:
plt.style.use('ggplot')
دریافت فهرست تمامی سهامها
حال میتوانیم در اولین قدم، فهرست تمامی سهمها را دریافت کنیم:
DF1 = tse.Build_Market_StockList(bourse=True,
farabourse=True,
payeh=True,
detailed_list=False,
show_progress=True,
save_excel=False,
save_csv=False)
ورودیهای تعریف شده برای این تابع، به ترتیب برای این موارد کاربرد دارند:
- دریافت سهام مربوط به بازار بورس
- دریافت سهام مربوط به بازار فرابورس
- دریافت سهام مربوط به بازار پایه
- اضافه کردن اطلاعات سربرگ سهام به دیتافریم خروجی
- نمایش روند دریافت داده
- ذخیره دیتافریم در فایل اکسل (Excel)
- ذخیره دیتافریم در فایل CSV
حال ۵ سطر ابتدایی دیتافریم دریافتشده را نشان میدهیم:
print(DF1.head())
که خواهیم داشت:
Market | Name | Ticker |
بورس | تولید نیروی برق آبادان | آبادا |
بورس | آسان پرداخت پرشین | آپ |
بورس | بیمه آسیا | آسیا |
بورس | کنتورسازی ایران | آکنتور |
بورس | فرآورده معدنی اپال کانی پارس | اپال |
توجه داشته باشید که میتوان با تغییر detailed_list به True میتوان فهرستی با جزئیات بیشتر دریافت کرد.
حال میتوانیم برای دریافت فهرستی از تمامی نمادها، به شکل زیر نوشت:
Tickers = DF1.index.to_list()
به این ترتیب، فهرستی به طول ۷۰۵ ایجاد میشود که شامل کل نمادهای بورس، فرابورس و بازار پایه است.
برای یادگیری برنامهنویسی با زبان پایتون، پیشنهاد میکنیم به مجموعه آموزشهای مقدماتی تا پیشرفته پایتون تم آف مراجعه کنید که لینک آن در ادامه آورده شده است.
دریافت تاریخچه شاخص کل
در اغلب بازارها، یک شاخص کل وجود دارد که برگرفته از کل بازار است و بر رفتار اغلب نمادها اثرگذار است. برای دریافت تاریخچه شاخص کل، میتوان به شکل زیر عمل کرد:
DF2 = tse.Get_CWI_History(start_date='1396-01-01',
end_date='1399-01-01',
ignore_date=False,
just_adj_close=False,
show_weekday=True,
double_date=True)
برای این تابع، ورودیهای تعریفشده اعمال زیر را تنظیم میکنند:
- تاریخ اولین داده
- تاریخ آخرین داده
- این ورودی در صورت True بودن، کل تاریخچه را برمیگرداند و دو ورودی قبلی را Ignore میکند.
- این ورودی در صورت True بودن، تنها مقدار تعدیل شده Close را برمیگرداند.
- اضافه کردن روز هفته به دیتافریم خروجی
- اضافه کردن تاریخ میلادی به دیتافریم خروجی
پس از اجرای کد فوق، دیتافریم به شکل زیر دریافت میشود:
Date Weekday Open High Low Close Adj Close Volume J-Date 1396-01-05 2017-03-25 Saturday 77239.0 77494.0 77239.0 77486.0 77485.8 282764388 1396-01-06 2017-03-26 Sunday 77505.0 77542.0 77493.0 77503.0 77502.9 362972179 1396-01-07 2017-03-27 Monday 77519.0 77529.0 77481.0 77523.0 77523.3 356510812 1396-01-08 2017-03-28 Tuesday 77533.0 77577.0 77533.0 77548.0 77548.5 466165632 1396-01-09 2017-03-29 Wednesday 77575.0 77607.0 77565.0 77584.0 77584.4 547432473
به این ترتیب، مشاهده میکنیم که مجموعه داده به صورت تعیینشده دریافت میشود.
حال میتوانیم یک نمودار شمعی (Candle Stick Plot) برای قیمت رسم کنیم. برای این کار ابتدا Index دیتافریم را به تاریخ میلادی تغییر میدهیم:
DF2.index = DF2['Date']
سپس برای رسم نمودار مینویسیم:
mplf.plot(DF2[-200:], type='candle', mav=(13, 55))
plt.show()
که نمودار زیر حاصل میشود.
به این ترتیب، نمودار مورد نظر رسم میشود.
میتوان نمودار OHLC را نیز به شکل زیر رسم کرد:
mplf.plot(DF2[-200:], type='ohlc', mav=(13, 55))
plt.show()
که در این صورت، شکل زیر را خواهیم داشت.
به این ترتیب، نمودار OHLC نیز رسم میشود. علاوه بر این دو نمودار، نمودارهای Line و Renko و PNF نیز قابل رسم هستند.
به جز شاخص کل، میتوان از توابع زیر استفاده کرد:
- Get_EWI_History: این تابع برای دریافت تاریخچه شاخص کل هم وزن کاربرد دارد.
- Get_INDI_History: این تابع برای دریافت تاریخچه شاخص صنعت کاربرد دارد.
- Get_ACT50_History: این تابع برای دریافت تاریخچه ۵۰ شرکت فعالتر کاربرد دارد.
- Get_LCI30_History: این تابع برای دریافت تاریخچه ۳۰ شرکت بزرگ کاربرد دارد.
علاوه بر موارد گفتهشده، توابع دیگری نیز وجود دارد.
برای مقایسه، میتوان اطلاعات دو شاخص کل و شاخص کل هموزن را در DF2 و DF3 دریافت کرد:
DF2 = tse.Get_CWI_History(start_date='1396-01-01',
end_date='1399-01-01',
ignore_date=False,
just_adj_close=False,
show_weekday=True,
double_date=True)
DF3 = tse.Get_EWI_History(start_date='1396-01-01',
end_date='1399-01-01',
ignore_date=False,
just_adj_close=False,
show_weekday=True,
double_date=True)
حال میتوانیم ستون Close را در کنار هم رسم کنیم:
CWI = DF2['Adj Close'].to_numpy()
EWI = DF3['Adj Close'].to_numpy()
plt.subplot(1, 2, 1)
plt.plot(CWI, ls='-', lw=1, c='crimson')
plt.title('Tehran Stock Exchange CWI')
plt.xlabel('Time')
plt.ylabel('Value')
plt.yscale('log')
plt.subplot(1, 2, 2)
plt.plot(EWI, ls='-', lw=1, c='crimson')
plt.title('Tehran Stock Exchange EWI')
plt.xlabel('Time')
plt.ylabel('Value')
plt.yscale('log')
plt.show()
که شکل زیر را خواهیم داشت.
همچنین، میتوانیم همبستگی بین این دو شاخص را نیز به شکل زیر در قالب یک نمودار نشان دهیم:
PCC = 100 * stt.pearsonr(CWI, EWI)[0]
plt.scatter(CWI, EWI, s=10, color='crimson')
plt.title(f'Tehran Stock Exchange CWI & EWI Correlation (PCC: {round(PCC, 2)} %)')
plt.xlabel('CWI')
plt.ylabel('EWI')
plt.show()
که نتیجه آن، شکل زیر است.
به این ترتیب، مشاهده میکنیم که شاخص کل با شاخص کل هموزن ٪۹۸ همبستگی دارد که عدد بزرگی است. از طرفی، در بخش ابتدایی نمودار مشاهده میکنیم که این رابطه در مقدارهای کمتر از ۱۰۰٬۰۰۰ شاخص کل، ضعیفتر است.
علاوه بر قیمت، میتوان نمودار بالا را برای لگاریتم قیمت نیز رسم کرد:
logCWI = np.log(CWI)
logEWI = np.log(EWI)
PCC = 100 * stt.pearsonr(logCWI, logEWI)[0]
plt.scatter(logCWI, logEWI, s=10, color='crimson')
plt.title(f'Tehran Stock Exchange log(CWI) & log(EWI) Correlation (PCC: {round(PCC, 2)} %)')
plt.xlabel('log(CWI)')
plt.ylabel('log(EWI)')
plt.show()
که در این صورت، نمودار زیر حاصل میشود.
به این ترتیب، مشاهده میکنیم که در حالت لگاریتمی، جزئیات بهتر دیده میشوند، از طرفی نیز مقدار ضریب همبستگی پیرسون به عدد ٪۹۷ کاهش مییابد. با توجه به رفتار نمایی بازار، همبستگی بین لگاریتم قیمتها، قابلاستنادتر است.
همین نمودار را میتوانیم برای تغییرات لگاریتم قیمت رسم کنیم:
difflogCWI = logCWI[1:] - logCWI[:-1]
difflogEWI = logEWI[1:] - logEWI[:-1]
PCC = 100 * stt.pearsonr(difflogCWI, difflogEWI)[0]
plt.scatter(difflogCWI, difflogEWI, s=10, color='crimson')
plt.title(f'Tehran Stock Exchange diff(log(CWI)) & diff(log(EWI)) Correlation (PCC: {round(PCC, 2)} %)')
plt.xlabel('diff(log(CWI))')
plt.ylabel('diff(log(EWI))')
plt.show()
که در این صورت، شکل زیر را خواهیم داشت.
به این ترتیب، مشاهده میکنیم که همبستگی ٪۹۷ که برای لگاریتم قیمت مشاهده شده بود، در تغییرات لگاریتم قیمت به ٪۸۰ کاهش یافته است. دلیل این اتفاق در انباشت تغییرات نهفته است. اگر یک بازه ۳۰ روز را در نظر بگیریم، اگر تغییرات هر دو شاخص با یکدیگر ٪۸۰ همبستگی داشته باشند، به دلیل انباشت این تغییرات روی هم، مقدار قیمت در طول این بازه همبستگی بیشتری از خود نشان خواهد داد.
به همین دلیل، معیار مهمتر و قابل اعتمادتر، همبستگی بین تغییرات لگاریتم قیمت است. میتوان تغییرات نسبی را نیز به جای این معیار استفاده کرد.
دریافت تاریخچه قیمت سهام
برای دریافت تاریخچه قیمت سهام، از تابع Get_Price_History به شکل زیر استفاده میکنیم:
DF4 = tse.Get_Price_History(stock='شپنا',
start_date='1397-01-01',
end_date='1399-01-01',
ignore_date=False,
adjust_price=True,
show_weekday=True,
double_date=True)
در این تابع ۲ ورودی جدید وجود دارد که اولی Stock بوده و نماد مورد بررسی را نشان میدهد. دومین مورد نیز مربوط به Adjust Price است که تعیین میکند قیمتهای تعدیلشده نیز در دیتافریم نهایی افزوده شوند یا خیر.
پس از اجرا، یک دیتا فریم با ۱۸ ستون ایجاد خواهد شد. میتوانیم دیتافریم را به شکل زیر تمیز و اصلاح کنیم:
DropList = ['Open', 'High', 'Low', 'Close', 'Final',
'No', 'Ticker', 'Name', 'Part']
DF4.drop(columns=DropList, axis=1, inplace=True)
RenameDict = {'Adj Open': 'Open',
'Adj High': 'High',
'Adj Low': 'Low',
'Adj Close': 'Close',
'Adj Final': 'Final'}
DF4.rename(columns=RenameDict, inplace=True)
به این ترتیب، دیتافریم تمیزتر شده و به شکل زیر در میآید:
Date Weekday Volume Value Open High Low Close Final J-Date 1397-01-05 2018-03-25 Sunday 2105211 9110653660 485 488 480 480 483 1397-01-06 2018-03-26 Monday 2920816 12508686541 484 485 475 475 479 1397-01-07 2018-03-27 Tuesday 2509378 10627250267 476 476 471 473 474 1397-01-08 2018-03-28 Wednesday 4395699 18484907932 479 479 467 468 470 1397-01-14 2018-04-03 Tuesday 4699234 19610457457 474 474 465 465 467
دریافت اطلاعات لحظهای بازار
علاوه بر تاریخچه شاخص و سهام، اطلاعات لحظهای نمادها نیز میتواند سودمند باشد که آنها را نیز میتوان به شکل زیر دریافت کرد:
DF5 = tse.Get_MarketWatch(save_excel=False)
در این دیتافریم، ستونهای متعددی از جمله قیمتها، درصد تغییرات، حد بالا و پایین قیمت مجاز روزانه، ارزش معاملات و صفها، میانگین ارزش سرانه صفها، حجم خرید حقیقی و حقوقی و… وجود دارد. برای آشنایی بیشتر با این تابع، میتوان دیتافریم حاصل را بررسی کرد و از اطلاعات موجود در آن، برای استخراج شرایط خاص استفاده کرد. یکی از کاربردهای این دیتافریم، فیلترنویسی است و به این طریق میتوان سهامی که از شرایط خاصی برخوردار هستند را شناسایی کرد.
در کتابخانه Finpy-TSE، علاوه به موارد ذکرشده، توابع و امکانات دیگری نیز برای دانلود دسته جمعی دیتا، ساخت پنل قیمت، دریافت ارزش صفها، دریافت دیتای عمق بازار، دریافت سابقه حقیقی-حقوقی وجود دارد که هرکدام بسته به نیاز میتوانند مورد استفاده قرار گیرند.
جمعبندی دریافت داده های بورس تهران
در این مطلب، دریافت داده های بورس تهران در بورس و پردازش آنها را بررسی و برخی از امکانات کتابخانه Finpy-TSE را معرفی کردیم.
برای مطالعه بیشتر این کتابخانه میتوانید Documentation آن را مطالعه کنید.