MA Shift C Bot

Created at 28 Feb 2019, 15:49
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!
RY

ryan.a.blake

Joined 28.01.2019

MA Shift C Bot
28 Feb 2019, 15:49


Hi,

I have recently create a Cbot based on a moverage average with shift and when 2 MA cross that both have shift coded into the indicators a trade is created but based on normal conditions as if the shift was set to 0 and not -1 or +2. Is this due to the Cbot not registering the shift part of the indicator?

Any ideas would be mch appreciated.

 

Kind regards.


@ryan.a.blake
Replies

PanagiotisCharalampous
28 Feb 2019, 16:45

Hi Ryan,

Unfortunately the information you provide is too little. We need you to share with us your indicator and cBot and tell us how to reproduce the issue so that we can advise you.

Best Regards,

Panagiotis


@PanagiotisCharalampous

ryan.a.blake
28 Feb 2019, 21:01

RE:

Panagiotis Charalampous said:

Hi Ryan,

Unfortunately the information you provide is too little. We need you to share with us your indicator and cBot and tell us how to reproduce the issue so that we can advise you.

Best Regards,

Panagiotis

Wow, apologies. I did not realise how bad I had written my previous post. No wonder why you did not understand. Anyway - Please see below copy of my code for the cbot.

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 MAShiftCbot : Robot
    {
        [Parameter("Instance Name", DefaultValue = "001")]
        public string InstanceName { get; set; }

        [Parameter("Lot Size", DefaultValue = 0.01)]
        public double lotsize { get; set; }

        [Parameter("Source #SMA1")]
        public DataSeries Source1 { get; set; }

        [Parameter("Source #SMA2")]
        public DataSeries Source2 { get; set; }

        [Parameter("Period #SMA1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
        public int Period1 { get; set; }

        [Parameter("Shift #SMA1", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
        public int Shift1 { get; set; }

        [Parameter("Period #SMA2", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
        public int Period2 { get; set; }

        [Parameter("Shift #SMA2", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
        public int Shift2 { get; set; }

        [Parameter("Loss", DefaultValue = 50)]
        public double loss { get; set; }

        [Parameter("TakeProfitPips", DefaultValue = 10)]
        public int TP { get; set; }

        [Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
        public int SL { get; set; }

        [Parameter("trigger ", DefaultValue = 20)]
        public int Trigger { get; set; }

        [Parameter("Trailing", DefaultValue = 10)]
        public int Trailing { get; set; }

        private SMAShift _sma1 { get; set; }
        private SMAShift _sma2 { get; set; }

        protected override void OnStart()
        {
            _sma1 = Indicators.GetIndicator<SMAShift>(Source1, Period1, Shift1);
            _sma2 = Indicators.GetIndicator<SMAShift>(Source2, Period2, Shift2);
        }
        protected override void OnTick()
        {
            TRAILING();

            if (_sma1.Result.Last(0) > _sma2.Result.Last(0))
                if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
                {

                    double volume = Symbol.QuantityToVolumeInUnits(lotsize);

                    ExecuteMarketOrder(TradeType.Buy, this.Symbol, volume, InstanceName, SL, TP, nullnull);

                    ClosePosition(TradeType.Sell);
                }
            if (_sma1.Result.Last(0) < _sma2.Result.Last(0))

                if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
                {

                    {
                        double volume = Symbol.QuantityToVolumeInUnits(lotsize);

                        ExecuteMarketOrder(TradeType.Sell, this.Symbol, volume, InstanceName, SL, TP, nullnull);

                        ClosePosition(TradeType.Buy);
                    }
                }
        }
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol, type);

            if (p != null)
            {
                ClosePosition(p);
            }
            if (Account.Balance <= loss)
                Stop();
        }
        private void TRAILING()
        {
            if (Trailing > 0 && Trigger > 0)
            {

                Position[] positions = Positions.FindAll(InstanceName, Symbol);

                foreach (Position position in positions)
                {

                    if (position.TradeType == TradeType.Sell)
                    {

                        double distance = position.EntryPrice - Symbol.Ask;

                        if (distance >= Trigger * Symbol.PipSize)
                        {

                            double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;

                            if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                            {

                                ModifyPosition(position, newStopLossPrice, position.TakeProfit);

                            }
                        }
                    }

                    else
                    {

                        double distance = Symbol.Bid - position.EntryPrice;

                        if (distance >= Trigger * Symbol.PipSize)
                        {

                            double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;

                            if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                            {

                                ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                            }
                        }
                    }
                }
            }
        }
    }
}

 

 

Please see code below for the indicator =

// -------------------------------------------------------------------------------------------------
//
//    Simple Moving Average Shift
//    This code is a cAlgo API example.
//    
// -------------------------------------------------------------------------------------------------

using System;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class SMAShift : Indicator
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter(DefaultValue = 14)]
        public int Periods { get; set; }

        [Parameter(DefaultValue = -2, MinValue = -100, MaxValue = 500)]
        public int Shift { get; set; }

        [Output("Main", Color = Colors.Blue)]
        public IndicatorDataSeries Result { get; set; }

        public override void Calculate(int index)
        {
            double sum = 0.0;

            for (int i = index - Periods + 1; i <= index; i++)
            {
                sum += Source[i];
            }
            Result[index - 1] = sum / Periods;
        }
    }
}


@ryan.a.blake

ryan.a.blake
28 Feb 2019, 21:15

So, as I attempted to explain in my very first post. The Cbot is based on a crossover of  MA = Period 3 (shift=0) & MA = Period 2 (shift= -1) with shift coded into the indicator (you will notice I have placed -1 into the code at the bottom of the indicator = Result{index - 1} = sum / Periods;) Im aware that this should have been 'shift' in that place instead, to link with what I have put in the parameters. Anyway as I run this cbot on renko charts everything appears to work smoothly until it places trades in the wrong direction when a cross happens, after further analysis of where trades were placed and the direction they are going whether it be buy or sell. I noticed that the trades taken were as if shift -1 was not working and as if it was two normal MA's, which as a result took incorrect trades causing loss. 

I hope this shoud now make sense.

Let me know if you require anything else.

Kind regards.


@ryan.a.blake

PanagiotisCharalampous
01 Mar 2019, 10:18

Hi ryan.a.blake,

Can you also provide us with backtesting parameters and backtesting results where we can see such trades? You can post a screenshot of a trade that you think is wrong and explain what would you expect to happen instead.

Best Regards,

Panagiotis


@PanagiotisCharalampous

ryan.a.blake
01 Mar 2019, 13:11 ( Updated at: 21 Dec 2023, 09:21 )

Hi Panagiotis,

Thank you for getting back to be.

Unfortunaltey i am not at my computer today and unable to post my actual backtesting results showing you where the Cbot went wrong. However if its ok with you I have posted screenshots from Trading view showing you examples of where the cbot went wrong.

The below image shows what the Cbot actually does, which creates non intended trades due to the moving averages not taking into account the shift part of my strategy which has been calculated into the moving averages indicator. 

The below image shows what the Cbot needs to do, which is to incorporate shift into the moving averages creating a gap between the two MA's creating cleaner entries for the cbot. However when the cbot is running this is not what happens. 

So the main problem with the cbot is that shift does not want to work or register when the cbot is running. Hopefully you should have all information now, however let m eknow if you need more.

 

Kind regards.

 


@ryan.a.blake

PanagiotisCharalampous
01 Mar 2019, 14:14

Hi ryan.a.blake,

When you have time, please share backtesting parameters and results. I need to be able to reproduce exactly what you can see in cTrader.

Best Regards,

Panagiotis


@PanagiotisCharalampous

ryan.a.blake
02 Mar 2019, 19:26

I unfortunately am unable to produce the backtesting results from where it went wrong. I have however tested this through backtesting and it does appear to work. Looking through some of the code I have placed the condition coding (if....) under OnBar instead of Ontick, which has moderated the trade results. Im wondering if that could have been the cause previously. Anyway, im planning on testing this again live on renko when monday comes round and will post any problems I come across (if any).

Kind regards.


@ryan.a.blake

ryan.a.blake
05 Mar 2019, 21:15 ( Updated at: 21 Dec 2023, 09:21 )

Hi Panagiotis,

Me again. I was unable to produce results from monday's session as it was having technical issues and not placing any trades due to the error in the code I created when trialing something that may fix it, which obviously didn't. 

After todays testing of the Cbot live on renko there still seems to be an error with it. Please see code for strategy below;

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 MAShiftCbot : Robot
    {
        [Parameter("Instance Name", DefaultValue = "001")]
        public string InstanceName { get; set; }

        [Parameter("Lot Size", DefaultValue = 0.01)]
        public double lotsize { get; set; }

        [Parameter("Source #SMA1")]
        public DataSeries Source1 { get; set; }

        [Parameter("Source #SMA2")]
        public DataSeries Source2 { get; set; }

        [Parameter("Period #SMA1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
        public int Period1 { get; set; }

        [Parameter("Shift #SMA1", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
        public int Shift1 { get; set; }

        [Parameter("Period #SMA2", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
        public int Period2 { get; set; }

        [Parameter("Shift #SMA2", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
        public int Shift2 { get; set; }

        [Parameter("Loss", DefaultValue = 50)]
        public double loss { get; set; }

        [Parameter("TakeProfitPips", DefaultValue = 10)]
        public int TP { get; set; }

        [Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
        public int SL { get; set; }

        [Parameter("trigger ", DefaultValue = 20)]
        public int Trigger { get; set; }

        [Parameter("Trailing", DefaultValue = 10)]
        public int Trailing { get; set; }

        private SMAShift _sma1 { get; set; }
        private SMAShift _sma2 { get; set; }

        protected override void OnStart()
        {
            _sma1 = Indicators.GetIndicator<SMAShift>(Source1, Period1, Shift1);
            _sma2 = Indicators.GetIndicator<SMAShift>(Source2, Period2, Shift2);
        }
        protected override void OnTick()
        {
            TRAILING();
        }
        protected override void OnBar()
        {

            if (_sma1.Result.Last(0) > _sma2.Result.Last(0))
                if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
                {

                    double volume = Symbol.QuantityToVolumeInUnits(lotsize);

                    ExecuteMarketOrder(TradeType.Buy, this.Symbol, volume, InstanceName, SL, TP, nullnull);

                    ClosePosition(TradeType.Sell);

                }
            if (_sma1.Result.Last(0) < _sma2.Result.Last(0))

                if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
                {

                    {
                        double volume = Symbol.QuantityToVolumeInUnits(lotsize);

                        ExecuteMarketOrder(TradeType.Sell, this.Symbol, volume, InstanceName, SL, TP, nullnull);

                        ClosePosition(TradeType.Buy);


                    }
                }
        }
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol, type);

            if (p != null)
            {
                ClosePosition(p);
            }
            if (Account.Balance <= loss)
                Stop();
        }
        private void TRAILING()
        {
            if (Trailing > 0 && Trigger > 0)
            {

                Position[] positions = Positions.FindAll(InstanceName, Symbol);

                foreach (Position position in positions)
                {

                    if (position.TradeType == TradeType.Sell)
                    {

                        double distance = position.EntryPrice - Symbol.Ask;

                        if (distance >= Trigger * Symbol.PipSize)
                        {

                            double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;

                            if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                            {

                                ModifyPosition(position, newStopLossPrice, position.TakeProfit);

                            }
                        }
                    }

                    else
                    {

                        double distance = Symbol.Bid - position.EntryPrice;

                        if (distance >= Trigger * Symbol.PipSize)
                        {

                            double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;

                            if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                            {

                                ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                            }
                        }
                    }
                }
            }
        }
    }
}

 

 

The code for the indicator is as posted earlier in the thread above. Please also see below image showing todays renko chart with MA shift indicators used for the strategy;

 

And finally please also see results from trades taken today for your analysis;

I trust this should be ok to hopefully find out what could be the underlying cause for the cbot not trading as expected. Im hoping this could possibly be the cbot requiring additional coding and not MA shift not being compatible with renko or being used in a cbot.

Il look forward to your reply.

Kind regards

Ryan


@ryan.a.blake

ryan.a.blake
05 Mar 2019, 21:26

Oops. Forgot to add my settings used for the MA shift. They are as follows = MA shift 1 (Red): MA =3, Shift =1 & MA shift 2 (Blue): MA= 4, Shift = -1.

No TP but Trailing Stoploss was triggered at 5 pips and trailed every 10pips.


@ryan.a.blake

juanbertrading
25 May 2020, 16:15

RE:

ryan.a.blake said:

Oops. Forgot to add my settings used for the MA shift. They are as follows = MA shift 1 (Red): MA =3, Shift =1 & MA shift 2 (Blue): MA= 4, Shift = -1.

No TP but Trailing Stoploss was triggered at 5 pips and trailed every 10pips.

Did you solve it? I'm also trying to set the shit on my robot but I cant....


@juanbertrading

access.vindicte
06 Nov 2020, 15:38

Hello please

Hello everyone, when I copy your code I get this error: Error CS0246: The type or namespace name 'ShiftKey' could not be found (is a using directive or assembly reference missing?)

Can you help me please

Thank you


@access.vindicte

access.vindicte
06 Nov 2020, 15:38

Hello please

Hello everyone, when I copy your code I get this error: Error CS0246: The type or namespace name 'ShiftKey' could not be found (is a using directive or assembly reference missing?)

Can you help me please

Thank you


@access.vindicte