Python’da Basit Bir Algoritmik Trading Stratejisi

Algo trade eden biri değilim (en azından şimdilik). Fakat eğer yapmak istesem faydalı bir güce sahip olduğumu ve yapmak isteyenlerin de bunu öğrenmesi gerektiğini düşünüyorum: Kodlama. Bu yazıda asıl amacım, stratejiden öte, bir strateji koda nasıl dökülebilir sorusuna cevap vermek ve Python ile pratik yapmak olacaktır.

Seçtiğim strateji basit: 50-200 basit hareketli ortalama ya da sma diyeceğimiz simple moving average.

  • 50 sma, 200 sma’yi aşağıdan yukarıya kesiyorsa (golden cross): AL (buy)
  • 50 sma, 200 sma’yi yukarıdan aşağıya kesiyorsa (death cross): SAT (sell)

Öncelikle ihtiyacımız olan modülleri import edelim.

import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("fivethirtyeight")

Verileri import edelim (verileri indirmek için tıklayın).

data = pd.read_excel("bist30.xlsx") #çalışma dizini: os.getcwd(), ayarlamak isterseniz: os.chdir()

Örnek hisse MGROS olacağı için o sütunu seçiyoruz. Seçtikten sonra da adını değiştirelim.

data = data[["DATE","MGROS"]]
print(data.head())
print(data.tail())
data = data.rename(columns={"MGROS":"STOCK"})

NA içeren satırları varsa kaldıralım.

#print(data.isna().sum())
data.dropna(inplace=True)

DATE sütununa göre sıralayalım. Sıralama yaparken index’i yok sayması gerekiyor.

data = data.sort_values(by=["DATE"], ignore_index=True)
#print(data.head())
#print(data.tail())

Görselleştirelim.

plt.figure(figsize=(12.5,4.5))
plt.rcParams.update({'font.size': 5})
plt.plot(data["STOCK"], label="MGROS", linewidth=1)
plt.title("MGROS Close Price History")
plt.xlabel("Jan. 02, 2003 - Jan. 15, 2021")
plt.ylabel("Close Price (TRY)")
plt.legend(loc="upper left")
plt.show()
Veriler Reuters’tan alınmıştır.

Şimdi 50 ve 200 sma’yi hesaplayıp veri çerçevesinin içine atalım.

data["SMA50"] = data["STOCK"].rolling(window=50).mean()
data["SMA200"] = data["STOCK"].rolling(window=200).mean()

Bunu da görselleştirelim.

plt.figure(figsize=(12.5,4.5))
plt.rcParams.update({'font.size': 5})
plt.plot(data["STOCK"], label="MGROS", linewidth=1)
plt.plot(data["SMA50"], label="SMA50", linewidth=1)
plt.plot(data["SMA200"], label="SMA200", linewidth=1)
plt.title("MGROS Close Price History")
plt.xlabel("Jan. 02, 2003 - Jan. 15, 2021")
plt.ylabel("Close Price (TRY)")
plt.legend(loc="upper left")
plt.show()

Şimdi BuySell isimli fonksiyonumuzu yazalım.

def BuySell(data):

BuySig ve SellSig adında iki tane boş liste oluşturacağız ve sinyalleri (aslında fiyatları) bunlardan hangisi geçerliyse ona atacağız. Bir de check adında bir değişken oluşturacağız ve bunun değerine default 0 diyeceğiz. Bu bizim sık sık sinyal üretmemizi engelleyecek. check’e buy ise 1; sell ise -1 diyeceğiz.

def BuySell(data):

    BuySig = []
    SellSig = []
    check = 0

Ardından fonksiyonun içinde bir for döngüsü çalıştıracağız. Bunun da içinde koşul ifadeleri olacak.

Buy sinyallerini üretecek koşul:

        if data["SMA50"][i] > data["SMA200"][i]:

            if check != 1:

                BuySig.append(data["STOCK"][i])
                SellSig.append(np.nan)
                check = 1

            else:

                BuySig.append(np.nan)
                SellSig.append(np.nan)

i. değerin SMA50’si, i. değerin SMA200’ünden büyükse ve check değişkeni 1’e eşit değilse; BuySig listesine STOCK (mgros) fiyatını at. SellSig listesine ise NaN at. Son olarak check’i 1 yap. Eğer burada check 1 yapılmazsa ve bir sonraki i’de aynı koşul sağlanırsa yine sinyal üretir.

Sell sinyalleri üretecek koşul:

        elif data["SMA50"][i] < data["SMA200"][i]:

            if check != -1:

                BuySig.append(np.nan)
                SellSig.append(data["STOCK"][i])
                check = -1

            else:

                BuySig.append(np.nan)
                SellSig.append(np.nan)

İlk koşul sağlanmazsa elif devreye girecek. i. değerin SMA50’si, i. değerin SMA200’ünden küçükse ve check değişkeni -1’e eşit değilse; SellSig listesine STOCK (mgros) fiyatını at. BuySig listesine ise NaN at. Son olarak check’i -1 yap. Eğer burada check -1 yapılmazsa ve bir sonraki i’de aynı koşul sağlanırsa yine sinyal üretir.

