Finans piyasalarında, fiyat hareketlerini anlamak ve geleceğe yönelik tahminlerde bulunmak için teknik analiz araçları hayati önem taşır. Bu araçların en popülerlerinden biri, özellikle kısa ve orta vadeli trendleri belirlemede etkili olan Üstel Hareketli Ortalama (Exponential Moving Average – EMA)’dır. EMA’nın ne olduğunu, neden bu kadar önemli olduğunu ve kendi borsa verileriniz üzerinde bu analizi otomatik olarak yapacak bir Python aracını nasıl kullanabileceğinizi ele alacağız.
Hareketli ortalamalar, belirli bir zaman dilimindeki fiyatların ortalamasını alarak fiyat dalgalanmalarını yumuşatan göstergelerdir. EMA, bu ortalama hesaplamasını yaparken son fiyatlara daha fazla ağırlık vererek, basit hareketli ortalamalardan (SMA) daha hızlı tepki verir. Bu özellik, yatırımcıların son piyasa değişikliklerini daha çabuk fark etmelerini sağlar.
EMA’nın temel mantığı, fiyatın EMA’nın üzerinde olması durumunda yükseliş trendinin devam ettiğini, altında olması durumunda ise düşüş trendinin hakim olduğunu gösterir. Farklı periyotlardaki EMA’ların birbiriyle kesişimi ise alım veya satım sinyali olarak yorumlanabilir.
Örneğin, kısa vadeli bir EMA’nın (örneğin EMA 8) uzun vadeli bir EMA’yı (örneğin EMA 21) yukarı yönlü kesmesi, güçlü bir alım sinyali olarak kabul edilebilir.
Python kodu, EMACalculator adında güçlü ve modüler bir sınıf yapısına sahiptir. Bu sınıf, borsa verilerinizi otomatik olarak okur, farklı periyotlarda EMA hesaplamaları yapar ve sonuçları düzenli bir şekilde kaydeder.
Kodun ana bölümleri
ema_periods: Kod, 5, 8, 13, 21, 34, 55, 89, 144, 233, 370 gibi finansal analizde sıkça kullanılan Fibonacci sayılarına dayalı EMA periyotlarını kullanır. Bu periyotlar, farklı zaman dilimlerindeki trendleri gözlemlemenize olanak tanır.
process_single_file: Bu metot, her bir hisse senedi için ayrı ayrı EMA’ları hesaplar. Girdi olarak alınan Excel dosyasından Tarih ve Kapanış verilerini okur ve her bir EMA periyodu için yeni sütunlar oluşturur.
find_input_files: StokData/Kapanis/ klasöründeki tüm Excel dosyalarını otomatik olarak bulur. Bu, yüzlerce hisse senedi verisini tek tek elle işlemek yerine toplu bir şekilde işlem yapmanızı sağlar.
main: Programın ana akışını yöneten metottur. Giriş dosyalarını bulur, her bir dosya için EMA hesaplamasını başlatır ve işlemin sonunda başarılı/başarısız dosyaların özetini gösteren bir rapor sunar.
Bu Makale Daha önceki Makalelerin devamı niteliğinde olduğu için, aşağıdaki makaleleri de incelemeniz büyük önem taşıyor.
Python ve PyCharm kurulumu
Çalışmaların tamamını içeren Google Drive Alanı
X_02_BorsaPin_Emas.py olarak dosyayı kayıt edebilirsiniz.
Python Kodu
import pandas as pd
import os
import numpy as np
from datetime import datetime
from colorama import Fore, init
import glob
"""
Borsapin StokData/Kapanis klasöründeki hisse kapanış datalarından EMA'larını hesaplar
www.kursatsenturk.com
"""
init(autoreset=True)
class EMACalculator:
def __init__(self):
self.ema_periods = [5, 8, 13, 21, 34, 55, 89, 144, 233, 370]
self.successful_files = []
self.failed_files = []
@staticmethod
def calculate_ema(data, period):
"""EMA hesaplama fonksiyonu"""
try:
return data.ewm(span=period, adjust=False).mean()
except Exception as e:
print(f"{Fore.RED}❌ EMA hesaplama hatası (Period {period}): {e}")
return pd.Series([np.nan] * len(data))
def process_single_file(self, file_path):
"""Tek dosya için EMA hesaplama"""
ticker_name = os.path.splitext(os.path.basename(file_path))[0]
try:
print(f"{Fore.YELLOW} EMA hesaplanıyor: {ticker_name}...")
df = pd.read_excel(file_path)
required_columns = ['Tarih', 'Kapanış']
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
raise ValueError(f"Eksik sütunlar: {missing_columns}")
if df.empty or df['Kapanış'].isna().all():
raise ValueError("Kapanış verisi boş veya geçersiz")
df = df.sort_values('Tarih').reset_index(drop=True)
result_df = pd.DataFrame()
result_df['Hisse_Adi'] = [ticker_name] * len(df)
result_df['Tarih'] = df['Tarih']
result_df['Kapanış'] = df['Kapanış']
print(f"{Fore.CYAN} ⚡ EMA hesaplanıyor: ", end="")
for i, period in enumerate(self.ema_periods):
ema_column_name = f'EMA_{period}'
print(f"{period}", end="")
ema_values = self.calculate_ema(df['Kapanış'], period)
result_df[ema_column_name] = ema_values.round(4)
if i < len(self.ema_periods) - 1:
print(", ", end="")
print()
output_folder = "StokData/Emas/"
os.makedirs(output_folder, exist_ok=True)
output_file = os.path.join(output_folder, f"{ticker_name}.xlsx")
result_df.to_excel(output_file, index=False)
print(f"{Fore.GREEN}✅ {ticker_name} EMA verileri başarıyla kaydedildi.")
print(f"{Fore.BLUE} Konum: {output_file}")
print(f"{Fore.BLUE} Toplam satır: {len(result_df)}")
self.successful_files.append(ticker_name)
return True
except Exception as e:
print(f"{Fore.RED}❌ {ticker_name} için hata: {e}")
self.failed_files.append(os.path.basename(file_path))
return False
@staticmethod
def find_input_files(input_folder="StokData/Kapanis/"):
"""Giriş dosyalarını bulma"""
try:
pattern = os.path.join(input_folder, "*.xlsx")
files = glob.glob(pattern)
if not files:
print(f"{Fore.RED}❌ {input_folder} klasöründe Excel dosyası bulunamadı!")
return []
print(f"{Fore.BLUE} {len(files)} adet Excel dosyası bulundu.")
return files
except Exception as e:
print(f"{Fore.RED}❌ Dosya arama hatası: {e}")
return []
@staticmethod
def validate_input_file(file_path):
"""Giriş dosyasını doğrulama"""
try:
df = pd.read_excel(file_path, nrows=1)
required_columns = ['Tarih', 'Kapanış']
if not all(col in df.columns for col in required_columns):
return False, f"Eksik sütunlar: {[col for col in required_columns if col not in df.columns]}"
return True, "OK"
except Exception as e:
return False, f"Dosya okuma hatası: {e}"
def print_summary(self):
"""Özet rapor"""
total = len(self.successful_files) + len(self.failed_files)
success_rate = (len(self.successful_files) / total * 100) if total > 0 else 0
print(f"\n{Fore.CYAN} ===== EMA HESAPLAMA RAPORU =====")
print(f"{Fore.BLUE} EMA Periyodları: {', '.join(map(str, self.ema_periods))}")
print(f"{Fore.GREEN}✅ Başarılı: {len(self.successful_files)}")
print(f"{Fore.RED}❌ Başarısız: {len(self.failed_files)}")
print(f"{Fore.BLUE} Başarı oranı: {success_rate:.1f}%")
if self.successful_files:
print(f"{Fore.GREEN} Başarılı dosyalar: {', '.join(self.successful_files[:10])}")
if len(self.successful_files) > 10:
print(f"{Fore.GREEN} ... ve {len(self.successful_files) - 10} dosya daha")
if self.failed_files:
print(f"{Fore.RED} Başarısız dosyalar: {', '.join(self.failed_files)}")
def save_failed_list(self, filename="basarisiz_ema_dosyalari.txt"):
"""Başarısız dosyaları kaydetme"""
if self.failed_files:
try:
with open(filename, 'w', encoding='utf-8') as f:
f.write("# Başarısız EMA hesaplama dosyaları\n")
f.write(f"# Tarih: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
for file_name in self.failed_files:
f.write(f"{file_name}\n")
print(f"{Fore.YELLOW} Başarısız dosyalar {filename} dosyasına kaydedildi.")
except Exception as e:
print(f"{Fore.RED}❌ Başarısız dosya listesi kaydetme hatası: {e}")
def create_sample_ema_analysis(self, ticker_name="SAMPLE"):
"""Örnek EMA analiz dosyası oluşturma"""
try:
dates = pd.date_range(start='2023-01-01', end='2024-01-01', freq='D')
np.random.seed(42)
base_price = 100
price_changes = np.random.normal(0, 2, len(dates))
prices = [base_price]
for change in price_changes[1:]:
new_price = prices[-1] * (1 + change / 100)
prices.append(max(new_price, 1))
df = pd.DataFrame({
'Tarih': dates,
'Kapanış': prices
})
result_df = pd.DataFrame()
result_df['Hisse_Adi'] = [ticker_name] * len(df)
result_df['Tarih'] = df['Tarih']
result_df['Kapanış'] = df['Kapanış']
for period in self.ema_periods:
ema_values = self.calculate_ema(df['Kapanış'], period)
result_df[f'EMA_{period}'] = ema_values.round(4)
output_folder = "StokData/Emas/"
os.makedirs(output_folder, exist_ok=True)
output_file = os.path.join(output_folder, f"{ticker_name}.xlsx")
result_df.to_excel(output_file, index=False)
print(f"{Fore.GREEN}✅ Örnek EMA dosyası oluşturuldu: {output_file}")
return True
except Exception as e:
print(f"{Fore.RED}❌ Örnek dosya oluşturma hatası: {e}")
return False
def main(self):
"""Ana fonksiyon"""
print(f"{Fore.CYAN} EMA Hesaplama Sistemi Başlatılıyor...")
print(f"{Fore.BLUE} EMA Periyodları: {', '.join(map(str, self.ema_periods))}")
input_files = self.find_input_files()
if not input_files:
print(f"{Fore.YELLOW}⚠️ Giriş dosyası bulunamadı. Örnek dosya oluşturuluyor...")
self.create_sample_ema_analysis()
return
print(f"{Fore.BLUE} Toplam işlenecek dosya: {len(input_files)}\n")
for i, file_path in enumerate(input_files, 1):
print(f"\n{Fore.MAGENTA}[{i}/{len(input_files)}] İşleniyor...")
is_valid, error_msg = self.validate_input_file(file_path)
if not is_valid:
print(f"{Fore.RED}❌ Geçersiz dosya: {os.path.basename(file_path)} - {error_msg}")
self.failed_files.append(os.path.basename(file_path))
continue
self.process_single_file(file_path)
self.save_failed_list()
self.print_summary()
print(f"\n{Fore.GREEN} EMA hesaplama işlemi tamamlandı!")
print(f"{Fore.BLUE} Çıktı klasörü: StokData/Emas/")
# Kullanım
if __name__ == "__main__":
calculator = EMACalculator()
calculator.main()
Bir sonraki makalede İdeal EMA dizilim (sıralama) yani Ema Alignment betiğini paylaşacağım.
Burada bütün hisseleri tarayıp belirli kurallara uyan hisseleri çalışma sayfalarında listeleteceğiz.
idealemaup, idealemadown, idealemanötr, potansiyel taşıyan ve 1 yıllık istatistikleri gösteren çalışma sayfaları olacak.

Ben bu hayatta hiç var olmadım ki zaten…
Ne birinin teninde ısındım,
Ne de bir kelimesinde yer bulabildim kendime.
Ne bir yürek beni anladı,
Ne bir ses adımı gerçekten söyledi.
Sanki bir rüyanın unutulan köşesiydim;
uyanıldığında hatırlanmayan,
bir hayalin eşiğinden bile geçemeyen silik bir iz.
Zaman aktı üzerimden,
ama ben hiçbir saate ait olmadım.
Bir gölgeydim belki;
ışık varsa varım, yoksa hiçim.
Hiçbir el tutmadı beni,
hiçbir bakışta kendimi bulamadım.
Bir gün gidecek olsam,
ardımdan ‘kimdi o?’ bile demez kimse.
Çünkü ben burada değildim aslında —
yalnızca yokluğumun yankısıydım sizin kalabalığınızda
Yazmazsam Unuturum…
Birlikte geçirdiğimiz kısa ama güzel anlar, dostluğunun ne kadar kıymetli olduğunu hep hatırlatacak bana. Sessizliğin artık çok daha derin, eksikliğin ise tarif edilemez…
Huzur içinde uyu, dostum. Seni hiç unutmayacağız.
Kitabında yer verdiğin cümlem içinde sonsuz teşekkürler..
“Aşk siyahı beyaz görebilme körlüğüydü, biz siyahı hep beyaz gördük.”
O satırlarda ismimi anman, beni her zaman onurlandırdı..
Şiirlerin artık sensiz, sessiz ve sahipsiz…
Ama bil ki, her dizede seni yaşatmaya devam edeceğiz.
Hoşçakal Kel Adam..
Finansal analiz ve algoritmik işlem geliştirmek isteyen herkesin ilk adımı, güvenilir hisse senedi kapanış verilerini elde etmektir. Bu veriler, teknik analizden sinyal üretimine kadar pek çok işlemin temelini oluşturur. Elinizdeki veriler ne kadar doğru ve güncelse, analizleriniz de o kadar isabetli olur.
Python ve yfinance kütüphanesi kullanılarak oluşturulmuş, Borsa İstanbul (BIST) hisselerine ait kapanış verilerini otomatik olarak indiren gelişmiş bir scripti detaylıca ele alacağız. Script, .xlsx formatında çıktılar üreterek analizlerinize doğrudan entegre edilebilir veriler sunar.
hisselistesi_txt.txt adlı dosyadan hisse senedi sembollerini okumak
Yahoo Finance üzerinden kapanış verilerini çekmek (yfinance)
Verileri işleyip Excel’e kaydetmek (pandas ve openpyxl)
Başarısız işlemleri tespit edip yeniden denemek
Kullanıcıya görsel ve metinsel özet rapor sunmak
Otomatik Hisse Formatlama
Yahoo Finance üzerinde işlem gören BIST hisseleri .IS uzantısına sahiptir.
Örneğin THYAO → THYAO.IS formatına otomatik olarak dönüştürülür.
Yeniden Deneme Mekanizması
Veri çekimi sırasında yaşanan geçici sorunlar için belirli aralıklarla otomatik yeniden deneme yapılır (max_retries, retry_delay).
Excel Kaydı ve Türkçe Sütunlar
Çekilen veriler şu sütunlar ile .xlsx dosyasına kaydedilir:
Tarih Açılış Yüksek Düşük Kapanış Hacim
Eksik Veri ve NaN Temizliği
İndirilen verilerdeki eksik veya bozuk kayıtlar otomatik olarak temizlenir. Bu sayede daha sağlıklı analizler yapılabilir.
Kullanıcı Dostu Konsol Çıktıları
colorama kütüphanesi sayesinde kullanıcıya renkli ve bilgilendirici çıktılar sunulur (örn. yeşil = başarı, kırmızı = hata).
Klasör Yapısı ve Çıktı
Kaydedilen dosyalar StokData/Kapanis/ klasörü altında saklanır. Her hisse senedi için ayrı bir Excel dosyası oluşturulur:
StokData/Kapanis/THYAO.xlsx gibi.
Kullanım Adımları
hisselistesi_txt.txt dosyasına BIST hisse sembollerini yazın (her satıra bir hisse, örn. AKBNK).
Temeli sağlam şirketleri listeleyebilirsiniz. Ya da belirli sektör yada endeks şirketlerin sembollerini de yazabilirsiniz. (XU100, XU030)
Scripti çalıştırdığınızda
Kapanış verileri indirilecek, işlenecek ve .xlsx olarak kaydedilecektir. Başarısız olan hisseler için sistem size yeniden deneme opsiyonu sunacaktır. Süreç sonunda konsolda özet rapor gösterilecektir.
Örnek Konsol Çıktısı
Veri çekiliyor: AKBNK (Deneme 1/3)…
✅ AKBNK verisi başarıyla kaydedildi.
Veri çekiliyor: THYAO (Deneme 1/3)…
❌ THYAO için hata (Deneme 1): Connection timed out.
⏳ 2 saniye bekleniyor…
…
===== ÖZET RAPOR =====
✅ Başarılı: 18
❌ Başarısız: 2
Başarı oranı: 90.0%
Başarısız hisseler: THYAO, TAVHL
Sonraki Adım
X_01_BorsaPin_StokData.py olarak kayıt edebilirsiniz.
Pyhon Kodumuz
import yfinance as yf
import os
import pandas as pd
from datetime import datetime, timedelta
from colorama import Fore, init
import time
from typing import List, Optional
"""
Borsapin StokData Yahoo Finans Üzerinden Kapanış Datalarını çekmeye yarar
www.kursatsenturk.com
"""
init(autoreset=True)
class StockDownloader:
def __init__(self, max_retries: int = 3, retry_delay: int = 2):
"""
Hisse senedi veri indirici sınıfı
Args:
max_retries: Maksimum yeniden deneme sayısı
retry_delay: Denemeler arası bekleme süresi (saniye)
"""
self.max_retries = max_retries
self.retry_delay = retry_delay
self.failed_tickers: List[str] = []
self.successful_tickers: List[str] = []
@staticmethod
def read_tickers(file_path: str) -> List[str]:
"""Hisse kodlarını dosyadan okuma fonksiyonu"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
tickers = [line.strip() for line in f.readlines() if line.strip()]
return tickers
except FileNotFoundError:
print(f"{Fore.RED}❌ {file_path} dosyası bulunamadı!")
return []
except Exception as e:
print(f"{Fore.RED}❌ Dosya okuma hatası: {e}")
return []
@staticmethod
def format_ticker(ticker: str) -> str:
"""Hisse sembolüne .IS eklemek"""
if not ticker.endswith('.IS'):
ticker = ticker + '.IS'
return ticker
@staticmethod
def save_to_excel(data: pd.DataFrame, file_path: str) -> bool:
"""Veriyi Excel'e kaydetme fonksiyonu"""
try:
data.to_excel(file_path, index=False)
return True
except Exception as e:
print(f"{Fore.RED}❌ Excel kaydetme hatası: {e}")
return False
def download_single_ticker(self, ticker: str, start_date: str, end_date: str, attempt: int = 1) -> bool:
"""Tek hisse için veri çekme fonksiyonu"""
formatted_ticker = self.format_ticker(ticker)
ticker_name = formatted_ticker.replace(".IS", "")
print(f"{Fore.YELLOW} Veri çekiliyor: {ticker_name} (Deneme {attempt}/{self.max_retries})...")
try:
# Veri çekme
stock_data = yf.download(
formatted_ticker,
start=start_date,
end=end_date,
progress=False,
timeout=30,
auto_adjust=True, # Uyarıyı önlemek için explicit olarak True
prepost=True,
threads=True
)
if stock_data is None or stock_data.empty:
raise ValueError("Veri boş veya None")
# MultiIndex sütunlarını düzelt
if isinstance(stock_data.columns, pd.MultiIndex):
# MultiIndex'i tek seviyeye indir
stock_data.columns = stock_data.columns.droplevel(1)
# Sütun isimlerini temizle
stock_data.columns = [str(col).strip() for col in stock_data.columns]
# Veri işleme - sadece gerekli sütunları al
required_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
available_columns = [col for col in required_columns if col in stock_data.columns]
if not available_columns:
raise ValueError("Gerekli sütunlar bulunamadı")
stock_data = stock_data[available_columns]
# Sayıları düzgün formatta işleme
for column in stock_data.columns:
if stock_data[column].dtype == 'object':
try:
stock_data[column] = pd.to_numeric(
stock_data[column].astype(str).str.replace(',', '.'),
errors='coerce'
)
except Exception:
continue
# NaN değerleri temizle
stock_data = stock_data.dropna()
# Boş veri kontrolü
if stock_data.empty:
raise ValueError("İşlenen veri boş")
# Dosya kaydetme
folder_path = "StokData/Kapanis/"
os.makedirs(folder_path, exist_ok=True)
file_path = os.path.join(folder_path, f"{ticker_name}.xlsx")
# Tarih formatı düzenleme
stock_data_copy = stock_data.copy()
# Index'i reset et ve tarih sütununu ekle
stock_data_copy.reset_index(inplace=True)
# Tarih sütunu varsa formatla
if 'Date' in stock_data_copy.columns:
stock_data_copy['Date'] = pd.to_datetime(stock_data_copy['Date']).dt.date
stock_data_copy.rename(columns={"Date": "Tarih"}, inplace=True)
# Sütun isimlerini Türkçeye çevirme
column_mapping = {
'Open': 'Açılış',
'High': 'Yüksek',
'Low': 'Düşük',
'Close': 'Kapanış',
'Volume': 'Hacim'
}
# Mevcut sütunları yeniden adlandır
for eng_name, tr_name in column_mapping.items():
if eng_name in stock_data_copy.columns:
stock_data_copy.rename(columns={eng_name: tr_name}, inplace=True)
# Kaydetme
if self.save_to_excel(stock_data_copy, file_path):
print(f"{Fore.GREEN}✅ {ticker_name} verisi başarıyla kaydedildi.")
return True
else:
raise Exception("Excel kaydetme başarısız")
except Exception as e:
print(f"{Fore.RED}❌ {ticker_name} için hata (Deneme {attempt}): {str(e)}")
return False
def download_with_retry(self, ticker: str, start_date: str, end_date: str) -> bool:
"""Yeniden deneme mekanizması ile veri çekme"""
for attempt in range(1, self.max_retries + 1):
if self.download_single_ticker(ticker, start_date, end_date, attempt):
self.successful_tickers.append(ticker)
return True
if attempt < self.max_retries:
print(f"{Fore.YELLOW}⏳ {self.retry_delay} saniye bekleniyor...")
time.sleep(self.retry_delay)
# Tüm denemeler başarısız
self.failed_tickers.append(ticker)
print(f"{Fore.RED} {ticker} için tüm denemeler başarısız!")
return False
def retry_failed_tickers(self, start_date: str, end_date: str) -> None:
"""Başarısız hisseleri tekrar deneme"""
if not self.failed_tickers:
print(f"{Fore.GREEN} Yeniden denenecek hisse yok!")
return
print(f"\n{Fore.CYAN} Başarısız {len(self.failed_tickers)} hisse tekrar deneniyor...")
print(f"{Fore.CYAN}Başarısız hisseler: {', '.join(self.failed_tickers)}")
retry_failed = []
retry_successful = []
# Başarısız hisselerin kopyasını al
failed_copy = self.failed_tickers.copy()
for ticker in failed_copy:
print(f"\n{Fore.MAGENTA} Tekrar deneniyor: {ticker}")
if self.download_with_retry(ticker, start_date, end_date):
retry_successful.append(ticker)
self.failed_tickers.remove(ticker)
else:
retry_failed.append(ticker)
# Sonuçları yazdır
if retry_successful:
print(f"\n{Fore.GREEN}✅ Tekrar denemede başarılı: {', '.join(retry_successful)}")
if retry_failed:
print(f"\n{Fore.RED}❌ Hala başarısız: {', '.join(retry_failed)}")
def save_failed_list(self, filename: str = "basarisiz_hisseler.txt") -> None:
"""Başarısız hisseleri dosyaya kaydet"""
if self.failed_tickers:
try:
with open(filename, 'w', encoding='utf-8') as f:
f.write('\n'.join(self.failed_tickers))
print(f"{Fore.YELLOW} Başarısız hisseler {filename} dosyasına kaydedildi.")
except Exception as e:
print(f"{Fore.RED}❌ Başarısız hisse listesi kaydetme hatası: {e}")
def print_summary(self) -> None:
"""Özet rapor yazdır"""
total = len(self.successful_tickers) + len(self.failed_tickers)
success_rate = (len(self.successful_tickers) / total * 100) if total > 0 else 0
print(f"\n{Fore.CYAN} ===== ÖZET RAPOR =====")
print(f"{Fore.GREEN}✅ Başarılı: {len(self.successful_tickers)}")
print(f"{Fore.RED}❌ Başarısız: {len(self.failed_tickers)}")
print(f"{Fore.BLUE} Başarı oranı: {success_rate:.1f}%")
if self.failed_tickers:
print(f"{Fore.RED} Başarısız hisseler: {', '.join(self.failed_tickers)}")
def main(self) -> None:
"""Ana fonksiyon"""
print(f"{Fore.CYAN} Veri çekme başlıyor...")
# Parametreler
tickers = self.read_tickers("hisselistesi_txt.txt")
if not tickers:
print(f"{Fore.RED}❌ Hisse listesi okunamadı, işlem sonlandırılıyor.")
return
start_date = '2020-01-01'
end_date = (datetime.today() + timedelta(days=1)).strftime('%Y-%m-%d')
print(f"{Fore.BLUE} Tarih aralığı: {start_date} - {end_date}")
print(f"{Fore.BLUE} Toplam hisse sayısı: {len(tickers)}")
print(f"{Fore.BLUE} Maksimum deneme sayısı: {self.max_retries}")
print(f"{Fore.BLUE}⏱️ Deneme arası bekleme: {self.retry_delay} saniye\n")
# İlk deneme
for i, ticker in enumerate(tickers, 1):
print(f"\n{Fore.BLUE}[{i}/{len(tickers)}] İşleniyor...")
self.download_with_retry(ticker, start_date, end_date)
# Başarısız hisseleri tekrar deneme
if self.failed_tickers:
user_input = input(
f"\n{Fore.YELLOW}❓ Başarısız {len(self.failed_tickers)} hisseyi tekrar denemek istiyor musunuz? (e/h): "
).lower().strip()
if user_input in ['e', 'evet', 'y', 'yes']:
self.retry_failed_tickers(start_date, end_date)
# Sonuçları kaydet ve yazdır
self.save_failed_list()
self.print_summary()
print(f"\n{Fore.GREEN} İşlem tamamlandı!")
# Kullanım
if __name__ == "__main__":
# Özelleştirilebilir parametreler
downloader = StockDownloader(
max_retries=3, # Maksimum deneme sayısı
retry_delay=2 # Denemeler arası bekleme süresi (saniye)
)
downloader.main()
Bu script, ileri seviye analizlerin temelini oluşturur. Bir sonraki yazımızda, bu verileri kullanarak:
5 8 13 21 34 55 89 144 233 370 EMA seviyelerini hesaplayan EMAs script yayınlayacağım.
Ve yatırım kararları için Python tabanlı teknik analiz sistemleri geliştirmeye devam edeceğiz.
Finansal analiz projelerinde Python, sunduğu zengin kütüphane ekosistemi ile güçlü bir araçtır. Borsa İstanbul (BIST) hisselerine ait kapanış verilerini çekmek ve bu veriler üzerinden teknik sinyaller üretmek için öncelikle bazı temel Python kütüphanelerine ihtiyaç duyarız.
Bu yazıda, gerekli kütüphanelerin sisteminizde yüklü olup olmadığını kontrol eden ve eksik olanları otomatik olarak kuran bir Python scriptini ele alacağız. Bu adım, ileri aşamalarda Borsa İstanbul Kapanış ve Hacim verilerini çekme ve analiz etme işlemleri için altyapı hazırlığı niteliğindedir.
Aşağıdaki kütüphaneler, veri çekme ve analiz süreçlerinde kullanılacaktır:
pandas: Veri manipülasyonu ve analiz için temel kütüphane.
numpy: Sayısal hesaplamalar için kullanılır.
colorama: Konsolda renkli yazı yazmak için kullanılır (bilgilendirici çıktılar için).
yfinance: Yahoo Finance üzerinden hisse senedi verilerini çekmeye yarar.
openpyxl: Excel dosyaları oluşturmak ve düzenlemek için kullanılır.
Kod özetle şunları yapar:
1. Belirlenen `required_packages` listesinde yer alan kütüphanelerin sistemde kurulu olup olmadığını kontrol eder.
2. Eğer bir kütüphane yüklü değilse, `pip install` komutu ile yükler.
3. Her bir paket için yükleme durumu kullanıcıya yazdırılır.
GerekliKütüphaneler.py diye kayıt edebilirsiniz.
Python Kodu
import subprocess
import sys
# Gerekli kütüphaneler listesi
required_packages = [
"pandas",
"numpy",
"colorama",
"yfinance",
"openpyxl"
]
def install_missing_packages():
for package in required_packages:
try:
__import__(package)
print(f"{package} zaten yüklü.")
except ImportError:
print(f"{package} eksik, yükleniyor...")
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
if __name__ == "__main__":
install_missing_packages()
Sonraki Adımlar
Eğer farklı bir kütüphaneye ihtiyaç duyduğumuzda bu betiğe ekleme yapacağız.
Şimdi bu temel kurulumu yaptıktan sonra, aşağıdaki adımlarla devam edeceğiz:
Borsa İstanbul Hisse Verilerinin Çekilmesi
yfinance kütüphanesini kullanarak BIST hisselerine ait günlük kapanış verilerini çekeceğiz. (2 Ocak 2020 tarihinden itibaren)
Verilerin Excel’e Aktarılması
pandas ve openpyxl kütüphaneleri sayesinde çekilen veriler .xlsx formatında saklanacak.
Teknik Göstergeler ve Sinyallerin Hesaplanması
EMA, EMA ALIGNMENT (İdeal Ema, Ema Sıralama), WaveTrend, Günlük Haftalık Aylık Yıllık Pivot, Lineer Regresyon kanalları gibi göstergeleri hesaplayıp, yatırım kararlarında kullanılabilecek potansiyel al/sat sinyallerinide analiz edeceğiz.
Sonuç olarak bu script, Python tabanlı finansal veri analizlerine başlamadan önce gerekli kütüphaneleri yükleyerek ortam hazırlığını otomatikleştirir. Böylece kullanıcılar doğrudan veri çekme ve analiz etme adımlarına geçebilirler.
Python, günümüzün en popüler programlama dillerinden biridir. Veri bilimi, yapay zeka, web geliştirme, otomasyon ve daha birçok alanda yaygın olarak kullanılır. Bu makalede, Python’u bilgisayarınıza nasıl kuracağınızı ve PyCharm adlı güçlü bir geliştirme ortamını (IDE) nasıl kullanmaya başlayacağınızı adım adım öğreneceksiniz.
Python Kurulumu
Adım 1: Python Web Sitesine Gidin
Tarayıcınızda https://www.python.org adresine gidin.
Adım 2: Python Sürümünü İndirin
Ana sayfadaki “Download Python X.X.X” (örneğin 3.13.5) butonuna tıklayın. İşletim sisteminiz otomatik olarak algılanır (Windows, macOS veya Linux).
Adım 3: Kurulum Dosyasını Çalıştırın
İndirilen .exe dosyasını çalıştırın.
Kurulum ekranında mutlaka “Add Python to PATH” seçeneğini işaretleyin.
Ardından “Install Now” seçeneğine tıklayın.
Adım 4: Kurulumu Doğrulayın
Başlat Menüsü > Komut İstemi’ni (cmd) açın ve şu komutu yazın:
PyCharm Kurulumu
PyCharm, Python için özel olarak geliştirilmiş bir IDE’dir. Kod yazmayı, çalıştırmayı, hata ayıklamayı ve projeleri yönetmeyi kolaylaştırır.
Adım 1: PyCharm Web Sitesine Gidin
https://www.jetbrains.com/pycharm adresini ziyaret edin.
Adım 2: Sürüm Seçimi
İki farklı sürüm vardır:
Community (Ücretsiz) – Başlangıç için yeterlidir.
Professional (Ücretli) – Web geliştirme, veri bilimi gibi ek özellikler içerir.
Community Edition’ı indirin.
Adım 3: Kurulumu Başlatın
İndirilen kurulum dosyasını açın ve yönergeleri takip ederek PyCharm’ı kurun.
Kurulum sırasında aşağıdaki seçenekleri işaretleyebilirsiniz:
64-bit launcher ekle
.py dosyalarını PyCharm ile ilişkilendirin
Adım 4: İlk Çalıştırma
Kurulum tamamlandıktan sonra PyCharm’ı başlatın ve tema (açık/koyu) gibi başlangıç ayarlarını yapın.
İlk Python Projeni Oluşturma
PyCharm’ı açın ve “New Project” seçeneğini seçin.
Projeye bir ad verin (örneğin: ilk_proje).
Python interpreter (yürütücü) olarak daha önce kurduğunuz Python sürümünü seçin. (Mesela venv)
main.py adlı bir dosya oluşturun ve şu kodu yazın:
print(“Merhaba, Python dünyası!”)
Sağ üstteki yeşil “Run” (Çalıştır) butonuna tıklayarak kodunuzu çalıştırın.
Ek Tavsiyeler
PyCharm kısayollarına zamanla alışmak size büyük hız kazandırır.
Terminal kullanarak pip komutu ile paketler kurabilirsiniz.
Örneğin: pip install numpy
Virtual environment (sanallaştırılmış çalışma ortamı) kullanmak projelerinizi izole tutar ve karışıklığı önler.
İzleyen makalelerde, Python kullanarak Yahoo Finance üzerinden BIST Spot hisse senetlerinin kapanış verilerini nasıl çekeceğimizi adım adım öğreneceğiz. Elde ettiğimiz bu verileri Excel formatında kaydederek, şu analizleri gerçekleştireceğiz:
Farklı periyotlara göre EMA (Üssel Hareketli Ortalama) hesaplamaları
Osilatör ve momentum göstergeleri
EMA Alignment analizi (ideal dizilim ve sapma durumları)
WaveTrend tabanlı sinyal üretimi
Belirli periyotlarda Doğrusal Regresyon (Linear Regression Channel) hesaplamaları
Her hisse için bu analizlerin Pearson korelasyon katsayısı ile değerlendirilmesi
Tüm bu analiz sonuçlarını Python ile tasarlanmış Excel şablonlarına aktararak, hisse senetlerinin teknik durumlarını görsel olarak kolayca takip edebileceğiniz tarama dosyaları oluşturabileceksiniz.
Pivot noktaları, teknik analizde sıklıkla kullanılan ve bir varlığın olası destek ve direnç seviyelerini belirlemek için kullanılan matematiksel seviyelerdir. Bu seviyeler, yatırımcılara alım-satım kararlarında yardımcı olan önemli araçlardan biridir.
TradingView platformu üzerinde Pine Script ile geliştirilen ve grafik üzerinde çizim yapmadan sadece tablo formatında çalışan gelişmiş bir pivot analiz aracını tanıtacağız. Ayrıca kullanıcıların tercihlerine göre Klasik, Fibonacci veya Woodie pivot yöntemlerinden birini seçerek analiz yapabilmesi mümkün olacak. Youtubeda ki bir çok yayıncının yaptığı gibi bilgiyi para karşılığı satan bir zihniyette olmadığım için ücretsiz bir şekilde yararlanabilirsiniz.
Zaman Dilimi Seçimi: Günlük, Haftalık, Aylık ve Yıllık pivot seviyeleri hesaplanır.
Yöntem Seçimi: Kullanıcı, Klasik, Fibonacci veya Woodie hesaplama yöntemlerinden birini tercih edebilir.
Tablo Üzerinden Görselleştirme: Pivot, 3 destek ve 3 direnç seviyesi; ilgili zaman dilimi ve yönteme göre tablo halinde görüntülenir.
Kapanış Bekleme Opsiyonu: Haftalık, aylık ve yıllık mum kapanışları henüz gerçekleşmediyse, bir önceki dönemin verileri kullanılır. Ancak kullanıcı, ayarlardan Güncel veriyi kullanmak isterse bu seçeneği pasifleştirerek o anki mum verileriyle hesaplama yapabilir.
P = (High + Low + Close) / 3
R1 = (2 * P) – Low
S1 = (2 * P) – High
R2 = P + (High – Low)
S2 = P – (High – Low)
R3 = High + 2*(P – Low)
S3 = Low – 2*(High – P)
P = (High + Low + Close) / 3
R1 = P + 0.382 * (High – Low)
R2 = P + 0.618 * (High – Low)
R3 = P + 1.000 * (High – Low)
S1 = P – 0.382 * (High – Low)
S2 = P – 0.618 * (High – Low)
S3 = P – 1.000 * (High – Low)
P = (High + Low + 2 * Close) / 4
R1 = (2 * P) – Low
S1 = (2 * P) – High
R2 = P + (High – Low)
S2 = P – (High – Low)
R3 = High + 2*(P – Low)
S3 = Low – 2*(High – P)
TradingView’de yeni bir Pine Script oluşturun.
Kodunuzu yapıştırarak çalıştırın.
İndikatör, grafikte herhangi bir çizim yapmaz. Ancak ekranın sağ üst köşesinde pivot değerlerini detaylı bir şekilde gösteren bir tablo oluşturur.
Ayarlar kısmından:
Pivot türünü (Classic, Fibonacci, Woodie)
Zaman dilimini (Günlük, Haftalık , Aylık, Yıllık)
Text uzantılı dosya olarak indirmek isterseniz buraya tıklayın.
Trading View Günlük haftalık Aylık Yıllık PivotTablo Pine Script Kodu
// Bu, Pine Script™ kodu Mozilla Kamu Lisansı 2.0 (MPL-2.0) altında lisanslandı
// © krstsntrk © BorsaPin code is priority
//@version=5
indicator(title = 'BorsaPin Pivot Sistem', shorttitle = 'BorsaPin Pivot Sistem', overlay = true)
// === Kullanıcı Ayarları ===
pivotType = input.string("Woodie", title="Pivot Tipi", options=["Classic", "Fibonacci", "Woodie"])
useCurrentBar = input.bool(true, title="Kapanış Bekleme Opsiyonu (Açık mum yerine önceki kapanışı kullanır.)")
showDaily = input.bool(true, title="Günlük Pivot Göster")
showWeekly = input.bool(true, title="Haftalık Pivot Göster")
showMonthly = input.bool(true, title="Aylık Pivot Göster")
showYearly = input.bool(true, title="Yıllık Pivot Göster")
// === Zaman Aralığına Göre High/Low/Close ===
getHigh(_tf) => useCurrentBar ? request.security(syminfo.tickerid, _tf, high) : request.security(syminfo.tickerid, _tf, high[1])
getLow(_tf) => useCurrentBar ? request.security(syminfo.tickerid, _tf, low) : request.security(syminfo.tickerid, _tf, low[1])
getClose(_tf) => useCurrentBar ? request.security(syminfo.tickerid, _tf, close) : request.security(syminfo.tickerid, _tf, close[1])
// === Pivot Hesaplayıcı Fonksiyon ===
calcPivots(high_, low_, close_, _type) =>
pivot = 0.0
r1 = 0.0
r2 = 0.0
r3 = 0.0
s1 = 0.0
s2 = 0.0
s3 = 0.0
if _type == "Classic"
pivot := (high_ + low_ + close_) / 3
r1 := 2 * pivot - low_
s1 := 2 * pivot - high_
r2 := pivot + (high_ - low_)
s2 := pivot - (high_ - low_)
r3 := high_ + 2 * (pivot - low_)
s3 := low_ - 2 * (high_ - pivot)
else if _type == "Fibonacci"
pivot := (high_ + low_ + close_) / 3
r1 := pivot + 0.382 * (high_ - low_)
r2 := pivot + 0.618 * (high_ - low_)
r3 := pivot + 1.000 * (high_ - low_)
s1 := pivot - 0.382 * (high_ - low_)
s2 := pivot - 0.618 * (high_ - low_)
s3 := pivot - 1.000 * (high_ - low_)
else if _type == "Woodie"
pivot := (high_ + low_ + 2 * close_) / 4
r1 := (2 * pivot) - low_
s1 := (2 * pivot) - high_
r2 := pivot + (high_ - low_)
s2 := pivot - (high_ - low_)
r3 := high_ + 2 * (pivot - low_)
s3 := low_ - 2 * (high_ - pivot)
[pivot, r1, r2, r3, s1, s2, s3]
// === Her Zaman Dilimi İçin High / Low / Close Al ===
dH = getHigh("D")
dL = getLow("D")
dC = getClose("D")
wH = getHigh("W")
wL = getLow("W")
wC = getClose("W")
mH = getHigh("M")
mL = getLow("M")
mC = getClose("M")
yH = getHigh("12M")
yL = getLow("12M")
yC = getClose("12M")
// === Pivotları Hesapla ===
[dP, dR1, dR2, dR3, dS1, dS2, dS3] = calcPivots(dH, dL, dC, pivotType)
[wP, wR1, wR2, wR3, wS1, wS2, wS3] = calcPivots(wH, wL, wC, pivotType)
[mP, mR1, mR2, mR3, mS1, mS2, mS3] = calcPivots(mH, mL, mC, pivotType)
[yP, yR1, yR2, yR3, yS1, yS2, yS3] = calcPivots(yH, yL, yC, pivotType)
// === Tablo Oluştur ===
var table pivotTable = table.new(position.top_right, 8, 20, border_width=1)
// === Başlıklar ===
if bar_index % 10 == 0
table.cell(pivotTable, 0, 0, "Zaman", text_color=color.black, bgcolor=color.gray)
table.cell(pivotTable, 1, 0, "P", text_color=color.navy)
table.cell(pivotTable, 2, 0, "R1", text_color=color.lime)
table.cell(pivotTable, 3, 0, "R2", text_color=color.lime)
table.cell(pivotTable, 4, 0, "R3", text_color=color.lime)
table.cell(pivotTable, 5, 0, "S1", text_color=color.red)
table.cell(pivotTable, 6, 0, "S2", text_color=color.red)
table.cell(pivotTable, 7, 0, "S3", text_color=color.red)
// === Veri Satırı Ekleme Fonksiyonu ===
addRow(idx, label, p, r1, r2, r3, s1, s2, s3) =>
table.cell(pivotTable, 0, idx, label, text_color=color.black)
table.cell(pivotTable, 1, idx, str.tostring(p, format.mintick))
table.cell(pivotTable, 2, idx, str.tostring(r1, format.mintick))
table.cell(pivotTable, 3, idx, str.tostring(r2, format.mintick))
table.cell(pivotTable, 4, idx, str.tostring(r3, format.mintick))
table.cell(pivotTable, 5, idx, str.tostring(s1, format.mintick))
table.cell(pivotTable, 6, idx, str.tostring(s2, format.mintick))
table.cell(pivotTable, 7, idx, str.tostring(s3, format.mintick))
// === Tabloda Göster ===
row = 1
if showDaily
addRow(row, "Günlük", dP, dR1, dR2, dR3, dS1, dS2, dS3)
row += 1
if showWeekly
addRow(row, "Haftalık", wP, wR1, wR2, wR3, wS1, wS2, wS3)
row += 1
if showMonthly
addRow(row, "Aylık", mP, mR1, mR2, mR3, mS1, mS2, mS3)
row += 1
if showYearly
addRow(row, "Yıllık", yP, yR1, yR2, yR3, yS1, yS2, yS3)
Bank of America (BoFA) gibi büyük finansal kurumların robotları (otomatik alım-satım sistemleri, “trading bots”) çok katmanlı, yüksek teknolojiye dayalı ve sürekli güncellenen yapılarla çalışır. Aşağıda bu robotların nasıl çalıştığını ana başlıklarla özetleyeceğim.
Teknik analizde en çok kullanılan araçlardan biri olan Fibonacci seviyeleri, doğadaki oransal düzeni finansal piyasalara taşıyan güçlü bir analiz yöntemidir. Fiyatların belirli oranlarda düzeltme veya genişleme yapma eğilimi olduğu düşüncesiyle, Fibonacci seviyeleri yatırımcılara hem trend takibi hem de geri çekilme (pullback) noktalarında stratejik kararlar alma imkânı sunar. Bu yazıda, Fibonacci dizisinin mantığı, düzeltme ve genişleme seviyeleri, hesaplama yöntemleri ve pratik kullanım alanlarını detaylı bir şekilde ele alacağız.
Fibonacci dizisi, her sayının kendisinden önce gelen iki sayının toplamı olduğu bir sayı serisidir:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
Bu diziden türeyen bazı altın oranlar (golden ratio) teknik analizde kullanılır:
0.236
0.382
0.500 (teknik analizde psikolojik oran olarak kabul edilir)
0.618 (Altın Oran)
0.786
1.000
1.272
1.618
2.618, vb.
Trendin tersine yapılan düzeltmeleri ölçmek için kullanılır. Yatırımcılar, fiyatın bu oranlara kadar geri çekilip ardından trend yönünde devam etmesini bekler.
Bir yükseliş trendinde:
Örneğin fiyat 100’den 200’e çıktıysa, düzeltme seviyeleri:
Fiyatın mevcut trend yönünde devam edeceği potansiyel hedef seviyeleri tahmin etmek için kullanılır. Genellikle 1.272, 1.618, 2.618 gibi oranlar kullanılır.
Fibonacci seviyeleri, potansiyel destek (aşağı yönlü) ve direnç (yukarı yönlü) alanlarını gösterir. Fiyat bu seviyelere yaklaştıkça tepki verme olasılığı artar.
Trend devam ederken fiyat düzeltme yapar. Bu düzeltmenin sona erip trendin devam edeceği seviyeler Fibonacci oranları ile tahmin edilir.
Bir pozisyona girdikten sonra kar al (take-profit) seviyeleri, genişleme oranları kullanılarak belirlenebilir.
Stop-loss noktaları, genellikle fibonacci seviyeleri altına yerleştirilerek daha mantıklı ve ölçülebilir riskler alınır.
Fibonacci seviyeleri çoğu zaman EMA, RSI, MACD, trend çizgileri, formasyonlar veya harmonik desenlerle birlikte kullanılır. Bu kombinasyonlar, daha güçlü alım-satım sinyalleri üretir.
Örnek:
Fibonacci seviyeleri, teknik analizde fiyatların olası geri çekilme ve ilerleme noktalarını belirlemede oldukça etkili ve yaygın kullanılan araçlardandır. Doğru bir şekilde kullanıldığında, alım-satım stratejilerine disiplin, hedef ve netlik kazandırır. Ancak her göstergede olduğu gibi, Fibonacci seviyeleri de tek başına yeterli değildir; mutlaka diğer analiz teknikleriyle birlikte kullanılmalı ve piyasa koşulları göz önünde bulundurularak esnek bir bakış açısıyla değerlendirilmelidir.
Teknik analizde pivot noktaları, yatırımcıların potansiyel destek ve direnç seviyelerini belirlemek için kullandığı güçlü araçlardır. Bu seviyeler, fiyatın yönü hakkında ipuçları sunar ve stratejik alım-satım kararlarında kritik rol oynar. Günlük, haftalık, aylık ve yıllık pivot seviyeleri, farklı zaman dilimlerinde yatırım yapan trader’lara piyasanın genel yönü hakkında fikir verir. Bu yazıda, bu seviyelerin nasıl hesaplandığı, hangi amaçlarla kullanıldığı ve teknik analiz stratejilerindeki yerini ele alacağız.
Pivot noktaları, önceki zaman diliminin yüksek (High), düşük (Low) ve kapanış (Close) fiyatlarının ortalaması alınarak hesaplanır. Bu noktalar temel alınarak destek (S1, S2, S3) ve direnç (R1, R2, R3) seviyeleri belirlenir.
Temel Pivot Formülü:
Ardından destek ve direnç seviyeleri şu şekilde hesaplanır:
Günlük pivot seviyeleri, bir önceki işlem gününün fiyat verileriyle hesaplanır. Kısa vadeli işlem yapanlar için önemlidir.
Kullanım Alanları:
Haftalık pivotlar, bir önceki haftanın verilerine göre hesaplanır. Swing trader’lar için daha uygundur.
Kullanım Alanları:
Aylık pivot seviyeleri, uzun vadeli trader ve yatırımcılar için önemli sinyaller verir. Büyük trendleri analiz etmekte kullanılır.
Kullanım Alanları:
Yıllık pivotlar, özellikle büyük fonlar, kurumsal yatırımcılar veya portföy yöneticileri için uzun vadeli yatırım kararlarında dikkate alınır.
Kullanım Alanları:
Piyasa fiyatı pivot seviyesinin üzerindeyse, bu durum yükseliş eğilimine; altındaysa düşüş eğilimine işaret edebilir.
Basit Strateji Örneği:
TradingView gibi platformlarda, günlük, haftalık, aylık pivotları otomatik hesaplayan göstergeler mevcuttur. Ayarlardan istediğiniz zaman dilimini seçerek grafik üzerine kolayca entegre edebilirsiniz.
Pivot noktaları, piyasada olası dönüş noktalarını öngörmek ve stratejik kararlar almak için etkili bir araçtır. Günlükten yıllığa kadar farklı zaman dilimlerinde uygulanabilirliği sayesinde, hem kısa vadeli hem de uzun vadeli yatırımcılara yardımcı olur.
Son Yorumlar