Using Output Attribute with cBots

Created at 30 Aug 2018, 13:25
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!
MY

myinvestmentsfx

Joined 06.11.2017

Using Output Attribute with cBots
30 Aug 2018, 13:25


Hi Spotware,

Is it possible use the Output Attribute with cBot.  When I use a similar approach using the newly added ChartDraw API's,  it draws the objects on the chart and gives me the value, hence, creating confluence between the output used in the indicator and the output used in the bot.

Below example of trying to use Output attribute on Bots, doesn't seem to work.  How do I get access to PlotType functionality without using the Output attribute or how to I invoke output within cBot?

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

namespace cAlgo
{
    [Indicator("Test", ScalePrecision = 5, IsOverlay = true)]
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SamplecBotReferenceSMA : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("SMA Period", DefaultValue = 14)]
        public int SmaPeriod { get; set; }

        [Output("Result", Color = Colors.Red, LineStyle = LineStyle.Solid, PlotType = PlotType.Line)]
        public IndicatorDataSeries Result { get; set; }

        private SampleSMA sma;

        protected override void OnStart()
        {
            sma = Indicators.GetIndicator<SampleSMA>(Source, SmaPeriod);
        }

        protected override void OnTick()
        {
            Result = sma.Result;
            Print("{0}", sma.Result.LastValue);
        }
    }
}

 


@myinvestmentsfx
Replies

PanagiotisCharalampous
30 Aug 2018, 14:12

Ηι myinvestmentsfx,

It is not possible to use Output attribute in cBots. If you explain to us more precisely what you are trying to do, we could propose a solution.

Best Regards,

Panagiotis


@PanagiotisCharalampous

myinvestmentsfx
30 Aug 2018, 14:46 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Ηι myinvestmentsfx,

It is not possible to use Output attribute in cBots. If you explain to us more precisely what you are trying to do, we could propose a solution.

Best Regards,

Panagiotis

Hi Panagiotis,

Below you will find the example, where when I create an indicator and run it in the cbot.  I get the value & it draws on the chart even though code is executed in bot.

 

using System;
using cAlgo;
using cAlgo.API;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Threading;
using cAlgo.API.Internals;

