Using Keltner CHannel in a Cbot

Created at 12 Jul 2019, 03:18
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!
RX

Rx1ooo

Joined 05.02.2018

Using Keltner CHannel in a Cbot
12 Jul 2019, 03:18


Morning,

I am trying to write a cbot that references Keltner Channels indicator.

I have been able to reference moving average indicators in the robot, but I am struggling to include Keltner channels.

Does anyone have any code to do this.

Happy to provide more info, if required.

Have a great day

Brian


@Rx1ooo
Replies

alexsanramon
12 Jul 2019, 03:23

Please set an example of the moving average on your bot so I can help you.


@alexsanramon

Rx1ooo
12 Jul 2019, 03:31

Many thanks for the quick response.

This is a snippet of the code I have written, trying to get Keltner Channel indicator referenced in my cbot.

Currently generating errors on build

        [Parameter("SlowMA Periods", DefaultValue = 50, MinValue = 1, MaxValue = 200, Step = 1)]
        public int SlowMAPeriods { get; set; }
        [Parameter("FastMA Periods", DefaultValue = 20, MinValue = 1, MaxValue = 100, Step = 1)]
        public int FastMAPeriods { get; set; }
        [Parameter("Advanced Protection", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int AdProtection { get; set; }
        [Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }

         ExponentialMovingAverage SlowMA, FastMA, KeltEMA;

        SimpleMovingAverage KeltSMA;
        KeltnerChannels Kelt;

        protected override void OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

        } 

 

Many thanks


@Rx1ooo

alexsanramon
12 Jul 2019, 03:43

Let me clarify a bit. 

How does the moving average affect your bot? Please show example so that I can show how to include the keltner channels to your example.


@alexsanramon

Rx1ooo
12 Jul 2019, 03:54

OK I will try to explain.

Code so far.


using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.EAustraliaStandardTime, AccessRights = AccessRights.None)]
    public class Keltner100 : Robot
    {
        [Parameter("Trade Start Hour", DefaultValue = 0, MinValue = 0, MaxValue = 24, Step = 1)]
        public int TradeStart { get; set; }
        [Parameter("Trade End Hour", DefaultValue = 23, MinValue = 0, MaxValue = 24, Step = 1)]
        public int TradeEnd { get; set; }
        [Parameter("Take Profit (Pips)", DefaultValue = 500, MinValue = 1, MaxValue = 500, Step = 1)]
        public int TakeProfit { get; set; }
        [Parameter("Stop Loss (Pips)", DefaultValue = 100, MinValue = 1, MaxValue = 100, Step = 1)]
        public int StopLoss { get; set; }
        [Parameter("Calculate Volume by Percentage?", DefaultValue = false)]
        public bool RiskPercent { get; set; }
        [Parameter("Quantity (%Risk or Lots)", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }
        [Parameter("SlowMA Periods", DefaultValue = 50, MinValue = 1, MaxValue = 200, Step = 1)]
        public int SlowMAPeriods { get; set; }
        [Parameter("FastMA Periods", DefaultValue = 20, MinValue = 1, MaxValue = 100, Step = 1)]
        public int FastMAPeriods { get; set; }
        [Parameter("Advanced Protection", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int AdProtection { get; set; }
        [Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }



        private DataSeries Price { get; set; }

//        protected override double GetFitness(GetFitnessArgs args)
//        {
//            //maximize count of winning trades and minimize count of losing trades
//            return args.WinningTrades / args.LosingTrades;
//        }

        ExponentialMovingAverage SlowMA, FastMA, KeltEMA;
        SimpleMovingAverage KeltSMA;
        KeltnerChannels Kelt;

        protected override void OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

        }

        protected override void OnBar()
        {

            int PosCount = 0;

            if (Time.Hour >= TradeStart || Time.Hour < TradeEnd)
            {

                foreach (var position in Positions.FindAll("Keltner100", Symbol))
                {
                    PosCount += 1;
                }

                CheckTrades();
                AdvancedProtection();

                if (PosCount < 4)
                {
                    if (FastMA.Result.Last(1) > SlowMA.Result.Last(1) && FastMA.Result.Last(3) < SlowMA.Result.Last(3) && FastMA.Result.IsRising())
                    {
                        Open(TradeType.Buy);
                    }
                    else if (FastMA.Result.Last(1) < SlowMA.Result.Last(1) && FastMA.Result.Last(3) > SlowMA.Result.Last(3) && FastMA.Result.IsFalling())
                    {
                        Open(TradeType.Sell);
                    }
                }
            }
        }

        private void Open(TradeType tradeType)
        {
            var volumeInUnits = CalculateVolume();

            ExecuteMarketOrder(tradeType, Symbol, volumeInUnits, "Keltner100", StopLoss, TakeProfit);
        }

        double CalculateVolume()
        {
            if (!RiskPercent)
            {
                return (Symbol.QuantityToVolumeInUnits(Quantity));
            }
            else
            {
                // Calculate the total risk allowed per trade.
                double riskPerTrade = (Account.Balance * Quantity) / 100;
                double totalSLPipValue = (StopLoss + Symbol.Spread) * Symbol.PipValue;
                double calculatedVolume = riskPerTrade / totalSLPipValue;

                double normalizedCalculatedVolume = Symbol.NormalizeVolumeInUnits(calculatedVolume, RoundingMode.ToNearest);
                return normalizedCalculatedVolume;
            }
        }

        private void CheckTrades()
        {
            foreach (var position in Positions.FindAll("Keltner100", Symbol))
            {
                if (position.TradeType == TradeType.Buy)
                {
                    if (FastMA.Result.IsFalling())
                    {
                        ClosePosition(position);
                    }
                }
                else if (position.TradeType == TradeType.Sell)
                {
                    if (FastMA.Result.IsRising())
                    {
                        ClosePosition(position);
                    }

                }
            }
        }

        private void AdvancedProtection()
        {
            double ST_ls = 0;
            double TA_pr = 0;
            double TrailingStop = 0;


            foreach (var position in Positions.FindAll("Keltner100", Symbol))
            {
                TA_pr = 0;
                ST_ls = 0;
                TrailingStop = 0;
                if (position.SymbolCode == Symbol.Code)
                {
                    if (position.Pips > AdProtection)
                    {
                        TrailingStop = position.Pips / 3;
                    }
                    if (TrailingStop > 0)
                    {
                        if (position.TradeType == TradeType.Sell)
                        {
                            TA_pr = position.EntryPrice - TakeProfit * Symbol.PipSize;
                            ST_ls = position.EntryPrice - TrailingStop * Symbol.PipSize;
                            if (ST_ls < position.StopLoss)
                            {
                                ModifyPosition(position, ST_ls, TA_pr);
                            }
                        }
                        if (position.TradeType == TradeType.Buy)
                        {
                            TA_pr = position.EntryPrice + TakeProfit * Symbol.PipSize;
                            ST_ls = position.EntryPrice + TrailingStop * Symbol.PipSize;
                            if (ST_ls > position.StopLoss)
                            {
                                ModifyPosition(position, ST_ls, TA_pr);
                            }
                        }
                    }
                }
            }
        }
    }
}

 

My intention is to add code to onbar section once I can reference the Keltner CHannel indicator. To test the closing price is above or below the upper & lower bands of the Keltner Channel to initiate a trade.

I hope this clarifies my intentions.

Many thanks


@Rx1ooo

alexsanramon
12 Jul 2019, 04:15

Ok. So please try this as reference:

 

Kelt.Top.LastValue
Kelt.Bottom.LastValue

 


@alexsanramon

Rx1ooo
12 Jul 2019, 04:26

Many thanks

Understand the code you have suggested, that was going to be my approach. :)

