English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
Python ve MQL5'te bir robot geliştirme (Bölüm 1): Veri ön işleme

Python ve MQL5'te bir robot geliştirme (Bölüm 1): Veri ön işleme

MetaTrader 5Alım-satım sistemleri |
206 71
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Giriş

Piyasa giderek daha karmaşık hale geliyor. Bugün bu bir algoritma savaşına dönüşmüştür. İşlem hacminin %95'inden fazlası robotlar tarafından üretilmektedir. 

Bir sonraki adım makine öğrenimidir. Bunlar güçlü yapay zeka değildir, ancak basit doğrusal algoritmalar da değildir. Makine öğrenimi modeli zor koşullarda kar elde etme yeteneğine sahiptir. Alım-satım sistemleri oluşturmak için makine öğrenimini uygulamak ilginç bir fikirdir. Sinir ağları sayesinde, alım-satım robotu büyük verileri analiz edecek, formasyonları bulacak ve fiyat hareketlerini tahmin edecektir.


Bir alım-satım robotunun geliştirme döngüsüne bakacağız: veri toplama, işleme, örneklem genişletme, özellik mühendisliği, model seçimi ve eğitimi, Python aracılığıyla bir alım-satım sistemi oluşturma ve işlemleri izleme.

Python'da çalışmanın kendine özgü avantajları vardır: makine öğrenimi alanında hızın yanı sıra özellikleri seçme ve oluşturma yeteneği. Modelleri ONNX'e aktarmak, Python'dakiyle tamamen aynı özellik oluşturma mantığını gerektirir ki bu kolay değildir. Bu yüzden Python üzerinden çevrimiçi alım-satımı seçtim.

Görevi belirleme ve araç seçme

Projenin amacı, Python'da alım-satım için karlı ve sürdürülebilir bir makine öğrenimi modeli oluşturmaktır. Çalışma aşamaları:

  • MetaTrader 5'ten veri toplama, birincil özellikleri yükleme.
  • Örneklemi genişletmek için veri artırımı.  
  • Verilerin etiketlerle işaretlenmesi.
  • Özellik mühendisliği: oluşturma, kümeleme, seçim.
  • ML modelinin seçimi ve eğitimi. Muhtemelen, topluluk oluşturma (ensembling).
  • Modellerin ölçütlere göre değerlendirilmesi.
  • Karlılık değerlendirmesi için sınayıcı geliştirme.  
  • Yeni veriler üzerinde pozitif sonuç elde etme.
  • Python MQL5 aracılığıyla alım-satım algoritmasının uygulanması.
  • MetaTrader 5 ile entegrasyon.
  • Modellerin iyileştirilmesi.

Araçlar: Python MQL5, hız ve işlevsellik için Python'da ML kütüphaneleri.

Böylece amaç ve hedefleri tanımlamış olduk. Makale çerçevesinde aşağıdaki çalışmaları gerçekleştireceğiz:

  • MetaTrader 5'ten veri toplama, birincil özellikleri yükleme.
  • Örneklemi genişletmek için veri artırımı.  
  • Verilerin etiketlerle işaretlenmesi.
  • Özellik mühendisliği: oluşturma, kümeleme, seçim.

Ortamın ayarlanması ve içe aktarma. Veri toplama

İlk olarak, MetaTrader 5 aracılığıyla geçmiş verileri almamız gerekiyor. Kod, terminal dosyasının yolunu başlatma metoduna ileterek işlem platformuyla bir bağlantı kurar.

Döngüde, şu parametrelerle mt5.copy_rates_range() metodunu kullanarak verileri alıyoruz: enstrüman, zaman dilimi, başlangıç ve bitiş tarihleri. Başarısız denemelerin bir sayacı ve kararlı bir bağlantı için bir gecikme vardır.

mt5.shutdown() metodu kullanılarak platformla bağlantı kesilir.

Bu, programda daha sonra çağrılmak üzere ayrı bir fonksiyondur. 

Komut dosyasını çalıştırmak için aşağıdaki kütüphaneleri yüklemeniz gerekecektir:

  1. NumPy: Çok boyutlu diziler ve matematiksel fonksiyonlarla çalışmak için kütüphane.

  2. Pandas: Tablolar ve zaman serileri ile çalışmak için uygun veri yapıları sağlayan bir veri analiz aracı.

  3. Random: Rastgele sayılar üretme ve sekanslardan rastgele öğeler seçme modülü.

  4. Datetime: Tarihler ve saatlerle çalışmak için sınıflar ve fonksiyonlar sağlar.

  5. MetaTrader5: MetaTrader 5 işlem terminali ile etkileşim için kütüphane.

  6. Time: Zaman ve program yürütme gecikmeleri ile çalışmak için modül.

  7. Concurrent.futures: Paralel ve asenkron görevleri çalıştırmak için kullanılan araç. Paralel çok dövizli işleyiş için gelecekte buna ihtiyacımız olacak.

  8. Tqdm: Yinelemeli süreçler gerçekleştirirken ilerleme göstergelerini görüntülemek için kütüphane. Paralel çok dövizli işleyiş için gelecekte buna ihtiyacımız olacak.

  9. Train_test_split: Makine öğrenimi modellerini eğitirken bir veri kümesini eğitim ve test kümelerine ayırma fonksiyonu.