namespace MGTradingLibrary
{
    /// <summary>
    /// This class is a collection of methods that can be used when building an Indicator.
    /// </summary>
    [Indicator(AccessRights = AccessRights.FullAccess, AutoRescale = true, IsOverlay = true, ScalePrecision = 5, TimeZone = TimeZones.SouthAfricaStandardTime)]
    public class IndicatorBuildingBlocks : Indicator
    {
        /// <summary>
        /// Summary: This method calculates the swinghigh points based on the MarketSeries.High or MarketSeries.Close property.
        /// <para> Will return IndicatorDataSeries with all the Swing High Points mapped to the appropriate index to plot points on the graph. </para>
        /// </summary>
        /// <param name="symbol">Enter the currency pair you want the calculation done on.</param>
        /// <param name="timeFrame">Enter the timeframe you want the calculation done on.</param>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="swingHighOnGetSeriesClose">If true, it will calculate the Swing Highs based on MarketSeries.Close values, else it will calculate on MarketSeries.High</param>
        /// <param name="iconName">Used if you want to multiple swingHighs for different periods on the same chart. (Auto Drawing on Chart)</param>
        /// <param name="drawSwingHighs">Toggle Auto-Drawing on or off. (Auto Drawing on Chart)</param>
        /// <code>
        /// using MGTradingLibrary; ---- import Library
        /// namespace cAlgo
        ///    {
        ///       [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]  --- Ensure Isoverlay is set to true.
        ///       public class Run : IndicatorBuildingBlocks --- Inherit IndicatorBuildingBlock Class from MGTradingLibrary.
        ///        {
        ///           public override void Calculate(int index)
        ///           {
        ///               zzzGetAndDrawSwingHighs(); --- You can modify default values should you choose to do so.
        ///           }
        ///
        ///       }
        ///   }
        /// </code>
        public IndicatorDataSeries zziGetAndDrawSwingHighs(Symbol symbol = null, TimeFrame timeFrame = null, string iconName = "iconName", int candleCount = 5, bool swingHighOnGetSeriesClose = false, bool drawSwingHighs = true)
        {
            IndicatorDataSeries Result;
            Result = CreateDataSeries();

            if (symbol == null)
                symbol = Symbol;
            if (timeFrame == null)
                timeFrame = TimeFrame;

            try
            {
                MarketSeries getSeriesData = MarketData.GetSeries(symbol, timeFrame);
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;

                if (swingHighOnGetSeriesClose)
                {
                    for (int bar = 0; bar < getSeriesData.Close.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.Close[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.Close[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;
                        }                       
                    }
                }
                else
                {
                    for (int bar = 0; bar < getSeriesData.High.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.High[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.High[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;

                            if(drawSwingHighs)
                            { 
                                var drawSwingHigh = Chart.DrawIcon(iconName + middleIndexHigh.ToString(), ChartIconType.DownArrow, middleIndexHigh, middleValueHigh, Color.Blue);
                            }
                        }
                    }
                }
                return Result;
            }
            catch (Exception error)
            {
                Print("zziGetAndDrawSwingHighs Method Error: ", error.ToString());
                return Result;
            }
        }

I execute method from cBot

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        public IndicatorBuildingBlocks ibb;



        protected override void OnStart()
        {
            ibb = Indicators.GetIndicator<IndicatorBuildingBlocks>();
        }

        protected override void OnTick()
        {
            ibb.zziGetAndDrawSwingHighs();
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

By doing this, I can now Get the data and it will draw it on the chart automatically when calling the method. (See Below).

However, if you want to use the same concept to automatically draw and get the data from the indicator and the indicator is something like an SMA, where you need to draw a line between two points mapped on the chart, the solution on the indicator side is to use Plotype.Line in combination with the Output attribute.  What would you do in this case?  IE is there something that can replace this Plotype.Line functionality.

Thank you for your help.


@myinvestmentsfx

myinvestmentsfx
30 Aug 2018, 14:46 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Ηι myinvestmentsfx,

It is not possible to use Output attribute in cBots. If you explain to us more precisely what you are trying to do, we could propose a solution.

Best Regards,

Panagiotis

Hi Panagiotis,

Below you will find the example, where when I create an indicator and run it in the cbot.  I get the value & it draws on the chart even though code is executed in bot.

 

using System;
using cAlgo;
using cAlgo.API;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Threading;
using cAlgo.API.Internals;

namespace MGTradingLibrary
{
    /// <summary>
    /// This class is a collection of methods that can be used when building an Indicator.
    /// </summary>
    [Indicator(AccessRights = AccessRights.FullAccess, AutoRescale = true, IsOverlay = true, ScalePrecision = 5, TimeZone = TimeZones.SouthAfricaStandardTime)]
    public class IndicatorBuildingBlocks : Indicator
    {
        /// <summary>
        /// Summary: This method calculates the swinghigh points based on the MarketSeries.High or MarketSeries.Close property.
        /// <para> Will return IndicatorDataSeries with all the Swing High Points mapped to the appropriate index to plot points on the graph. </para>
        /// </summary>
        /// <param name="symbol">Enter the currency pair you want the calculation done on.</param>
        /// <param name="timeFrame">Enter the timeframe you want the calculation done on.</param>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="swingHighOnGetSeriesClose">If true, it will calculate the Swing Highs based on MarketSeries.Close values, else it will calculate on MarketSeries.High</param>
        /// <param name="iconName">Used if you want to multiple swingHighs for different periods on the same chart. (Auto Drawing on Chart)</param>
        /// <param name="drawSwingHighs">Toggle Auto-Drawing on or off. (Auto Drawing on Chart)</param>
        /// <code>
        /// using MGTradingLibrary; ---- import Library
        /// namespace cAlgo
        ///    {
        ///       [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]  --- Ensure Isoverlay is set to true.
        ///       public class Run : IndicatorBuildingBlocks --- Inherit IndicatorBuildingBlock Class from MGTradingLibrary.
        ///        {
        ///           public override void Calculate(int index)
        ///           {
        ///               zzzGetAndDrawSwingHighs(); --- You can modify default values should you choose to do so.
        ///           }
        ///
        ///       }
        ///   }
        /// </code>
        public IndicatorDataSeries zziGetAndDrawSwingHighs(Symbol symbol = null, TimeFrame timeFrame = null, string iconName = "iconName", int candleCount = 5, bool swingHighOnGetSeriesClose = false, bool drawSwingHighs = true)
        {
            IndicatorDataSeries Result;
            Result = CreateDataSeries();

            if (symbol == null)
                symbol = Symbol;
            if (timeFrame == null)
                timeFrame = TimeFrame;

            try
            {
                MarketSeries getSeriesData = MarketData.GetSeries(symbol, timeFrame);
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;

                if (swingHighOnGetSeriesClose)
                {
                    for (int bar = 0; bar < getSeriesData.Close.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.Close[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.Close[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;
                        }                       
                    }
                }
                else
                {
                    for (int bar = 0; bar < getSeriesData.High.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.High[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.High[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;

                            if(drawSwingHighs)
                            { 
                                var drawSwingHigh = Chart.DrawIcon(iconName + middleIndexHigh.ToString(), ChartIconType.DownArrow, middleIndexHigh, middleValueHigh, Color.Blue);
                            }
                        }
                    }
                }
                return Result;
            }
            catch (Exception error)
            {
                Print("zziGetAndDrawSwingHighs Method Error: ", error.ToString());
                return Result;
            }
        }

I execute method from cBot

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        public IndicatorBuildingBlocks ibb;



        protected override void OnStart()
        {
            ibb = Indicators.GetIndicator<IndicatorBuildingBlocks>();
        }

        protected override void OnTick()
        {
            ibb.zziGetAndDrawSwingHighs();
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

By doing this, I can now Get the data and it will draw it on the chart automatically when calling the method. (See Below).

However, if you want to use the same concept to automatically draw and get the data from the indicator and the indicator is something like an SMA, where you need to draw a line between two points mapped on the chart, the solution on the indicator side is to use Plotype.Line in combination with the Output attribute.  What would you do in this case?  IE is there something that can replace this Plotype.Line functionality.

Thank you for your help.


@myinvestmentsfx

PanagiotisCharalampous
30 Aug 2018, 15:05

Hi myinvestmentsfx,

If you want to join the points with a line you can use Chart.DrawTrendLine() method. However it is just going to be a collection of straight lines rather than a smoothed line used in the case of an indicator.

Best Regards,

 


@PanagiotisCharalampous

myinvestmentsfx
30 Aug 2018, 18:25

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

If you want to join the points with a line you can use Chart.DrawTrendLine() method. However it is just going to be a collection of straight lines rather than a smoothed line used in the case of an indicator.

Best Regards,

 

Thank you for the reply, I assume should I want this it will be a new feature request? Or I have to just keep it seperate for now.


@myinvestmentsfx

PanagiotisCharalampous
31 Aug 2018, 10:26

Hi myinvestmentsfx,

Yes that would be a feature. You could post it in UserVoice so that we can see the demand and consider it.

Best Regards,

Panagiotis


@PanagiotisCharalampous