Add a "Label" and a "Comment" in the Trading Panel code

Created at 24 Mar 2024, 11:04
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!
Obiriec's avatar

Obiriec

Joined 08.03.2019

Add a "Label" and a "Comment" in the Trading Panel code
24 Mar 2024, 11:04


I tried to insert the parameters into the "Trading Panel" code to define a "label" and a "comment" when opening positions.

At the moment the code only works if, before running the cBot, the description of the label or comment is inserted in the string that is provided when the cBot is opened.

I would like to know if it is possible to correct the code to make it possible to insert data directly from the panel that is running on the graph.

Practically the same as for lots, stop loss and take profit.

 

During graphic execution, the texts written in the boxes highlighted in red are not acquired.
 

 

This only works if the text is written here:

 

The code I compiled is below:

using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleTradingPanel : Robot
    {
        [Parameter("Vertical Position", Group = "Panel alignment", DefaultValue = VerticalAlignment.Top)]
        public VerticalAlignment PanelVerticalAlignment { get; set; }

        [Parameter("Horizontal Position", Group = "Panel alignment", DefaultValue = HorizontalAlignment.Left)]
        public HorizontalAlignment PanelHorizontalAlignment { get; set; }

        [Parameter("Default Lots", Group = "Default trade parameters", DefaultValue = 0.01)]
        public double DefaultLots { get; set; }

        [Parameter("Default Take Profit (pips)", Group = "Default trade parameters", DefaultValue = 20)]
        public double DefaultTakeProfitPips { get; set; }

        [Parameter("Default Stop Loss (pips)", Group = "Default trade parameters", DefaultValue = 20)]
        public double DefaultStopLossPips { get; set; }

        [Parameter("Default Label", Group = "Default trade parameters", DefaultValue = "Label here")]
        public string UserLabel { get; set; }

        [Parameter("Default Comment", Group = "Default trade parameters", DefaultValue = "Comment here")]
        public string UserComment { get; set; }


        //public string DefaultLabel = "";
        public string LabelImputKey = "L";

        //public string DefaultComment = "";
        public string CommentImputKey = "C";

        protected override void OnStart()
        {
            if (LabelImputKey == "L")
            {
                LabelImputKey = UserLabel;
            }
            if (CommentImputKey == "C")
            {
                CommentImputKey = UserComment;
            }


            var tradingPanel = new TradingPanel(this, Symbol, DefaultLots, DefaultStopLossPips, DefaultTakeProfitPips, UserLabel, UserComment);

            var border = new Border
            {
                VerticalAlignment = PanelVerticalAlignment,
                HorizontalAlignment = PanelHorizontalAlignment,
                Style = Styles.CreatePanelBackgroundStyle(),
                Margin = "20 40 20 20",
                Width = 225,
                Child = tradingPanel
            };

            Chart.AddControl(border);
        }
    }

    public class TradingPanel : CustomControl
    {
        private const string LotsInputKey = "LotsKey";
        private const string TakeProfitInputKey = "TPKey";
        private const string StopLossInputKey = "SLKey";
        public string LabelImputKey = "LabelKey";
        public string CommentImputKey = "CommentKey";
        private readonly IDictionary<string, TextBox> _inputMap = new Dictionary<string, TextBox>();
        private readonly Robot _robot;
        private readonly Symbol _symbol;



        public TradingPanel(Robot robot, Symbol symbol, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips, string DefaultLabel, string DefaultComment)
        {
            _robot = robot;
            _symbol = symbol;
            AddChild(CreateTradingPanel(defaultLots, defaultStopLossPips, defaultTakeProfitPips, DefaultLabel, DefaultComment));
        }

        private ControlBase CreateTradingPanel(double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips, string defaultLabel, string defaultComment)
        {
            var mainPanel = new StackPanel();

            var header = CreateHeader();
            mainPanel.AddChild(header);

            var contentPanel = CreateContentPanel(defaultLots, defaultStopLossPips, defaultTakeProfitPips, defaultLabel, defaultComment);
            mainPanel.AddChild(contentPanel);

            return mainPanel;
        }

        private ControlBase CreateHeader()
        {
            var headerBorder = new Border
            {
                BorderThickness = "0 0 0 1",
                Style = Styles.CreateCommonBorderStyle()
            };

            var header = new TextBlock
            {
                Text = "Quick Trading Panel",
                Margin = "10 7",
                Style = Styles.CreateHeaderStyle()
            };

            headerBorder.Child = header;
            return headerBorder;
        }

        private StackPanel CreateContentPanel(double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips, string defaultLabel, string defaultComment)
        {
            if (LabelImputKey == "LabelKey")
            {
            LabelImputKey = defaultLabel;
            }
            if (CommentImputKey == "CommentKey")
            {
            CommentImputKey = defaultComment;
            }

            var contentPanel = new StackPanel
            {
                Margin = 10
            };
            var grid = new Grid(6, 3);
            grid.Columns[1].SetWidthInPixels(5);

            var sellButton = CreateTradeButton("SELL", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(sellButton, 0, 0);

            var buyButton = CreateTradeButton("BUY", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buyButton, 0, 2);

            var lotsInput = CreateInputWithLabel("Quantity (Lots)", defaultLots.ToString("F2"), LotsInputKey);
            grid.AddChild(lotsInput, 1, 0, 1, 3);

            var stopLossInput = CreateInputWithLabel("Stop Loss (Pips)", defaultStopLossPips.ToString("F1"), StopLossInputKey);
            grid.AddChild(stopLossInput, 2, 0);

            var takeProfitInput = CreateInputWithLabel("Take Profit (Pips)", defaultTakeProfitPips.ToString("F1"), TakeProfitInputKey);
            grid.AddChild(takeProfitInput, 2, 2);

            var labelImput = CreateInputWithLabel("Label", defaultLabel.ToString(), LabelImputKey);
            grid.AddChild(labelImput, 3, 0);

            var commentImput = CreateInputWithLabel("Label", defaultComment.ToString(), CommentImputKey);
            grid.AddChild(commentImput, 3, 2);

            var closeAllButton = CreateCloseAllButton();
            grid.AddChild(closeAllButton, 4, 0, 1, 3);

            contentPanel.AddChild(grid);

            return contentPanel;
        }

        private Button CreateTradeButton(string text, Style style, TradeType tradeType)
        {
            var tradeButton = new Button
            {
                Text = text,
                Style = style,
                Height = 25
            };

            tradeButton.Click += args => ExecuteMarketOrderAsync(tradeType);

            return tradeButton;
        }

        private ControlBase CreateCloseAllButton()
        {
            var closeAllBorder = new Border
            {
                Margin = "0 10 0 0",
                BorderThickness = "0 1 0 0",
                Style = Styles.CreateCommonBorderStyle()
            };

            var closeButton = new Button
            {
                Style = Styles.CreateCloseButtonStyle(),
                Text = "Close All",
                Margin = "0 10 0 0"
            };

            closeButton.Click += args => CloseAll();
            closeAllBorder.Child = closeButton;

            return closeAllBorder;
        }

        private Panel CreateInputWithLabel(string label, string defaultValue, string inputKey)
        {
            var stackPanel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                Margin = "0 10 0 0"
            };

            var textBlock = new TextBlock
            {
                Text = label
            };

            var input = new TextBox
            {
                Margin = "0 5 0 0",
                Text = defaultValue,
                Style = Styles.CreateInputStyle()
            };

            _inputMap.Add(inputKey, input);

            stackPanel.AddChild(textBlock);
            stackPanel.AddChild(input);

            return stackPanel;
        }

        private void ExecuteMarketOrderAsync(TradeType tradeType)
        {
            var lots = GetValueFromInput(LotsInputKey, 0);
            if (lots <= 0)
            {
                _robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
                return;
            }

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);

            string label = LabelImputKey;
            string comment = CommentImputKey;


            _robot.Print(string.Format("Open position with: LotsParameter: {0}, StopLossPipsParameter: {1}, TakeProfitPipsParameter: {2}", lots, stopLossPips, takeProfitPips, label, comment));

            var volume = _symbol.QuantityToVolumeInUnits(lots);
            _robot.ExecuteMarketOrderAsync(tradeType, _symbol.Name, volume, label, stopLossPips, takeProfitPips, comment);
        }

        private double GetValueFromInput(string inputKey, double defaultValue)
        {
            double value;

            return double.TryParse(_inputMap[inputKey].Text, out value) ? value : defaultValue;
        }

        private void CloseAll()
        {
            foreach (var position in _robot.Positions)
                _robot.ClosePositionAsync(position);
        }
    }

    public static class Styles
    {
        public static Style CreatePanelBackgroundStyle()
        {
            var style = new Style();
            style.Set(ControlProperty.CornerRadius, 3);
            style.Set(ControlProperty.BackgroundColor, GetColorWithOpacity(Color.FromHex("#292929"), 0.85m), ControlState.DarkTheme);
            style.Set(ControlProperty.BackgroundColor, GetColorWithOpacity(Color.FromHex("#FFFFFF"), 0.85m), ControlState.LightTheme);
            style.Set(ControlProperty.BorderColor, Color.FromHex("#3C3C3C"), ControlState.DarkTheme);
            style.Set(ControlProperty.BorderColor, Color.FromHex("#C3C3C3"), ControlState.LightTheme);
            style.Set(ControlProperty.BorderThickness, new Thickness(1));

            return style;
        }

        public static Style CreateCommonBorderStyle()
        {
            var style = new Style();
            style.Set(ControlProperty.BorderColor, GetColorWithOpacity(Color.FromHex("#FFFFFF"), 0.12m), ControlState.DarkTheme);
            style.Set(ControlProperty.BorderColor, GetColorWithOpacity(Color.FromHex("#000000"), 0.12m), ControlState.LightTheme);
            return style;
        }

        public static Style CreateHeaderStyle()
        {
            var style = new Style();
            style.Set(ControlProperty.ForegroundColor, GetColorWithOpacity("#FFFFFF", 0.70m), ControlState.DarkTheme);
            style.Set(ControlProperty.ForegroundColor, GetColorWithOpacity("#000000", 0.65m), ControlState.LightTheme);
            return style;
        }

        public static Style CreateInputStyle()
        {
            var style = new Style(DefaultStyles.TextBoxStyle);
            style.Set(ControlProperty.BackgroundColor, Color.FromHex("#1A1A1A"), ControlState.DarkTheme);
            style.Set(ControlProperty.BackgroundColor, Color.FromHex("#111111"), ControlState.DarkTheme | ControlState.Hover);
            style.Set(ControlProperty.BackgroundColor, Color.FromHex("#E7EBED"), ControlState.LightTheme);
            style.Set(ControlProperty.BackgroundColor, Color.FromHex("#D6DADC"), ControlState.LightTheme | ControlState.Hover);
            style.Set(ControlProperty.CornerRadius, 3);
            return style;
        }

        public static Style CreateBuyButtonStyle()
        {
            return CreateButtonStyle(Color.FromHex("#009345"), Color.FromHex("#10A651"));
        }

        public static Style CreateSellButtonStyle()
        {
            return CreateButtonStyle(Color.FromHex("#F05824"), Color.FromHex("#FF6C36"));
        }

        public static Style CreateCloseButtonStyle()
        {
            return CreateButtonStyle(Color.FromHex("#F05824"), Color.FromHex("#FF6C36"));
        }

        private static Style CreateButtonStyle(Color color, Color hoverColor)
        {
            var style = new Style(DefaultStyles.ButtonStyle);
            style.Set(ControlProperty.BackgroundColor, color, ControlState.DarkTheme);
            style.Set(ControlProperty.BackgroundColor, color, ControlState.LightTheme);
            style.Set(ControlProperty.BackgroundColor, hoverColor, ControlState.DarkTheme | ControlState.Hover);
            style.Set(ControlProperty.BackgroundColor, hoverColor, ControlState.LightTheme | ControlState.Hover);
            style.Set(ControlProperty.ForegroundColor, Color.FromHex("#FFFFFF"), ControlState.DarkTheme);
            style.Set(ControlProperty.ForegroundColor, Color.FromHex("#FFFFFF"), ControlState.LightTheme);
            return style;
        }

        private static Color GetColorWithOpacity(Color baseColor, decimal opacity)
        {
            var alpha = (int)Math.Round(byte.MaxValue * opacity, MidpointRounding.AwayFromZero);
            return Color.FromArgb(alpha, baseColor);
        }
    }
}


