Matrislerden Modellere: MQL5'te ML Veri Hattı Nasıl Oluşturulur ve ONNX'e Nasıl Dışa Aktarılır?
Giriş
Terminalde makine öğrenimini (ML) korkutucu kılan şey, modelin kendisinden çok etrafındaki her şeydir. Ayrı bir yığın, Python komut dosyaları ve karmaşık entegrasyon olmadan yapamayız gibi görünebilir. Sonuç olarak, ML'nin MetaTrader 5 bağlamında harici bir unsur olduğu hissine kapılıyoruz.
Ancak ekstra katmanları kaldırdığımızda, resim daha net hale geliyor. Herhangi bir ML veri hattı, bir dizi temel işlemden oluşur: özellikler oluşturma, bunları ölçeklendirme, fazlalıkları giderme ve sonucu modele iletme. Bu, sinir ağlarının sihri değil, sıradan doğrusal cebirdir.
Ve işte kilit nokta geliyor. Veri hazırlama bir MQL5 görevidir. Terminalde özellikler oluşturulur, normalleştirme yapılır ve gerekirse verilerin boyutluluğunu azaltmak ve ilişkili gürültüyü ortadan kaldırmak için PCA (Principal Component Analysis, temel bileşen analizi) uygulanır. Yani, modele giden tüm veri yolu, modelin kullanıldığı yerde yeniden oluşturulmalıdır. Bu olmadan sonuçların eşleştirilmesi mümkün değildir.
Bu kritiktir çünkü veri hattını kısmen aktarmaya yönelik herhangi bir girişim tutarlılığı bozar. Python'da veriler bir yöne giderken, terminalde başka bir yöne gider. Aradaki fark çok az olabilir, ancak model için burası zaten farklı bir alan. Sonuç olarak, sinyal kaybolmaz - ancak bozulur.
Bu noktada Python'ın rolü çok daha kolay ve doğru hale geliyor. Modeli eğitmek ve parametreleri hesaplamak için kullanılır - normalleştirme, PCA ve ağırlıkların kendileri. Sonrasında model, hesaplama grafiğini koruyan ve modelin kodu yeniden yazmadan aktarılmasını sağlayan bir format olan ONNX'e (Open Neural Network Exchange) dışa aktarılır.
Ardından her şey MQL5 tarafından belirlenir. ONNX modeli hesaplamaları gerçekleştirir ancak girdiyi kontrol etmez. Bu, eğitim sırasında kullanılan aynı veri yolunun terminalde yeniden oluşturulması gerektiği anlamına gelir.
İşte burada matrisler ön plana çıkıyor. Yerleşik matrix ve vector, tüm dönüşümleri matematikte tanımlandıkları gibi doğrudan tanımlamamıza olanak tanır. Normalleştirme, projeksiyon, girdi hazırlama - tüm bunlar ara bozulmalar olmadan bir doğrusal işlemler zinciri olarak gerçekleştirilir. Kod denklemleri yorumlamaz, onları tekrarlar.
İşte bu anda karmaşıklık hissi ortadan kalkıyor. ML, bir dizi farklı teknoloji gibi görünmeyi bırakır ve tamamen terminal içinde kontrol edilen bir dizi net adıma dönüşür.
Bu makalede, matrisleri ve vektörleri ana araç olarak kullanarak, gereksiz teoriye girmeden bu süreci adım adım ele alacağız. Odak noktası ana hedeftir: hem eğitimde hem de gerçek bir alım-satım ortamında tekrarlanabilir sonuçların nasıl elde edileceği.

