Python ile Kaufman Hareketli ortalaması

Ünlü bir borsa indikatörü olduğunu öğrendiğim ama aslında hiç ilgisi olmayan bir yerde büyük data analizi için sıradışı hareketlerle tahminler üretmek amacıyla kullandığım Kaufman ortalaması gerçekten hayat kurtarabiliyormuş. Bunu kullanmamı öneren, ufuk ve zihin açıcı ve gerçekten her açıdan fikirleri ile beni çok ciddi zehirleyen ve istikrarlı bir şekilde uykularımı kaçıran -ismini ne yazık ki yazamayacağım- kişiye de selam olsun 🙂

Bu uyarlanabilir hareketli ortalama, Perry Kaufman tarafından geliştirilmiştir. Perry Kaufman, 40 yılı aşkın süredir kurumlara ve bireysel yatırımcılar için sistematik stratejiler çalışan nicel finans teorisyenidir. Algoritmik ticaret programlarının geliştirilmesinde önde gelen bir uzman olarak kabul edilir. Kaufman’ın Uyarlanabilir Hareketli Ortalaması (KAMA) güçlü trend takip eden bir gösterge olup, temeli “Üstel Hareketli Ortalama” ‘ya (EMA) dayanır. Hem trend, hem de oynaklığa duyarlıdır.

Kaufman’ın Uyarlanabilir Hareketli Ortalamasını buradan sonra KAMA olarak anacağım.

İnternet gerçekten müthiş bir kaynak. Aradığınız her detayı rahatlıkla bulabiliyorsunuz. KAMA ile ilgilide -hele ki konu borsa ile alakalı olunca- onlarca kaynağa ulaşabilirisiniz. Ben sadece bunu python üzerinde kolayca nasıl kullanacağınızı göstermek istiyorum ve hedefim de bu.

İşin native matematiği ile ilgili iseniz şurada güzel bir kaynak önerebilirim;

https://fxcodebase.com/wiki/index.php/Kaufman%27s_Adaptive_Moving_Average_(KAMA)

KAMA formülü girişlerini anlamak için şu kaynak gerçekten çok açıklayıcı;

https://corporatefinanceinstitute.com/resources/equities/kaufmans-adaptive-moving-average-kama/

En altta bir çok kaynak paylaşacağım, şimdilik anlamak üzere üstteki linkler yeterli; uygulama tarafına geçeyim. Uygulama da kullandığım modüller

  1. Pandas : https://pypi.org/project/pandas/
  2. Numpy : https://pypi.org/project/numpy/
  3. Matplotlib : https://pypi.org/project/matplotlib/
  4. Görsel zenginlik için tabii ki Seaborn : https://pypi.org/project/seaborn/

Kullandığım hesaplayıcı fonksiyon şöyle;

def kama(getValue, length=None, fast=None, slow=None, drift=None, offset=None, **kwargs):
    """Indicator: Kaufman's Adaptive Moving Average (KAMA) - @hmustak"""
    # Validate Arguments
    length = int(length) if length and length > 0 else 10
    fast = int(fast) if fast and fast > 0 else 2
    slow = int(slow) if slow and slow > 0 else 30
    getValue = verify_series(getValue, max(fast, slow, length))
    drift = get_drift(drift)
    offset = get_offset(offset)

    if getValue is None: return

    # Calculate Result
    def weight(length: int) -> float:
        return 2 / (length + 1)

    fr = weight(fast)
    sr = weight(slow)

    abs_diff = non_zero_range(getValue, getValue.shift(length)).abs()
    peer_diff = non_zero_range(getValue, getValue.shift(drift)).abs()
    peer_diff_sum = peer_diff.rolling(length).sum()
    er = abs_diff / peer_diff_sum
    x = er * (fr - sr) + sr
    sc = x * x

    m = getValue.size
    result = [npNaN for _ in range(0, length - 1)] + [0]
    for i in range(length, m):
        result.append(sc.iloc[i] * getValue.iloc[i] + (1 - sc.iloc[i]) * result[i - 1])

    kama = Series(result, index=getValue.index)

    # Offset
    if offset != 0:
        kama = kama.shift(offset)

    # Handle fills
    if "fillna" in kwargs:
        kama.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        kama.fillna(method=kwargs["fill_method"], inplace=True)

    # Name & Category
    kama.name = f"KAMA_{length}_{fast}_{slow}"
    kama.category = "overlap"

    return kama

 

Burada bizim senaryomuza göre Excel üzerine indirdiğimiz ~150bin verinin 200, 2, 30 ve 20, 2, 30 ‘luk KAMA değeri ile 30 datalık Hareketli ortalamasını almak üzere yola çıktık. Excelde istediğimiz kolonun grafiğini hazırlarken, başka kolonlara göre de bazı filtrasyonları da çalıştırmayı denedik. Kod içine ufak notlar aldım, inceleyebilirsiniz. Kodlardan görebildiğiniz üzere benim excelim’de referans olarak tarih, kolon_1 ve kolon_2 kolonları bulunmakta.

# -*- coding: utf-8 -*-
"""
@author: Hakan Müştak @2022 #hmustak
@mail: hakan[@]mustak.org
@web: mustak.org
@social: twitter.com/hmustak
"""

