HOW TO : Turn an indicator into a robot

Created at 16 Nov 2013, 09:54
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!
GB

gb1980be

Joined 16.10.2013

HOW TO : Turn an indicator into a robot
16 Nov 2013, 09:54


Hi,

I want to turn the Super Profit indicator from atrader (available here : /algos/indicators/show/249 ) into a robot because I can't stay all the day in front of my screen :-).

I would also like to thank atrader for this useful indicator.

I do not have sufficient knowledge to do that. If any interested person could create and post. It would be very convenient.

using System;
using cAlgo.API;
using System.Runtime.InteropServices;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true)]
    public class SuperProfit : Indicator
    {
        // Alert
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

        [Parameter(DefaultValue = 35)]
        public int DllPeriod { get; set; }

        [Parameter(DefaultValue = 1.7)]
        public double Period { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Weighted)]
        public MovingAverageType MaType { get; set; }

        [Parameter]
        public DataSeries Price { get; set; }

        [Parameter(DefaultValue = 5)]
        public int StopLoss { get; set; }

        [Output("Up", PlotType = PlotType.Points, Thickness = 4)]
        public IndicatorDataSeries UpSeries { get; set; }

        [Output("Down", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        public IndicatorDataSeries DownSeries { get; set; }


        private DateTime openTime;

        //datetime g_time_112;
        private MovingAverage _movingAverage1;
        private MovingAverage _movingAverage2;
        private MovingAverage _movingAverage3; 
        private IndicatorDataSeries _dataSeries;
        private IndicatorDataSeries _trend;
        

        protected override void Initialize()
        {
            _dataSeries = CreateDataSeries();
            _trend = CreateDataSeries();

            var period1 = (int)Math.Floor(DllPeriod/Period);
            var period2 = (int)Math.Floor(Math.Sqrt(DllPeriod));
            
            _movingAverage1 = Indicators.MovingAverage(Price, period1, MaType);
            _movingAverage2 = Indicators.MovingAverage(Price, DllPeriod, MaType);
            _movingAverage3 = Indicators.MovingAverage(_dataSeries, period2, MaType);
            
        }
        public override void Calculate(int index)
        {
            if(index < 1) return;

            _dataSeries[index] = 2.0*_movingAverage1.Result[index] - _movingAverage2.Result[index];
            _trend[index] = _trend[index-1];

            if (_movingAverage3.Result[index] > _movingAverage3.Result[index - 1])
                _trend[index] = 1;                
            else if (_movingAverage3.Result[index] < _movingAverage3.Result[index - 1])
                _trend[index] = -1;

            if(_trend[index] > 0)
            {
                UpSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] < 0.0)                                    
                {
                    UpSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsRealTime)
                    {
                        var stopLoss = MarketSeries.Low[index - 1] - StopLoss * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != openTime)
                        {
                            openTime = MarketSeries.OpenTime[index];
                            DisplayAlert("Buy signal", 0, stopLoss, entryPrice);
                        }
                    }
                }

                DownSeries[index] = double.NaN;
            }
            else if (_trend[index] < 0)
            {
                DownSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] > 0.0)
                {
                    DownSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsRealTime)
                    {
                        var stopLoss = MarketSeries.High[index - 1] - StopLoss * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != openTime)
                        {
                            openTime = MarketSeries.OpenTime[index];
                            DisplayAlert("Sell signal", 0, stopLoss, entryPrice);
                        }
                    }
                }

                UpSeries[index] = double.NaN;
            }

        }

        protected void DisplayAlert(string tradyTypeSignal, double takeProfit, double stopLoss, double entryPrice)
        {
            string entryPricetext;
            string takeProfitText;
            string stopLossText;

            entryPricetext = entryPrice != 0.0 ? string.Format(" at price {0}", Math.Round(entryPrice, 4)) : "";
            takeProfitText = takeProfit  != 0.0 ? string.Format(", TP on  {0}", Math.Round(takeProfit, 4)) : "";
            stopLossText = stopLoss != 0.0 ? string.Format(", SL on {0}", Math.Round(stopLoss, 4)) : "";

            var alertMessage = string.Format("{0} {1} {2} {3} {4}", tradyTypeSignal, entryPricetext, takeProfitText,
                                             stopLossText, Symbol.Code);

            MessageBox(new IntPtr(0), alertMessage, "Trade Signal", 0);

        }
    }
}

 

 


@gb1980be
Replies

jeex
16 Nov 2013, 19:49 ( Updated at: 21 Dec 2023, 09:20 )

Easy but useless

As often with indicators, they show how beautiful things would have been. This indicator shows a beautiful and predictable market, but calculates this backwards:

UpSeries[index - 1] = _movingAverage3.Result[index - 1];

When things went wrong, it makes an alteration in to the curve in the past - changing history. In trading that is simply impossible. See the results in the 1H timefame. Dito for the 4H timeframe.

Charts show results of the indicator with an extra CCI mechanism. It makes some huge wins and very many small losses. Unfortunately these are not predictable by an indicator. Like with CCI you could use the MacD to limit the bad entry points, then test it on a volatile pair and it might give positive results but not steady enough.


@jeex

hobaho
18 Nov 2013, 10:54 ( Updated at: 21 Dec 2023, 09:20 )

RE: Easy but useless

jeex said:

As often with indicators, they show how beautiful things would have been. This indicator shows a beautiful and predictable market, but calculates this backwards:

UpSeries[index - 1] = _movingAverage3.Result[index - 1];

When things went wrong, it makes an alteration in to the curve in the past - changing history. In trading that is simply impossible. See the results in the 1H timefame. Dito for the 4H timeframe.

Charts show results of the indicator with an extra CCI mechanism. It makes some huge wins and very many small losses. Unfortunately these are not predictable by an indicator. Like with CCI you could use the MacD to limit the bad entry points, then test it on a volatile pair and it might give positive results but not steady enough.

I agree it corrects itself one bar back. But the point is that when using indicators to trade you need to check more than just the last value. So, if you are going to look back 2 or more bars before you enter/exit a trade then this indicator is still providing a pretty good indication. Moreover, you cannot rely on just one indicator. You usually compare a few indicators and if their signals match then you trade. And that is just technical analysis which also by itself is not good enough you need fundamental analysis, too :)


@hobaho

jeex
18 Nov 2013, 22:03

Calculate

All might be nice for people, but we are talking about robots.

A robot acts on the values provided by the function Calculate (in the  indicator). Now if Calculate recalculates the former tick or bar, then during the former tick or bar the robot already made a wrong decision. It does not know that the value it gets returned from Calculate is to be corrected (or not) during the next tick or bar. It can not make assumptions, it can only act or not act on data.

This indicator might work nice as an indicator for people who like to work with indicators, i do not oppose to that. It simply does not work for robots.


@jeex

gerardeur
20 Jan 2014, 13:14

RE:

I can do this for you! (gerardeur@hotmail.fr)

gb1980be said:

Hi,

I want to turn the Super Profit indicator from atrader (available here : /algos/indicators/show/249 ) into a robot because I can't stay all the day in front of my screen :-).

I would also like to thank atrader for this useful indicator.

I do not have sufficient knowledge to do that. If any interested person could create and post. It would be very convenient.

using System;
using cAlgo.API;
using System.Runtime.InteropServices;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true)]
    public class SuperProfit : Indicator
    {
        // Alert
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

        [Parameter(DefaultValue = 35)]
        public int DllPeriod { get; set; }

        [Parameter(DefaultValue = 1.7)]
        public double Period { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Weighted)]
        public MovingAverageType MaType { get; set; }

        [Parameter]
        public DataSeries Price { get; set; }

        [Parameter(DefaultValue = 5)]
        public int StopLoss { get; set; }

        [Output("Up", PlotType = PlotType.Points, Thickness = 4)]
        public IndicatorDataSeries UpSeries { get; set; }

        [Output("Down", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        public IndicatorDataSeries DownSeries { get; set; }


        private DateTime openTime;

        //datetime g_time_112;
        private MovingAverage _movingAverage1;
        private MovingAverage _movingAverage2;
        private MovingAverage _movingAverage3; 
        private IndicatorDataSeries _dataSeries;
        private IndicatorDataSeries _trend;
        

        protected override void Initialize()
        {
            _dataSeries = CreateDataSeries();
            _trend = CreateDataSeries();

            var period1 = (int)Math.Floor(DllPeriod/Period);
            var period2 = (int)Math.Floor(Math.Sqrt(DllPeriod));
            
            _movingAverage1 = Indicators.MovingAverage(Price, period1, MaType);
            _movingAverage2 = Indicators.MovingAverage(Price, DllPeriod, MaType);
            _movingAverage3 = Indicators.MovingAverage(_dataSeries, period2, MaType);
            
        }
        public override void Calculate(int index)
        {
            if(index < 1) return;

            _dataSeries[index] = 2.0*_movingAverage1.Result[index] - _movingAverage2.Result[index];
            _trend[index] = _trend[index-1];

            if (_movingAverage3.Result[index] > _movingAverage3.Result[index - 1])
                _trend[index] = 1;                
            else if (_movingAverage3.Result[index] < _movingAverage3.Result[index - 1])
                _trend[index] = -1;

            if(_trend[index] > 0)
            {
                UpSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] < 0.0)                                    
                {
                    UpSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsRealTime)
                    {
                        var stopLoss = MarketSeries.Low[index - 1] - StopLoss * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != openTime)
                        {
                            openTime = MarketSeries.OpenTime[index];
                            DisplayAlert("Buy signal", 0, stopLoss, entryPrice);
                        }
                    }
                }

                DownSeries[index] = double.NaN;
            }
            else if (_trend[index] < 0)
            {
                DownSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] > 0.0)
                {
                    DownSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsRealTime)
                    {
                        var stopLoss = MarketSeries.High[index - 1] - StopLoss * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != openTime)
                        {
                            openTime = MarketSeries.OpenTime[index];
                            DisplayAlert("Sell signal", 0, stopLoss, entryPrice);
                        }
                    }
                }

                UpSeries[index] = double.NaN;
            }

        }

        protected void DisplayAlert(string tradyTypeSignal, double takeProfit, double stopLoss, double entryPrice)
        {
            string entryPricetext;
            string takeProfitText;
            string stopLossText;

            entryPricetext = entryPrice != 0.0 ? string.Format(" at price {0}", Math.Round(entryPrice, 4)) : "";
            takeProfitText = takeProfit  != 0.0 ? string.Format(", TP on  {0}", Math.Round(takeProfit, 4)) : "";
            stopLossText = stopLoss != 0.0 ? string.Format(", SL on {0}", Math.Round(stopLoss, 4)) : "";

            var alertMessage = string.Format("{0} {1} {2} {3} {4}", tradyTypeSignal, entryPricetext, takeProfitText,
                                             stopLossText, Symbol.Code);

            MessageBox(new IntPtr(0), alertMessage, "Trade Signal", 0);

        }
    }
}

 

 

 


@gerardeur

goodtrades
20 Aug 2014, 20:25

converted to bot

Hi gerardeur - did you convert to bot already - how were the results?

 


@goodtrades

emeeder
20 Aug 2014, 23:03

This Indicator is similar to teh Supertrend indicator that i am trying to use in a Cbot. I posted a question about it today. The code is there as well.

/forum/cbot-support/1111

Does anyone know what output the Cbot should be looking for to start and stop trades based on the UpTrend or DownTrend outputs?