Veri hattının temeli olarak matrisler: Özelliklerden veri uzayına
Piyasa verileri sürekli bir fiyat akışıdır. Ancak modelin kendisi doğrudan onunla çalışmaz. Önceden hazırlanmış bir dizi özelliğe ihtiyaç duyar: getiriler, aralıklar, sapmalar, gecikmeler. Ve burada hemen pratik bir soru ortaya çıkıyor: her özelliği ayrı ayrı tutmak mı yoksa tek bir yapıda toplamak mı? Pratikte, ikinci yolun çok daha istikrarlı olduğu ortaya çıkmaktadır.
Bu nedenle, özellikleri, satırları gözlemlere, sütunları ise özelliklere karşılık gelen X matrisine indirgemek uygundur. Bu noktadan itibaren veriler, tek tek değerlerin dağınık bir kümesi olmaktan çıkar. Veriler, sıralı işleme için tek bir nesne haline gelir. Yerleşik MQL5 matris işlemleri, dönüşümlerin tek tek değerler yerine bir kerede tüm veri uzayı üzerinde gerçekleştirilmesine olanak tanır. Bu sadece kodu değil, aynı zamanda işleme mantığını da değiştirir.
Bu özellikle normalleştirme için önemlidir. Piyasa özellikleri neredeyse her zaman farklı ölçeklerde mevcuttur: fiyat, aralık, getiri, sapma, hacim. Bunlar karşılaştırılabilir bir biçime getirilmezse, model sinyal yapısına değil sayıların büyüklüğüne yanıt vermeye başlayacaktır. Bu nedenle, veri hazırlamada zorunlu bir adım olarak normalleştirme gereklidir. Ve bunu MQL5 tarafında yönetmek daha uygundur. Burada yerleşik matrix ve vector, piyasa serilerini hemen elde etmemize ve ardından Mean ve Std gibi istatistiksel işlemleri doğrudan hazırlanan matrise uygulamamıza olanak tanır.
matrix<double> vRates; if(!vRates.CopyRates(cSymbol.Name(), PERIOD_CURRENT, COPY_RATES_OHLC | COPY_RATES_VERTICAL, 1, HistoryBars)) { PrintFormat("Error of load rates %d", GetLastError()); return; } matrix<double> means=matrix<double>::Zeros(vRates.Rows(),vRates.Cols()); matrix<double> STDs=matrix<double>::Zeros(vRates.Rows(),vRates.Cols()); means.Row(vRates.Mean(0),0); STDs.Row(vRates.Std(0)+DBL_EPSILON,0); means=means.CumSum(0); STDs=STDs.CumSum(0); vRates=(vRates-means)/STDs;
İlk bakışta normalleştirmenin ONNX modeli içinde gizlenmesi daha kolay gibi görünebilir. Ancak bu çözümün de sınırları vardır. MQL5'te ONNX esas olarak bir yürütme katmanı olarak tasarlanmıştır. Model OnnxCreate aracılığıyla yüklenir. Daha sonra girdi ve çıktı şekilleri belirlenir. Ardından OnnxRun aracılığıyla başlatılır. Bu çıkarım için harikadır, ancak girdi uzayını yönetmek için aynı kolaylığı ve şeffaflığı sağlamaz. Normalleştirme MQL5'te ayarlandığında, doğrudan sınayıcıda veya grafikte test etmek, tekrarlamak, değiştirmek ve gerçek piyasa verileriyle karşılaştırmak daha kolaydır.
Önemli bir nokta daha var. Sembolü veya zaman dilimini değiştirdiğimizde, veri dağılımı değişir. Normalleştirme ONNX grafiğine gömülürse, modelin eski girdi dağılımına katı bir şekilde bağlı olduğu ortaya çıkar. Bu durumda, ortamdaki herhangi bir önemli değişiklik sadece hedeflenen ayarlamaları değil, tam bir yeniden eğitim ve yeniden dışa aktarma gerektirir. Normalleştirme MQL5'te ayarlanırsa, parametrelerini güncellemek ve modeli gerekli ölçekteki verilerle beslemek yeterlidir. Bu, girdi yapısını korur ve tüm modeli tamamen yeniden oluşturmadan çalışmamızı sağlar.
Bu nedenle terminaldeki harici matris katmanı, her şeyi ONNX içinde tamamlamaya çalışmaktan daha fazla esneklik sağlar. Python'da model bir kez eğitilir. MQL5'te veriler her seferinde tutarlı bir şekilde dönüştürülür. Bu, mimarinin gücüdür: model bir model olarak kalır ve terminaldeki matrisler ve vektörler girdiyi hazırlama ve kontrol etme işini üstlenir.
Sıkıştırma ve stabilizasyon: Matris mantığının bir uzantısı olarak PCA
Piyasa göstergeleri neredeyse hiçbir zaman bağımsız değildir. Fiyat, getiriler, aralık, sapmalar - tüm bunlar aynı hareketin farklı projeksiyonlarıdır. Sonuç olarak, verilerde fazlalık ortaya çıkar: birkaç özellik aynı piyasa davranışını yalnızca farklı açılardan tanımlar. Model için bu bir sinyal iyileştirmesi değil, bir gürültü ve istikrarsızlık kaynağıdır.
İşte bu noktada PCA (Principal Component Analysis, temel bileşen analizi) matris yaklaşımının doğal bir devamı haline gelmektedir. Kullanımının arkasındaki fikir basittir: modele her şeyi tek seferde beslemeye çalışmamak, bunun yerine bilgileri verilerdeki varyansın çoğunu yakalayan daha kompakt bileşenler halinde toplamak.
Matematiksel açıdan bakıldığında yeni bir şey görünmüyor. Bu aynı doğrusal cebirdir. X özellik matrisi ortalanır ve özvektörler matrisi ile çarpılır. Sonuç, özelliklerin piyasa değişiminin bağımsız bileşenlerini temsil ettiği yeni bir alandır.
Burada önemli olan nokta denklem değil, etkidir. PCA iki sorunu aynı anda çözer. Bir yandan, gereksiz boyutları kaldırarak özellik uzayını sıkıştırır. Öte yandan, gürültü ve korelasyonlar artık sinyali bir dizi değişken arasında dağıtmadığı için verileri stabilize eder. Model daha temiz bir veri yapısıyla çalışmaya başlar.
Pratik sonuç hemen hissedilir. Eğitim daha sağlam hale gelir, model davranışı daha öngörülebilir olur ve küçük ve rastgele dalgalanmalara karşı duyarlılık azalır. Üstelik kod hiç de daha karmaşık hale gelmez. Değişen tek şey, önceden hazırlanmış X üzerinde başka bir matris işlemidir.
Ve burada daha önce olduğu gibi aynı mimari mantığı sürdürmek önemlidir. PCA ayrı hesaplamalarda ve döngülerde ayarlanmamıştır. MQL5'te tek bir matris devresinin parçası olarak kalır.
Sonuç olarak, veriler sadece tek bir ölçeğe getirilmekle kalmaz, aynı zamanda yapısal olarak basitleştirilir. Fazlalıkları kaybeder ancak bilgi özünü korur. Bu, alım-satım bağlamında PCA'nın temel etkisidir: model daha az gürültü ama daha fazla anlam kazanır.
Veri hattının bir sonraki seviyesi bu şekilde oluşur. Verileri normalleştirdikten sonra yapısını düzenliyoruz. Ve bu alan ne kadar temiz olursa, model o kadar istikrarlı davranır.
Model ve ONNX: Eğitimden yürütmeye
Veri uzayı temizlendikten ve kararlı bir forma getirildikten sonra, veri hattı mantığı doğal olarak bir sonraki adıma, yani modelin kendisine geçer. Ancak ilkeyi hemen belirlemek önemlidir: buradaki model sistemin merkezi değil, nihai ifadesidir.
Eğitim terminal dışında, Python'da gerçekleşir. Bu rastgele bir seçim değil, bir kolaylık ve ekosistem meselesidir. Model eğitimi birbirinden net bir şekilde ayrılmış iki aşamadan oluşur ve tüm sistemin istikrarını belirleyen de budur.
İlk aşamada, eğitim setinin tüm hacmi kullanılır. Burada modelin kendisi henüz inşa edilmemekte, daha ziyade koordinat sistemi oluşturulmaktadır. Normalleştirme parametreleri hesaplanır: her özellik için ortalama değerler ve standart sapmalar. PCA paralel olarak hesaplanır. Orijinal özellik uzayının daha kompakt ve sıralı bir temsile dönüştürülmesini belirtir.
# Standardize features and apply PCA to retain 99% variance scaler = StandardScaler() X_scaled = scaler.fit_transform(X) pca = PCA(n_components=NComponents, random_state=42) X_pca = pca.fit_transform(X_scaled)
Veri hazırlama aşaması kritik öneme sahiptir. Esasen, modelin çalışacağı uzay burada sabitlenir. Bu seviyedeki herhangi bir sapma otomatik olarak ileriye taşınır. Bu nedenle, sistemin sonraki tüm kararlılığını belirler.
Veri uzayı sabitlendikten sonra ikinci aşamaya geçiş gerçekleşir. Model çok özel bir mekanizma olarak bir araya getirilir. Bu noktada, özellikler normalize edilmiş ve PCA'dan geçmiştir, böylece piyasanın tutarlı, yoğun bir temsili ağa beslenir. Şu önemli bir noktadır: LSTM, başlangıç değerlerinin kaosunu çözmek zorunda değildir. Kendisi için hazırlanan uzayla hemen çalışmaya başlar.
İlk olarak, veriler PyTorch için uygun bir formata dönüştürülür.
# --- LSTM training block with PyTorch --- # Prepare data for LSTM: form rolling sequence windows X_np = X_pca.astype(np.float32) y_np = y.to_numpy(dtype=float) n_sequences = X_np.shape[0] if n_sequences <= 0: print("Not enough samples for sequence windows; reduce window_size or collect more data.") quit() X_tensor = torch.tensor(X_np, dtype=torch.float32).unsqueeze(1) # (n_samples, 1, n_features) y_tensor = torch.tensor(y_np.reshape(-1, 1), dtype=torch.float32)
Bu aşamada akıllıca bir şey gerçekleşmez ancak bundan sonraki tüm çalışmaların teknik doğruluğunun temeli burada atılır. Dizi bir tensöre dönüştürülür ve ona fazladan bir boyut eklenir. Bu küçük bir ayrıntıdır, ancak LSTM için temeldir: ağ sadece bir özellik kümesi değil, bir sekans beklemektedir. Sekans uzunluğu bir olsa bile, girdi şeklinin kendisi tekrarlayan bir ağın mimarisine karşılık gelir.
Sonrasında veriler eğitim ve doğrulama bölümlerine ayrılır. Burada sıradan gibi görünen bir adım önemli bir rol oynamaktadır: model sadece geçmişi hatırlamakla kalmaz, aynı zamanda veri setinin ayrılmış bir kısmı üzerinde kendini test etme fırsatı bulur. Bir formasyon bulmayı öğrenip öğrenmediğini ya da sadece gürültüyü tekrarlayıp tekrarlamadığını bu şekilde anlayabilirsiniz.
# Train/validation split split = int(Train_test_split * len(X_tensor)) train_ds = TensorDataset(X_tensor[:split], y_tensor[:split]) val_ds = TensorDataset(X_tensor[split:], y_tensor[split:]) train_loader = DataLoader(train_ds, batch_size=Batch_size, shuffle=False) val_loader = DataLoader(val_ds, batch_size=Batch_size, shuffle=False)
Veriler daha sonra DataLoader'a beslenir. Ve burada süreç bir çalışma ritmi kazanır. Ağı her seferinde bir örnekle beslemek yerine, bunları gruplar halinde sunuyoruz. Bu, eğitimi daha istikrarlı hale getirir ve optimize etmeyi önemli ölçüde kolaylaştırır.
Ardından, modelin kendisi inşa edilir. Burada önemli olan, gereksiz karmaşıklıkla aşırı yüklememektir. Kodda, bu düzgün, kompakt bir mimaridir: birkaç tekrarlayan katman, sabit büyüklükte bir gizli durum, aşırı uyumu azaltmak için Dropout ve ağın iç durumunu tek bir tahmin sayısına dönüştüren son bir doğrusal katman.
class LSTMRegressor(nn.Module): def __init__(self, input_size, hidden_size=64, num_layers=3, dropout=0.1): super().__init__() self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, batch_first=True, dropout=dropout) self.fc = nn.Linear(hidden_size, 1) def forward(self, x): # x: (batch, seq_len, input_size) out, (hn, cn) = self.lstm(x) last_h = hn[-1] return self.fc(last_h) device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(f"Using device: {device}") model = LSTMRegressor(input_size=X_np.shape[1], hidden_size=64, num_layers=Layers, dropout=0.2).to(device)
Mantık basit ama çok etkili: ağ önce anlamı topluyor ve sonra cevabı formüle ediyor.
Model kullanılabilir bir cihaza aktarılır. GPU varsa, hesaplamalar oraya gider. Aksi takdirde, her şey CPU üzerinde çalışır. Finansal veriler için bu bir lüks değil, normal bir mühendislik uygulamasıdır: sıralı hesaplamalar ve büyük veri setleri hızla ağırlaşır ve hızlanma burada gerçekten önemlidir.
Devamında, Adam optimize edici ve MSELoss kayıp fonksiyonu.
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.MSELoss() Gerçek eğitim ancak bu aşamada başlar. Bu noktaya kadar sadece sahneyi dikkatlice inşa ettik: verileri hazırladık, girdi şeklini tanımladık, mimariyi bir araya getirdik ve ağırlık güncelleme mekanizmasını yapılandırdık.
for epoch in range(1, Epochs + 1): model.train() train_loss = 0.0 for xb, yb in train_loader: xb, yb = xb.to(device), yb.to(device) optimizer.zero_grad() preds = model(xb) loss = criterion(preds, yb) loss.backward() optimizer.step() train_loss += loss.item() * xb.size(0) train_loss /= len(train_loader.dataset) model.eval() val_loss = 0.0 with torch.no_grad(): for xb, yb in val_loader: xb, yb = xb.to(device), yb.to(device) preds = model(xb) loss = criterion(preds, yb) val_loss += loss.item() * xb.size(0) val_loss /= len(val_loader.dataset) if len(val_loader.dataset) > 0 else float('nan') print(f"Epoch {epoch}/{Epochs} — train_loss: {train_loss:.6f} val_loss: {val_loss:.6f}")
Veri hattının gücü adımlar zincirinde yatmaktadır: veri hazırlama → model oluşturma → eğitim. Bu sıralama, giriş eşleşmesi kaybı olmadan ONNX aracılığıyla MQL5'e aktarımı kolaylaştırır.
Eğitim sırasında, sistemin davranışsal kısmı oluşturulur - model ağırlıkları, analiz edilen verilere tepkisi ve tahmin yapısı. Ancak şunu anlamak önemlidir: model ham veriler üzerinde değil, halihazırda sağlanmış ve sıkıştırılmış temsil üzerinde eğitilir.
Sonuç, karıştırılamayan iki bloktur. Bunlardan ilki istatistiksel temeldir: normalleştirme ve PCA. İkincisi, bu uzayda eğitilen modelin kendisidir. Birlikte tek bir veri akışı hattı oluştururlar.
Eğitimden sonra model ONNX'e dışa aktarılır. Format, hesaplama grafiğini yakalar ve modeli taşınabilir hale getirir.
# Try exporting to ONNX try: onnx_path = os.path.join(data_path, 'MQL5', 'Files', 'lstm3.onnx') dummy_input = torch.randn(1, 1, X_np.shape[1], device=device) model.eval() torch.onnx.export( model, dummy_input, onnx_path, input_names=['PCA_features'], output_names=['Forecast'], opset_version=18, dynamo=True, external_data=False, verify=True ) print(f"Exported model to ONNX: {onnx_path}") except Exception as e: print("ONNX export failed:", e)
ONNX, mimaride bir hesaplama deposu olarak kalır. Modeli, OnnxCreate ve OnnxRun aracılığıyla MQL5'te yürütülmeye hazır sabit bir fonksiyon olarak depolar. Ancak tüm veri hazırlama mantığı ONNX'in dışında kalır ve terminalde matrisler ve vektörler aracılığıyla katı bir şekilde tekrarlanır.
Bu nedenle Python bu yapıda son derece sınırlı bir rol oynamaktadır. Modeli eğitmek ve parametrelerini sabitlemek için bir kez gereklidir. Dışa aktarımdan sonra, artık karar alma sürecine dahil değildir. Diğer tüm çalışmalar terminale aktarılır.
Bu şekilde net bir rol dağılımı oluşur. Python modeli oluşturmaktan sorumludur. ONNX bunu bir hesaplama nesnesi olarak yakalar. MQL5, girdi veri hattının ve çıkarım yürütmesinin yeniden oluşturulmasını sağlar. Ve bu rol dağılımı ne kadar doğru uygulanırsa, sistem gerçek bir alım-satım ortamında o kadar istikrarlı davranır.
MQL5'te yürütme ve veri kontrolü
Model ONNX'e dışa aktarıldıktan sonra çalışma terminale aktarılır. Ve burada matrislerin ve vektörlerin neden en başından beri tüm mimarinin temel unsurları olduğu özellikle açıktır. Bu yapıda MQL5, modelin eğitildiği tüm veri hazırlama yolunu yeniden oluşturur.
Ve burada hemen iki farklı modu birbirinden ayırt etmeliyiz. Bunlardan ilki, Uzman Danışman başlatıldığında bir kez gerçekleştirilen başlatma işlemidir. İkincisi, her yeni çubukta tekrarlanan bir çalışma zamanı döngüsüdür. Bu ayrım çok önemlidir. Hesaplamayı istikrarlı hale getirir. Yapılabilecek her şey önceden hazırlanmalıdır. Çubuk başına döngüde yalnızca canlı piyasa mantığı kalmalıdır.
Başlatma aşamasında, MQL5 modelin dayandırılacağı tüm altyapıyı hazırlar. Normalleştirme parametreleri, PCA uzay merkezi ve bileşen matrisi ilk olarak yüklenir.
if(!LoadBinaryParams(sFileName, vMeans, vScales, vPCAmeans, mPCAcomponents, vEvr, iNFeatures, iNComponents)) { PrintFormat("Error of load PCA params: %d", GetLastError()); return INIT_FAILED; } PrintFormat("Loaded PCA params: features=%d components=%d", iNFeatures, iNComponents);
Burada önemli bir ayrıntıya dikkat etmekte fayda var. Normalleştirme parametreleri vektörlere yüklenirken, PCA bileşenleri matrise yüklenir. Bu doğal görünüyor, ancak aslında veri hazırlama yapısını iyi bir şekilde ortaya koyuyor.
Ortalamalar ve standart sapmalar tek değişkenli istatistiklerdir. Her özelliğin kendi ortalaması ve sapması vardır. Bu nedenle vektörler olarak temsil edilirler. Böyle bir vektörün her bir elemanı, girdi uzayının ayrı bir özelliğine karşılık gelir. Mantık doğrusal ve şeffaftır.
PCA ile durum farklıdır. Burada tek tek oranlardan değil, tüm özellik uzayının dönüşümünden bahsediyoruz. Bileşenlerin matrise yüklenmesinin nedeni budur. Ve bu artık sadece bir veri deposu değildir. Matris, orijinal özellik uzayından yeni, sıkıştırılmış bileşen uzayına geçiş kuralını tanımlar. Buradaki her satır, PCA dönüşümünden sonra yeni eksenin yönünü açıklamaktadır. Aslında terminal, Python'da eğitim seti üzerine inşa edilmiş hazır bir uzay geometrisi alır.
Bu, tüm mimariyi anlamak için çok önemli bir noktadır. Vektörler, tek tek özellikler üzerindeki yerel işlemlerden (merkezleme ve ölçekleme) sorumludur. Matris, tüm veri uzayının toplu olarak dönüşümünden sorumludur. MQL5'teki yerleşik matrix ve vector, bu matematiksel yapıyı doğrudan koda mükemmel bir şekilde yansıtır.
Daha sonra ONNX modeli yüklenir, girdi ve çıktı boyutları belirtilir.
//--- load models hONNX = OnnxCreateFromBuffer(model, ONNX_DEFAULT); if(hONNX == INVALID_HANDLE) { Print("OnnxCreateFromBuffer error ", GetLastError()); return INIT_FAILED; } const ulong input_state[] = {1, 1, iNComponents}; if(!OnnxSetInputShape(hONNX, 0, input_state)) { PrintFormat("OnnxSetInputShape error: %d ", GetLastError()); OnnxRelease(hONNX); return INIT_FAILED; } const ulong output_forecast[] = {1, vForecast.Size()}; if(!OnnxSetOutputShape(hONNX, 0, output_forecast)) { Print("OnnxSetOutputShape error ", GetLastError()); OnnxRelease(hONNX); return INIT_FAILED; }
İşte burada çok önemli bir mimari nokta devreye giriyor. Modelin girdi büyüklüğü artık orijinal özelliklerin sayısına eşit değildir. PCA bileşenlerinin sayısına, zaten sıkıştırılmış veri uzayının boyutlarına eşittir.
Bu, modelin tam bir başlangıç göstergeleri ve türetilmiş değerler setiyle değil, PCA'dan sonra kompakt temsilleriyle çalıştığı anlamına gelir. Gürültü ve aşırı korelasyonlar orijinal uzayda kalırken, ONNX daha istikrarlı ve konsantre bir sinyal alır.
Pratikte, bu aynı anda birkaç etki yaratır. Azaltılmış girdi tensörü büyüklüğü. Düşük hesaplama yükü. Basitleştirilmiş model görevi. Ancak asıl önemli olan, girdi uzayının daha kararlı hale gelmesidir. Ağ, karşılıklı olarak yinelenen özellikleri işlemek için kaynak israfını durdurur ve piyasa yapısının daha yoğun bir temsiliyle çalışmaya başlar.
Bu nedenle PCA burada sadece boyutluluğu azaltmanın bir yolu değildir. Ham piyasa verileri ile model arasında bir ara katman haline gelir. MQL5 matrisleri bu katmanı doğrudan terminalin içinde Python'da var olduğu şekliyle yeniden oluşturmamıza olanak tanır.
Ardından göstergeler bağlanır ve çalışma arabellekleri hazırlanır.
//--- Indicators if(!ciSMA.Create(Symb.Name(), TimeFrame, 12, 0, MODE_SMA, PRICE_CLOSE)) { Print("SMA create error ", GetLastError()); OnnxRelease(hONNX); return INIT_FAILED; } ciSMA.BufferResize(2); for(uint i = 0; i < ciMACD.Size(); i++) { if(!ciMACD[i].Create(Symb.Name(), TimeFrame, int(mMACDset[i, 0]), int(mMACDset[i, 1]), int(mMACDset[i, 2]), PRICE_CLOSE)) { PrintFormat("MACD %d create error %d", i, GetLastError()); OnnxRelease(hONNX); return INIT_FAILED; } ciMACD[i].BufferResize(4); }
Bu sadece teknik bir formalite değildir. Bu, terminalin, modelin Python'da eğitildiği aynı istatistiksel temeli aldığı andır. Başka bir deyişle, MQL5, model tarafından üretilen tahminin anlamlı olduğu ortamı yeniden yapılandırır.
Bu durum özellikle veri hazırlama parametreleri yüklenirken ortaya çıkmaktadır. Bunlar yeniden hesaplanmaz veya seçilmez. Terminale çoktan hazırlanmış olarak varırlar. Bu, matris yaklaşımının güçlü yönüdür. Veri hazırlama parametreleri bir kez yüklenir ve hesaplama yapısında sabitlenir; yeniden hesaplanmazlar. Sonuç olarak, terminal belirli bir veri uzayına bağlı bir modelle çalışmaya başlar.
Sonrasında çalışma döngüsü başlar. Artık tamamen farklı bir türde. Her yeni çubukta, Uzman Danışman yeni piyasa verilerini toplar.
ciSMA.Refresh(); for(uint i = 0; i < ciMACD.Size(); i++) ciMACD[i].Refresh(); if(!vRates.CopyRates(Symb.Name(), TimeFrame, COPY_RATES_CLOSE, 1, 12)) { Print("CopyRates error ", GetLastError()); return; }
Özellik vektörü oluşturulur...
vInputs[0] = vRates[11] - vRates[10]; vInputs[1] = (vRates[11] - vRates[0]) / 11; vInputs[2] = vInputs[1] - vInputs[0]; vInputs[3] = float(ciSMA.Main(1)); for(uint i = 0; i < ciMACD.Size(); i++) { vInputs[4 + i * 6] = float(ciMACD[i].Main(1)); vInputs[5 + i * 6] = float(ciMACD[i].Main(1) - ciMACD[i].Main(2)); vInputs[6 + i * 6] = float(ciMACD[i].Signal(1)); vInputs[7 + i * 6] = float(ciMACD[i].Signal(1) - ciMACD[i].Signal(2)); vInputs[8 + i * 6] = vInputs[6 + i * 6] - vInputs[4 + i * 6]; vInputs[9 + i * 6] = vInputs[7 + i * 6] - vInputs[5 + i * 6]; }
...ve eğitim sırasında kullanılan aynı dönüşümlerden geçirilir. Önce normalleştirme, ardından PCA projeksiyonu gelir.
bool TransformPCA(const vector<float> &data, const vector<float> &scaler_mean, const vector<float> &scaler_scale, const vector<float> &pca_mean, const matrix<float> &pca_components, vector<float> &out) { ulong n = data.Size(); if(n == 0) return false; //--- vector<float> centered = (data - scaler_mean) / scaler_scale - pca_mean; //--- projection: out = pca_components * centered (matrix * vertical vector) out = pca_components.MatMul(centered); return true; }
MQL5 yerleşik matematiğinin avantajı burada özellikle belirgindir. Kod pratikte matematiksel gösterimin kendisini tekrarlar. Terminal, modeli eğitmek için kullanılan aynı işlemleri yeniden gerçekleştirir.
Ancak bundan sonra hazırlanan vektör ONNX'e iletilir.
//--- ONNX if(!OnnxRun(hONNX, ONNX_LOGLEVEL_INFO, vCompressed, vForecast)) { PrintFormat("OnnxRun error: %d ", GetLastError()); return; }
Burada artık ağır hazırlıklara veya yeniden başlatmaya yer yoktur. Her şey bir taşıma bandı gibi çalışır. Yeni çubuk - yeni girdi. Ancak bu girişin güzergahı değişmemiştir.
MQL5 yerleşik matrislerinin ve vektörlerinin pratik değeri burada ortaya çıkmaktadır. Tüm veri yapısını bir kez bir araya getirmemize ve ardından gereksiz uğraşlara girmeden ve tutarlılık kaybı olmadan gerektiği kadar yeniden oluşturmamıza olanak tanırlar. Başlatma çerçeveyi ayarlar. Çalışma döngüsü basitçe onu kullanır. Bu, sistemi sadece kompakt değil, aynı zamanda disiplinli hale getirir. Terminaldeki makine öğrenimi için disiplin, gösterişli sözlerden daha önemlidir. Çünkü modeli gerçekten çalışabileceği aynı alanda tutan şey disiplindir.
Sonucun test edilmesi: Modelden alım-satım davranışına
Model Python'da eğitilirken, hesaplama veri hattı MQL5'te dikkatlice yeniden oluşturulur. Normalleştirme ve PCA, matrisler ve vektörler aracılığıyla çalışır. ONNX modeli terminale yüklenir. Tüm unsurlar tek bir sisteme bağlanır. Şimdi asıl soru basit: bu sistem piyasada nasıl davranacak?
MetaTrader 5 strateji sınayıcının devreye girdiği yer burasıdır. Sadece modelin çalıştığını değil, aynı zamanda veri hazırlamadan alım-satım kararına kadar tüm ML veri hattının ne kadar istikrarlı olduğunu da gösterir. Bu, tüm mimarinin canlı piyasa dinamikleri üzerinde tam teşekküllü bir testidir.
Bu, platformun en güçlü yönlerinden biridir. Python'da eğitim seti üzerinde iyi kayıp fonksiyonu değerleri veya yüksek doğruluk elde etmek kolaydır. Ancak piyasa bu tür sonuçların gücünü hızla test eder. MetaTrader 5 sınayıcısı bu anı hemen görmemizi sağlar. MetaTrader 5 tarafından sağlanan ölçütlerin kombinasyonu önemlidir. Sınayıcının gerçek değerini gösterdiği yer burasıdır. Stratejiye kendi davranışı, riski, istikrarı ve iç yapısı olan canlı bir sistem olarak bakmamızı sağlar.

- Geçmiş Kalitesi önemli bir başlangıç noktasıdır.
Test koşulları, çalışmanın doğruluğu hakkındaki tüm şüpheleri ortadan kaldırır. Sonuçlar teknik olarak güvenilir kabul edilebilir, bu da ölçüt analizinin anlamlı olduğu anlamına gelir. - Finansal sonuç (Toplam Net Kar), 1000.00 USD başlangıç bakiyesi ile 373.80 USD olarak gerçekleşti.
Bu, stratejinin testi pozitif sonuçlarla tamamladığı anlamına gelir. Ancak, bu ölçüt tek başına mantık kalitesi hakkında bir şey söylemez, bu nedenle diğer ölçütlerle birlikte değerlendirilmelidir. - Brüt Kar 612.94 USD olarak gerçekleşirken, Brüt Zarar -239.14 USD oldu.
Bu, karlı işlemlerin zararla kapanan işlemlerden önemli ölçüde daha fazla olduğu ve pozitif sonuca yol açtığı anlamına gelir. Strateji, pozitif sonuçların istikrarlı bir şekilde baskın olmasından kazanç sağlamaktadır. - Kar Faktörü 2.56'ya eşittir.
Bu güçlü bir ölçüttür. Kar, zararın iki buçuk katından daha fazladır. Bir alım-satım sistemi için bu, pozitif işlemlerin negatif işlemlerden daha fazla olduğunun bir işaretidir. - Beklenen Getiri 7.19 oldu.
Bu da ortalama olarak her bir işlemin pozitif matematiksel katkı sağladığı anlamına gelmektedir. Sistem, bir ya da iki başarılı seriye dayanarak işleyişini sürdürmez; bunun yerine işlem düzeyinde pozitif bir beklenti sürdürür. - 1.58 değerindeki Düzelme Faktörü, elde edilen sonucun yaşanan düşüşü ne ölçüde telafi ettiğini göstermektedir.
Bu durumda, güvenlik marjının çok büyük olduğu söylenemese de sistem kayıpları telafi edebilmektedir. Strateji işe yarıyor, ancak düşüşler hafife alınmamalıdır. - Sharpe Oranı 15.38'e ulaştı.
Bu, getirinin sonuç oynaklığına oranının yüksek olduğunu gösteren çok güçlü bir değerdir. Ancak burada şunu unutmamak gerekir ki, sınayıcıda bu gösterge, düşüşler ve işlemlerin seriliği ile birlikte değerlendirilmelidir. - AHPR 1.0065, yani %0.65 olarak gerçekleşti. GHPR 1.0061, yani %0.61 olarak gerçekleşti.
Bu ölçütler bir işlemin ortalama karlılığını aritmetik ve geometrik olarak gösterir. Buradan çıkan sonuç açıktır: büyüme vardır ve bu büyüme işlem akışının yapısında yer almaktadır. - Mutlak Bakiye Düşüşü 55.57 USD, Maksimum Bakiye Düşüşü 84.62 USD olarak gerçekleşti ve bu da %6.46'ya karşılık gelmektedir (Göreceli Bakiye Düşüşü).
Bu da stratejinin nispeten dengeli kaldığı anlamına gelmektedir. Kapanan işlemler kabul edilebilir bir bakiye eğrisi oluşturmuştur. - Varlık Düşüşü tamamen farklı bir resim göstermektedir. Mutlak düşüş 99.08 USD, maksimum düşüş ise 235.84 USD olup %17.12'ye karşılık gelmektedir.
Bu önemli bir noktadır: nihai bakiye makul görünse bile açık pozisyonlar piyasa riski yaratmıştır. Buradaki sonuç dürüsttür: strateji para kazanabilir, ancak bunu iç gerilim olmadan yapamaz. - Teminat Seviyesi %125.35 olarak gerçekleşti.
Bu güvenli bir seviyedir, ancak önemli bir marj yoktur. Teminat rezervinin yeterli olduğunu göstermektedir. Ancak sistem steril koşullar altında çalışmamıştır. Alım-satım mantığı, hesap üzerinde kritik bir baskı olmaksızın çalışma aralığı içinde kalmıştır. - Z-Skoru %51.61 anlamlılık düzeyinde -0.70 oldu.
Bu, net bir şekilde tanımlanabilen olağandışı bir kazanç ve kayıp serisinin olmadığını gösterir. Başka bir deyişle, sonuçlar rastgele bir şans eseri gibi görünmüyor. İşlemlerin dizilimi, rastgele gürültüden ziyade çalışan bir alım-satım yapısına daha yakındır. - LR Korelasyonu 0.90, LR Standart Hatası ise 64.55'tir.
Korelasyon, varlık eğrisinde oldukça yumuşak bir doğrusal trend olduğunu belirtmektedir. Standart hata, hareketin tamamen yumuşak olmadığını ifade etmektedir. Büyüme var, ancak bu normal piyasa dalgalanmalarıyla oluşmuştur. - Toplamda 52 pozisyon (Toplam İşlem) açıldı ve 95 deal (Toplam Deal) gerçekleşti.
Bu stratejinin doğasını görmek için yeterli bir hacimdir. Test, birkaç rastgele girdi ile sınırlı kalmamakta, aksine oldukça anlamlı bir resim sunmaktadır. - Satış İşlemleri %68.42 oranında karlı 19 işlem içerirken, Alış İşlemleri %39.39 oranında karlı 33 işlemden oluşmaktadır.
İşlemlerin yönünde ilginç bir tutarsızlık vardır. Bu çok önemli bir sinyaldir. Strateji, satış işlemlerini alış işlemlerinden belirgin şekilde daha iyi yönetiyor. Bu, aşağı yönlü hareketlere karşı önemli bir yanlılığa sahip olabileceği anlamına gelir. - Karla Kapanan İşlemler ve Zararla Kapanan İşlemler aynı oldu - her biri 26 işlem, yani her biri %50.00.
İlk bakışta bu bir denge durumu gibi görünse de, sistemin karlılığını sürdürmesine engel teşkil etmez. Strateji, işlemlerin kalitesi sayesinde para kazanır. - Maksimum Kar 171.36 USD, Maksimum Zarar ise -31.46 USD oldu.
Ortalama Kar 23.57 USD, Ortalama Zarar ise -9.20 USD'dir. Bunlar belki de rapordaki en önemli ölçütlerden bazılarıdır. Ortalama kar, ortalama zararın iki katından daha fazladır. Sistem, başarılı girişlerin idealden daha az olduğu durumlarda bile üstünlüğünü koruyabilmektedir. - Maksimum Ardışık Kazanç 139.90 USD tutarında 5 işlem içerirken, Maksimum Ardışık Kayıp -61.24 USD tutarında 6 işlemden oluşmaktadır.
Bu, stratejinin iyi seriler yakalayabildiğini, ancak kayıp serilerine karşı savunmasız olmadığını göstermektedir.
Her bir ölçüt, strateji mekaniğinin farklı bir yönünü temsil eder. Platformun ana avantajı budur: sadece sonucu değil, aynı zamanda yapısını da görmemizi sağlar.
Sonuç
Alım-satımda makine öğrenimi genellikle karmaşık ve aşırı yüklü bir konu gibi görünür. Ancak uygulamada durum farklıdır. MetaTrader 5, tam teşekküllü bir ML veri hattı oluşturmak için gereken araçların çoğunu içerir. Makalenin temel amacı da tam olarak buydu. Sihirli bir model göstermek ve piyasayı tahmin etmek için başka bir girişimde bulunmak yerine, yolun kendisini analiz ediyor: sıradan piyasa verilerinden terminal içinde çalışan bir ONNX modeline. Yerleşik MQL5 matrislerinin ve vektörlerinin burada kilit bir rol oynaması özellikle önemlidir. Veri hazırlamayı bir dizi farklı işlemden net ve yönetilebilir bir hesaplama yapısına dönüştürürler.
Normalleştirme, istatistiksel hesaplama, özellik uzayı ile çalışma, PCA dönüşümü - tüm bunlar doğrudan terminalin içinde matematiksel olarak tanımlandığı hemen hemen aynı biçimde yeniden oluşturulur. Kod, teknik ayrıntılarla aşırı yüklü olmaktan çıkar ve hesaplamaların mantığını yansıtmaya başlar. Bu, bir yatırımcı için makine öğrenimi geliştirmeye giriş eşiğini önemli ölçüde düşürür.
ONNX için destek de önemlidir. MetaTrader 5, modelin hazır bir hesaplama bloğu olarak kullanılmasına olanak tanır. Python, modeli hazırlamak için bir araç olarak kalır, terminal ise modelin istikrarlı bir şekilde yürütülmesi ve kontrol edilmesi için bir ortam haline gelir. Bu ayrım, mimariyi çok daha temiz ve pratik hale getirir. Model bir kez eğitilir ve daha sonraki çalışmalar MQL5'e aktarılır. Bu da şeffaflık, tekrarlanabilirlik ve girdi verileri üzerinde tam kontrol sağlar.
MetaTrader 5 strateji sınayıcı özellikle değerlidir. Sadece nihai karı değil, aynı zamanda tüm sistemin iç davranışını da değerlendirmemizi sağlar. Düşüş, varlık istikrarı, işlem yapısı, kayıplardan kurtulma kalitesi, işlem ritminin istikrarı - tüm bunlar zengin bir dizi yerleşik ölçüt aracılığıyla ölçülebilir hale gelir. Bu ölçütlerin her birinin arkasında stratejinin davranışının ayrı bir yönü yatmaktadır. Test sürecini biçimsel bir kontrolden tam teşekküllü bir mühendislik analizine dönüştüren de bu yaklaşımdır.
Sonuç olarak MetaTrader 5, mantığı harici altyapıya aktarmadan ML veri hatlarının inşa edilmesi ve yeniden oluşturulması için kullanılabilir. Ana sonuç: MetaTrader 5'te makine öğrenimi, doğrusal matematik, matrisler ve şeffaf veri hazırlama yoluyla, makine öğreniminin terminalden ayrı bir yerde var olduğu hissi olmadan uygulanır.
Makalede kullanılan programlar
| # | Ad | Tür | Açıklama |
|---|---|---|---|
| 1 | create_pca_lstm.py | Komut dosyası | Modeli oluşturmak ve eğitmek için komut dosyası |
| 2 | MLpipeline.mq5 | Uzman Danışman | ONNX modelini test etmek için Uzman Danışman |
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/22474
Uyarı: Bu materyallerin tüm hakları MetaQuotes Ltd'ye aittir. Bu materyallerin tamamen veya kısmen kopyalanması veya yeniden yazdırılması yasaktır.
Yeni Raylara Adım Atın: MQL5'te Özel Göstergeler
MetaTrader 5'in Gücü: Birleşik Bir Ortamda Adım Adım Hata Ayıklamadan EX5 Korumasına
İşte Karışınızda Yeni MetaTrader 5 ve MQL5
Harici Kütüphaneler Kullanmadan 3D Görselleştirme: MetaTrader 5, MQL5 + DX11 ile Optimizasyon Sonuçlarını Nasıl Gösteriyor?
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Web sitesi politikasını ve kullanım şartlarını kabul edersiniz
Bana kalırsa, tüm veri kümesinde normalizasyon ve PCA hesaplaması yapıp ancak bundan sonra veriyi eğitim ve doğrulama örneklemlerine ayırmak, geleceği öngörmeye çalışmak anlamına gelir. Çevrimiçi çalışırken, normalizasyonu değiştiremez veya en son verileri dikkate alarak PCA’yı uyarlayamazsınız. Dürüst bir deney, verilerin başlangıçta iki kümeye ayrılması, ardından sadece örneklem içi (in-sample) kısımda normalizasyon ve PCA'nın uygulanması, daha sonra da bulunan meta-parametrelerin örneklem dışı (out-of-sample) verilerde uygulanması şeklinde olurdu.
Sonuç olarak, sıradan bir ok göstergesi bile oklarını "en uç noktalarda" gösteriyor.
Bu tehlikeli bir durum; tuzağın ne olduğunu hemen anlayamazsınız.