Hiç bir koşul sağlanmıyor ise else durumuna girecek.

            else:

                BuySig.append(np.nan)
                SellSig.append(np.nan)

Fonksiyonlarımızı return ile bitiriyorduk.

    return (BuySig, SellSig)

Fonksiyonun tamamı:

def BuySell(data):

    BuySig = []
    SellSig = []
    check = 0

    for i in range(len(data)):

        if data["SMA50"][i] > data["SMA200"][i]:

            if check != 1:

                BuySig.append(data["STOCK"][i])
                SellSig.append(np.nan)
                check = 1

            else:

                BuySig.append(np.nan)
                SellSig.append(np.nan)

        elif data["SMA50"][i] < data["SMA200"][i]:

            if check != -1:

                BuySig.append(np.nan)
                SellSig.append(data["STOCK"][i])
                check = -1

            else:

                BuySig.append(np.nan)
                SellSig.append(np.nan)

        else:

            BuySig.append(np.nan)
            SellSig.append(np.nan)

    return (BuySig, SellSig)

BuySell’in 0’ı buy sinyallerini; 1’i sell sinyallerini veriyor. Bunları veri çerçevesine atalım. Kaydetmek istersiniz diye bir satır daha bırakıyorum.

BuySell = BuySell(data)
data["BuySigPrice"] = BuySell[0]
data["SellSigPrice"] = BuySell[1]
#data.to_excel("data.xlsx")

Bakalım ortalama sell fiyatı ile ortalama buy fiyatı arasında fark ne olacak? Sonuç, ortalamada + ise kar; – ise zarar diyeceğiz (1 lot ve 0 komisyon).

AvgPL = data["SellSigPrice"].mean() - data["BuySigPrice"].mean()
print("""

Ortalama Buy: {} TRY
Ortalama Sell: {} TRY
Ortalama P/L: {} TRY

""".format(round(data["BuySigPrice"].mean(), ndigits=2),
           round(data["SellSigPrice"].mean(), ndigits=2),
           round(AvgPL, ndigits=2)))

Ortalama Buy: 12.45 TRY
Ortalama Sell: 14.8 TRY
Ortalama P/L: 2.35 TRY

Son görselleştirmemizi yapalım.

plt.figure(figsize=(12.5,4.5))
plt.rcParams.update({'font.size': 5})
plt.plot(data["STOCK"], label="MGROS", alpha=0.50, linewidth=1)
plt.plot(data["SMA50"], label="SM50", alpha=0.50, linewidth=1)
plt.plot(data["SMA200"], label="SMA200", alpha=0.50, linewidth=1)
plt.scatter(data.index, data["BuySigPrice"], label="BUY", marker="^", color="green")
plt.scatter(data.index, data["SellSigPrice"], label="SELL", marker="v", color="red")
plt.title("MGROS Buy & Sell Signals")
plt.suptitle("No Investment Advice. The Content is for informational purposes only.")
plt.xlabel("Jan. 02, 2003 - Jan. 15, 2021")
plt.ylabel("Close Price (TRY)")
plt.legend(loc="upper left")
plt.show()
Yatırım tavsiyesi değildir. İçerik yalnızca bilgi amaçlıdır.

7 thoughts on “Python’da Basit Bir Algoritmik Trading Stratejisi

  • 31 Ocak 2021 tarihinde, saat 19:53
    Permalink

    Öncelikle elinize sağlık Ustad,

    data = pd.read_excel("bist30.xlsx")
    

    parametresinde dizin ile alakalı hata alıyorum ama

    Yanıtla
    • 1 Şubat 2021 tarihinde, saat 14:19
      Permalink

      Teşekkürler.

      os modülünü import ettikten sonra os.getcwd() yapar mısınız? Size verdiği sonuç ile dosyanın bulunduğu yeri karşılaştırın. Aynı yer değilse dosyanın konumunu os.chdir() ‘in içine yazın. Ardından tekrar os.getcwd() yaparak değişip değişmediğini kontrol edin. Eğer hata ile karşılaşmaya devam ederseniz buraya yazabilirsiniz.

      Yanıtla
  • 1 Şubat 2021 tarihinde, saat 21:38
    Permalink

    Tamamdır, çok ama çok teşekkür ederim.

    [code]openpyxl[/] yükledikten sonra sıkıntı kalmadı. Daha da fazla python içerikleri görmek dileğiyle takipteyim.

    Yanıtla
  • 13 Mayıs 2021 tarihinde, saat 23:29
    Permalink

    Merhaba iyi günler, hisse fiyatlarını hangi scraping metodu ile elde ettiniz? Python üzerinden ise kullandığınız site ve kütüphaneleri söyleyebilir misiniz?

    Yanıtla
    • 15 Mayıs 2021 tarihinde, saat 02:02
      Permalink

      Merhaba, verileri Reuters’tan aldım fakat iki paket önerebilirim: yfinance ve quandl.

      Yanıtla
      • 16 Mayıs 2021 tarihinde, saat 21:24
        Permalink

        Teşekkür ederim. Önerdiğiniz paketler Türkiye için geçerli değil sanırım. Türkiye için araştırıyorum ama kolay bir yolu yok gibi. Investing den falan deneyeceğim.

        Yanıtla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir