hocam neyaptın

 avatar
neron
plain_text
5 months ago
14 kB
2
Indexable
import ccxt
import numpy as np
import pandas as pd
from pandas import DataFrame
import pandas_ta as ta
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import f1_score
from sklearn.utils import resample
import joblib
import os
from datetime import datetime, timedelta, timezone 
import time
import logging
import tzlocal 

# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Binance borsasına bağlanın
exchange = ccxt.binanceusdm()
binance = ccxt.binance({
    'enableRateLimit': True,
})
symbols = ['BNB/USDT']
timeframe = '1m'
limit = 500
ma_period = 10

# Tahmin sonuçlarını saklamak için bir liste
predictions_history = []
correct_predictions = 0
total_predictions = 0
learning_rate = 0.1

# Pişmanlık değerlerini saklamak için bir liste
regrets_history = []

def remaining_time(clock, timeframe):
    # Zaman dilimlerini dakika cinsinden saklayan bir sözlük
    timeframe_to_minutes = {
        '1m': 1,
        '3m': 3,
        '5m': 5,
        '15m': 15,
        '30m': 30,
        '1h': 60,
        '2h': 120,
        '4h': 240,
        '6h': 360,
        '12h': 720,
        '1d': 1440
    }

    # Geçerli zaman diliminin dakika cinsinden değeri
    interval_minutes = timeframe_to_minutes.get(timeframe)

    if interval_minutes is None:
        raise ValueError(f"Desteklenmeyen zaman dilimi: {timeframe}")

    total_seconds_in_interval = interval_minutes * 60
    elapsed_seconds = (clock.minute * 60 + clock.second) % total_seconds_in_interval

    wait_time = total_seconds_in_interval - elapsed_seconds
    return wait_time


def timeframe_to_seconds(timeframe):
    if timeframe.endswith('m'):
        return int(timeframe[:-1]) * 60
    elif timeframe.endswith('h'):
        return int(timeframe[:-1]) * 60 * 60
    elif timeframe.endswith('d'):
        return int(timeframe[:-1]) * 24 * 60 * 60
    return 0

# Timeframe'in dakika cinsinden değeri
timeframe_to_minutes = {
    '1m': 1,
    '3m': 3,
    '5m': 5,
    '15m': 15,
    '30m': 30,
    '1h': 60,
    '2h': 120,
    '4h': 240,
    '6h': 360,
    '12h': 720,
    '1d': 1440,
}

# Zaman dilimlerini milisaniye cinsine çeviren bir fonksiyon
timeframe_minutes = timeframe_to_minutes[timeframe]

# Oyun teorisi tabanlı özellikleri hesaplama fonksiyonu
def calculate_game_theory_features(df):
    df['price_change'] = df['close'].diff()
    df['up_moves'] = np.where(df['price_change'] > 0, 1, 0)
    df['down_moves'] = np.where(df['price_change'] < 0, 1, 0)
    
    df['total_up_moves'] = df['up_moves'].cumsum()
    df['total_down_moves'] = df['down_moves'].cumsum()
    
    df['volume_change'] = df['volume'].diff().fillna(0)
    df['volume_up'] = np.where(df['volume_change'] > 0, 1, 0)
    df['volume_down'] = np.where(df['volume_change'] < 0, 1, 0)
    
    df['total_volume_up'] = df['volume_up'].cumsum()
    df['total_volume_down'] = df['volume_down'].cumsum()
    
    df = df.dropna()  # NaN değerleri olan satırları kaldır
    return df

# Zaman damgasını dönüştürme fonksiyonu
def convert_timestamp_to_local(df):
    local_tz = tzlocal.get_localzone()  # Sistem saat dilimini algıla
    df['timestamp'] = df['timestamp'].apply(lambda x: pd.to_datetime(x, unit='ms', utc=True))
    df['timestamp'] = df['timestamp'].dt.tz_convert(local_tz)  # Algılanan saat dilimine dönüştür
    return df


