Open trade when touches a line

Created at 28 May 2021, 04:32
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!
MA

maciel.rafael1

Joined 17.09.2020

Open trade when touches a line
28 May 2021, 04:32


I'm trying to create a bot that when it hits a line from below open a sell and from above it opens a buy. Is there any basics example that I can use to base my bot?


@maciel.rafael1
Replies

amusleh
28 May 2021, 20:24

Hi,

Not sure what you are after, is the line drawn on your chart by user while the cBot is running? if that's the case then you can iterate over Chart.Objects collection and find the line, then check the current price to see if it touched/crossed the line or not, this indicator is a sample:

using cAlgo.API;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class LineAlert : Indicator
    {

        private readonly List<ChartObjectAlert> _chartObjectAlerts = new List<ChartObjectAlert>();

        [Parameter("Single Alert", DefaultValue = true, Group = "General")]
        public bool SingleAlert { get; set; }

        [Parameter("Trend/Ray", DefaultValue = true, Group = "Line Types")]
        public bool TrendLine { get; set; }

        [Parameter("Horizontal", DefaultValue = true, Group = "Line Types")]
        public bool HorizontalLine { get; set; }

        [Parameter("Vertical", DefaultValue = true, Group = "Line Types")]
        public bool VerticalLine { get; set; }

        [Parameter("Show Comment", DefaultValue = true, Group = "Comment")]
        public bool ShowComment { get; set; }

        [Parameter("Comment Suffix", Group = "Comment")]
        public string CommentSuffix { get; set; }
		
		[Parameter("Sound File", Group = "Alert")]
        public string AlertSoundFile { get; set; }

        protected override void Initialize()
        {
        }

        public override void Calculate(int index)
        {
            foreach (var chartObject in Chart.Objects)
            {
                if (!string.IsNullOrEmpty(CommentSuffix) && !chartObject.Comment.EndsWith(CommentSuffix, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                var chartObjectAlert = new ChartObjectAlert 
                {
                    ChartObject = chartObject,
                    AlertBarIndex = index,
                    TouchType = TouchType.None
                };

                if (chartObject.ObjectType == ChartObjectType.TrendLine || chartObject.ObjectType == ChartObjectType.HorizontalLine)
                {
                    var linePriceValue = double.NaN;

                    if (TrendLine && chartObject.ObjectType == ChartObjectType.TrendLine)
                    {
                        var chartTrendLine = chartObject as ChartTrendLine;

                        if (chartTrendLine != null)
                            linePriceValue = chartTrendLine.CalculateY(index);
                    }
                    else if (HorizontalLine && chartObject.ObjectType == ChartObjectType.HorizontalLine)
                    {
                        var chartHorizontalLine = chartObject as ChartHorizontalLine;

                        if (chartHorizontalLine != null)
                            linePriceValue = chartHorizontalLine.Y;
                    }

                    if (Bars.ClosePrices[index] >= linePriceValue && Bars.ClosePrices[index - 1] < linePriceValue)
                    {
                        chartObjectAlert.TouchType = TouchType.Up;
                    }

                    if (Bars.ClosePrices[index] <= linePriceValue && Bars.ClosePrices[index - 1] > linePriceValue)
                    {
                        chartObjectAlert.TouchType = TouchType.Down;
                    }
                }
                else if (VerticalLine && chartObject.ObjectType == ChartObjectType.VerticalLine)
                {
                    var chartVerticalLine = chartObject as ChartVerticalLine;

                    if (chartVerticalLine != null && Bars.OpenTimes[index] >= chartVerticalLine.Time && Bars.OpenTimes[index - 1] < chartVerticalLine.Time)
                    {
                        chartObjectAlert.TouchType = TouchType.Right;
                    }
                }

                if (chartObjectAlert.TouchType != TouchType.None)
                {
                    TriggerAlert(Bars.ClosePrices[index], chartObjectAlert);
                }
            }
        }



        private void TriggerAlert(double price, ChartObjectAlert chartObjectAlert)
        {
            var previousChartObjectAlert = _chartObjectAlerts.LastOrDefault(iChartObjectAlert => iChartObjectAlert.ChartObject == chartObjectAlert.ChartObject);

            if ((SingleAlert && previousChartObjectAlert != null) || (previousChartObjectAlert != null && previousChartObjectAlert.AlertBarIndex == chartObjectAlert.AlertBarIndex))
            {
                return;
            }

            _chartObjectAlerts.Add(chartObjectAlert);

            var touchType = string.Empty;

            if (chartObjectAlert.TouchType == TouchType.Up)
            {
                touchType = "⬆";
            }
            else if (chartObjectAlert.TouchType == TouchType.Down)
            {
                touchType = "⬇";
            }
            else if (chartObjectAlert.TouchType == TouchType.Right)
            {
                touchType = "→";
            }

           Notifications.PlaySound(AlertSoundFile);
        }

    }
	
	public class ChartObjectAlert
    {
        public ChartObject ChartObject { get; set; }

        public int AlertBarIndex { get; set; }

        public TouchType TouchType { get; set; }
    }
	
	public enum TouchType
    {
        None,
        Up,
        Down,
        Right
    }
}

The above indicator play's a sound file whenever price touches a line on your chart, the indicator uses line objects comment to find them, you have to use the same comment suffix on your line object comment.

That's a sample that you can use on your cBot for all line types including trend line.


@amusleh

maciel.rafael1
29 May 2021, 17:15

RE:

amusleh said:

Hi,

Not sure what you are after, is the line drawn on your chart by user while the cBot is running? if that's the case then you can iterate over Chart.Objects collection and find the line, then check the current price to see if it touched/crossed the line or not, this indicator is a sample:

using cAlgo.API;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class LineAlert : Indicator
    {

        private readonly List<ChartObjectAlert> _chartObjectAlerts = new List<ChartObjectAlert>();

        [Parameter("Single Alert", DefaultValue = true, Group = "General")]
        public bool SingleAlert { get; set; }

        [Parameter("Trend/Ray", DefaultValue = true, Group = "Line Types")]
        public bool TrendLine { get; set; }

        [Parameter("Horizontal", DefaultValue = true, Group = "Line Types")]
        public bool HorizontalLine { get; set; }

        [Parameter("Vertical", DefaultValue = true, Group = "Line Types")]
        public bool VerticalLine { get; set; }

        [Parameter("Show Comment", DefaultValue = true, Group = "Comment")]
        public bool ShowComment { get; set; }

        [Parameter("Comment Suffix", Group = "Comment")]
        public string CommentSuffix { get; set; }
		
		[Parameter("Sound File", Group = "Alert")]
        public string AlertSoundFile { get; set; }

        protected override void Initialize()
        {
        }

        public override void Calculate(int index)
        {
            foreach (var chartObject in Chart.Objects)
            {
                if (!string.IsNullOrEmpty(CommentSuffix) && !chartObject.Comment.EndsWith(CommentSuffix, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                var chartObjectAlert = new ChartObjectAlert 
                {
                    ChartObject = chartObject,
                    AlertBarIndex = index,
                    TouchType = TouchType.None
                };

                if (chartObject.ObjectType == ChartObjectType.TrendLine || chartObject.ObjectType == ChartObjectType.HorizontalLine)
                {
                    var linePriceValue = double.NaN;

                    if (TrendLine && chartObject.ObjectType == ChartObjectType.TrendLine)
                    {
                        var chartTrendLine = chartObject as ChartTrendLine;

                        if (chartTrendLine != null)
                            linePriceValue = chartTrendLine.CalculateY(index);
                    }
                    else if (HorizontalLine && chartObject.ObjectType == ChartObjectType.HorizontalLine)
                    {
                        var chartHorizontalLine = chartObject as ChartHorizontalLine;

                        if (chartHorizontalLine != null)
                            linePriceValue = chartHorizontalLine.Y;
                    }

                    if (Bars.ClosePrices[index] >= linePriceValue && Bars.ClosePrices[index - 1] < linePriceValue)
                    {
                        chartObjectAlert.TouchType = TouchType.Up;
                    }

                    if (Bars.ClosePrices[index] <= linePriceValue && Bars.ClosePrices[index - 1] > linePriceValue)
                    {
                        chartObjectAlert.TouchType = TouchType.Down;
                    }
                }
                else if (VerticalLine && chartObject.ObjectType == ChartObjectType.VerticalLine)
                {
                    var chartVerticalLine = chartObject as ChartVerticalLine;

                    if (chartVerticalLine != null && Bars.OpenTimes[index] >= chartVerticalLine.Time && Bars.OpenTimes[index - 1] < chartVerticalLine.Time)
                    {
                        chartObjectAlert.TouchType = TouchType.Right;
                    }
                }

                if (chartObjectAlert.TouchType != TouchType.None)
                {
                    TriggerAlert(Bars.ClosePrices[index], chartObjectAlert);
                }
            }
        }



        private void TriggerAlert(double price, ChartObjectAlert chartObjectAlert)
        {
            var previousChartObjectAlert = _chartObjectAlerts.LastOrDefault(iChartObjectAlert => iChartObjectAlert.ChartObject == chartObjectAlert.ChartObject);

            if ((SingleAlert && previousChartObjectAlert != null) || (previousChartObjectAlert != null && previousChartObjectAlert.AlertBarIndex == chartObjectAlert.AlertBarIndex))
            {
                return;
            }

            _chartObjectAlerts.Add(chartObjectAlert);

            var touchType = string.Empty;

            if (chartObjectAlert.TouchType == TouchType.Up)
            {
                touchType = "⬆";
            }
            else if (chartObjectAlert.TouchType == TouchType.Down)
            {
                touchType = "⬇";
            }
            else if (chartObjectAlert.TouchType == TouchType.Right)
            {
                touchType = "→";
            }

           Notifications.PlaySound(AlertSoundFile);
        }

    }
	
	public class ChartObjectAlert
    {
        public ChartObject ChartObject { get; set; }

        public int AlertBarIndex { get; set; }

        public TouchType TouchType { get; set; }
    }
	
	public enum TouchType
    {
        None,
        Up,
        Down,
        Right
    }
}

The above indicator play's a sound file whenever price touches a line on your chart, the indicator uses line objects comment to find them, you have to use the same comment suffix on your line object comment.

That's a sample that you can use on your cBot for all line types including trend line.

So the idea of the bot I`m trying to make would be that I`ll give it 10 horizontal Lines and whenever it touches a line from the bottom I get a down alert and if it touches from the top a top alert


@maciel.rafael1

amusleh
30 May 2021, 10:23

Hi,

For horizontal lines you have to set and handler for Chart.ObjectsAdded/Removed/Updated events.

Check the object that has been added/removed/updated, if its of type horizontal line then save it on a collection like list.

On your cBot OnTick method, keep checking the current symbol latest Bid/Ask prices, if it touched/crossed any of your lines inside the collection then execute your trade, that's very simple.


@amusleh