Aşağıdaki komutları çalıştırarak bunları 'pip' ile yükleyebilirsiniz:

pip install numpy pandas MetaTrader5 concurrent-futures tqdm sklearn matplotlib imblearn
import numpy as np
import pandas as pd
import random
from datetime import datetime
import MetaTrader5 as mt5
import time
import concurrent.futures
from tqdm import tqdm
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.utils import class_weight
from imblearn.under_sampling import RandomUnderSampler

# GLOBALS
MARKUP = 0.00001
BACKWARD = datetime(2000, 1, 1)
FORWARD = datetime(2010, 1, 1)
EXAMWARD = datetime(2024, 1, 1)
MAX_OPEN_TRADES = 3
symbol = "EURUSD"

def retrieve_data(symbol, retries_limit=300):
    terminal_path = "C:/Program Files/MetaTrader 5/Arima/terminal64.exe"

    attempt = 0
    raw_data = None

    while attempt < retries_limit:
        if not mt5.initialize(path=terminal_path):
            print("MetaTrader initialization failed")
            return None

        instrument_count = mt5.symbols_total()
        if instrument_count > 0:
            print(f"Number of instruments in the terminal: {instrument_count}")
        else:
            print("No instruments in the terminal")

        rates = mt5.copy_rates_range(symbol, mt5.TIMEFRAME_H1, BACKWARD, EXAMWARD)
        mt5.shutdown()

        if rates is None or len(rates) == 0:
            print(f"Data for {symbol} not available (attempt {attempt+1})")
            attempt += 1
            time.sleep(1)
        else:
            raw_data = pd.DataFrame(rates[:-1], columns=['time', 'open', 'high', 'low', 'close', 'tick_volume'])
            raw_data['time'] = pd.to_datetime(raw_data['time'], unit='s')
            raw_data.set_index('time', inplace=True)
            break

    if raw_data is None:
        print(f"Data retrieval failed after {retries_limit} attempts")
        return None

    # Add simple features
    raw_data['raw_SMA_10'] = raw_data['close'].rolling(window=10).mean()
    raw_data['raw_SMA_20'] = raw_data['close'].rolling(window=20).mean()
    raw_data['Price_Change'] = raw_data['close'].pct_change() * 100

    # Additional features
    raw_data['raw_Std_Dev_Close'] = raw_data['close'].rolling(window=20).std()
    raw_data['raw_Volume_Change'] = raw_data['tick_volume'].pct_change() * 100

    raw_data['raw_Prev_Day_Price_Change'] = raw_data['close'] - raw_data['close'].shift(1)
    raw_data['raw_Prev_Week_Price_Change'] = raw_data['close'] - raw_data['close'].shift(7)
    raw_data['raw_Prev_Month_Price_Change'] = raw_data['close'] - raw_data['close'].shift(30)

    raw_data['Consecutive_Positive_Changes'] = (raw_data['Price_Change'] > 0).astype(int).groupby((raw_data['Price_Change'] > 0).astype(int).diff().ne(0).cumsum()).cumsum()
    raw_data['Consecutive_Negative_Changes'] = (raw_data['Price_Change'] < 0).astype(int).groupby((raw_data['Price_Change'] < 0).astype(int).diff().ne(0).cumsum()).cumsum()
    raw_data['Price_Density'] = raw_data['close'].rolling(window=10).apply(lambda x: len(set(x)))
    raw_data['Fractal_Analysis'] = raw_data['close'].rolling(window=10).apply(lambda x: 1 if x.idxmax() else (-1 if x.idxmin() else 0))
    raw_data['Price_Volume_Ratio'] = raw_data['close'] / raw_data['tick_volume']
    raw_data['Median_Close_7'] = raw_data['close'].rolling(window=7).median()
    raw_data['Median_Close_30'] = raw_data['close'].rolling(window=30).median()
    raw_data['Price_Volatility'] = raw_data['close'].rolling(window=20).std() / raw_data['close'].rolling(window=20).mean()

    print("\nOriginal columns:")
    print(raw_data[['close', 'high', 'low', 'open', 'tick_volume']].tail(100))

    print("\nList of features:")
    print(raw_data.columns.tolist())

    print("\nLast 100 features:")
    print(raw_data.tail(100))

    # Replace NaN values with the mean
    raw_data.fillna(raw_data.mean(), inplace=True)

    return raw_data

