پیاده سازی میانگین متحرک هال در پایتون — راهنمای گام به گام

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

در مطالب گذشته مجله فرادرس، به روش‌های کاهش «تأخیر» (Lag) در میانگین‌های متحرک پرداختیم و چندین روش را مشاهده کردیم. در این مطلب می‌خواهیم به میانگین متحرک هال (Hull Moving Average) یا HMA بپردازیم که تأخیر بسیار کمی دارد و بسیار عالی عمل می‌کند. به همین منظور، این میانگین متحرک، در بین دیگران، پرطرفدار است.

میانگین متحرک هال

برای محاسبه این میانگین متحرک در پنجره زمانی L، به شکل زیر دو «میانگین متحرک وزن‌دار» (Weighted Moving Average) یا WMA محاسبه می‌کنیم:

$$ \begin{gathered}
W M A_{s}=W M A\left(X, \frac{L}{2}\right) \\
W M A_{l}=W M A(X, L)
\end{gathered} $$

برای آشنایی بیشتر با میانگین متحرک وزن‌دار، می‌توانید به مطلب «میانگین متحرک وزن دار در پایتون — راهنمای گام به گام» مراجعه کنید.

به این ترتیب، دو میانگین متحرک کوتاه (Short) و بلند (Long) خواهیم داشت. حال می‌توانیم همانند حالتی که در میانگین متحرک دوگانه (Double Exponential Moving Average) یا DEMA داشتیم، اختلاف دو میانگین متحرک وزن‌دار را به میانگین متحرک کوتاه اضافه کنیم:

$$\text { Raw HMA }=W M A_{s}+\left(W M A_{s}-W M A_{l}\right)=2 \times W M A_{s}-W M A_{l}$$

به این ترتیب، بخشی از تأخیر با استفاده از میانگین متحرک وزن‌دار رفع می‌شود. بخشی دیگر از تأخیر نیز با استفاده از طول بازه‌های مختلف و اصلاح آن‌ها برطرف می‌شود. برای هموار کردن (Smoothing) خروجی اندیکاتور (Indicator)، بار دیگر میانگین متحرک وزن‌دار را روی خروجی قبلی اعمال می‌کنیم:

$$H M A=W M A(\operatorname{Ram} H M A, \sqrt{L}) $$

به این ترتیب، خروجی حاصل هم هموار بوده و هم دارای تأخیر کمتری است.

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

پیاده سازی میانگین متحرک هال در پایتون

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

1import numpy as np
2import yfinance as yf
3import matplotlib.pyplot as plt

این سه کتابخانه به ترتیب برای محاسبات برداری، دریافت داده و رسم نمودار استفاده خواهند شد.

تنظیمات کتابخانه Matplotlib را نیز به شکل زیر تعریف می‌کنیم:

1plt.style.use('ggplot')

حال داده‌های یک سال اخیر مربوط به شرکت Microsoft که با نماد MSFT شناخته می‌شود را دریافت می‌کنیم:

1Ticker = yf.Ticker('MSFT')
2DF = Ticker.history(period='1y', interval='1d')

پس از اجرای کد، ۵ سطر ابتدایی را می‌توانیم با کد زیر مشاهده کنیم:

1print(DF.head())

که خروجی به شکل زیر خواهد بود:

                  Open        High         Low       Close    Volume  Dividends  Stock Splits
Date
2021-03-22  228.409512  234.985934  228.280557  234.083298  30127000        0.0             0
2021-03-23  235.571177  239.102411  235.154572  235.660446  31638400        0.0             0
2021-03-24  235.928260  236.077042  233.418703  233.557571  25620100        0.0             0
2021-03-25  233.398890  235.025639  229.699031  230.462799  34061900        0.0             0
2021-03-26  229.679176  234.797489  229.679176  234.569336  25479900        0.0             0

حال می‌توان نموداری برای ستون مربوط به قیمت Close رسم کرد:

1DF.plot(y='Close',
2        kind='line',
3        title='MSFT Last 1 Year Historical Price',
4        logy=True,
5        xlabel='Date',
6        ylabel='Price ($)')
7
8plt.show()

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

میانگین متحرک هال

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

1def WMA(S:np.ndarray, L:int):
2    W = np.arange(start=1, stop=L+1, step=1)
3    W = W / W.sum()
4    nD0 = S.size
5    nD = nD0 - L + 1
6    wma = np.zeros(nD)
7    for i in range(nD):
8        wma[i] = np.multiply(S[i:i + L], W).sum()
9    return wma

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

1def HMA(S:np.ndarray, L:int):