I mainly want to use this along with other indicators as a Buysafe/Sellsafe indicator.

Thanks to anyone that can help me out.

 

 


GDPR-24_203122
03 Jun 2016, 13:08

RE:

 

I tried making a robot of this indicator that opens buys when "TimeToBuy" = true and sells when "TimeToBuy = false, and closes the other trade when the it reverses. 

There is a problem in OnStart, "parameters count", when invoking the indicator. I'm not sure how and which of the parameters should be included. Of course the finished bot shouldn't have any stop loss or take profit, but they are here now (even duplicated), on this test code of the robot (below the indicator). If anyone has spare time, I guess this might be worth while to look into... Also please post a reply, if you can fix it...

Indicator:

using System;
using cAlgo.API;
using System.Runtime.InteropServices;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SuperProfit : Indicator
    {
        // Alert
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

        [Parameter(DefaultValue = 35)]
        public int DllPeriod { get; set; }

        [Parameter(DefaultValue = 1.7)]
        public double Period { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Weighted)]
        public MovingAverageType MaType { get; set; }

        [Parameter()]
        public DataSeries Price { get; set; }

        [Parameter(DefaultValue = 5)]
        public int StopLoss { get; set; }

        [Parameter(DefaultValue = 20)]
        public int TakeProfit { get; set; }

        [Output("Up", PlotType = PlotType.Points, Thickness = 4)]
        public IndicatorDataSeries UpSeries { get; set; }

        [Output("Down", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        public IndicatorDataSeries DownSeries { get; set; }

        public bool TimeToBuy;

        private DateTime _openTime;

        private MovingAverage _movingAverage1;
        private MovingAverage _movingAverage2;
        private MovingAverage _movingAverage3;
        private IndicatorDataSeries _dataSeries;
        private IndicatorDataSeries _trend;


        protected override void Initialize()
        {
            _dataSeries = CreateDataSeries();
            _trend = CreateDataSeries();

            var period1 = (int)Math.Floor(DllPeriod / Period);
            var period2 = (int)Math.Floor(Math.Sqrt(DllPeriod));

            _movingAverage1 = Indicators.MovingAverage(Price, period1, MaType);
            _movingAverage2 = Indicators.MovingAverage(Price, DllPeriod, MaType);
            _movingAverage3 = Indicators.MovingAverage(_dataSeries, period2, MaType);

        }

        public override void Calculate(int index)
        {
            if (index < 1)
                return;

            _dataSeries[index] = 2.0 * _movingAverage1.Result[index] - _movingAverage2.Result[index];
            _trend[index] = _trend[index - 1];

            if (_movingAverage3.Result[index] > _movingAverage3.Result[index - 1])
                _trend[index] = 1;
            else if (_movingAverage3.Result[index] < _movingAverage3.Result[index - 1])
                _trend[index] = -1;

            if (_trend[index] > 0)
            {
                UpSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] < 0.0)
                {
                    UpSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsLastBar)
                    {
                        var stopLoss = MarketSeries.Low[index - 1] - StopLoss * Symbol.PipSize;
                        var takeProfit = MarketSeries.Close[index] + TakeProfit * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != _openTime)
                        {
                            _openTime = MarketSeries.OpenTime[index];
                            //                      DisplayAlert("Buy signal", takeProfit, stopLoss, entryPrice);
                            TimeToBuy = true;
                        }
                    }
                }

                DownSeries[index] = double.NaN;
            }
            else if (_trend[index] < 0)
            {
                DownSeries[index] = _movingAverage3.Result[index];

                if (_trend[index - 1] > 0.0)
                {
                    DownSeries[index - 1] = _movingAverage3.Result[index - 1];

                    if (IsLastBar)
                    {
                        var stopLoss = MarketSeries.High[index - 1] + StopLoss * Symbol.PipSize;
                        var takeProfit = MarketSeries.Close[index] - TakeProfit * Symbol.PipSize;
                        var entryPrice = MarketSeries.Close[index - 1];

                        if (MarketSeries.OpenTime[index] != _openTime)
                        {
                            _openTime = MarketSeries.OpenTime[index];
                            //                      DisplayAlert("Sell signal", takeProfit, stopLoss, entryPrice);
                            TimeToBuy = false;
                        }
                    }
                }

                UpSeries[index] = double.NaN;
            }

        }

        protected void DisplayAlert(string tradyTypeSignal, double takeProfit, double stopLoss, double entryPrice)
        {
            string entryPricetext = entryPrice != 0.0 ? string.Format(" at price {0}", Math.Round(entryPrice, 4)) : "";
            string takeProfitText = takeProfit != 0.0 ? string.Format(", TP on  {0}", Math.Round(takeProfit, 4)) : "";
            string stopLossText = stopLoss != 0.0 ? string.Format(", SL on {0}", Math.Round(stopLoss, 4)) : "";

            var alertMessage = string.Format("{0} {1} {2} {3} {4}", tradyTypeSignal, entryPricetext, takeProfitText, stopLossText, Symbol.Code);

            MessageBox(new IntPtr(0), alertMessage, "Trade Signal", 0);

        }
    }
}