retrieve_data(symbol)

Global değişkenleri tanımlıyoruz: makas maliyetleri ve aracı kurum komisyonları, eğitim ve test örneklemleri için tarihler, maksimum işlem sayısı, sembol.

MetaTrader 5'ten fiyatları bir döngü içinde yüklüyoruz. Veriler bir DataFrame'e dönüştürülür ve özelliklerle zenginleştirilir:

  • 10 ve 20 periyotlu SMA hareketli ortalamaları
  • Fiyat değişimi 
  • Fiyatın standart sapması
  • Hacim değişimi
  • Günlük/aylık fiyat değişimi
  • Fiyat medyanları

Bu özellikler, fiyatı etkileyen faktörlerin dikkate alınmasına yardımcı olur.

DataFrame sütunları ve en son girişler hakkında bilgi görüntülenir.

İlk fonksiyonumuzun nasıl çalıştığını görelim:

İlk fonksiyon

Her şey çalışıyor. Kod, fiyatları başarıyla yükledi, özellikleri hazırladı ve yükledi. Kodun bir sonraki bölümüne geçelim.


Örneklemi genişletmek için veri artırımı

Veri artırımı, örneklem büyüklüğünü artırmak ve model kalitesini iyileştirmek için mevcut örneklere dayalı olarak yeni eğitim örneklerinin oluşturulmasıdır. Sınırlı veriye sahip zaman serilerinin tahmin edilmesiyle ilgilidir. Ayrıca, model hatalarını azaltır ve sağlamlığı artırır.

Finansal veri artırma yöntemleri:

  • Gürültüye karşı sağlamlık için gürültü (rastgele sapmalar) ekleme.
  • Farklı geliştirme senaryolarının modellenmesi için zaman kayması.
  • Fiyat artışlarını/düşüşlerini modellemek için ölçeklendirme.
  • Kaynak veriyi ters çevirme.

DataFrame'i ve her yöntem için yeni örnek sayısını kabul eden girdi artırma fonksiyonunu uyguladım. Farklı yaklaşımlar kullanarak yeni veriler oluşturur ve bunları orijinal DataFrame ile birleştirir.

def augment_data(raw_data, noise_level=0.01, time_shift=1, scale_range=(0.9, 1.1)):
    print(f"Number of rows before augmentation: {len(raw_data)}")

    # Copy raw_data into augmented_data
    augmented_data = raw_data.copy()

    # Add noise
    noisy_data = raw_data.copy()
    noisy_data += np.random.normal(0, noise_level, noisy_data.shape)

    # Replace NaN values with the mean
    noisy_data.fillna(noisy_data.mean(), inplace=True)

    augmented_data = pd.concat([augmented_data, noisy_data])
    print(f"Added {len(noisy_data)} rows after adding noise")

    # Time shift
    shifted_data = raw_data.copy()
    shifted_data.index += pd.DateOffset(hours=time_shift)

    # Replace NaN values with the mean
    shifted_data.fillna(shifted_data.mean(), inplace=True)

    augmented_data = pd.concat([augmented_data, shifted_data])
    print(f"Added {len(shifted_data)} rows after time shift")

    # Scaling
    scale = np.random.uniform(scale_range[0], scale_range[1])
    scaled_data = raw_data.copy()
    scaled_data *= scale

    # Replace NaN values with the mean
    scaled_data.fillna(scaled_data.mean(), inplace=True)

    augmented_data = pd.concat([augmented_data, scaled_data])
    print(f"Added {len(scaled_data)} rows after scaling")

    # Inversion
    inverted_data = raw_data.copy()
    inverted_data *= -1

    # Replace NaN values with the mean
    inverted_data.fillna(inverted_data.mean(), inplace=True)

    augmented_data = pd.concat([augmented_data, inverted_data])
    print(f"Added {len(inverted_data)} rows after inversion")

    print(f"Number of rows after augmentation: {len(augmented_data)}")

    # Print dates by years
    print("Print dates by years:")
    for year, group in augmented_data.groupby(augmented_data.index.year):
        print(f"Year {year}: {group.index}")

    return augmented_data

Kodu çağıralım. Aşağıdaki sonuçları elde ederiz:

2

Veri artırma yöntemlerini uyguladıktan sonra, 150.000 H1 fiyat çubuğundan oluşan orijinal setimiz etkileyici bir şekilde 747.000’e genişledi. Makine öğrenimi alanındaki birçok yetkili çalışma, sentetik örneklerin üretilmesi yoluyla eğitim verisi hacminde böylesine önemli bir artışın, eğitilen modellerin kalite ölçütleri üzerinde olumlu bir etkiye sahip olduğunu göstermektedir. Bizim durumumuzda da bu tekniğin istenen etkiyi yaratacağını umuyoruz.