اکنون طول پنجره برای میانگین متحرک‌ها را محاسبه کنیم:

1def HMA(S:np.ndarray, L:int):
2    lShort = round(L / 2)
3    lLong = L
4    lSmooth = round(L**0.5)

توجه داشته باشید که چون ممکن است $$ \frac {L}2$$ و $$\sqrt {L}$$ اعداد طبیعی نباشند، باید از تابع Round برای تبدیل این اعداد به Integer استفاده کنیم.

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

1def HMA(S:np.ndarray, L:int):
2    lShort = round(L / 2)
3    lLong = L
4    lSmooth = round(L**0.5)
5    sWMA = WMA(S, lShort)
6    lWMA = WMA(S, lLong)

حال می‌توانیم Raw HMA را محاسبه کنیم. برای محاسبه، باید طول دو میانگین متحرک وزن‌دار با یکدیگر برابر باشد، برای این منظور، به شکل زیر عمل می‌کنیم:

1def HMA(S:np.ndarray, L:int):
2    lShort = round(L / 2)
3    lLong = L
4    lSmooth = round(L**0.5)
5    sWMA = WMA(S, lShort)
6    lWMA = WMA(S, lLong)
7    sWMA = sWMA[-lWMA.size:]

حال رابطه مربوط به Raw HMA را اعمال می‌کنیم:

1def HMA(S:np.ndarray, L:int):
2    lShort = round(L / 2)
3    lLong = L
4    lSmooth = round(L**0.5)
5    sWMA = WMA(S, lShort)
6    lWMA = WMA(S, lLong)
7    sWMA = sWMA[-lWMA.size:]
8    rawHMA = 2 * sWMA - lWMA

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

1def HMA(S:np.ndarray, L:int):
2    lShort = round(L / 2)
3    lLong = L
4    lSmooth = round(L**0.5)
5    sWMA = WMA(S, lShort)
6    lWMA = WMA(S, lLong)
7    sWMA = sWMA[-lWMA.size:]
8    rawHMA = 2 * sWMA - lWMA
9    hma = WMA(rawHMA, lSmooth)
10    return hma

به این ترتیب، تابع کامل می‌شود.

حال به شکل زیر تابع را فراخوانی می‌کنیم:

1S = DF['Close'].to_numpy()
2
3hma = HMA(S, 15)

اکنون می‌توان نموداری برای نمایش رفتار میانگین متحرک هال در مقابل قیمت رسم کرد:

1T = np.arange(S.size)
2
3plt.semilogy(T, S, lw=0.9, c='crimson', label='Price')
4plt.semilogy(T[-hma.size:], hma, lw=0.9, c='teal', label='HMA(15)')
5# plt.semilogy(T[-ema.size:], ema, lw=0.9, c='k', label='EMA(15)')
6# plt.semilogy(T[-wma.size:], wma, lw=0.9, c='lime', label='WMA(15)')
7plt.title('MSFT Last 1 Year Historical Price')
8plt.xlabel('Time (Day)')
9plt.ylabel('Price ($)')
10plt.legend()
11plt.show()

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

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

به این ترتیب، مشاهده می‌کنیم که رفتار بسیار مناسبی از میانگین متحرک هال ایجاد می‌شود. با افزایش طول پنجره از ۱۵ به ۳۰، نمودار به شکل زیر تغییر می‌یابد.

میانگین متحرک

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

برای مقایسه رفتار این میانگین متحرک با سایرین، کد مربوط به میانگین متحرک ساده را نیز وارد کد می‌کنیم:

1def SMA(S:np.ndarray, L:int):
2    nD0 = np.size(S)
3    nD = nD0 - L + 1
4    sma = np.zeros(nD)
5    for i in range(nD):
6        sma[i] = np.mean(S[i:i + L])
7    return sma

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

1sma = SMA(S, 30)
2wma = WMA(S, 30)
3hma = HMA(S, 30)
4
5T = np.arange(S.size)
6
7plt.semilogy(T, S, lw=0.9, c='crimson', label='Price')
8plt.semilogy(T[-sma.size:], sma, lw=0.9, c='teal', label='SMA(30)')
9plt.semilogy(T[-wma.size:], wma, lw=0.9, c='k', label='WMA(30)')
10plt.semilogy(T[-hma.size:], hma, lw=0.9, c='lime', label='HMA(30)')
11plt.title('MSFT Last 1 Year Historical Price')
12plt.xlabel('Time (Day)')
13plt.ylabel('Price ($)')
14plt.legend()
15plt.show()

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

نمودار قیمت