from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
import pandas as pd
from pandas import Series
from numpy import nan as npNaN
import seaborn as sns
from matplotlib import pyplot as plt


def kama(getValue, length=None, fast=None, slow=None, drift=None, offset=None, **kwargs):
    """Indicator: Kaufman's Adaptive Moving Average (KAMA)"""
    # Validate Arguments
    length = int(length) if length and length > 0 else 10
    fast = int(fast) if fast and fast > 0 else 2
    slow = int(slow) if slow and slow > 0 else 30
    getValue = verify_series(getValue, max(fast, slow, length))
    drift = get_drift(drift)
    offset = get_offset(offset)

    if getValue is None: return

    # Calculate Result
    def weight(length: int) -> float:
        return 2 / (length + 1)

    fr = weight(fast)
    sr = weight(slow)

    abs_diff = non_zero_range(getValue, getValue.shift(length)).abs()
    peer_diff = non_zero_range(getValue, getValue.shift(drift)).abs()
    peer_diff_sum = peer_diff.rolling(length).sum()
    er = abs_diff / peer_diff_sum
    x = er * (fr - sr) + sr
    sc = x * x

    m = getValue.size
    result = [npNaN for _ in range(0, length - 1)] + [0]
    for i in range(length, m):
        result.append(sc.iloc[i] * getValue.iloc[i] + (1 - sc.iloc[i]) * result[i - 1])

    kama = Series(result, index=getValue.index)

    # Offset
    if offset != 0:
        kama = kama.shift(offset)

    # Handle fills
    if "fillna" in kwargs:
        kama.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        kama.fillna(method=kwargs["fill_method"], inplace=True)

    # Name & Category
    kama.name = f"KAMA_{length}_{fast}_{slow}"
    kama.category = "overlap"

    return kama


# İstediğimiz Kama limitleri
KAMA_1_value = 200
KAMA_2_value = 20
# İstediğimiz HO Limitleri
HO_data = 30

# Sayfaya açılacak ekranda label2larda şık göürnsün
KAMA_data_label = f"{KAMA_1_value},2,30"
KAMA_fast_label = f"{KAMA_2_value},2,30"
HO_label = f"HO: {HO_data} data"

# veriyi barındıran excel
uniformity_data_file = "ExcelDoc.xlsx"

# excelden gelen veriyi pandas aracılığı ile dataset oluşturulmasında kullanıyoruz
all_dataset = pd.read_excel(uniformity_data_file, 'Sheet1')

# örnek olsun diye excelden gelen kolnlarda filtrasyon denemeleri
all_dataset = all_dataset[all_dataset.FILTRE_KOLON_2 <= 10]
all_dataset = all_dataset[all_dataset.FILTRE_KOLON_3 == 'DENEME']

# KAMA değerlerini dataset üzerinde yeni kolonlara hesaplıyoruz
calcKAMA_1_Value = kama(all_dataset['KOLON_1'], KAMA_1_value, 2, 30, 1, 0)
calcKAMA_2_Value = kama(all_dataset['KOLON_1'], KAMA_2_value, 2, 30, 1, 0)
all_dataset['calcKAMA_1_Value'] = calcKAMA_1_Value
all_dataset['calcKAMA_2_Value'] = calcKAMA_2_Value

# Hareketli ortalamayı da hesaplıyoruz - Hazır elimiz değmişken
all_dataset['HO'] = all_dataset.KOLON_1.rolling(HO_data).mean()

# Son 3000 data desek?
all_dataset = all_dataset.tail(3000)

# Matplotlib oluşturmaya başladık
plt.figure(figsize=(12, 6))
plt.subplots_adjust(left=0.05, right=0.99, bottom=0.05, top=0.99, wspace=0.2, hspace=0.2)

# ve seaborn ile show başlıyor :)
sns.set()
# sns.set_theme(style="whitegrid", palette="pastel")

sns.lineplot(data=all_dataset, x='Tarih', y='kolon_1', color='limegreen', label='Güncel Data', linewidth=0.3)
sns.lineplot(data=all_dataset, x='Tarih', y='calcKAMA_2_Value', color='red', label=KAMA_data_label, linewidth=.6)
sns.lineplot(data=all_dataset, x='Tarih', y='calcKAMA_2_Value', color='blue', label=KAMA_fast_label, linewidth=.6)
sns.lineplot(data=all_dataset, x='Tarih', y='HO', color='gray', label=HO_label, linewidth=1.2)
sns.lineplot(data=all_dataset, x='Tarih', y=100, color='maroon', label='LIMIT', linewidth=1.5)

plt.show()

 

Bu üstte paylaştığım en basic haliyle kodun mevcut herhangi bir veriseti ile çalışabilmesi için. Ben bir arayüzle tüm değişkenlerin kullanıcı tarafından girilebilen ve GUI olan başka bir versiyon da yazdım, onu da sorunsuzca kullanmaktayım.

Ekran görüntüleri de şöyle;

 

 

Teknik olarak faydalandığım bazı siteler;

 

Bir soru yada sorununuz olursa ulaşabilirsiniz : twitter.com/hmustak

Hakan Müştak @2022-11

 

 

 


Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*

Captcha Kontrolü * Zaman aşımı, sayfayı tekrar yükleyin


Top