Verileri etiketleme

Veri etiketleme, denetimli öğrenme algoritmalarının başarısı için kritik öneme sahiptir. Kaynak verilere, modelin daha sonra öğreneceği etiketleri sağlamamıza olanak tanır. Etiketlenmiş veriler doğruluğu artırır, genellemeyi iyileştirir, eğitimi hızlandırır ve modellerin değerlendirilmesini kolaylaştırır. EURUSD tahmin probleminde, bir sonraki fiyat değişikliğinin makas ve komisyondan daha büyük olup olmadığını gösteren "labels" ikili sütununu ekledik. Bu, modelin makas tekrarlama ve geri dönüşsüz trend kalıplarını öğrenmesini sağlar.

    Etiketleme, makine öğrenimi algoritmalarının ham haliyle görülemeyen verilerdeki karmaşık formasyonları bulmasına olanak tanıyan kilit bir rol oynar. Koda bakalım.

    def markup_data(data, target_column, label_column, markup_ratio=0.00002):
        data.loc[:, label_column] = np.where(data.loc[:, target_column].shift(-1) > data.loc[:, target_column] + markup_ratio, 1, 0)
    
        data.loc[data[label_column].isna(), label_column] = 0
    
        print(f"Number of markups on price change greater than markup: {data[label_column].sum()}")
    
        return data

    Bu kodu çalıştıralım ve verilerdeki etiket sayısını alalım. Fonksiyon bir DataFrame geri döndürür. Her şey çalışıyor. Bu arada, 700.000'den fazla veri noktasından sadece 70.000'inde fiyat, makastan daha fazla değişmiştir.

    3

    Şimdi başka bir veri işaretleme fonksiyonumuz var. Bu kez, gerçek kazançlara daha yakın.


    Hedef etiketleri fonksiyonu

    def label_data(data, symbol, min=2, max=48):
        terminal_path = "C:/Program Files/MetaTrader 5/Arima/terminal64.exe"
    
        if not mt5.initialize(path=terminal_path):
            print("Error connecting to MetaTrader 5 terminal")
            return
    
        symbol_info = mt5.symbol_info(symbol)
        stop_level = 100 * symbol_info.point
        take_level = 800 * symbol_info.point
    
        labels = []
    
        for i in range(data.shape[0] - max):
            rand = random.randint(min, max)
            curr_pr = data['close'].iloc[i]
            future_pr = data['close'].iloc[i + rand]
            min_pr = data['low'].iloc[i:i + rand].min()
            max_pr = data['high'].iloc[i:i + rand].max()
    
            price_change = abs(future_pr - curr_pr)
    
            if price_change > take_level and future_pr > curr_pr and min_pr > curr_pr - stop_level:
                labels.append(1)  # Growth
            elif price_change > take_level and future_pr < curr_pr and max_pr < curr_pr + stop_level:
                labels.append(0)  # Fall
            else:
                labels.append(None)
    
        data = data.iloc[:len(labels)].copy()
        data['labels'] = labels
    
        data.dropna(inplace=True)
    
        X = data.drop('labels', axis=1)
        y = data['labels']
    
        rus = RandomUnderSampler(random_state=2)
        X_balanced, y_balanced = rus.fit_resample(X, y)
    
        data_balanced = pd.concat([X_balanced, y_balanced], axis=1)
    
        return data

    Fonksiyon, makine öğrenimi modellerini alım-satım karları üzerinde eğitmek için hedef etiketleri elde eder. Fonksiyon MetaTrader 5'e bağlanır, sembol bilgilerini alır ve SL/TP seviyelerini hesaplar. Ardından, her giriş noktası için rastgele bir periyottan sonra gelecekteki fiyat belirlenir. Fiyat değişikliği TP seviyesini aşar ve SL seviyesine dokunmazsa ve ayrıca artış/düşüş koşullarını yerine getirirse, 1.0/0.0 işareti buna göre eklenir. Aksi takdirde, None olarak işaretlenir. Yalnızca etiketli verileri içeren yeni bir DataFrame oluşturulur. Hiçbiri ortalamalarla değiştirilmez.

    Artış/düşüş etiketlerinin sayısı görüntülenir.

    Her şey amaçlandığı gibi çalışıyor. Verileri ve türevlerini aldık. Veriler artırıldı, önemli ölçüde genişletildi ve iki farklı fonksiyonla işaretlendi. Bir sonraki adıma geçelim - sınıf dengeleme.

    Bu arada, makine öğrenimi konusunda deneyimli okuyucuların, nihayetinde bir regresyon modeli değil, bir sınıflandırma modeli geliştireceğimizi uzun zamandır anladığına inanıyorum. Regresyon modellerini daha çok seviyorum, çünkü onlarda sınıflandırma modellerinden biraz daha fazla tahmin mantığı görüyorum. 

    Bir sonraki hamlemiz sınıf dengeleme olacak.


    Sınıfları dengeleme. Sınıflandırma nedir?

    Sınıflandırma, bilginin ortak özelliklere göre yapılandırılmasına yönelik insanın doğal yeteneğine dayanan temel bir analiz yöntemidir. Sınıflandırmanın ilk kullanımlarından biri, jeolojik özelliklere dayalı olarak gelecek vaat eden alanların belirlenerek maden yataklarının araştırılmasıdır.

    Bilgisayarların ortaya çıkmasıyla sınıflandırma yeni bir seviyeye ulaştı, ancak özü hala aynı kaldı - detayların görünen kaosundaki formasyonları keşfetmek. Finansal piyasalar için fiyat dinamiklerini artış/düşüş olarak sınıflandırmak önemlidir. Ancak, sınıflar dengesiz olabilir - az sayıda trend ve çok sayıda yatay hareket vardır.

    Bu nedenle, sınıf dengeleme yöntemleri kullanılır: baskın örneklerin kaldırılması veya nadir örneklerin üretilmesi. Bu, modellerin önemli ancak nadir fiyat dinamiği modellerini güvenilir bir şekilde tanımasını sağlar.

    pip install imblearn

        data = data.iloc[:len(labels)].copy()
        data['labels'] = labels
    
        data.dropna(inplace=True)
    
        X = data.drop('labels', axis=1)
        y = data['labels']
    
        rus = RandomUnderSampler(random_state=2)
        X_balanced, y_balanced = rus.fit_resample(X, y)
    
        data_balanced = pd.concat([X_balanced, y_balanced], axis=1)

    Sınıflarımız artık dengeli. Her sınıf için eşit sayıda etiketimiz var (fiyat artışı ve düşüşü).

    Veri tahminindeki en önemli konuya geçelim - özellikler.


    Makine öğreniminde özellikler nedir?

    Özellikler, çocukluktan itibaren herkesin aşina olduğu temel kavramlardır. Bir nesneyi tanımlarken, onun özelliklerini listeleriz. Bu tür özelliklerden oluşan bir küme, bir nesneyi tam olarak karakterize etmemizi sağlar.

    Veri analizinde de aynı şey söz konusudur - her gözlem, sayısal ve kategorik özellikler kümesi ile tanımlanır. Bilgilendirici özelliklerin seçimi başarı için kritik öneme sahiptir.

    Daha yüksek bir seviyede ise, incelenen nesneyi daha iyi tanımlamak için başlangıç parametrelerinden yeni türetilmiş özelliklerin oluşturulduğu özellik mühendisliği yer almaktadır.

    Böylece, nesnelerin özelliklerine göre tanımlanması yoluyla dünyayı anlamaya yönelik insan deneyimi, biçimselleştirme ve otomasyon düzeyinde bilime aktarılır.


    Otomatik özellik çıkarma

    Özellik mühendisliği, makine öğrenimi modellerini eğitmek için kaynak verilerin bir özellik kümesine dönüştürülmesidir. Amaç, en bilgilendirici özellikleri bulmaktır. Manuel bir yaklaşım (bir kişi özellikleri seçer) ve otomatik bir yaklaşım (algoritmalar kullanarak) vardır.

    Otomatik yaklaşımı kullanacağız. Verilerimizden en iyi özellikleri otomatik olarak çıkarmak için özellik oluşturma metodunu uygulayalım. Ardından ortaya çıkan kümeden en bilgilendirici olanları seçeceğiz.

    Yeni özellikler oluşturma metodu: 

    def generate_new_features(data, num_features=200, random_seed=1):
        random.seed(random_seed)
        new_features = {}
    
        for _ in range(num_features):
            feature_name = f'feature_{len(new_features)}'
    
            col1_idx, col2_idx = random.sample(range(len(data.columns)), 2)
            col1, col2 = data.columns[col1_idx], data.columns[col2_idx]
    
            operation = random.choice(['add', 'subtract', 'multiply', 'divide', 'shift', 'rolling_mean', 'rolling_std', 'rolling_max', 'rolling_min', 'rolling_sum'])
    
            if operation == 'add':
                new_features[feature_name] = data[col1] + data[col2]
            elif operation == 'subtract':
                new_features[feature_name] = data[col1] - data[col2]
            elif operation == 'multiply':
                new_features[feature_name] = data[col1] * data[col2]
            elif operation == 'divide':
                new_features[feature_name] = data[col1] / data[col2]
            elif operation == 'shift':
                shift = random.randint(1, 10)
                new_features[feature_name] = data[col1].shift(shift)
            elif operation == 'rolling_mean':
                window = random.randint(2, 20)
                new_features[feature_name] = data[col1].rolling(window).mean()
            elif operation == 'rolling_std':
                window = random.randint(2, 20)
                new_features[feature_name] = data[col1].rolling(window).std()
            elif operation == 'rolling_max':
                window = random.randint(2, 20)
                new_features[feature_name] = data[col1].rolling(window).max()
            elif operation == 'rolling_min':
                window = random.randint(2, 20)
                new_features[feature_name] = data[col1].rolling(window).min()
            elif operation == 'rolling_sum':
                window = random.randint(2, 20)
                new_features[feature_name] = data[col1].rolling(window).sum()
    
        new_data = pd.concat([data, pd.DataFrame(new_features)], axis=1)
    
        print("\nGenerated features:")
        print(new_data[list(new_features.keys())].tail(100))
    
        return data

    Lütfen aşağıdaki parametreye dikkat edin:

    random_seed=42

    random_seed parametresi, yeni özellikler oluşturma sonuçlarının tekrarlanabilirliği için gereklidir. generate_new_features fonksiyonu kaynak verilerden yeni özellikler oluşturur. Girdileri: veri, özellik sayısı, seed.

    Random, belirli bir seed ile başlatılır. Döngüde: bir ad oluşturulur, 2 mevcut özellik ve bir işlem (toplama, çıkarma vb.) rastgele seçilir. Seçilen işlem için yeni bir özellik hesaplanır.

    Oluşturmadan sonra, orijinal verilere yeni özellikler eklenir. Otomatik olarak oluşturulan özelliklerle güncellenmiş veriler geri döndürülür.

    Kod, makine öğreniminin kalitesini artırmak için otomatik olarak yeni özellikler oluşturmamızı sağlar.

    Kodu çalıştıralım ve sonuca göz atalım:

    5

    100 yeni özellik oluşturuldu. Bir sonraki aşamaya geçelim - özelliklerin kümelenmesi.


    Özelliklerin kümelenmesi

    Özellik kümeleme, sayılarını azaltmak için benzer özellikleri gruplar halinde birleştirir. Bu, gereksiz verilerin kaldırılmasına, korelasyonun azaltılmasına ve aşırı uyum olmadan modelin basitleştirilmesine yardımcı olur.

    Popüler algoritmalar: k-ortalama (küme sayısı belirtilir, özellikler merkezler etrafında gruplandırılır) ve hiyerarşik kümeleme (çok seviyeli ağaç yapısı).

    Özelliklerin kümelenmesi, bir grup işe yaramaz özelliği ayıklamamıza ve model verimliliğini artırmamıza olanak tanır.

    Şimdi özellik kümeleme koduna bakalım:

    from sklearn.mixture import GaussianMixture
    
    def cluster_features_by_gmm(data, n_components=4):
        X = data.drop(['label', 'labels'], axis=1)
    
        X = X.replace([np.inf, -np.inf], np.nan)
        X = X.fillna(X.median())
    
        gmm = GaussianMixture(n_components=n_components, random_state=1)
    
        gmm.fit(X)
    
        data['cluster'] = gmm.predict(X)
    
        print("\nFeature clusters:")
        print(data[['cluster']].tail(100))
    
        return data

    Özellik kümeleme için Gauss Karışım Modeli (Gaussian Mixture Model, GMM) algoritmasını kullanıyoruz. Temel fikir, verilerin her bir dağılımın bir küme olduğu normal dağılımların bir karışımı olarak üretilmesidir.

    İlk olarak, küme sayısını ayarlarız. Ardından modelin başlangıç parametrelerini belirleriz: ortalamalar, kovaryans matrisleri ve küme olasılıkları. Algoritma, bu parametreleri değişmeleri durana kadar maksimum olabilirlik yöntemini kullanarak döngüsel olarak yeniden hesaplar.

    Sonuç olarak, yeni özelliğin hangi kümeye ait olduğunu belirleyebileceğimiz her bir küme için nihai parametreleri elde ederiz.

    GMM harika bir şey. Farklı görevlerde kullanılır. Kümelerin karmaşık şekillere ve bulanık sınırlara sahip olduğu veriler için iyidir.

    Bu kod, özellikleri kümelere ayırmak için GMM kullanır. Orijinal veriler alınır ve sınıf etiketleri kaldırılır. GMM, belirli sayıda kümeye bölmek için kullanılır. Küme numaraları yeni bir sütun olarak eklenir. Sonunda, elde edilen kümelerin bir tablosu yazdırılır.

    Kümeleme kodunu çalıştıralım ve sonuçları görelim:

    6

    En iyi özellikleri seçme fonksiyonuna geçelim.


    En iyi özelliklerin seçilmesi

    from sklearn.feature_selection import RFECV
    from sklearn.ensemble import RandomForestClassifier
    import pandas as pd
    
    def feature_engineering(data, n_features_to_select=10):
        # Remove the 'label' column as it is not a feature
        X = data.drop(['label', 'labels'], axis=1)
        y = data['labels']
    
        # Create a RandomForestClassifier model
        clf = RandomForestClassifier(n_estimators=100, random_state=1)
    
        # Use RFECV to select n_features_to_select best features
        rfecv = RFECV(estimator=clf, step=1, cv=5, scoring='accuracy', n_jobs=-1, verbose=1,
                      min_features_to_select=n_features_to_select)
        rfecv.fit(X, y)
    
        # Return a DataFrame with the best features, 'label' column, and 'labels' column
        selected_features = X.columns[rfecv.get_support(indices=True)]
        selected_data = data[selected_features.tolist() + ['label', 'labels']]  # Convert selected_features to a list
    
        # Print the table of best features
        print("\nBest features:")
        print(pd.DataFrame({'Feature': selected_features}))
    
        return selected_data
    
    labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=10)

    Bu fonksiyon, verilerimizden en iyi ve en kullanışlı özellikleri çıkarır. Girdiler, sınıf özelliklerini ve etiketlerini içeren orijinal veri ve seçilmesi istenen özellik sayısıdır.

    İlk olarak, sınıf etiketleri özellik seçimine yardımcı olmayacağı için kaldırılır. Ardından Rastgele Orman (Random Forest) algoritması başlatılır - rastgele özellik kümeleri üzerinde bir grup karar ağacı oluşturan bir modeldir.

    Tüm ağaçlar eğitildikten sonra, Rastgele Orman her bir özelliğin ne kadar önemli olduğunu ve sınıflandırmayı ne kadar etkilediğini değerlendirir. Bu önem puanlarına dayanarak, fonksiyon en iyi özellikleri seçer.

    Son olarak, seçilen özellikler veriye eklenir ve sınıf etiketleri geri getirilir. Fonksiyon, seçilen özellikleri içeren bir tablo yazdırır ve güncellenmiş verileri geri döndürür.

    Bütün bu kargaşa niye? Böylece sadece süreci yavaşlatan gereksiz özelliklerden kurtuluyoruz. En iyi özellikleri tutuyoruz, bu sayede model bu tür veriler üzerinde eğitim alarak daha iyi sonuçlar gösterir.

    Fonksiyonu başlatalım ve sonuçları görelim:

    8

    Fiyat tahmini için en iyi göstergenin açılış fiyatının kendisi olduğu ortaya çıktı. En üstte hareketli ortalama, fiyat değişimi, standart sapma, günlük ve aylık fiyat değişimlerine dayalı özellikler yer aldı. Otomatik olarak oluşturulan özelliklerin bilgilendirici olmadığı ortaya çıktı.

    Kod, model performansını ve genelleme yeteneğini artırabilecek önemli özelliklerin otomatik olarak seçilmesine olanak tanır.


    Sonuç

    Gelecekteki makine öğrenimi modelimizin geliştirilmesini bekleyen veri manipülasyon kodunu oluşturduk. Attığımız adımları kısaca gözden geçirelim:

    • EURUSD döviz çiftine ilişkin ilk veriler MetaTrader 5 platformundan çıkarıldı. Ardından, örneklem büyüklüğünü önemli ölçüde artırmak için rastgele işlemler - gürültü ekleme, kaydırma ve ölçeklendirme - kullanılarak dönüşümler gerçekleştirildi.
    • Bir sonraki adım, fiyat değerlerini özel trend etiketleriyle işaretlemekti - SL ve TP seviyelerini dikkate alarak artış ve düşüş. Sınıfları dengelemek için gereksiz örnekler çıkarıldı.
    • Ardından, karmaşık bir özellik mühendisliği prosedürü gerçekleştirildi. İlk olarak, yüzlerce yeni türetilmiş özellik orijinal zaman serisinden otomatik olarak oluşturuldu. Daha sonra fazlalığı tespit etmek için Gauss Karışım Modeli algoritmasıyla kümeleme gerçekleştirildi. Son olarak, değişkenlerin en bilgilendirici alt kümesini seçmek için Rastgele Orman algoritması kullanıldı.
    • Sonuç olarak, optimum özelliklere sahip yüksek kaliteli zenginleştirilmiş bir veri kümesi oluşturuldu. Makine öğrenimi modellerinin eğitimi ve MetaTrader 5'e entegrasyon ile Python'da bir alım-satım stratejisinin geliştirilmesi için bir temel oluşturacaktır.


    Bir sonraki makalede, en uygun sınıflandırma modelini seçmeye, iyileştirmeye, çapraz doğrulamayı uygulamaya ve Python/MQL5 paketi için bir sınayıcı fonksiyonu yazmaya odaklanacağız.

    MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
    Orijinal makale: https://www.mql5.com/ru/articles/14350

    Ekli dosyalar |
    synergy_ml_bot.py (11.74 KB)
    Son yorumlar | Tartışmaya git (71)
    Andreas Kress
    Andreas Kress | 10 Eki 2024 saat 07:58
    raw_Prev_Day_Price_Change
    raw_Prev_Week_Price_Change
    raw_Prev_Week_Price_Change
    Nasıl çalışması gerektiğini anlamıyorum, sanırım bunu hesaplamadan önce günlük zaman dilimine ihtiyacımız var mı, yok mu?
    Andreas Kress
    Andreas Kress | 10 Eki 2024 saat 08:03
    stenli21 #:

    Sayın yazar.

    Lütfen bana kullanılan python sürümlerini ve modülleri söyleyin.


    Komut dosyasını çalıştırırken bir hata ortaya çıkıyor




    Yolunuzda ansi yok. Степан.
    Tüm kullanıcılar için python yüklemeyi deneyin. Bu, python'u c:\Program Files\python'a yükleyecektir
    Ya da bunun gibi bir şey

    Veya python'u C:\python'a yükleyin
    Gerekirse sistem yolu değişkenini değiştirmeyi unutmayın
    stenli21
    stenli21 | 16 Eki 2024 saat 19:16
    Andreas Kress #:
    Yolunuzda ansi eksik. Stepan.
    Tüm kullanıcılar için python yüklemeyi deneyin. Bu işlem python'u c:\Program Files\python konumuna yükleyecektir.
    Ya da bunun gibi bir şey

    Ya da python'u C:\python'a yükleyin.
    Gerekirse sistem yolu değişkenini değiştirmeyi unutmayın

    Yanıt için teşekkürler.

    Evet, sorun gerçekten de Rus harfli yollardan kaynaklanıyordu. düzelttim ve her şey çalıştı.....

    Andreas Kress
    Andreas Kress | 30 Eki 2024 saat 08:43
    3. bölüm ne zaman geliyor?
    Roberto Liguoro
    Roberto Liguoro | 22 Tem 2025 saat 08:48
    Harika bir makale
    Python ve MQL5'te bir robot geliştirme (Bölüm 2): Model seçimi, oluşturulması ve eğitimi, özel Python sınayıcısı Python ve MQL5'te bir robot geliştirme (Bölüm 2): Model seçimi, oluşturulması ve eğitimi, özel Python sınayıcısı
    Python ve MQL5'te bir alım-satım robotu geliştirmeye yönelik makale serisine devam ediyoruz. Bugün bir model seçme ve eğitme, test etme, çapraz doğrulama uygulama, ızgara arama (grid search) ve model topluluğu (ensemble) problemini çözeceğiz.
    Model aramada brute force yaklaşımı (Bölüm VI): Döngüsel optimizasyon Model aramada brute force yaklaşımı (Bölüm VI): Döngüsel optimizasyon
    Bu makalede, MetaTrader 4 ve 5’te alım-satım için tüm otomasyon zincirini tamamlamamı sağlayan ve aynı zamanda çok daha ilginç bir şey yapmamı sağlayan iyileştirmelerin ilk bölümünü göstereceğim. Şu andan itibaren, bu çözüm hem Uzman Danışman oluşturmayı hem de optimizasyonu tamamen otomatikleştirmeme ve etkili alım-satım konfigürasyonları bulmak için harcanan emeği en aza indirmeme olanak tanıyor.
    Python'da bir alım-satım robotu geliştirme (Bölüm 3): Model tabanlı bir alım-satım algoritmasının uygulanması Python'da bir alım-satım robotu geliştirme (Bölüm 3): Model tabanlı bir alım-satım algoritmasının uygulanması
    Python ve MQL5'te bir alım-satım robotu geliştirmeye yönelik makale serisine devam ediyoruz. Bu makalede Python'da bir alım-satım algoritması oluşturacağız.
    Gösterge Bilgisinin Ölçülmesi Gösterge Bilgisinin Ölçülmesi
    Makine öğrenimi, strateji geliştirme için popüler bir yöntem haline gelmiştir. Karlılığı ve tahmin doğruluğunu en üst düzeye çıkarmaya daha fazla odaklanılırken, tahmin modelleri oluşturmak için kullanılan verilerin işlenmesinin önemine çok fazla dikkat edilmemiştir. Bu makalede, Timothy Masters'ın “Testing and Tuning Market Trading Systems” (piyasa alım-satım sistemlerinin test edilmesi ve ayarlanması) kitabında belgelendiği gibi, tahmin modeli oluşturmada kullanılacak göstergelerin uygunluğunu değerlendirmek için entropi kavramını kullanmayı ele alacağız.