Robot:

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SuperProfitBot : Robot
    {

        [Parameter(DefaultValue = 1000)]
        public int Volume { get; set; }

        [Parameter("Source")]
        public DataSeries SourceSeries { get; set; }

        [Parameter(DefaultValue = 35)]
        public int DllPeriod { get; set; }

        [Parameter(DefaultValue = 1.7)]
        public double Period { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Weighted)]
        public MovingAverageType MaType { get; set; }

        [Parameter()]
        public DataSeries Price { get; set; }

        [Output("Up", PlotType = PlotType.Points, Thickness = 4)]
        public IndicatorDataSeries UpSeries { get; set; }

        [Output("Down", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        public IndicatorDataSeries DownSeries { get; set; }

        [Parameter("TP (pips)", DefaultValue = 500)]
        public int TP { get; set; }
        [Parameter("SL (pips)", DefaultValue = 500)]
        public int SL { get; set; }


        private SuperProfit _SuperProfit;



        protected override void OnStart()
        {
            _SuperProfit = Indicators.GetIndicator<SuperProfit>(DllPeriod, Period, MaType, Price, 100, 100);

        }




        protected override void OnBar()
        {

            if (_SuperProfit.TimeToBuy == true)
            {
                Print("Buy");
                //            foreach (var position in Positions)
                //           {
                //               if (position.TradeType == TradeType.Sell)
                //               {
                //                   ClosePosition(position);
                //                }
                //           }
                ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, "Label", SL, TP);
            }

            if (_SuperProfit.TimeToBuy == false)
            {
                Print("Sell");

                //            foreach (var position in Positions)
                //            {
                //                if (position.TradeType == TradeType.Buy)
                //                {
                //                   ClosePosition(position);
                //                }
                //            }
                ExecuteMarketOrder(TradeType.Sell, Symbol, Volume, "Label", SL, TP);
            }
        }
    }
}


jani
28 Oct 2019, 19:00

RE:

emeeder said:

This Indicator is similar to teh Supertrend indicator that i am trying to use in a Cbot. I posted a question about it today. The code is there as well.

/forum/cbot-support/1111

Does anyone know what output the Cbot should be looking for to start and stop trades based on the UpTrend or DownTrend outputs?

I mainly want to use this along with other indicators as a Buysafe/Sellsafe indicator.

Thanks to anyone that can help me out.

 

 

This indicator can also be synthesized almost one-to-one results by adjusting Tilson T3 using values: (period 10, volume factor 0.7).

 

I'm working on cBot to use T3 but mainly as a filter, not an entry trigger. I can tell you from experience any profits made on your SuperProfit indicator on a trending market are given away in sideways market...


@jani