Kaufman Adaptive Moving Average Cbot

Created at 28 Jan 2019, 22:37
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

Kaufman Adaptive Moving Average Cbot
28 Jan 2019, 22:37


I have recently created a Cbot based on the simple moving average Cbot and have just amended a few of the text to incorporate the KAMA indicator but does not work.

 

Could somebody help with a mistake it may have?

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class KAMACbot : Robot
    {
        #region Parameters

        [Parameter("Instance Name", DefaultValue = "23078549")]
        public string InstanceName { get; set; }

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

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

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

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

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

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

        [Parameter("Fast #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
        public int Fast2 { get; set; }

        [Parameter("Slow #2", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
        public int Slow2 { get; set; }

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

        #endregion

        #region Indicator declarations

        private KAMA _Kama1 { get; set; }
        private KAMA _Kama2 { get; set; }
        public int LastValue { get; private set; }

        #endregion
        #region Indicator

        double _volume;
        protected override void OnStart()
        {
            {
                _Kama1 = Indicators.GetIndicator<KAMA>(Source1, Fast1, Slow1, Period1);
                _Kama2 = Indicators.GetIndicator<KAMA>(Source2, Fast2, Slow2, Period2);
                _volume = Symbol.QuantityToVolumeInUnits(lotsize);
                Positions.Closed += Positions_Closed;
            }
        }
        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            if (obj.Position.NetProfit < 0)
                _volume += 1000;
            else
                _volume = Symbol.QuantityToVolumeInUnits(lotsize);
        }
        #endregion

        #region Position management

        private void ManagePositions()
        {
            if (_Kama1.LastValue > _Kama2.LastValue)
            {

                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }

 

                if (_Kama1.LastValue < _Kama2.LastValue)
                {

                    if (!IsPositionOpenByType(TradeType.Sell))
                    {
                        OpenPosition(TradeType.Sell);
                    }
                }
            }
        }
        private void OpenPosition(TradeType type)
        {

 

            // open a new position
            ExecuteMarketOrder(type, this.Symbol, _volume, InstanceName, null, null);
        }


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

            if (p != null)
            {
                ClosePosition(p);
            }
        }

        #endregion

        #region Position Information


        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol, type);

            if (p.Count() >= 1)
            {
                return true;
            }

            return false;
        }

        #endregion
    }
}


@ryan.a.blake
Replies

ryan.a.blake
29 Jan 2019, 15:10

RE:

ryan.a.blake said:

I have recently created a Cbot based on the simple moving average Cbot and have just amended a few of the text to incorporate the KAMA indicator but does not work.

 

Could somebody help with a mistake it may have?

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class KAMACbot : Robot
    {
        #region Parameters

        [Parameter("Instance Name", DefaultValue = "23078549")]
        public string InstanceName { get; set; }

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

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

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

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

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

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

        [Parameter("Fast #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
        public int Fast2 { get; set; }

        [Parameter("Slow #2", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
        public int Slow2 { get; set; }

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

        #endregion

        #region Indicator declarations

        private KAMA _Kama1 { get; set; }
        private KAMA _Kama2 { get; set; }
        public int LastValue { get; private set; }

        #endregion
        #region Indicator

        double _volume;
        protected override void OnStart()
        {
            {
                _Kama1 = Indicators.GetIndicator<KAMA>(Source1, Fast1, Slow1, Period1);
                _Kama2 = Indicators.GetIndicator<KAMA>(Source2, Fast2, Slow2, Period2);
                _volume = Symbol.QuantityToVolumeInUnits(lotsize);
                Positions.Closed += Positions_Closed;
            }
        }
        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            if (obj.Position.NetProfit < 0)
                _volume += 1000;
            else
                _volume = Symbol.QuantityToVolumeInUnits(lotsize);
        }
        #endregion

        #region Position management

        private void ManagePositions()
        {
            if (_Kama1.LastValue > _Kama2.LastValue)
            {

                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }

 

                if (_Kama1.LastValue < _Kama2.LastValue)
                {

                    if (!IsPositionOpenByType(TradeType.Sell))
                    {
                        OpenPosition(TradeType.Sell);
                    }
                }
            }
        }
        private void OpenPosition(TradeType type)
        {

 

            // open a new position
            ExecuteMarketOrder(type, this.Symbol, _volume, InstanceName, null, null);
        }


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

            if (p != null)
            {
                ClosePosition(p);
            }
        }

        #endregion

        #region Position Information


        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol, type);

            if (p.Count() >= 1)
            {
                return true;
            }

            return false;
        }

        #endregion
    }
}

The above coding does not buy or Sell. Can anyone help.


@ryan.a.blake

PanagiotisCharalampous
29 Jan 2019, 15:28

