Martinagle bot code

Created at 06 Jun 2024, 10:19
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
nyegin's avatar

nyegin

Joined 02.05.2024

Martinagle bot code
06 Jun 2024, 10:19


Hi, I wrote this code for a martingale bot strategy with a KDJ indicator. if KDJ crosses it will buy and set TP and SL. After 1. buy if it go down until "Martingale pip difference" it will buy second position with the martingale ratio. if there is an open position and KDJ cross it won't buy. only for Martingale, it can buy until close all open positions in a salon way (long or short) it is working but only buying when KDJ crosses. price is going down until the martingale level but it is not buying second time. wrhere my mstake at code. can anyone help me?

=================================

using System; // System ad alanını kullan
using cAlgo.API; // cTrader Automate API ad alanını kullan

namespace cAlgo // cAlgo ad alanını tanımla
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] // Robotu ve ayarlarını tanımla
    public class SampleMartingalecBot : Robot // Robot sınıfından türeyen SampleMartingalecBot sınıfını tanımla
    {
        [Parameter("Başlangıç Miktarı (Lot)", Group = "Hacim", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double InitialQuantity { get; set; } // Başlangıç miktarını tanımla

        [Parameter("Zarar Durdur (Pip)", Group = "Koruma", DefaultValue = 50)]
        public int StopLossPips { get; set; } // Zarar durdur parametresini tanımla

        [Parameter("Kar Al (Pip)", Group = "Koruma", DefaultValue = 50)]
        public int TakeProfitPips { get; set; } // Kar al parametresini tanımla

        [Parameter("Martingale Oranı", Group = "Koruma", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
        public double MartingaleRatio { get; set; } // Martingale oranı parametresini tanımla

        [Parameter("Maksimum Martingale Sayısı", Group = "Koruma", DefaultValue = 10, MinValue = 1, Step = 1)]
        public int MaxMartingaleCount { get; set; } // Maksimum Martingale sayısını tanımla
        
        [Parameter("Martingale Pip Farkı", Group = "Koruma", DefaultValue = 20, MinValue = 1, Step = 1)]
        public int MartingalePipDifference { get; set; } // Martingale pip farkı parametresini tanımla
        
        [Parameter("K Periyodu", Group = "KDJ", DefaultValue = 14)]
        public int KPeriod { get; set; } // K periyodu parametresini tanımla
        
        [Parameter("D Periyodu", Group = "KDJ", DefaultValue = 3)]
        public int DPeriod { get; set; } // D periyodu parametresini tanımla

        [Parameter("Uzun Pozisyon Ticareti", Group = "Ticaret Türü", DefaultValue = true)]
        public bool LongTradeEnabled { get; set; } // Uzun pozisyon ticaretini seçilebilir yap

        [Parameter("Kısa Pozisyon Ticareti", Group = "Ticaret Türü", DefaultValue = true)]
        public bool ShortTradeEnabled { get; set; } // Kısa pozisyon ticaretini seçilebilir yap

        private double lastK = 50;
        private double lastD = 50;
        private double lastJ = 50;
        private double previousK = 50;
        private double previousD = 50;
        private int martingaleCount = 0; // Martingale sayaç

        protected override void OnStart() // OnStart metodunu geçersiz kıl
        {
            Positions.Closed += OnPositionsClosed; // Positions.Closed olayına abone ol
        }

        protected override void OnBar() // Her yeni bar oluştuğunda çağrılan metod
        {
            previousK = lastK;
            previousD = lastD;
            CalculateKdj(); // KDJ indikatörünü hesapla

            var tradeType = GetKdjTradeType();
            if (tradeType.HasValue && !HasOpenPosition(tradeType.Value) && IsTradeTypeEnabled(tradeType.Value))
            {
                ExecuteOrder(InitialQuantity, tradeType.Value); // KDJ indikatörüne göre işlem türü ile başlangıç emri ver
            }
        }

        private bool IsTradeTypeEnabled(TradeType tradeType) // Ticaret türünü kontrol eden metod
        {
            return (tradeType == TradeType.Buy && LongTradeEnabled) || (tradeType == TradeType.Sell && ShortTradeEnabled);
        }

        private bool HasOpenPosition(TradeType tradeType) // Aynı yönde açık pozisyon olup olmadığını kontrol eden metod
        {
            foreach (var position in Positions)
            {
                if (position.SymbolName == SymbolName && position.TradeType == tradeType)
                {
                    return true; // Aynı yönde açık pozisyon var
                }
            }
            return false; // Aynı yönde açık pozisyon yok
        }

        private void ExecuteOrder(double quantity, TradeType tradeType) // Emir vermek için metod
        {
            if (CountOpenPositions() >= MaxMartingaleCount) // Maksimum açık pozisyon kontrolü
            {
                Print("Maksimum açık pozisyon sayısına ulaşıldı");
                return;
            }

            var volumeInUnits = Symbol.QuantityToVolumeInUnits(quantity); // Miktarı birim hacmine dönüştür
            var result = ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, "Martingale", StopLossPips, TakeProfitPips); // Piyasa emrini gerçekleştir

            if (result.Error == ErrorCode.NoMoney) // Yetersiz bakiye hatasını kontrol et
            {
                Stop(); // Bakiye yoksa cBot'u durdur
                return;
            }

            UpdateAllPositions(tradeType); // Tüm pozisyonları güncelle
        }

        private void OnPositionsClosed(PositionClosedEventArgs args) // Pozisyonlar kapandığında çağrılan olay işleyici
        {
            Print("Kapandı"); // "Kapandı" mesajını günlüğe yazdır
            var position = args.Position; // Kapanan pozisyonu al

            if (position.Label != "Martingale" || position.SymbolName != SymbolName) // Pozisyonun ilgili olup olmadığını kontrol et
                return;

            if (position.GrossProfit > 0) // Pozisyon karlı ise
            {
                martingaleCount = 0; // Martingale sayacını sıfırla
            }
            else if (martingaleCount < MaxMartingaleCount) // Maksimum martingale sayısı kontrolü
            {
                martingaleCount++; // Martingale sayacını artır
                double additionalQuantity = position.Quantity * MartingaleRatio;
                double pipDifference = MartingalePipDifference * Symbol.PipSize; // Martingale pip farkını hesapla

                if (position.TradeType == TradeType.Buy) // Alış işlemi için
                {
                    if (Symbol.Bid - position.EntryPrice >= pipDifference) // Pip farkı kadar bekle
                    {
                        ExecuteOrder(additionalQuantity, position.TradeType); // Yeni martingale emri ver
                    }
                }
                else // Satış işlemi için
                {
                    if (position.EntryPrice - Symbol.Ask >= pipDifference) // Pip farkı kadar bekle
                    {
                        ExecuteOrder(additionalQuantity, position.TradeType); // Yeni martingale emri ver
                    }
                }
            }
        }

        private TradeType? GetKdjTradeType() // KDJ indikatörüne göre işlem türü almak için metod
        {
            if (previousK <= previousD && lastK > lastD) // K değeri D değerini yukarı kesince alım sinyali
                return TradeType.Buy;
            else if (previousK >= previousD && lastK < lastD) // K değeri D değerini aşağı kesince satım sinyali
                return TradeType.Sell;

            return null; // Kesişme yoksa işlem türü döndürme
        }

        private void CalculateKdj() // KDJ indikatörünü hesaplamak için metod
        {
            double highestHigh = MarketSeries.High.Maximum(KPeriod);
            double lowestLow = MarketSeries.Low.Minimum(KPeriod);
            double close = MarketSeries.Close.LastValue;

            double rsv = (close - lowestLow) / (highestHigh - lowestLow) * 100;

            lastK = (lastK * (DPeriod - 1) + rsv) / DPeriod;
            lastD = (lastD * (DPeriod - 1) + lastK) / DPeriod;
            lastJ = 3 * lastK - 2 * lastD;
        }

        private int CountOpenPositions() // Açık pozisyon sayısını kontrol eden metod
        {
            int count = 0;
            foreach (var position in Positions)
            {
                if (position.SymbolName == SymbolName && position.Label == "Martingale")
                {
                    count++;
                }
            }
            return count;
        }

        private void UpdateAllPositions(TradeType tradeType) // Tüm pozisyonları güncellemek için metod
        {
            double totalQuantity = 0;
            double totalCost = 0;

            // Tüm pozisyonların toplam miktarını ve toplam maliyetini hesapla
            foreach (var position in Positions)
            {
                if (position.SymbolName == SymbolName && position.Label == "Martingale" && position.TradeType == tradeType)
                {
                    totalQuantity += position.Quantity;
                    totalCost += position.EntryPrice * position.Quantity;
                }
            }

            if (totalQuantity == 0) // Eğer açık pozisyon yoksa geri dön
                return;

            double averageCost = totalCost / totalQuantity; // Ortalama maliyeti hesapla

            // Her pozisyonun zarar durdur ve kar al noktalarını güncelle
            foreach (var position in Positions)
            {
                if (position.SymbolName == SymbolName && position.Label == "Martingale" && position.TradeType == tradeType)
                {
                    double stopLossPrice;
                    double takeProfitPrice;

                    if (tradeType == TradeType.Buy)
                    {
                        stopLossPrice = averageCost - StopLossPips * Symbol.PipSize;
                        takeProfitPrice = averageCost + TakeProfitPips * Symbol.PipSize;
                    }
                    else
                    {
                        stopLossPrice = averageCost + StopLossPips * Symbol.PipSize;
                        takeProfitPrice = averageCost - TakeProfitPips * Symbol.PipSize;
                    }

                    position.ModifyStopLossPrice(stopLossPrice); // Zarar durdur noktasını güncelle
                    position.ModifyTakeProfitPrice(takeProfitPrice); // Kar al noktasını güncelle
                }
            }
        }
    }
}

 


@nyegin