کار با داده های مالی در پایتون — راهنمای مقدماتی

۱۴۸۳ بازدید
آخرین به‌روزرسانی: ۰۷ شهریور ۱۴۰۲
زمان مطالعه: ۷ دقیقه
کار با داده های مالی در پایتون — راهنمای مقدماتی

به دلیل اهمیت و کاربرد بالای داده‌های مالی، بررسی عمیق‌تر آن‌ها برای فهم بهترشان امری ضروری است. داده‌های مالی می‌تواند شامل سری‌های زمانی و سایر داده‌ها شود. در این مطلب به آموزش مقدماتی کار با داده های مالی در پایتون خواهیم پرداخت. این داده‌ها از نوع سری‌های زمانی شامل تاریخچه قیمت برخی نمادها هستند.

کتابخانه های مورد نیاز برای کار با داده های مالی در پایتون

وارد محیط برنامه‌نویسی پایتون شده و کتابخانه‌های مورد نیاز را فراخوانی می‌کنیم:

1import numpy as np
2import pandas as pd
3import yfinance as yf
4import matplotlib.pyplot as plt
5import statsmodels.graphics.tsaplots as tsaplt

این کتابخانه‌ها به ترتیب برای موارد زیر استفاده خواهند شد:

  1. کار با آرایه‌ها و محاسبات برداری
  2. کار با دیتافریم‌ها و فایل‌های داده
  3. دریافت داده‌های مالی به صورت آنلاین از طریف API مربوط به Yahoo Finance
  4. رسم نمودار
  5. رسم نمودارهای خودهمبستگی

تنظیمات مربوط به برخی کتابخانه‌ها را نیز به‌شکل زیر می‌نویسیم:

1np.random.seed(0)
2plt.style.use('ggplot')

برای یادگیری برنامه‌نویسی با زبان پایتون، پیشنهاد می‌کنیم به مجموعه آموزش‌های مقدماتی تا پیشرفته پایتون فرادرس مراجعه کنید که لینک آن در ادامه آورده شده است.

دریافت آنلاین داده از API

برای دریافت اطلاعات مربوط به تاریخچه قیمت، از API (مخفف Application Programming Interface) مربوط به Yahoo Finance استفاده خواهیم کرد. به این منظور، به‌شکل زیر نماد مورد نظر را تعریف می‌کنیم:

1Ticker = yf.Ticker('GLD')

در این سطر از اسم اختصار GLD که مربوط به طلا است استفاده می‌کنیم.

حال می‌توانیم تاریخچه را با استفاده از متد history دریافت کنیم:

1DF = Ticker.history(interval='1d', start='2017-01-01', end='2022-01-01')

این متد در خروجی یک دیتافریم برمی‌گرداند. توجه داشته باشید که ورودی‌های بیشتری نیز برای این متد قابل تعریف است که برخی مهم‌ترین‌ها در زیر آورده شده‌اند:

  1. period: این ورودی نشان‌دهنده مدت زمان مورد درخواست است.
  2. interval: این ورودی نشان‌دهنده تایم فریم ثبت داده است.
  3. start: این ورودی تاریخ اولین رکورد را تعیین می‌کند.
  4. end: این ورودی تاریخ آخرین رکورد را تعیین می‌کند.
  5. tz: این ورودی منطقه زمانی (Time Zone) مورد نظر برای داده را تعیین می‌کند.

حال برای مشاهده ۱۰ سطر اول دیتافریم دریافت‌شده، به‌شکل زیر عمل می‌کنیم:

1print(DF.head(10))

که در خروجی خواهیم داشت:

                  Open        High         Low       Close   Volume  Dividends  Stock Splits
Date
2017-01-03  109.620003  111.000000  109.370003  110.470001  7527400          0             0
2017-01-04  111.059998  111.220001  110.610001  110.860001  4904100          0             0
2017-01-05  112.160004  112.940002  112.070000  112.580002  9606800          0             0
2017-01-06  111.809998  112.379997  111.570000  111.750000  7686100          0             0
2017-01-09  112.389999  113.040001  112.180000  112.669998  5674600          0             0
2017-01-10  112.940002  113.449997  112.639999  113.150002  6093400          0             0
2017-01-11  112.870003  114.190002  112.169998  113.500000  9918700          0             0
2017-01-12  114.519997  114.930000  113.809998  113.910004  8457300          0             0
2017-01-13  113.650002  114.309998  113.190002  114.209999  7261500          0             0
2017-01-17  115.889999  115.959999  115.500000  115.849998  9142400          0             0

