Topics
27 Oct 2020, 18:01
 3
 1339
 2
24 Sep 2020, 16:41
 1058
 6
17 Sep 2020, 21:10
 1405
 2
Replies

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

maciel.rafael1
27 Oct 2020, 17:50 ( Updated at: 21 Dec 2023, 09:22 )

RE:

bart1 said:

Here is a simple instruction to add Telegram notifications into your cBot or indicator.

First you need to create your own bot by chatting with BotFather in Telegram

Send /newbot and it will ask desired display name and user name for your new Telegram bot.

From the final message you need Token. Also you need to get chat ID for your new bot to send messages to you.

Go to your bot by clicking link in the final message and send some text.

To get chat ID you need to request latest updates from your bot by entering following URL in your browser:  https://api.telegram.org/bot<TOKEN>/getUpdates
replace <TOKEN> placeholder with your bot token

In response you will get text where you can find chat id
Example: ..."chat":{"id":123,...

Now you have 2 required parameters to send Telegram notifications and you can create cBot or indicator to test it. Telegram messages can be send using simple HTTP request. Here is a helper class that will do it for you.

public class TelegramBot
{
    public string Token { get; private set; }
    public int ChatId { get; private set; }

    public TelegramBot(string token, int chatId)
    {
        UseTls12();
        Token = token;
        ChatId = chatId;
    }

    public bool Send(string message)
    {
        var url = string.Format("https://api.telegram.org/bot{0}/sendMessage?chat_id={1}&text={2}", Token, ChatId, message);
        var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
        var response = (System.Net.HttpWebResponse)request.GetResponse();
        return response.StatusCode == System.Net.HttpStatusCode.OK;
    }

    public bool Send(string message, params object[] args)
    {
        var formattedMessage = string.Format(message, args);
        return Send(formattedMessage);
    }

    private void UseTls12()
    {
        // Required for SSL/TLS connection with Telegram
        // Will work only on .Net 4.5 or higher
        // Using number to avoid compilation error
        System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072;
    }
}

 

After adding this class to your cBot or indicator you can send notifications like this:
replace <TOKEN> and <CHAT_ID> with yours

private TelegramBot TelegramBot;

protected override void OnStart()
{
    TelegramBot = new TelegramBot("<TOKEN>", <CHAT_ID>);
    TelegramBot.Send("Started {0} {1}", SymbolName, TimeFrame);
}

 

NOTE: cBot and indicators need extended permission. You need to use Internet or FullAccess permissions:

[Robot(AccessRights = AccessRights.Internet)]
public class NewcBot : Robot

 

I tried this in my bot and I get the following errors : TelegramBot is a type but is used like a variable and the second error is an object reference is required for the non-static field, method, or property. Both points to the lines OnStart

 

Any suggestions how to fix?


@maciel.rafael1

maciel.rafael1
24 Sep 2020, 17:25

RE:

Where can I send it in private to have it looked at?

 

PanagiotisCharalampous said:

Hi maciel.rafael1,

You need to be more specific. Please provide the cBot code and the exception you get.

Best Regards,

Panagiotis 

Join us on Telegram

 


@maciel.rafael1

maciel.rafael1
24 Sep 2020, 17:06

RE:

Hi,

 

I verified and the log says that it is because both bots are accessing at the same time. Do you have an idea how can I fix it that one can write and the other read at the same time?

 

Thank you

 

PanagiotisCharalampous said:

Hi maciel.rafael1,

cTrader does not stop cBots. cBots are either stopped manually/automatically by the trader or due to some exception. Did you check your logs? Are there any messages there indicating why the cBot has stopped?

Best Regards,

Panagiotis 

Join us on Telegram

 


@maciel.rafael1

maciel.rafael1
24 Sep 2020, 16:48

RE:

Hi Pani,

When I try this bot on back testing and I verify the information on trading view the value for the RSI is not the same

Could it be that the bot is selecting the wrong price ?

PanagiotisCharalampous said:

Hi Sam,

Here you go

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        RelativeStrengthIndex _rsiDaily;
        RelativeStrengthIndex _rsiHourly;
        protected override void OnStart()
        {
            var dailyBars = MarketData.GetBars(TimeFrame.Daily);
            var hourlyBars = MarketData.GetBars(TimeFrame.Hour);
            _rsiDaily = Indicators.RelativeStrengthIndex(dailyBars.ClosePrices, 14);
            _rsiHourly = Indicators.RelativeStrengthIndex(hourlyBars.ClosePrices, 14);
        }

        protected override void OnBar()
        {
            if (_rsiDaily.Result.Last(1) > 60 && _rsiHourly.Result.Last(1) > 60)
            {
                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1000);
            }
        }

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

Best Regards,

Panagiotis 

Join us on Telegram

 


@maciel.rafael1