def fetch_and_update_data(symbol, timeframe, limit):
    filename = f"{symbol.replace('/', '_')}_{timeframe}.csv"
    filepath = os.path.join(os.getcwd(), filename)

    df = pd.DataFrame()  # df'i başlangıçta boş bir DataFrame olarak tanımlayalım
    last_timestamp_ms = None

    if os.path.exists(filepath):
        try:
            df = pd.read_csv(filepath)
            if not df.empty:
                last_timestamp = df['timestamp'].max()
                try:
                    last_timestamp_ms = int(pd.to_datetime(last_timestamp).timestamp() * 1000)
                except ValueError:
                    last_timestamp_ms = int(last_timestamp)
        except Exception as e:
            logging.error(f"{filepath} okunurken hata oluştu: {e}")
            df = pd.DataFrame()  # Eğer hata varsa, df'i yine boş bırak

    # Veriyi çekin
    ohlcv_data = exchange.fetch_ohlcv(symbol, timeframe, since=last_timestamp_ms) 

    try:
        print(f"Çekilen veri sayısı: {len(ohlcv_data)}")
    except Exception as e:
        print(f"Veri çekme hatası: {e}")
        return df

    if len(ohlcv_data) > 0:
        new_df = pd.DataFrame(ohlcv_data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
        
         # Zaman damgasını sistem saat dilimine göre dönüştür
        new_df = convert_timestamp_to_local(new_df)

        # Yeni verileri mevcut veri çerçevesine ekleme
        df = pd.concat([df, new_df], ignore_index=True)

        # Tekrar eden satırları kaldırma
        df = df.drop_duplicates(subset='timestamp', keep='last')  # 'timestamp' üzerinden kontrol edilir
        
        df['symbol'] = symbol
        
        # Gösterge hesaplamaları
        df['rsi'] = ta.rsi(df['close'], length=14)
        bbands = ta.bbands(df['close'], length=20, std=2)
        for col in bbands.columns:
            df[col] = bbands[col]
        df['bollinger_flag'] = np.where(df['close'] > df['BBU_20_2.0'], 1, np.where(df['close'] < df['BBL_20_2.0'], -1, 0))
        
        stoch = ta.stoch(df['high'], df['low'], df['close'], k=14, d=3)
        df['stoch_k'] = stoch['STOCHk_14_3_3']
        df['stoch_d'] = stoch['STOCHd_14_3_3']
        df['stochastic_flag'] = np.where(df['stoch_k'] < 20, -1, np.where(df['stoch_k'] > 80, 1, 0))
        
        macd = ta.macd(df['close'])
        for col in macd.columns:
            df[col] = macd[col]
        df['macd_signal'] = np.where((df['MACD_12_26_9'].shift(1) < df['MACDs_12_26_9'].shift(1)) & 
                                      (df['MACD_12_26_9'] > df['MACDs_12_26_9']), 1, 
                                      np.where((df['MACD_12_26_9'].shift(1) > df['MACDs_12_26_9'].shift(1)) & 
                                               (df['MACD_12_26_9'] < df['MACDs_12_26_9']), -1, 0))
        
        df['ma'] = ta.sma(df['close'], length=ma_period)
        df['ma_flag'] = np.where(df['close'] > df['ma'], 1, 0)
        df['body_size'] = np.abs(df['close'] - df['open']).round(2)
        df['unit_diff'] = df['close'].diff().round(2)
        df['percent_diff'] = (df['unit_diff'] / df['close'].shift(1) * 100).round(2)
        df['percent_high_diff'] = ((df['high'] - df['open']) / df['open'] * 100).round(2)
        df['percent_low_diff'] = ((df['low'] - df['open']) / df['open'] * 100).round(2)

        df = calculate_game_theory_features(df)

        df.dropna(inplace=True)
        df.to_csv(filepath, index=False)
        logging.info(f'{symbol} için veri başarıyla güncellendi ve kaydedildi.')
    else:
        logging.info("Yeni veri bulunmuyor, CSV dosyasına veri eklenmedi.")

    return df


def train_and_evaluate_model(df):
    global correct_predictions, total_predictions, learning_rate, regrets_history

    # Sadece sayısal sütunları filtreleyin
    X = df.drop(['timestamp', 'percent_diff'], axis=1)
    numeric_columns = X.select_dtypes(include=[np.number]).columns
    X_numeric = X[numeric_columns]
    
    y = np.where(df['percent_diff'] > 0, 1, 0)

    # SimpleImputer'ı yalnızca sayısal sütunlar üzerinde kullanın
    imputer = SimpleImputer(strategy='mean')
    X_imputed = pd.DataFrame(imputer.fit_transform(X_numeric), columns=X_numeric.columns)

    class_0 = df[df['percent_diff'] <= 0].shape[0]
    class_1 = df[df['percent_diff'] > 0].shape[0]

    # Veri dengesizliği durumunda yukarı örnekleme
    if class_0 < class_1:
        X_minority = X_imputed[y == 1]
        y_minority = y[y == 1]
        X_majority = X_imputed[y == 0]
        y_majority = y[y == 0]

        X_minority_upsampled, y_minority_upsampled = resample(X_minority, y_minority,
                                                               replace=True,
                                                               n_samples=class_0,
                                                               random_state=42)
        X_balanced = np.vstack((X_majority, X_minority_upsampled))
        y_balanced = np.hstack((y_majority, y_minority_upsampled))
    else:
        X_balanced = X_imputed
        y_balanced = y

    X_train, X_test, y_train, y_test = train_test_split(X_balanced, y_balanced, test_size=0.2, random_state=42)

    model = GradientBoostingClassifier()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)

    f1 = f1_score(y_test, y_pred)
    logging.info(f'F1 Skoru: {f1}')

    correct_predictions += np.sum(y_pred == y_test)
    total_predictions += len(y_test)

    # Pişmanlık hesaplama
    regret = np.sum(np.abs(y_test - y_pred))  # Yanlış tahminlerin sayısı
    regrets_history.append(regret)

    # Model kaydetme
    model_filename = 'gradient_boosting_model.pkl'
    if os.path.exists(model_filename):
        previous_model = joblib.load(model_filename)
        y_prev_pred = previous_model.predict(X_test)
        prev_f1 = f1_score(y_test, y_prev_pred)
        logging.info(f'Önceki Modelin F1 Skoru: {prev_f1}')
        
        if f1 > prev_f1:
            joblib.dump(model, model_filename)
            logging.info("Yeni model kaydedildi.")
            active_model = model
        else:
            logging.info("Önceki model daha iyi performans gösteriyor, yeni model kaydedilmedi.")
            active_model = previous_model
    else:
        joblib.dump(model, model_filename)
        logging.info("Model ilk kez kaydedildi.")
        active_model = model

    # Öğrenme oranı güncellemesi
    if total_predictions > 0:
        accuracy = correct_predictions / total_predictions
        if accuracy < 0.5:
            learning_rate *= 1.1
            logging.info(f"Öğrenme oranı artırıldı: {learning_rate}")
        else:
            learning_rate *= 0.9
            logging.info(f"Öğrenme oranı azaltıldı: {learning_rate}")

    return active_model