My issue is that the build is generating errors on the following line of code.

 Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

the errors include the following:

Error CS1502: The best overloaded method match for 'cAlgo.API.Internals.IIndicatorsAccessor.KeltnerChannels(int, cAlgo.API.MovingAverageType, int, cAlgo.API.MovingAverageType, double)' has some invalid arguments

Error CS1503: Argument 2: cannot convert from 'cAlgo.API.Indicators.ExponentialMovingAverage' to 'cAlgo.API.MovingAverageType'

Error CS1503: Argument 4: cannot convert from 'cAlgo.API.Indicators.SimpleMovingAverage' to 'cAlgo.API.MovingAverageType'

Unable to move past this point.


@Rx1ooo

Rx1ooo
12 Jul 2019, 07:57

Perhaps I have asked the wrong question.

 

I want to be able to optimise the cbot.

That includes the Keltner Channel indicator periods, hence the declaration in the Onstart section.

OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

....

Sorry for any confusion.

This line of code is currently generator errors, that I am trying to resolve.

Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

 

Many thanks for any help

 


@Rx1ooo

mparama
14 Jul 2019, 04:18

 [Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }

         ExponentialMovingAverage SlowMA, FastMA, KeltEMA;

        SimpleMovingAverage KeltSMA;
        KeltnerChannels Kelt;

        protected override void OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA ??, KeltATRPeriod, KeltSMA ??, 2);

        } 

 

KeltEMA has no value

KeltSMA has no value

you should insert them in the parameter giving a value as:

[Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }

These does'nt give any value:

ExponentialMovingAverage SlowMA, FastMA, KeltEMA;

SimpleMovingAverage KeltSMA;

To check if it works give compatible numerical value:

Kelt = Indicators.KeltnerChannels(KeltPeriod, num. value, KeltATRPeriod, num. value, 2);

All the parameters in the indicator that give a value should coincide with 

(KeltPeriod, num. value, KeltATRPeriod, num. value, 2);


@mparama

Rx1ooo
15 Jul 2019, 01:47

Morning,

I have know solved my issue and the code buildis without any errors.

These are the changes I have made.

From this:

        [Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }

         ExponentialMovingAverage SlowMA, FastMA, KeltEMA;

        SimpleMovingAverage KeltSMA;
        KeltnerChannels Kelt;

        protected override void OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);
        } 

To this:

         [Parameter("Kelt Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltPeriod { get; set; }
        [Parameter("Kelt ATR Priod", DefaultValue = 35, MinValue = 1, MaxValue = 100, Step = 1)]
        public int KeltATRPeriod { get; set; }
        [Parameter("KeltEMA MAtype")]
        public MovingAverageType KeltEMA { get; set; }
        [Parameter("KeltSMA MAtype")]
        public MovingAverageType KeltSMA { get; set; }


        private DataSeries Price { get; set; }

        ExponentialMovingAverage SlowMA, FastMA;
        KeltnerChannels Kelt;

        protected override void OnStart()
        {
            SlowMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, SlowMAPeriods);
            FastMA = Indicators.ExponentialMovingAverage(MarketSeries.Close, FastMAPeriods);
            Kelt = Indicators.KeltnerChannels(KeltPeriod, KeltEMA, KeltATRPeriod, KeltSMA, 2);

        }

Not sure that I understand all of the reasons why, but happy now to build some logic around this indicator.

To all those that helped many thanks.

Have a good trading day. :)


@Rx1ooo