@Obiriec
Replies

PanagiotisCharalampous
25 Mar 2024, 07:28

Hi there,

This happens because you do not acquire the text box value anywhere. See below

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);

            string label = LabelImputKey;
            string comment = CommentImputKey;

You acquire the sl and tp from the text boxes but you use the default label and comment.

Best regards,

Panagiotis


@PanagiotisCharalampous

Obiriec
25 Mar 2024, 13:59

RE: Add a "Label" and a "Comment" in the Trading Panel code

PanagiotisCharalampous said: 

Hi there,

This happens because you do not acquire the text box value anywhere. See below

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);            string label = LabelImputKey;            string comment = CommentImputKey;

You acquire the sl and tp from the text boxes but you use the default label and comment.

Best regards,

Panagiotis

Good morning, I certainly misunderstood.

How should I correct the code so that the text that is written in the on-screen panel box is then used to be written in the label or comment when a position is opened?

Now it only works well if the text is written in the parameters window.

I need the insertion to become interactive even when the panel is on the screen, that is, when the cBot is in the start state.

Thank you and I hope I have been able to explain myself better.

Best regard,

Armando


@Obiriec

Obiriec
25 Mar 2024, 13:59

RE: Add a "Label" and a "Comment" in the Trading Panel code

PanagiotisCharalampous said: 

