English Русский Deutsch 日本語 Italiano
preview
Rutin İşler Olmadan Algoritmik Alım-Satım: SQLite ile MetaTrader 5'te Hızlı İşlem Analizi

Rutin İşler Olmadan Algoritmik Alım-Satım: SQLite ile MetaTrader 5'te Hızlı İşlem Analizi

MetaTrader 5Örnekler |
36 1
MetaQuotes
MetaQuotes

Algoritmik alım-satımda geri bildirim problemi

Algoritmik alım-satım yalnızca rekabetçi stratejilerin geliştirilmesini değil, aynı zamanda sonuçların sürekli izlenmesini de gerektirir. Geri bildirim olmadan bir alım-satım sistemi kontrol edilemez hale gelebilir. Bir stratejinin gerçek zamanlı olarak nasıl davrandığını görene kadar, bir sistemi yönetmiyorsunuz, bir dizi tahmini yönetiyorsunuz.

Modern borsalarda ve FOREX'te işlemlerin sıklığı katlanarak artmıştır. Veriler, sonuç çıkarabileceğinizden daha hızlı bir şekilde güncelliğini yitirir. Veriler eskidikçe, bunlara dayanarak varılan sonuçlar da eskir. Ayrıca, tekrarlayan, rutin manuel eylemler kaçınılmaz olarak gecikmelere ve hatalara neden olur. Basitçe kişinin yorgun, dikkati dağınık ya da acelesi olduğu için ortaya çıkarlar.

MetaTrader 5'in özellikle değerli hale geldiği yer burasıdır. SQLite (yerel bir veritabanı) için yerleşik destek oyunun kurallarını değiştirir. Veritabanı artık sadece harici bir depolama alanı değil, alım-satım sürecinin ayrılmaz bir parçasıdır. Sorgular neredeyse anında yürütülür, istatistikler otomatik olarak güncellenir ve işlem analizi saatler yerine saniyeler sürer. Ve analiz sonuçları, terminalin dışında bir yerde değil, alım-satım sürecinin yanında, tam olarak ihtiyaç duyuldukları yerde sunulur.

Makale, algoritmik bir yatırımcının “temel çalışma setini” incelemektedir: bir işlem günlüğü veritabanının yapısı, güvenli, hızlı veri kaydı, analitik SQL sorguları ve MetaTrader 5'te etkileşimli bir panelde önemli istatistiklerin görüntülenmesi. Bu, rutin işlerin çoğunu ortadan kaldırmaya yardımcı olur ve yatırımcının yaratıcı tarafa odaklanmasını sağlar: alım-satım sistemini analiz etmek ve iyileştirmek.


Algoritmik bir yatırımcı neden yerel bir veritabanına ihtiyaç duyar?

Alım-satım stratejilerinin geliştirilmesi ve test edilmesi muazzam miktarda veri üretir. Optimizasyon sonuçları, işlem geçmişleri, gösterge sinyalleri, makroekonomik olaylar - tüm bunlar sadece depolama değil, aynı zamanda yapılandırma ve hızlı erişim gerektirir. Yerel bir veritabanı, her ciddi algoritmik yatırımcının karşılaştığı bu sorunları çözer.

Test ve optimizasyon sonuçlarını kaydetme

Parametreleri numaralandırarak bir stratejiyi optimize etmek, yüzlerce, hatta belki binlerce parametre varyasyonu üretir. Her geçiş, ölçütler, parametre değerleri ve sonuçlardan oluşan bir settir. Onları birbirleriyle nasıl karşılaştırabiliriz? Bir stratejinin zaman içindeki gelişimi nasıl takip edilir? Veritabanı, optimizasyonların eksiksiz bir geçmişini saklamaya ve basit tablolardan karmaşık korelasyonlara kadar herhangi bir bağlamda analiz etmeye olanak tanır.

Otomatik işlem günlüğü

Bir elektronik tabloda rutin olarak günlük tutmak yerine, terminalde bir Uzman Danışman çalıştırın ve her işlemin tam bir özellik setiyle otomatik olarak günlüğe kaydedilmesini sağlayın: sembol, sihirli sayı, hacim, fiyat, zaman, sonuç ve yorum. Veriler veritabanına gerçek zamanlı olarak girilir ve yatırımcı tarafından herhangi bir ek eylem yapılmadan anında analiz için kullanılabilir hale gelir.

İşlem sinyalleri analizi

İşlem sinyallerini kaydetmek ve analiz etmek, normal günlüklerle çalışırken kullanılamayan fırsatları ortaya çıkarır. Sinyaller ne kadar etkili? Hangi göstergeler birbiriyle ilişkilidir? Hangi koşullar altında girişler ve çıkışlar idealdir? Tüm yatırımcılar bu soruların yanıtlarını bilmek ister. SQL sorguları, ek kod yazmaya gerek kalmadan güçlü bir analiz aracı sağlar.

SQLite ile çalışmaya başlamak için sadece üç fonksiyona ihtiyacımız var:

  1. DatabaseOpen - veritabanını açar
  2. DatabaseExecute - veritabanında bir sorgu yürütür
  3. DatabaseClose - veritabanını kapatır

Bu, algoritmik bir yatırımcının karşılaştığı sorunların %90'ını çözmek için yeterlidir.

Bir veritabanını açma ve kapatma örneği:

int db = DatabaseOpen("trading.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(db == INVALID_HANDLE)
 {
  Print("Error opening Database: ", GetLastError());
  return;
 }
// ... working with the database ...
DatabaseClose(db);     // close the database

En önemlisi: SQLite, MetaTrader 5 sistemine "kullanıma hazır" olarak entegre edilmiştir ve doğrudan terminal çekirdeği ile çalışır. Excel ve diğer elektronik tablolar, bir MQL5 Uzman Danışmanının OLE otomasyonu gibi eski yöntemlerle veya harici bir CSV dosyası aracılığıyla eriştiği harici programlardır. MetaTrader 5'te SQLite lehine olan fark, hız, rahatlık ve güvenilirlik açısından muazzamdır.


Tablo düzeni: İşlem günlüğü mimarisi

Veritabanı tasarımı şu soruyla başlar: tam olarak neyin depolanması gerekiyor? Bir işlem günlüğü için cevap açıktır: işlem geçmişi, sinyaller ve olaylar. Ama neden tek bir “büyük ve evrensel” tablo değil de tam olarak üç tablo? DEALS, SIGNALS ve EVENTS olarak ayrılması bir keyfiyet değil, bir gerekliliktir. Her bir unsur ayrı olarak saklanır ve bir sorguda ihtiyaç duyulduğunda diğerlerine bağlanır. “Güven seviyesi %80'in üzerinde olan bir sinyalden sonraki tüm işlemleri” bilmek ister misiniz? SQLite, işlem terminalinden ayrılmanıza gerek kalmadan bunu kolayca ve zarif bir şekilde halledecektir.

DEALS tablosu - işlem geçmişi

Tablo, her bir işlem hakkında eksiksiz bilgi içermektedir: Kimlik, fişler, sembol, "sihirli" sayı (strateji kimliği), hacim, açılış ve kapanış fiyatları, zaman, finansal sonuç ve isteğe bağlı yorum. Bu, bir işlem günlüğünün “iskeletidir” - herhangi bir analizin temeli.

SIGNALS tablosu - sinyal geçmişi

Tablo, göstergelerden ve alım-satım sistemlerinden gelen sinyalleri depolar: sembol, zaman dilimi, sinyal türü (alış/satış), fiyat, oluşma zamanı ve ek parametreler. Ayrıca sinyallerin kalitesini ve gerçek işlemlerle korelasyonunu analiz etmeye olanak tanır - stratejinizin işe yarayıp yaramadığını anlamanın anahtarı.

EVENTS tablosu - haber içeriği

Tablo önemli ekonomik olaylar hakkında bilgiler içerir: ad, para birimi, önem seviyesi, beklenti, açıklanan değer ve yayınlanma zamanı. İşlem sonuçları ile haberler arasındaki bağlantıları bulmayı sağlar - sonuçta piyasa dış etkenlerden bağımsız hareket etmez.

Aşağıdaki şekil bir ER (Entity-Relationship) diyagramını göstermektedir - veritabanı yapısının ve tablolar arasındaki ilişkilerin görsel bir temsili:

Entity-Relationship diyagramı

Şekil 1: İşlem günlüğü tablolarının ER diyagramı

Tablo oluşturma kodu:

   //  Deal history table - DEALS:
   string createDeals = "CREATE TABLE IF NOT EXISTS DEALS ("
                       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                       "deal_ticket INTEGER UNIQUE, "
                       "order_ticket INTEGER, "
                       "symbol TEXT NOT NULL, "
                       "type INTEGER, "                // 0=BUY, 1=SELL
                       "direction INTEGER, "           // 0=IN, 1=OUT, 2=IN/OUT
                       "volume REAL, "
                       "price_open REAL, "
                       "price_close REAL, "
                       "profit REAL, "
                       "swap REAL, "
                       "commission REAL, "
                       "sl REAL, "
                       "tp REAL, "
                       "magic INTEGER, "
                       "comment TEXT, "
                       "time INTEGER, "                // Unix timestamp
                       "time_msc INTEGER, "
                       "reason INTEGER"
                       ");";
   
   //  Trading signals table - SIGNALS:
   string createSignals = "CREATE TABLE IF NOT EXISTS SIGNALS ("
                         "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                         "symbol TEXT NOT NULL, "
                         "signal_type TEXT, "          // 'BUY', 'SELL', 'CLOSE'
                         "price REAL, "
                         "stop_loss REAL, "
                         "take_profit REAL, "
                         "strength REAL, "             // 0.0 - 1.0
                         "source TEXT, "               // Strategy name
                         "notes TEXT, "
                         "time INTEGER"
                         ");";
   
   //  Events table - EVENTS:
   string createEvents = "CREATE TABLE IF NOT EXISTS EVENTS ("
                        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        "event_type TEXT, "            // 'NEWS', 'ERROR', 'NOTE', etc.
                        "symbol TEXT, "
                        "description TEXT, "
                        "importance INTEGER, "         // 1=Low, 2=Medium, 3=High
                        "time INTEGER,"
                        "actual REAL, "
                        "previous REAL, "
                        "forecast REAL "
                        ");";
   
   //  Indices to speed up search queries:
   string createIndexes[] = 
    {
      "CREATE INDEX IF NOT EXISTS idx_deals_symbol ON DEALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_deals_magic ON DEALS(magic);",
      "CREATE INDEX IF NOT EXISTS idx_deals_time ON DEALS(time);",
      "CREATE INDEX IF NOT EXISTS idx_signals_symbol ON SIGNALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_signals_time ON SIGNALS(time);"
    };
   
   //  Create tables in the database:
   if(!DatabaseExecute(database, createDeals))
    {
      Print("Error creating DEALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createSignals))
    {
      Print("Error creating SIGNALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createEvents))
    {
      Print("Error creating EVENTS table: ", GetLastError());
      return(false);
    }
   
   //  Create indices:
   for(int i = 0; i < ArraySize(createIndexes); i++)
    {
      DatabaseExecute(database, createIndexes[i]);
    }

Şu indekslere dikkat edin: idx_deals_symbol, idx_deals_magic, idx_deals_time, idx_signals_symbol ve idx_signals_time. Önemli alanlardaki sorguları hızlandırırlar: DEALS tablosundaki symbol, magic ve time ve SIGNALS tablosundaki symbol ve time. İndeksler, her analitik sorguda karşılığını veren bir performans yatırımıdır.


Veri ekleme ve transaction'lar: Hız önemlidir

MQL5 tablolara veri eklemek için iki yol sunar: doğrudan bir SQL sorgusu yürütmek ve hazırlanmış ifadeler kullanmak. Hangisi seçilmeli? Cevap açıktır: hazırlanmış ifadeler hem güvenlik hem de performans açısından tercih edilir.

DatabaseExecute aracılığıyla doğrudan ekleme:

string sql = StringFormat(
                         "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                         "VALUES (%d, '%s', %d, %.2f, %.5f, %I64d, %.2f)",
                         ticket, symbol, magic, volume, price, TimeCurrent(), profit);
DatabaseExecute(db, sql);

DatabasePrepare aracılığıyla parametrelendirilmiş sorgu:

//  Create a parameterized query:
int request = DatabasePrepare(db,
                             "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                             "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)");

//  Set the value of the first query parameter - in the DatabaseBind function, the indexing of fields in the entry starts from zero:
DatabaseBind(request, 0, ticket);
DatabaseTransactionBegin(db);

//  Set the values of the remaining parameters before adding the entry:
DatabaseBind(request, 1, symbol);
DatabaseBind(request, 2, magic);
DatabaseBind(request, 3, volume);
DatabaseBind(request, 4, price);
DatabaseBind(request, 5, TimeCurrent());
DatabaseBind(request, 6, profit);

//  Execute a request for inserting the entry:
DatabaseRead(request);
DatabaseFinalize(request);
DatabaseTransactionCommit(db);

Transaction'ları kullanmak bir seçenek değil, bir gerekliliktir. Toplu ekleme ve güncelleme operasyonları için transaction'lar performansı yüzlerce hatta binlerce kat hızlandırır. Neden? Bir transaction olmadan, her operasyon diske ayrı ayrı işlenir. Bir transaction ile tüm operasyonlar gruplandırılır ve tek bir blokta kaydedilir.

Test sonuçlarımız etkileyici: MQL5'teki SQLite performansı yerel C++ koduyla (LLVM 9.0) karşılaştırılabilir düzeydedir. Çoğu testte fark %5'ten azdır ve bazı senaryolarda MQL5 C++'dan bile daha iyi performans göstermektedir. Aşağıdaki diyagram, transaction içermeyen 1000 kayıt ile transaction içeren 25,000 kaydın ekleme süresini karşılaştırmaktadır - kayıt başına 3500 kattan fazla bir fark var!

Transaction karşılaştırması

Şekil 2. Ekleme hızı karşılaştırması: transaction içeren/içermeyen

Toplu ekleme için bir transaction kullanma örneği:

DatabaseTransactionBegin(db);
for(int i = 0; i < ArraySize(deals); i++)
 {
  InsertDeal(db, deals[i]);  // inserting the next trade - an element of the array of deals[] structures
 }
DatabaseTransactionCommit(db);

Tüm testler MQL5 forum bölümünde incelenebilir (ve kontrol edilebilir!): MQL5'te SQLite: Yeni özellikler ve performans testleri.


SQL sorguları: Programlama olmadan analiz

SQL'in temel avantajlarından biri, tek bir sorgu ile karmaşık analizler elde etme yeteneğidir. MetaTrader 5'te bu özelliğe doğrudan erişilebilir. Döngüler yok, koşullar yok, zaman değişkenleri yok. Bir sorgu yeterlidir. Bazı tipik senaryolara göz atalım.

İşlem sembollerine ilişkin istatistikler

Hangi enstrümanlar kar sağlıyor ve hangileri bakiyenizi sessizce "yiyip bitiriyor"? Bu soru ve beraberindeki SQL sorgusu, her yatırımcının cephaneliğinde ilk sırada yer almalıdır. Her sembol için özet bilgileri gösterir: işlem sayısı, toplam kar ve ortalama sonuç.

string sql = "SELECT symbol, COUNT(*) as deals, "
             "SUM(profit) as total_profit, "
             "AVG(profit) as avg_profit "
             "FROM DEALS GROUP BY symbol "
             "ORDER BY total_profit DESC";
DatabasePrint(db, sql);

Sorgu elemanlarının ayrıştırılması:

Sorgu elemanı Açıklama
SELECT symbol Bir sembol adına sahip sütunu seç
COUNT(*) Bir sembol için işlem sayısını say
SUM(profit) Tüm sembol işlemlerinin karını topla
GROUP BY symbol Sembole göre sonuçları gruplandır
ORDER BY total_profit DESC Toplam kara göre azalan şekilde sırala

Stratejilere göre analiz (sihirli sayılar)

Sihirli sayı, her işleme eklenen benzersiz bir Uzman Danışman kimliğidir. Bir hesap üzerinde birden fazla strateji çalışıyorsa, bu sorgu hangisinin daha verimli olduğunu gösterecektir. Önemli bir özellik, karlı işlemleri hesaplamak için koşullu bir CASE ifadesinin kullanılmasıdır.

string sql = "SELECT magic, COUNT(*) as trades, "
             "SUM(CASE WHEN profit > 0 THEN 1 ELSE 0 END) as wins, "
             "SUM(profit) as net_profit "
             "FROM DEALS GROUP BY magic";
DatabasePrint(db, sql);

Sorgu elemanlarının ayrıştırılması:

Sorgu elemanı Açıklama
SELECT magic Sihirli sayının bulunduğu sütunu seç
COUNT(*) Seçilen strateji için toplam işlem sayısı
CASE WHEN profit > 0 Koşul: kar pozitif ise
THEN 1 ELSE 0 END Karlı işlemler için 1, zararla sonuçlananlar için 0 geri döndür
SUM(wins) Karlı işlemlerin (wins) sayısını elde etmek için birimleri topla

Karlı işlemlerin (wins) sayısını toplam sayıya (trades) bölerek, strateji kalitesini değerlendirmek için önemli bir ölçüt olan karlı işlemlerin yüzdesini elde ederiz. Negatif bir toplam kar ile yüksek bir yüzde mi elde ettiniz? Bu, bir risk yönetimi sorununun işaretidir: zarar eden işlemlerin tutarı, kar eden işlemlerin tutarından daha yüksektir.

İşlemlerin saatlere göre dağılımı

Strateji en iyi ne zaman işe yarıyor? Avrupa seansı sırasında mı? Yoksa Amerika seansı sırasında mı? Ya da belki "sessiz saatlerde"? Strftime fonksiyonu, işlem açılış zamanından saati çıkararak (00--23 formatı) en çok ve en az karlı zaman aralıklarını belirlememize olanak tanır.

string sql = "SELECT strftime('%H', time, 'unixepoch') as hour, "
             "COUNT(*) as trades, SUM(profit) as profit "
             "FROM DEALS GROUP BY hour";
DatabasePrint(db, sql);

Önemli: MQL5 ve SQLite'da zaman, Unix zaman damgası olarak saklanır (1970-01-01'den bu yana geçen saniye). Bu nedenle, 'unixepoch' değiştiricisi eklenmiştir. Benzer şekilde, dağılımı haftanın gününe strftime('%w', ...), aya strftime('%m', ...) veya kombinasyonlara göre analiz edebiliriz.

Sorgu elemanlarının ayrıştırılması:

Sorgu elemanı Açıklama
strftime('%H', ...) İşlem açılış zamanından saati çıkar (00-23)
time İşlem açılış zamanını içeren sütun
GROUP BY hour Açılış saatine göre işlemleri grupla


İstatistik paneli: Terminal içinde görselleştirme

Kuru rakamlar iyidir, ancak netlik daha iyidir. Veritabanı, terminal içindeki grafiksel panellerle kolayca entegre olarak verileri anlaşılabilir görsel bilgilere dönüştürür. Etkileşimli istatistik paneli gerçek zamanlı olarak çalışır ve yatırımcının tam olarak neye ihtiyacı olduğunu gösterir.

Aşağıdaki panel, belirli bir gün sayısı için toplam sonucu (SUMMARY), enstrümana göre ayrılmış sonucu (BY SYMBOL) ve en iyi işlem saatlerini (BEST HOURS) gösterir. Bir yapıya veri okumak için DatabaseReadBind fonksiyonunu kullanın:

İstatistik paneli

Şekil 3. Terminalde etkileşimli istatistik paneli

struct DealStats
 {
  string symbol;
  int count;
  double total_profit;
  double avg_profit;
 };

int request = DatabasePrepare(db,
                             "SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, "
                             "AVG(profit) as avg_profit FROM DEALS GROUP BY symbol");
DealStats stats;
while(DatabaseReadBind(request, stats))
 {
  //  Output to the table on the dashboard:
  AddRowToTable(stats);
 }
DatabaseFinalize(request);

DatabaseReadBind fonksiyonu, yapı alanlarını ada göre sorgu sütunlarıyla otomatik olarak eşleştirir. SQL sorgusundaki sütun adlarına karşılık gelen alanlara sahip bir yapı bildirmek yeterlidir.

Panel yönetimi

[Refresh] düğmesi istatistikleri tam bir yeniden hesaplama ile günceller. [Export] düğmesi, hesaplanan verileri veritabanı tablolarından CSV dosyalarına dışa aktarır: genel çalışma sonucu, işlemler, olaylar ve sinyaller. Dışa aktarma örneği:

(#),symbol,trades,total_profit,avg_profit,wins,losses
1,XAGUSD,196,322.25,1.64,14,181
2,AUDUSD,196,-12.0,-0.06,82,99
3,EURUSD,58,-38.5,-0.66,23,35
4,GBPUSD,57,-43.2,-0.75,17,40

Hızlı kontrol için "kısayol" tuşları:

  • 'A' veya 'a' - analizleri güncelle,
  • 'E' veya 'e' - verileri bir CSV dosyasına dışa aktar,
  • 'R' veya 'r' - işlem geçmişini yükle,
  • 'P' veya 'p' - panel gösterimini etkinleştirir/devre dışı bırak.

Uzman Danışman ayarları:

  • «Database file name» - veritabanı dosyasının adı (varsayılan: "TradingJournal.db"),
  • «Auto-import trade history» - geçmişin otomatik yüklenmesi (varsayılan: true),
  • «History depth in days» - geçmiş derinliği (varsayılan: 30 gün),
  • «Export path» - CSV dosyalarının yolu (varsayılan: "MQL5/Files"),
  • «Export to CSV format» - CSV'ye dışa aktar (varsayılan: true),
  • «Show statistics dashboard on chart» - panel gösterimi (varsayılan: true).


MetaEditor: Bir veritabanı aracı

MetaTrader 5'te bulunan MetaEditor, SQLite ile çalışmak için yerleşik bir araca sahiptir: tabloları açma ve düzenleme, SQL sorgularını yürütme ve değişiklikleri geri alma. SQLite veritabanı kullanıcının bilgisayarında tek bir dosyada saklandığından, tabloların yapısını ve içeriğini incelemek ve hata ayıklama sorgularını çalıştırmak için MetaEditor kılavuzu aracılığıyla herhangi bir zamanda erişilebilir.

Bu, özellikle bir veritabanı ile çalışan MQL5 uygulamalarında hata ayıklarken kullanışlıdır. Hangi verilerin görüntülendiğini gerçek zamanlı olarak görmeye çalışın ve Uzman Danışmanın mantığını ayarlayın.

Bu makaledeki TradingJournalSQLite-EA test Uzman Danışmanı tarafından oluşturulan örnek bir veritabanını kullanarak bunun nasıl kolayca yapılabileceğini görelim. Veritabanını ve içindeki tabloları açalım, birkaç SQL sorgusu çalıştıralım ve kapatalım. Tüm bunlar kelimelerle uzun uzun anlatılabilir ama bir kez görmekte fayda var...

1. En basit şeyle başlayalım - veritabanını açalım ve istediğimiz tabloyu seçelim:

    Açın/Seçin/Kapatın

    Şekil 4.  Açın/Tablo seçin/Kapatın

    DEALS tablosu, adının üzerine farenin sol tuşuyla çift tıklanarak seçilir. Bu, kılavuzda bir SQL sorgusu çalıştırmaya eşdeğerdir:

    SELECT * FROM 'DEALS';
    2. Zaman formatını ayarlayalım:

      Zaman formatı

      Şekil 5. Zaman formatı

      3. Asıl soru: Hangi sembol ne kadar kazanç sağlıyor? Cevabı milisaniyeler içinde öğrenelim:
        SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

        Uzun satırlardan hoşlanmayanlar için:

        SELECT symbol,
        COUNT(*) as count,
        SUM(profit) as total_profit,
        AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;
        

        PnL

        Şekil 6. Hangi sembol ne kadar kazanç sağlıyor?

        4. Toplam kara göre azalan şekilde sıralayalım:
          SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol
          ORDER BY total_profit DESC;
          

          Sıralı PnL

          Şekil 7. Toplam karın azalan sıralaması


          5. Toplam kar ne kadar? Hadi bulalım:
            SELECT  SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit FROM DEALS;

            Net PnL

            Şekil 8. Toplam

            Karmaşık bir sorguda hata ayıklamak mı istiyorsunuz? Sorun değil:

            SELECT   COUNT(*) as total_deals, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END) as closed_trades, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_wins, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_losses, 
                            ROUND(100.0 * SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) / 
                            NULLIF(SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END), 0), 2) as overall_win_rate, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN swap ELSE 0 END) as total_swap,
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN commission ELSE 0 END) as total_commission, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE 0 END) as net_result, 
                            ROUND(AVG(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE NULL END), 2) as avg_profit_per_trade, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) as gross_profit, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) as gross_loss, 
                            CASE WHEN SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) > 0 
                            THEN ROUND(SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) / 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END), 2) 
                            ELSE 0 END as profit_factor, 
                            COUNT(DISTINCT symbol) as symbols_traded, 
                            COUNT(DISTINCT magic) as strategies_used 
                            FROM DEALS;
            

            Karmaşık istek

            Şekil 9. Karmaşık SQL sorgusu

            SQL sorgusu, makaleye ekli TradingJournalSQLite-EA test Uzman Danışmanından değişiklik yapılmadan alınmıştır.


            Sonuç: Doğrudan MetaTrader 5'te bir alım-satım ve analiz sistemi

            İşlem günlüğü artık dışa aktarılması, üçüncü taraf bir programda açılması ve manuel olarak uygun bir formata getirilmesi gereken statik bir dosya değildir. MetaTrader 5'te, alım-satım ve analiz sisteminin bir parçası haline geldi - doğru, güvenilir ve gerçek zamanlı değişikliklere duyarlı. Bu yerel olarak gerçekleştirilir - SQLite, MetaTrader 5 terminaline çekirdek düzeyinde entegre edilmiştir.

            Bu, MetaTrader 5'i kendi kendine yeterli bir alım-satım ve analiz sistemi olarak kullanmamıza ve yeni fikirlere uyacak şekilde genişletme ve değiştirme imkanıyla birlikte SQL sorgularının tüm gücünden yararlanmamıza olanak tanır. Bu, yatırımcılara aşağıdaki faydaları sağlar:

              • Veriler otomatik olarak kaydedilir ve göründükten hemen sonra analiz için kullanılabilir;
              • Analitik SQL sorguları, Uzman Danışman kodunu karmaşıklaştırmadan hızlı ve esnek bir şekilde değiştirilebilir;
              • Analiz paneli, doğrudan alım-satımın gerçekleştiği terminaldeki grafik üzerinde yer alır;
              • Sistem, üçüncü taraf uygulamalara başvurmadan yeni fikirleri, ölçütleri ve analitik görünümleri barındıracak şekilde kolayca genişletilebilir.

              Bu nedenle MetaTrader 5'teki yerleşik SQLite desteği, kullanışlı bir veri depolama çözümünden daha fazlasıdır, alım-satım ve analizin tek bir ortamda, tek bir dil ve yerel SQL desteği kullanılarak çalıştığı tam teşekküllü bir alım-satım ve analiz altyapısı için sağlam bir temeldir.


              MQL5'te SQLite'ı derinlemesine incelemek için önerilen kaynaklar:

              Makaleye ekli dosyaların listesi:

              Dosya adı Açıklama
              TradingJournalSQLite-EA.mq5 Alım-satım istatistiklerini içeren bir panel oluşturan bir test Uzman Danışmanının kodunun bulunduğu dosya

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

              Ekli dosyalar |
              Son yorumlar | Tartışmaya git (1)
              Gerard William G J B M Dinh Sy
              Gerard William G J B M Dinh Sy | 5 May 2026 saat 12:35
              Teşekkürler
              Yeni Raylara Adım Atın: MQL5'te Özel Göstergeler Yeni Raylara Adım Atın: MQL5'te Özel Göstergeler
              Yeni terminalin ve dilin tüm yeni olanaklarını ve özelliklerini listelemeyeceğim. Bunlar sayısızdır ve bazı yenilikler ayrı bir makalede tartışılmaya değerdir. Ayrıca burada nesne yönelimli programlama ile yazılmış bir kod yoktur, geliştiriciler için ek avantajlar olarak bir bağlamda basitçe bahsedilemeyecek kadar ciddi bir konudur. Bu makalede, MQL4'e kıyasla göstergeleri, yapılarını, çizimlerini, türlerini ve programlama ayrıntılarını ele alacağız. Umarım bu makale hem yeni başlayanlar hem de deneyimli geliştiriciler için faydalı olacaktır, belki bazıları yeni bir şeyler bulacaktır.
              MetaTrader 5'te L1 Trend Filtrelemeyi Uygulama MetaTrader 5'te L1 Trend Filtrelemeyi Uygulama
              Bu makale, MetaTrader 5'te L1 trend filtrelemenin pratik uygulamasını ele almakta ve hem matematiksel temellerini hem de MQL5 programlarındaki kullanımını kapsamaktadır. L1 filtresi, fiyat gürültüsünü azaltırken temel piyasa yapısını koruyan parçalı doğrusal trendlerin çıkarılmasını sağlar. Çalışma, parametre ölçeklendirmesini, trend hesaplama davranışını ve yöntemin algoritmik alım-satım stratejilerine entegrasyonunu analiz etmektedir. Deneysel sonuçlar, L1 trend filtrelemenin sinyal kararlılığını, işlem zamanlamasını ve alım-satım sistemlerinin genel sağlamlığını nasıl iyileştirebileceğini göstermektedir.
              İşte Karışınızda Yeni MetaTrader 5 ve MQL5 İşte Karışınızda Yeni MetaTrader 5 ve MQL5
              Bu MetaTrader 5 ile ilgili sadece kısa bir inceleme. Sistemin tüm yeni özelliklerini bu kadar kısa sürede açıklayamam, test süreci 09.09.2009’da başladı. Bu sembolik bir tarihtir ve şanslı sayı olacağına eminim. MetaTrader 5 terminalinin ve MQL5’in beta sürümünü beş gün önce aldım. Tüm özelliklerini deneme şansım olmadı ama şimdiden etkilendim.
              Forex'te portföy optimizasyonu: VaR ve Markowitz teorisinin birleştirilmesi Forex'te portföy optimizasyonu: VaR ve Markowitz teorisinin birleştirilmesi
              Forex'te portföy alım-satımı nasıl çalışır? Portföy dağılımı optimizasyonu için Markowitz portföy teorisi ve portföy risk optimizasyonu için VaR modeli nasıl birleştirilebilir? Bir yandan düşük risk, diğer yandan kabul edilebilir uzun vadeli karlılık elde edeceğimiz portföy teorisine dayalı bir kod oluşturuyoruz.