Python ve MQL5'te bir robot geliştirme (Bölüm 1): Veri ön işleme
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:
-
NumPy: Çok boyutlu diziler ve matematiksel fonksiyonlarla çalışmak için kütüphane.
-
Pandas: Tablolar ve zaman serileri ile çalışmak için uygun veri yapıları sağlayan bir veri analiz aracı.
-
Random: Rastgele sayılar üretme ve sekanslardan rastgele öğeler seçme modülü.
-
Datetime: Tarihler ve saatlerle çalışmak için sınıflar ve fonksiyonlar sağlar.
-
MetaTrader5: MetaTrader 5 işlem terminali ile etkileşim için kütüphane.
-
Time: Zaman ve program yürütme gecikmeleri ile çalışmak için modül.
-
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.
-
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.
-
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:

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:

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.

Ş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:

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:

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:

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
Uyarı: Bu materyallerin tüm hakları MetaQuotes Ltd.'a aittir. Bu materyallerin tamamen veya kısmen kopyalanması veya yeniden yazdırılması yasaktır.
Bu makale sitenin bir kullanıcısı tarafından yazılmıştır ve kendi kişisel görüşlerini yansıtmaktadır. MetaQuotes Ltd, sunulan bilgilerin doğruluğundan veya açıklanan çözümlerin, stratejilerin veya tavsiyelerin kullanımından kaynaklanan herhangi bir sonuçtan sorumlu değildir.
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'da bir alım-satım robotu geliştirme (Bölüm 3): Model tabanlı bir alım-satım algoritmasının uygulanması
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz
raw_Prev_Day_Price_Changeraw_Prev_Week_Price_Changeraw_Prev_Week_Price_ChangeNası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?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 eksik. Stepan.
Yanıt için teşekkürler.
Evet, sorun gerçekten de Rus harfli yollardan kaynaklanıyordu. düzelttim ve her şey çalıştı.....
Yeni makale Python ve MQL5'te bir robotun geliştirilmesi (Bölüm 1): Veri ön işleme yayınlandı:
Yazar: Yevgeniy Koshtenko