Hi there,

This happens because you do not acquire the text box value anywhere. See below

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);            string label = LabelImputKey;            string comment = CommentImputKey;

You acquire the sl and tp from the text boxes but you use the default label and comment.

Best regards,

Panagiotis

Good morning, I certainly misunderstood.

How should I correct the code so that the text that is written in the on-screen panel box is then used to be written in the label or comment when a position is opened?

Now it only works well if the text is written in the parameters window.

I need the insertion to become interactive even when the panel is on the screen, that is, when the cBot is in the start state.

Thank you and I hope I have been able to explain myself better.

Best regard,

Armando


@Obiriec

PanagiotisCharalampous
26 Mar 2024, 06:48

RE: RE: Add a "Label" and a "Comment" in the Trading Panel code

Obiriec said: 

PanagiotisCharalampous said: 

Hi there,

This happens because you do not acquire the text box value anywhere. See below

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);            string label = LabelImputKey;            string comment = CommentImputKey;

You acquire the sl and tp from the text boxes but you use the default label and comment.

Best regards,

Panagiotis

Good morning, I certainly misunderstood.

How should I correct the code so that the text that is written in the on-screen panel box is then used to be written in the label or comment when a position is opened?

Now it only works well if the text is written in the parameters window.

I need the insertion to become interactive even when the panel is on the screen, that is, when the cBot is in the start state.

Thank you and I hope I have been able to explain myself better.

Best regard,

Armando

Hi Armando,

I cannot write the code for you but the way stop loss and take profit are obtained can be used as guidance on developing this feature further

            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);

@PanagiotisCharalampous