به این ترتیب، مشاهده می‌کنیم که داده به‌درستی دریافت شده و شامل ستون‌های زیر است:

  1. Date: تاریخ هر سطر از داده را نشان می‌دهد.
  2. Open: اولین قیمت مشاهده‌شده در روز مربوطه را نشان می‌دهد.
  3. High: بیشترین قیمت مشاهده‌شده در روز مربوطه را نشان می‌دهد.
  4. Low: کمترین قیمت مشاهده‌شده در روز مربوطه را نشان می‌دهد.
  5. Close: آخرین قیمت مشاهده‌شده در روز مربوطه را نشان می‌دهد. توجه داشته باشید که در برخی از بازارها، قیمت Close میانگینی وزن‌دار از معاملات آن روز است و از قیمت Last به عنوان آخرین قیمت مشاهده شده استفاده می‌شود.
  6. Volume: تعداد و حجم معاملات در روز مربوطه را نشان می‌دهد.

در ادامه، دیتافریم دو ستون اضافه نیز وجود دارد که خالی می‌باشند به همین دلیل، آن‌ها را به‌شکل زیر حذف می‌کنیم:

1DF.drop(['Dividends', 'Stock Splits'], axis=1, inplace=True)

پس از اعمال کد فوق، دیتافریم به‌صورت زیر خواهد بود:

                  Open        High         Low       Close   Volume
Date
2017-01-03  109.620003  111.000000  109.370003  110.470001  7527400
2017-01-04  111.059998  111.220001  110.610001  110.860001  4904100
2017-01-05  112.160004  112.940002  112.070000  112.580002  9606800
2017-01-06  111.809998  112.379997  111.570000  111.750000  7686100
2017-01-09  112.389999  113.040001  112.180000  112.669998  5674600
2017-01-10  112.940002  113.449997  112.639999  113.150002  6093400
2017-01-11  112.870003  114.190002  112.169998  113.500000  9918700
2017-01-12  114.519997  114.930000  113.809998  113.910004  8457300
2017-01-13  113.650002  114.309998  113.190002  114.209999  7261500
2017-01-17  115.889999  115.959999  115.500000  115.849998  9142400

به این ترتیب، ستون‌های اضافه حذف می‌شوند.

حال می‌توانیم درصد تغییرات قیمت در هر روز معاملاتی را محاسبه و در یک ستون جدید وارد دیتافریم کنیم.

درصد تغییرات قیمت به‌صورت زیر قابل محاسبه است:

$$\text { Relative Change }(\%)=100 \times \frac{\text { Close }-\text { Open }}{\text { Open }}=100 \times\left(\frac{\text { Close }}{\text { Open }}-1\right) $$

برای این منظور، می‌توانیم بنویسیم:

1DF['Return'] = 100 * (DF['Close'] / DF['Open'] - 1)

پس از اعمال کد فوق، دیتافریم به‌صورت زیر درمی‌آید:

                  Open        High         Low       Close   Volume    Return
Date
2017-01-03  109.620003  111.000000  109.370003  110.470001  7527400  0.775405
2017-01-04  111.059998  111.220001  110.610001  110.860001  4904100 -0.180080
2017-01-05  112.160004  112.940002  112.070000  112.580002  9606800  0.374463
2017-01-06  111.809998  112.379997  111.570000  111.750000  7686100 -0.053660
2017-01-09  112.389999  113.040001  112.180000  112.669998  5674600  0.249131
2017-01-10  112.940002  113.449997  112.639999  113.150002  6093400  0.185939
2017-01-11  112.870003  114.190002  112.169998  113.500000  9918700  0.558162
2017-01-12  114.519997  114.930000  113.809998  113.910004  8457300 -0.532652
2017-01-13  113.650002  114.309998  113.190002  114.209999  7261500  0.492739
2017-01-17  115.889999  115.959999  115.500000  115.849998  9142400 -0.034516

به این ترتیب، ستون مربوط به درصد تغییرات قیمت به دیتافریم اضافه می‌شود.

رسم برخی نمودارهای مهم

ابتدا نمودار مربوط به قیمت Close را رسم می‌کنیم تا تغییرات قیمت نشان داده شود. برای این منظور، می‌نویسیم:

1plt.plot(DF['Close'])
2plt.show()

در خروجی کد فوق، نمودار زیر حاصل می‌شود:

نمودار مربوط به قیمت Close

به این ترتیب، مشاهده می‌کنیم که نمودار قیمت در مقابل زمان رسم شده است. این نمودار مشکلاتی دارد، برای مثال بهتر است از نمودار نیمه لگاریتمی (Semi-Logarithm) استفاده کنیم:

1plt.semilogy(DF['Close'])
2plt.show()

در خروجی، تصویر زیر را خواهیم داشت.

نمودار نیمه لگاریتمی

به این ترتیب، نمودار حاصل روند، سطوح حمایت و سطوح مقاومت را به خوبی نشان می‌دهد.

بهتر است یک عنوان برای نمودار Title و برچسب‌هایی برای محورها Xlabel & Ylabel تعیین کنیم. کاهش ضخامت خط نمودار نیز می‌تواند جزئیات نمودار را بهتر نشان دهد:

1plt.semilogy(DF['Close'], lw=0.9)
2plt.title('Gold Price Over Last 5 Years')
3plt.xlabel('Time (Day)')
4plt.ylabel('Price ($)')
5plt.show()

که شکل زیر را خواهیم داشت.

عنوان نمودار

به این ترتیب، نمودار مد نظر رسم می‌شود و به‌خوبی اطلاعات مربوط به قیمت را نشان می‌دهد.

می‌توانیم نمودار دیگری نیز برای درصد تغییرات قیمت رسم کنیم:

1plt.plot(DF['Return'], lw=0.9)
2plt.title('Gold Return Over Last 5 Years')
3plt.xlabel('Time (Day)')
4plt.ylabel('Relative Change (%)')
5plt.show()

که نمودار زیر حاصل خواهد شد.

کار با داده های مالی در پایتون

به این ترتیب، مشاهده می‌کنیم که در اغلب روزها، تغییرات قیمت کمتر از ٪۱ بوده است. برای تشخیص روزهایی با تغییرات قیمت غیرعادی، می‌توانیم از دامنه میان‌چارکی استفاده کنیم.

اگر برای یک متغیر چارک‌های اول و سوم را با نماد $$q_1$$ و $$q_3$$ نشان دهیم، دامنه میان‌چارک به‌صورت زیر تعریف می‌شود:

$$ i q r = q_3 - q _ 1 $$

سپس می‌توانیم «حد بالا» (Upper Bound) و «حد پایین» (Lower Bound) را به‌شکل زیر تعریف کنیم:

$$ \begin{aligned}
&U=q _3+1.5 \times i q r=2.5 \times q_{3}-1.5 \times q_{1} \\
&L=q _1-1.5 \times i q r=2.5 \times q_{1}-1.5 \times q_{3}
\end{aligned} $$

داده‌هایی که در خارج از این بازه قرار گیرند، می‌توانند به‌عنوان ناهنجاری (Anomaly) تشخیص داده شوند. به این منظور، می‌توانیم محاسبات لازم را انجام داده و دو خط مربوط به حد بالا و حد پایین را روی نمودار قبلی رسم کنیم:

1q1 = DF['Return'].quantile(0.25)
2q3 = DF['Return'].quantile(0.75)
3iqr = q3 - q1
4U = q3 + 1.5 * iqr
5L = q1 - 1.5 * iqr
6
7plt.plot(DF['Return'], lw=0.9, label='Return')
8plt.plot([DF.index[0], DF.index[-1]], [U, U], lw=1.2, c='k', label='Lower Bound')
9plt.plot([DF.index[0], DF.index[-1]], [L, L], lw=1.2, c='k', label='Upper Bound')
10plt.title('Gold Return Over Last 5 Years')
11plt.xlabel('Time (Day)')
12plt.ylabel('Relative Change (%)')
13plt.legend()
14plt.show()

با اجرای کد فوق، نمودار زیر در خروجی نشان داده می‌شود.

رسم نمودار قیمت

به این ترتیب، روزهای با تغییرات غیرعادی به‌خوبی تشخیص داده می‌شود. در تحلیل سری‌های زمانی، بعضاً اصلاح این داده‌ها از اهمیت بالایی برخوردار است.

می‌توانیم حد بالا و پایین را با توجه به میانگین و انحراف معیار نیز تعریف کنیم:

$$ \begin{aligned}
M &=\frac{1}{n} \sum_{i=1}^{n} x_{i} \\
S &=\sqrt{\frac{1}{n} \sum_{i=1}^{n}\left(x_{i}-M\right)^{2}} \\
U &=M+2 \times S \\
L &=M-2 \times S
\end{aligned} $$

برای این حالت نیز کدنویسی به‌شکل زیر تغییر می‌کند:

1M = DF['Return'].mean()
2S = DF['Return'].std()
3U = M + 2 * S
4L = M - 2 * S
5
6plt.plot(DF['Return'], lw=0.9, label='Return')
7plt.plot([DF.index[0], DF.index[-1]], [U, U], lw=1.2, c='k', label='Lower Bound')
8plt.plot([DF.index[0], DF.index[-1]], [L, L], lw=1.2, c='k', label='Upper Bound')
9plt.title('Gold Return Over Last 5 Years')
10plt.xlabel('Time (Day)')
11plt.ylabel('Relative Change (%)')
12plt.legend()
13plt.show()

که شکل زیر را خواهیم داشت.

رسم نمودار پایتون

مشاهده می‌کنیم که تفاوت چندانی با روش قبلی مشاهده نمی‌شود.

خودهمبستگی قیمت