predictions_history = []

def predict_next_movement(active_model, df):
    global predictions_history, regrets_history
    
    # Son veriyi alırken sadece sayısal sütunları kullan
    next_input = df.iloc[-1:].drop(['timestamp', 'percent_diff'], axis=1)
    numeric_columns = next_input.select_dtypes(include=[np.number]).columns
    next_input_numeric = next_input[numeric_columns].values

    # Eğer next_input_numeric boşsa, modelin tahmin yapmasını sağlamak için uyarı ver
    if next_input_numeric.size == 0:
        logging.error("Son veride sayısal sütun bulunmuyor, tahmin yapılamıyor.")
        return

    next_prediction = active_model.predict(next_input_numeric)
    prediction_proba = active_model.predict_proba(next_input_numeric)
    last_timestamp = df.iloc[-1]['timestamp']

    up_probability = prediction_proba[0][1] * 100
    down_probability = prediction_proba[0][0] * 100

    if len(predictions_history) >= 10:
        predictions_history.pop(0)

    predictions_history.append(next_prediction[0])

    correct_label = np.where(df['percent_diff'].iloc[-1] > 0, 1, 0)
    
    # Pişmanlık güncelleme
    if predictions_history[-1] != correct_label:
        regret_value = 1  # Yanlış tahmin için pişmanlık değeri
        regrets_history.append(regret_value)
        logging.info("Yanlış tahmin, pişmanlık değeri eklendi.")
    else:
        regrets_history.append(0)  # Doğru tahmin için pişmanlık değeri yok

    if next_prediction[0] == 1:
        logging.info(f"Tahmin: Gelecek mumda fiyat yükselecek. Olasılık: {up_probability:.2f}%. Zaman: {last_timestamp}")
    else:
        logging.info(f"Tahmin: Gelecek mumda fiyat düşecek. Olasılık: {down_probability:.2f}%. Zaman: {last_timestamp}")

    if len(predictions_history) >= 10:
        # Yeniden eğitim için veri hazırlama
        df['prediction'] = np.nan
        df['prediction'].iloc[-1] = predictions_history[-1]
        retrain_data = df.dropna()

        if len(retrain_data) > 0:
            active_model = train_and_evaluate_model(retrain_data)

        predictions_history = []


while True:
    # Geçerli zaman
    current_time = datetime.now(timezone.utc).astimezone()

    # Bekleme süresi hesapla ve ilk çalıştırmada bekle
    wait_time = remaining_time(current_time, timeframe)
    logging.info(f"Kalan süre: {wait_time} saniye")
    
    time.sleep(wait_time)  # İlk veri çekimi başlamadan önce bekle

    # Veriyi güncelle
    for symbol in symbols:
        df = fetch_and_update_data(symbol, timeframe, limit)
        
        if df is not None and not df.empty:
                active_model = train_and_evaluate_model(df)
                predict_next_movement(active_model, df)

                
        # Veriler yeterliyse eğit ve değerlendir
        if len(df) >= 100:  # 100'den fazla veri noktası varsa
            train_and_evaluate_model(df)

    # Bekleme süresini döngüde hesaplayarak belirli bir süre bekle
    wait_time = remaining_time(current_time, timeframe)
    time.sleep(wait_time)  # Burada belirlenen bekleme süresince uykuya geçilir
Editor is loading...
Leave a Comment