Replies

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

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
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