با توجه به اینکه داده‌ها از نوع سری زمانی (Time Series) هستند، می‌توان همبستگی قیمت با خود را نیز بررسی کرد که خودهمبستگی (Autocorrelation) نام دارد. برای مطالعه بیشتر می‌توانید به مطلب «مدل خودهمبسته (Autoregressive) در پایتون – راهنمای گام به گام» مراجعه کنید.

برای رسم نمودار تابع خودهمبستگی (Autocorrelation Function - ACF) می‌توانیم به‌صورت زیر بنویسیم:

1tsaplt.plot_acf(DF['Close'], lags=800, c='teal', lw=0.4, markersize=1)
2plt.xlabel('Lags (Days)')
3plt.ylabel('Pearson Correlation Coefficient')
4plt.show()

پس از اجرای کد، نمودار به‌صورت زیر حاصل می‌شود.

کار با داده های مالی در پایتون

به این ترتیب، مشاهده می‌کنیم که قیمت طلا با ۱۲۰ روز گذشته رابطه معنادار داشته و با Lag=760 نیز بیشترین رابطه عکس را دارد. از طرفی، نبود هیچ‌گونه همبستگی با Lag=395 نیز به‌خوبی قابل مشاهده است.

می‌توانیم نمودار تابع خودهمبستگی جزئی (Partial Autocorrelation Function - PACF) را نیز به‌شکل زیر رسم کنیم:

1tsaplt.plot_pacf(DF['Close'], lags=200, c='teal', lw=0.4, markersize=1)
2plt.xlabel('Lags (Days)')
3plt.ylabel('Pearson Correlation Coefficient')
4plt.show()

که نمودار زیر حاصل می‌شود.

نمودار تابع خودهمبستگی جزئی

مشاهده می‌کنیم که قیمت با تأخیرهای زیر رابطه معنادار خوبی دارد:

$$ \text {Lags}={0,1,6,29,101,149,156,157,193} $$

به این صورت می‌توانیم تأخیرهای مهم را استخراج کنیم و در مدل‌سازی‌ها استفاده کنیم.

دو نمودار اخیر را برای ستون Return نیز رسم می‌کنیم که نتایج به‌شکل زیر می‌شود.

کار با داده های مالی در پایتون

و

کار با داده های مالی در پایتون

کاملاً مشهود است که تغییرات زیادی در نمودارها ایجاد شده است. به این ترتیب، نشان داده شد که اعمال اپراتور تغییرات نسبی باعث تغییرات زیادی در رفتار و همبستگی سری زمانی می‌شود. به این دلیل، پیش‌پردازش اعمال‌شده روی سری زمانی، در نتایج مدل‌سازی بسیار تأثیرگذار است.

ذخیره فایل نهایی برای استفاده‌های بعدی

در صورت استفاده از نمادهای زیاد، دریافت تمامی داده‌ها در هر بار اجرای الگوریتم‌ها، به‌دلیل برخی محدودیت‌های API، زمان‌بر بودن دریافت داده و کمبود منابع سخت‌افزاری، بهتر است تا داده‌ها را ذخیره کنیم و در دفعات بعدی از فایل‌های ذخیره‌شده استفاده کنیم.

به این منظور، می‌توانیم به‌صورت زیر عمل کنیم:

1DF.to_csv('GLD.csv', sep=',', encoding='utf-8', index=True)

در خروجی این کد، یک فایل CSV در کنار برنامه ایجاد می‌شود که می‌توانید آن را از اینجا (+) دانلود کنید.

به این ترتیب، مجموعه داده نیز ذخیره می‌شود و در استفاده‌های بعدی می‌توان از آن استفاده کرد.

جمع‌بندی کار با داده های مالی در پایتون

در این مطلب، به کار با داده های مالی در پایتون از قبیل پردازش، رسم نمودار و تحلیل‌های پایه در رابطه با داده‌های مالی پرداختیم.

برای مطالعه بیشتر می‌توان به پرسش‌‌های زیر پاسخ داد:

  1. خود همبستگی لگاریتم قیمت به چه صورت است؟
  2. چگونه می‌توان یک مدل خودهمبسته برای پیش‌بینی تغییرات قیمت ایجاد کرد؟
  3. ارتباط بین قیمت طلا و نقره به چه صورت است؟
  4. چگونه می‌توان داده روزهای با تغییرات ناهنجار را اصلاح کرد؟
بر اساس رای ۱۲ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
مجله فرادرس
۲ دیدگاه برای «کار با داده های مالی در پایتون — راهنمای مقدماتی»

سلام
وقت بخیر
کد ناقص نیستش؟
DF کجا تعریف شده؟ به نظر میرسه جا مونده

سلام، وقت شما بخیر؛

از بابت اطلاع‌رسانی شما در این رابطه بسیار سپاسگزاریم. مطلب اصلاح و به روز رسانی شد.

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *