Cant get Trailing StopLoss Working

Created at 04 Feb 2024, 18:31
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!
JM

jmenotts

Joined 08.03.2021

Cant get Trailing StopLoss Working
04 Feb 2024, 18:31


Hi first and foremost I would like to apologise if this is in the wrong section of the website :)

For the life of me i cannot get the trailing stop loss to work when i run a backtest the only variables that change the outcome of the cbot is take profit and stop loss this is really confusing me now im very new to coding ive spent a full day on this now before coming here lol i tried, could someone please explain what ive done wrong and how to correct it please?

any help would be very much appreciated thankyou in advance

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ADXCrossingBot : Robot
    {
        private bool isTradeOpen = false;
        
        [Parameter("Instance Name", DefaultValue = "ADX TS")]
        public string InstanceName { get; set; }

        [Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("ADX Periods", Group = "ADX", DefaultValue = 20, MinValue = 6, Step = 1, MaxValue = 1000)]
        public int AdxPeriods { get; set; }

        [Parameter("MA", Group = "ADX", DefaultValue = 21, MinValue = 6, Step = 1, MaxValue = 1000)]
        public int TrendMME { get; set; }
        
        [Parameter("Take Profit", Group = "Risk", DefaultValue = 150, MinValue = 0, Step = 1, MaxValue = 1000)]
        public int TakeProfit { get; set; }
        
        [Parameter("Stop Loss", Group = "Risk", DefaultValue = 150, MinValue = 0, Step = 1, MaxValue = 1000)]
        public int StopLoss { get; set; }

        //[Parameter("Trade Label", DefaultValue = "ADX Crossing")]
        //public string TradeLabel { get; set; }

        [Parameter("Include Trailing Stop", Group = "Risk",DefaultValue = true)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", Group = "Risk", DefaultValue = 20)]
        public double TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", Group = "Risk", DefaultValue = 10)]
        public double TrailingStopStep { get; set; }

        private DirectionalMovementSystem adx;
        private double volumeInUnits;
        private ExponentialMovingAverage mme;
        private RelativeStrengthIndex rsi;
        

        protected override void OnStart()
        {
            volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
            adx = Indicators.DirectionalMovementSystem(AdxPeriods);
            mme = Indicators.ExponentialMovingAverage(Bars.ClosePrices, TrendMME);
            rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);

            Positions.Closed += OnPositionClosed;
        }

        protected override void OnTick()
        {
            // Check if a trade is already open
            if (isTradeOpen)
                return;

           if (IncludeTrailingStop)
            {
                // Trailing stop logic
                SetTrailingStop();
            }

            if (adx.DIMinus.Last(3) < adx.DIPlus.Last(3) && adx.DIMinus.Last(1) > adx.DIPlus.Last(1) && adx.DIMinus.LastValue > adx.DIPlus.LastValue)
            {
                if (Symbol.Bid < mme.Result.Last(2))
                    if (rsi.Result.LastValue <= 70)
                    {
                        ExecuteMarketOrder(TradeType.Sell, SymbolName, volumeInUnits, InstanceName, StopLoss, TakeProfit);
                        isTradeOpen = true;
                    }
            }
            else if (adx.DIPlus.Last(3) < adx.DIMinus.Last(3) && adx.DIPlus.Last(1) > adx.DIMinus.Last(1) && adx.DIPlus.LastValue > adx.DIMinus.LastValue)
            {
                if (Symbol.Bid > mme.Result.Last(2))
                    if (rsi.Result.LastValue >= 30)
                    {
                        ExecuteMarketOrder(TradeType.Buy, SymbolName, volumeInUnits, InstanceName, StopLoss, TakeProfit);
                        isTradeOpen = true;
                        
                        
                    }
            }
        }

private void SetTrailingStop()
{
    var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);
    foreach (var position in sellPositions)
    {
        double distance = position.EntryPrice - Symbol.Ask;
        if (distance < TrailingStopTrigger * Symbol.PipSize)
            continue;

        double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;
        double newTakeProfit = position.TakeProfit ?? 0;

        if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
        {
            ModifyPosition(position, newStopLossPrice, newTakeProfit);
            Print("Trailing Stop Loss triggered...");
        }
    }

    var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);
    foreach (var position in buyPositions)
    {
        double distance = Symbol.Bid - position.EntryPrice;
        if (distance < TrailingStopTrigger * Symbol.PipSize)
            continue;

        double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;
        double newTakeProfit = position.TakeProfit ?? 0;

        if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
        {
            ModifyPosition(position, newStopLossPrice, newTakeProfit);
            Print("Trailing Stop Loss triggered...");
        }
    }
}


        private void OnPositionClosed(PositionClosedEventArgs args)
        {
            // Reset the flag when a position is closed
            isTradeOpen = false;
            
                if (args.Position.Label != InstanceName)   //Comment changed to InstanceName
                return;

            if (args.Reason == PositionCloseReason.StopLoss || args.Reason == PositionCloseReason.TakeProfit)
            {
                Print($"Position closed by {args.Reason}. Profit: {args.Position.GrossProfit}");
            }
        }
    }
}


@jmenotts