How to reference custom indicator in cBot?

Created at 15 Feb 2023, 14:53
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!
CT

ctid5292619

Joined 08.10.2022

How to reference custom indicator in cBot?
15 Feb 2023, 14:53


Mr PanagiotisCharalampous sends everybody with similar question to https://help.ctrader.com/ctrader-automate/guides/indicators/ , but I don's see there correct response.

I know Indicators.GetIndicator<>() function, but it doesn't work. I always get "15/02/2023 13:49:37.095 | Crashed in Initialize with NullReferenceException: Object reference not set to an instance of an object." error. I give correct type of indicator and all parameters.

 

Could anybody please write working simplest possible example in documentation?

Or place there useful link?


@ctid5292619
Replies

PanagiotisChar
16 Feb 2023, 15:57

Hi there,

The exception indicates that you are doing something wrong in your indicator code. Share your cBot and indicator code so that we can advise further.

Aieden Technologies

Need help? Join us on Telegram

Need premium support? Trade with us

 


@PanagiotisChar

ctid5292619
17 Feb 2023, 10:17

RE:

Thank your for your response.

Could you PLEASE give me a link to working demo of custom indicator and cBot?

I'm learning to code in cTrader and I prefer to have generic simple example then something complicated (and my indicator is a little complicated), I may have trouble to use later in different circumstances.

Thank you!


@ctid5292619

ctid5292619
18 Feb 2023, 13:52 ( Updated at: 18 Feb 2023, 13:56 )

RE:

I have found working example of custom indicator in cBot ( https://ctrader.com/algos/indicators/show/1086 ).

Indicator name: Renko.

I didn't test if everything is working fine, but code compiles (with many warnings as indicator is quite old).

 

Indicator:

using cAlgo.API;

using cAlgo.API.Indicators;

using cAlgo.API.Internals;

using cAlgo.Indicators;

using System;

using System.Collections.Generic;

using System.Linq;

 

namespace cAlgo

{

    [Indicator("Renko", IsOverlay = true, AutoRescale = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]

    public class Renko : Indicator

    {

        [Parameter("Renko (Pips)", DefaultValue = 10, MinValue = 0.1, Step = 1)]

        public double RenkoPips { get; set; }

 

        [Parameter("Bricks To Show", DefaultValue = 100, MinValue = 1)]

        public int BricksToShow { get; set; }

 

        [Parameter("Zoom Level", DefaultValue = 3, MinValue = 0, MaxValue = 5, Step = 1)]

        public double ZoomLevel { get; set; }

 

        [Parameter("Bullish Color", DefaultValue = "SeaGreen")]

        public string ColorBull { get; set; }

 

        [Parameter("Bearish Color", DefaultValue = "Tomato")]

        public string ColorBear { get; set; }

 

        [Output("Open", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]

        public IndicatorDataSeries Open { get; set; }

 

        [Output("High", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]

        public IndicatorDataSeries High { get; set; }

 

        [Output("Low", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]

        public IndicatorDataSeries Low { get; set; }

 

        [Output("Close", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]

        public IndicatorDataSeries Close { get; set; }

 

        public class Brick

        {

            public double Open { get; set; }

            public double Close { get; set; }

        }

 

        public List<Brick> Bricks = new List<Brick>();

 

        private double closeLastValue, thickness, renkoPips, renkoLastValue;

        private Colors colorBull, colorBear;

        private bool colorError;

        private int lastCount;

 

        protected override void Initialize()

        {

            if (!Enum.TryParse<Colors>(ColorBull, out colorBull) || !Enum.TryParse<Colors>(ColorBear, out colorBear))

                colorError = true;

 

            renkoPips = RenkoPips * Symbol.PipSize;

            thickness = Math.Pow(2, ZoomLevel) - (ZoomLevel > 0 ? 1 : 0);

            renkoLastValue = 0;

        }

 

        public override void Calculate(int index)

        {

            if (colorError)

            {

                ChartObjects.DrawText("Error0", "{o,o}\n/)_)\n \" \"\nOops! Incorrect colors.", StaticPosition.TopCenter, Colors.Gray);

                return;

            }

 

            if (renkoLastValue == 0)

            {

                var open = MarketSeries.Open.LastValue;

 

                renkoLastValue = open - (open % renkoPips) + renkoPips / 2;

            }

 

            closeLastValue = MarketSeries.Close.LastValue;

 

            while (closeLastValue >= renkoLastValue + renkoPips * 1.5)

            {

                renkoLastValue += renkoPips;

                Bricks.Insert(0, new Brick

                {

                    Open = renkoLastValue - renkoPips / 2,

                    Close = renkoLastValue + renkoPips / 2

                });

 

                if (Bricks.Count() > BricksToShow)

                    Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);

                if (IsLastBar)

                    UpdateHistory(index);

            }

            while (closeLastValue <= renkoLastValue - renkoPips * 1.5)

            {

                renkoLastValue -= renkoPips;

                Bricks.Insert(0, new Brick

                {

                    Open = renkoLastValue + renkoPips / 2,

                    Close = renkoLastValue - renkoPips / 2

                });

 

                if (Bricks.Count() > BricksToShow)

                    Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);

                if (IsLastBar)

                    UpdateHistory(index);

            }

 

            bool isNewBar = MarketSeries.Close.Count > lastCount;

 

            if (IsLastBar && isNewBar)

            {

                UpdateHistory(index);

 

                Open[index - BricksToShow] = double.NaN;

                High[index - BricksToShow] = double.NaN;

                Low[index - BricksToShow] = double.NaN;

                Close[index - BricksToShow] = double.NaN;

 

                lastCount = MarketSeries.Close.Count;

            }

 

            if (IsRealTime)

                UpdateLive(index);

        }

 

        private void UpdateHistory(int index)

        {

            for (int i = 0; i < BricksToShow - 1 && i < Bricks.Count() - 1; i++)

            {

                var color = Bricks[i].Open < Bricks[i].Close ? colorBull : colorBear;

 

                ChartObjects.DrawLine(string.Format("renko.Last({0})", i + 1), index - i - 1, Bricks[i].Open, index - i - 1, Bricks[i].Close, color, thickness, LineStyle.Solid);

 

                Open[index - i - 1] = Bricks[i].Open;

                High[index - i - 1] = Math.Max(Bricks[i].Open, Bricks[i].Close);

                Low[index - i - 1] = Math.Min(Bricks[i].Open, Bricks[i].Close);

                Close[index - i - 1] = Bricks[i].Close;

            }

        }

 

        private void UpdateLive(int index)

        {

            double y1, y2;

            var top = Math.Max(Bricks[0].Open, Bricks[0].Close);

            var bottom = Math.Min(Bricks[0].Open, Bricks[0].Close);

 

            if (closeLastValue > top)

                y1 = top;

            else if (closeLastValue < bottom)

                y1 = bottom;

            else

                y1 = closeLastValue;

 

            y2 = closeLastValue;

 

            var colorLive = y1 < y2 ? colorBull : colorBear;

 

            ChartObjects.DrawLine("renko.Live", index, y1, index, y2, colorLive, thickness, LineStyle.Solid);

 

            Open[index] = y1;

            High[index] = y1 > y2 ? y1 : y2;

            Low[index] = y1 < y2 ? y1 : y2;

            Close[index] = y2;

        }

    }

}

 

 

 

and cBot:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class ReferencecustomindicatordemocBot : Robot
    {
        public double RenkoPips = 10;
        public int BricksToShow = 10;
 
        private Renko renko;
 
        protected override void OnStart()
        {
            renko = Indicators.GetIndicator<Renko>(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");
        }
 
        protected override void OnTick()
        {
            bool isLastBrickBullish = renko.Open.Last(1) < renko.Close.Last(1);
 
            if (isLastBrickBullish)
            {
                ExecuteMarketOrder(TradeType.Buy, Symbol, 1000);
            }
        }
    }
}


@ctid5292619

ctid5292619
18 Feb 2023, 14:10

RE:

I have found example of custom indicator in cBot, but I need also more complicated demo, when cBot is using outputs of custom indicator.

Could you please Mr PanagiotisChar place a link to such example?

Thank you!


@ctid5292619