Hi ryan.a.blake,

First of all the cBot does not build. We get the following error

Error CS1061: 'cAlgo.Indicators.KAMA' does not contain a definition for 'LastValue' and no extension method 'LastValue' accepting a first argument of type 'cAlgo.Indicators.KAMA' could be found (are you missing a using directive or an assembly reference?)

I assume you need to use

_Kama1.kama.LastValue

instead of

_Kama1.LastValue

Then the cBot does not have an OnBar or OnTick method. So I would not expect it to do anything since it is not programmed to do anything. If you add the below

        protected override void OnBar()
        {
            ManagePositions();
        }

you will start seeing something. But still there are no exit conditions for positions. But I cannot assume what you would like to do.

Usually, it is easier for others to help when they know what you expect the cBot to do instead of a general "it doesn't work". 

Best Regards,

Panagiotis


@PanagiotisCharalampous

ryan.a.blake
04 Feb 2019, 21:22

RE:

Hi Panagiotis,

Thankyou for your help above. I have now completed the Cbot, however when backtesting I keep getting the following in the log - Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object. I have tried to solve this with - if (p =! null) but still comes up with the error. I have copied my code below, what could be the issue.

Also im trying to alter the code to only allow one trade per cross and by a certain distance. Any advice?

Many Thanks.

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class KAMACbot : Robot
    {
        #region Parameters

        [Parameter("Instance Name", DefaultValue = "2307")]
        public string InstanceName { get; set; }

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

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

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

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

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

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

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

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

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

        [Parameter("Fast #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
        public int Fast2 { get; set; }

        [Parameter("Slow #2", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
        public int Slow2 { get; set; }

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

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }


        #endregion

        #region Indicator declarations

        private KAMA _Kama1 { get; set; }
        private KAMA _Kama2 { get; set; }

        #endregion

        #region cTrader events


        protected override void OnStart()
        {
            // construct the indicators
            _Kama1 = Indicators.GetIndicator<KAMA>(Source1, Fast1, Slow1, Period1);
            _Kama2 = Indicators.GetIndicator<KAMA>(Source2, Fast2, Slow2, Period2);
        }


        protected override void OnTick()
        {
            if (CalculateOnBar)
            {
                return;
            }

            ManagePositions();
        }

 

        protected override void OnBar()
        {
            if (!CalculateOnBar)
            {
                return;
            }

            ManagePositions();
        }


        protected override void OnStop()
        {
            // unused
        }

        #endregion

        #region Position management

        private void ManagePositions()
        {
            if (_Kama1.kama.LastValue > _Kama2.kama.LastValue) 
            {

                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }
                ClosePosition();
            }


            if (_Kama1.kama.LastValue < _Kama2.kama.LastValue)
            {

                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }

                ClosePosition();
            }
        }


        private void OpenPosition(TradeType type)
        {

            double volume = Symbol.QuantityToVolumeInUnits(lotsize);

            // open a new position
            ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, SL, TP, null, null);
        }

        private void ClosePosition()
        {
            var OpenPosition = Positions.Find(InstanceName, this.Symbol);

            if (OpenPosition.Pips >= profit)
            {
                ClosePosition(OpenPosition);
            }
        }

        #endregion

        #region Position Information


        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol, type);
            if (p != null)
                if (p.Count() == 0)
                {
                    return true;
                }

            return false;
        }

        #endregion
    }
}


@ryan.a.blake

PanagiotisCharalampous
05 Feb 2019, 10:40

Hi Ryan,

You do not seem to check this function somewhere though

        private void ClosePosition()
        {
            var OpenPosition = Positions.Find(InstanceName, this.Symbol);

            if (OpenPosition.Pips >= profit)
            {
                ClosePosition(OpenPosition);
            }
        }

OpenPosition could be null and crash your cBot

Best Regards,

Panagiotis


@PanagiotisCharalampous

ryan.a.blake
05 Feb 2019, 22:57

RE:

 Hi Panagiotis, 

Im not sure what you mean, im actually just starting out coding and slowly beginning to understand how to create a Cbot but unsure of how to solve the errors.

The above Cbot needs to open positions when Kama1 crosses above Kama2 for a buy and vise versa, aloowing 1 trade per cross. However the above Cbot appears to be placing more than 1 trade at once when the indicator has not even crossed yet. This could be due to how i have coded the cross and not specify at which point the cbot needs to place trades.

Could you please advise.

Kind regards.


@ryan.a.blake

PanagiotisCharalampous
06 Feb 2019, 09:29

Hi Ryan,

From a first look IsPositionOpenByType seems to be doing the opposite of what it is intended to do. It returns true when no positions are open.

Best Regards,

Panagiotis


@PanagiotisCharalampous