به این ترتیب، چند نکته در نمودار نمایان می‌شود:

  1. میانگین متحرک ساده دارای بیشترین تأخیر و میانگین متحرک هال دارای کمترین تأخیر است.
  2. میانگین متحرک هال، در هر روند، داخل شمع‌ها حرکت می‌کند.
  3. تقاطع این سه میانگین متحرک تقریباً با هم همزمان است.
  4. یک بار شکست میانگین متحرک هال، نشانه خوبی از ضعیف شدن روند است که پس از آن به احتمال زیاد خنثی شدن روند و به دنبال آن تغییر روند مشاهده می‌شود.
  5. میانگین متحرک هال، مومنتوم (Momentum) قیمت را بهتر نشان می‌دهد.
  6. میانگین متحرک هال، تمایل بالایی به خطی شدن در طول روند دارد.
  7. علامت تغییرات میانگین متحرک هال، ارتباط بالایی با جهت روند کلی دارد.

برای بررسی مورد ۷، به شکل زیر تفاضل مقادیر میانگین متحرک هال را محاسبه می‌کنیم:

1hma = HMA(S, 30)
2dhma = hma[1:] - hma[:-1]

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

1z = np.zeros_like(dhma)
2
3T = np.arange(S.size)
4
5plt.subplot(2,1,1)
6plt.semilogy(T, S, lw=0.8, c='teal', label='Price')
7plt.title('MSFT Last 1 Year Historical Price')
8plt.ylabel('Price ($)')
9plt.xlim(left=-1, right=S.size)
10
11plt.subplot(2,1,2)
12plt.fill_between(T[-dhma.size:], z, dhma, where=(dhma >= z), color='lime')
13plt.fill_between(T[-dhma.size:], z, dhma, where=(dhma < z), color='crimson')
14plt.xlabel('Time (Day)')
15plt.ylabel('Value')
16plt.xlim(left=-1, right=S.size)
17
18plt.show()

توجه داشته باشید که به دلیل اختلاف در طول آرایه قیمت و dHMA، باید xlim تعیین شود مقدار محود X بین هر دو نمودار یکسان باشد.

پس از اجرا نمودار زیر حاصل می‌شود.

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

به این ترتیب مشاهده می‌کنیم که تمایل درونی بازار برای رشد یا ریزش، به‌خوبی با تغییرات میانگین متحرک هال همبستگی دارد. به همین دلیل، در تحلیل تکنیکال (Technical Analysis) علاوه بر رسم نمودار میانگین متحرک هال، رنگ آن را نیز با توجه به علاوت تغییرات تعیین می‌کنند که بسیار کمک‌کننده است.

معرفی فیلم آموزش پیاده سازی اندیکاتورهای تکنیکال با پایتون Python

فیلم آموزش پایتون

اندیکاتورهای مالی از ابزارهای مهم تحلیل معاملات هستند که با کمک زبان‌های برنامه‌نویسی می‌توان محاسبات مربوط به آن‌ها را انجام داد. در آموزش پیاده سازی اندیکاتورهای تکنیکال با پایتون Python که در ۲ ساعت و ۱۶ دقیقه تهیه و تدوین شده است، ضمن آشنایی کوتاه با ۱۰ اندیکاتور پرکاربرد، پیاده‌سازی گام به گام آن‌ها در محیط زبان برنامه‌نویسی پایتون (Python) ارائه شده است.

  • برای مشاهده آموزش پیاده سازی اندیکاتورهای تکنیکال با پایتون Python + اینجا کلیک کنید.

جمع‌بندی

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

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

  1. اگر به جای استفاده از WMA در محاسبات، از EMA استفاده کنیم، نتایج چگونه خواهد بود؟
  2. سایر نکات گفته‌شده در مورد ویژگی‌های میانگین متحرک هال را بررسی کرده و به شکل نمودار نشان دهید.
  3. مقدار مناسب برای طول پنجره را در بازه ۱۰ روز تا ۱۰۰ روز بیابید.
  4. ارتباط بین علامت تغییرات SMA و EMA و WMA را با روند قیمت مقایسه کنید.
  5. نمودار Raw HMA را به همراه HMA رسم کنید و رفتار هر کدام را توضیح دهید.

مطلبی که در بالا مطالعه کردید بخشی از مجموعه مطالب «آموزش پیاده‌سازی انواع میانگین های متحرک‌ در پایتون» است. در ادامه، می‌توانید فهرست این مطالب را ببینید:

بر اساس رای ۱۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
مجله فرادرس
نظر شما چیست؟

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