waym77
waym77's avatar

Info

Username:waym77
Name:waym77
Member since: 22 Jul 2021

About

None

Signature

None

Last Forum Posts

@Fractals and engulfing:  15 Sep 2021, 15:34


amusleh said:

I recommend you to calculate the fractals by your self, instead of using cTrader fractals indicator, that way you will be sure about how it works and what kind of result it should give you.

Try this:

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Fractal Period", DefaultValue = 5, MinValue = 5)]
        public int Period { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double FirstVolume { get; set; }

        private Fractals _fractal;

        protected override void OnStart()
        {
            _fractal = Indicators.Fractals(Period);
        }

        protected override void OnBar()
        {
            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.UpFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }

            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.DownFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }
        }
    }
}

My sample uses cTrader fractals and if the next candle after fractal was an engulfing candle it executes the trade.

But I don't know how the cTrader fractals indicator works, so its better to calculate it by yourself or search and you might find some fractal indicators already developed by other community members.

Hi,

I have adapted the code from a bot to an indicator, however, I am struggling to get the logic working in the correct order. As I mentioned before: As soon as the latest bar closes and turns into Bar 1, there needs to have been a fractal on 1 and an engulfing on 0. This is only possible with fractal at 3.

Additionally, I need these signals to print further over the index so I can backtest it. 

For clarification, please see the image, code in question, and custom fractals indicator:

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class FractalMomentum : Indicator
    {
        [Parameter("Fractal Period", DefaultValue = 3, MinValue = 1)]
        public int Period { get; set; }

        [Parameter("Print Offset (Pips)", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 100.0, Step = 0.1)]
        public double _PO_Parameter { get; set; }

        private double _offset, _offset_calc;

        private CustomFractals _fractal;

        protected override void Initialize()
        {
            _fractal = Indicators.GetIndicator<CustomFractals>(Period);
        }

        public override void Calculate(int index)
        {
            _offset = _PO_Parameter * Symbol.PipValue;

            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                _offset_calc = Bars.LowPrices.LastValue - _offset;
                Chart.DrawIcon("Sell", ChartIconType.DownTriangle, Bars.OpenTimes.LastValue, _offset_calc, Color.OrangeRed);
            }
            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                _offset_calc = Bars.HighPrices.LastValue + _offset;
                Chart.DrawIcon("Buy", ChartIconType.UpTriangle, Bars.OpenTimes.LastValue, _offset_calc, Color.Green);
            }
        }
    }
}

--------------------

using cAlgo.API;


namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class CustomFractals : Indicator
    {
        [Parameter(DefaultValue = 3, MinValue = 1)]
        public int Period { get; set; }

        [Output("Up Fractal", LineColor = "Red", PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries UpFractal { get; set; }

        [Output("Down Fractal", LineColor = "Green", PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries DownFractal { get; set; }

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

            DrawUpFractal(index);
            DrawDownFractal(index);

        }

        private void DrawUpFractal(int index)
        {
            int period = Period % 2 == 0 ? Period - 1 : Period;
            int middleIndex = index - period / 2;
            double middleValue = Bars.HighPrices[middleIndex];

            bool up = true;

            for (int i = 0; i < period; i++)
            {
                if (middleValue < Bars.HighPrices[index - i])
                {
                    up = false;
                    break;
                }
            }
            if (up)
                UpFractal[middleIndex] = middleValue;

        }

        private void DrawDownFractal(int index)
        {
            int period = Period % 2 == 0 ? Period - 1 : Period;
            int middleIndex = index - period / 2;
            double middleValue = Bars.LowPrices[middleIndex];
            bool down = true;

            for (int i = 0; i < period; i++)
            {
                if (middleValue > Bars.LowPrices[index - i])
                {
                    down = false;
                    break;
                }
            }
            if (down)
                DownFractal[middleIndex] = middleValue;

        }


    }
}

Your help and advice is greatly appreciated, thanks.

@Fractals and engulfing:  15 Sep 2021, 12:33


amusleh said:

I recommend you to calculate the fractals by your self, instead of using cTrader fractals indicator, that way you will be sure about how it works and what kind of result it should give you.

Try this:

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Fractal Period", DefaultValue = 5, MinValue = 5)]
        public int Period { get; set; }

        [Parameter("Volume", DefaultValue = 1000)]
        public double FirstVolume { get; set; }

        private Fractals _fractal;

        protected override void OnStart()
        {
            _fractal = Indicators.Fractals(Period);
        }

        protected override void OnBar()
        {
            if (double.IsNaN(_fractal.UpFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) <= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) < Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) > Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.UpFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }

            if (double.IsNaN(_fractal.DownFractal.Last(Period)) == false && Bars.ClosePrices.Last(Period - 1) >= Bars.OpenPrices.Last(Period) && Bars.ClosePrices.Last(Period - 1) > Bars.OpenPrices.Last(Period - 1) && Bars.ClosePrices.Last(Period) < Bars.OpenPrices.Last(Period))
            {
                Print(_fractal.DownFractal.Last(Period));

                foreach (var position in Positions)
                {
                    if (position.SymbolName == SymbolName && position.Label == "Fractal")
                        ClosePosition(position);
                }
                ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, "Fractal", null, null, null, false);
            }
        }
    }
}

My sample uses cTrader fractals and if the next candle after fractal was an engulfing candle it executes the trade.

But I don't know how the cTrader fractals indicator works, so its better to calculate it by yourself or search and you might find some fractal indicators already developed by other community members.

Hi amusleh,

Thanks for the code suggestions, I'll have a look at it now.

The cTrader fractals has a natural limitation of min 5 periods, which didn't work for me. As a result, I am already using a custom fractal system I found on the community forum.

Basic fractals, but with a min limit of < 5.

Thanks again.

@Fractals and engulfing:  14 Sep 2021, 11:31


Hi, I'm working with fractals and I'm having trouble with the logic of how the logic is supposed to work.

Here is an image example of what I need:



 

I understand that fractals will take some extra bars to form (in this instance, the period is set to 3), which means the entry will come when Bar 0 turns into Bar 1.

In a bearish situation such as the image, if Bar 1 has printed an up fractal and Bar 0 became a bearish engulfing, a sell should happen. The reverse is true for bullish.

I would like this to be defined by a boolean, where true would be bullish and false would be bearish. I have added some code to explain where I'm struggling.

_FractalQ = GetFractal();
_EngulfingQ = GetEngulfing();



private bool GetFractal()
        {
            //??
        }

private bool GetEngulfing()
        {
            //??
        }

@Pending Order/Fragmentation Trading Panel:  08 Sep 2021, 09:56


amusleh said:

Hi,

You should use a loop to execute multiple orders, try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class EasyStop : 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 Price", Group = "Default trade parameters", DefaultValue = 1.17)]
        public double DefaultPrice { get; set; }

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

        [Parameter("Default Fragmentation", Group = "Default trade parameters", DefaultValue = 1)]
        public double DefaultFrag { get; set; }

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

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

        protected override void OnStart()
        {
            var tradingPanel = new TradingPanel(this, Symbol, DefaultPrice, DefaultFrag, DefaultLots, DefaultStopLossPips, DefaultTakeProfitPips);

            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 PriceInputKey = "PriceKey";
        private const string FragInputKey = "FragKey";
        private const string TakeProfitInputKey = "TPKey";
        private const string StopLossInputKey = "SLKey";
        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 defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            _robot = robot;
            _symbol = symbol;
            AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultStopLossPips, defaultTakeProfitPips));
        }

        private ControlBase CreateTradingPanel(double defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            var mainPanel = new StackPanel();

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

            var contentPanel = CreateContentPanel(defaultPrice, defaultFrag, defaultLots, defaultStopLossPips, defaultTakeProfitPips);
            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 defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            var contentPanel = new StackPanel
            {
                Margin = 10
            };
            var grid = new Grid(9, 3);
            grid.Columns[1].SetWidthInPixels(5);

            var sellmarketButton = CreateMarketTradeButton("MARKET SELL", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(sellmarketButton, 0, 0);

            var buymarketButton = CreateMarketTradeButton("MARKET BUY", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buymarketButton, 0, 2);

            var sellstopButton = CreateStopTradeButton("SELL STOP", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(sellstopButton, 1, 0);

            var buystopButton = CreateStopTradeButton("BUY STOP", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buystopButton, 1, 2);

            var selllimitButton = CreateLimitTradeButton("SELL LIMIT", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(selllimitButton, 3, 0);

            var buylimitButton = CreateLimitTradeButton("BUY LIMIT", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buylimitButton, 3, 2);

            var priceInput = CreateInputWithLabel("Pending Price", defaultPrice.ToString("F2"), PriceInputKey);
            grid.AddChild(priceInput, 4, 0);

            var fragInput = CreateInputWithLabel("Order Fragmentation", defaultFrag.ToString("F2"), FragInputKey);
            grid.AddChild(fragInput, 4, 2);

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

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

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

            var closeAllPendingButton = CreateCloseAllPendingButton();
            grid.AddChild(closeAllPendingButton, 7, 0, 1, 3);

            var closeAllOpenButton = CreateCloseAllOpenButton();
            grid.AddChild(closeAllOpenButton, 8, 0, 1, 3);

            contentPanel.AddChild(grid);

            return contentPanel;
        }

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

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

            return tradeButton;
        }

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

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

            return tradeButton;
        }

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

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

            return tradeButton;
        }

        private ControlBase CreateCloseAllPendingButton()
        {
            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 Pending",
                Margin = "0 10 0 0"
            };

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

            return closeAllBorder;
        }

        private ControlBase CreateCloseAllOpenButton()
        {
            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 Open",
                Margin = "0 10 0 0"
            };

            closeButton.Click += args => CloseAllOpen();
            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 PlaceMarket(TradeType tradeType)
        {
            var _vol_usable = Calc_LPT();
            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
            var _price_usable = GetValueFromInput(PriceInputKey, 0);

            var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);
            var lots = GetValueFromInput(LotsInputKey, 0);

            if (lots <= 0)
            {
                _robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
                return;
            }

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                for (int i = 0; i < _frag; i++)
                {
                    _robot.ExecuteMarketOrderAsync(tradeType, _symbol.Name, _volume_units, string.Empty, stopLossPips, takeProfitPips);
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }
        }

        private void PlaceStop(TradeType tradeType)
        {
            var _vol_usable = Calc_LPT();
            var lots = GetValueFromInput(LotsInputKey, 0);
            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
            var _price_usable = GetValueFromInput(PriceInputKey, 0);

            var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);

            if (lots <= 0)
            {
                _robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
                return;
            }

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                for (int i = 0; i < _frag; i++)
                {
                    _robot.PlaceStopOrderAsync(tradeType, _symbol.Name, _volume_units, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }
        }

        private void PlaceLimit(TradeType tradeType)
        {
            var _vol_usable = Calc_LPT();
            var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
            var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
            var _price_usable = GetValueFromInput(PriceInputKey, 0);

            var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);
            var lots = GetValueFromInput(LotsInputKey, 0);
            if (lots <= 0)
            {
                _robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
                return;
            }

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                for (int i = 0; i < _frag; i++)
                {
                    _robot.PlaceLimitOrderAsync(tradeType, _symbol.Name, _volume_units, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }
        }

        private double Calc_LPT()
        {
            var _lots = GetValueFromInput(LotsInputKey, 0);
            var _frag = GetValueFromInput(FragInputKey, 0);
            var result = Math.Round(_lots / _frag, 2);
            return result;
        }

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

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

        private void CloseAllPending()
        {
            foreach (var pending in _robot.PendingOrders)
                _robot.CancelPendingOrderAsync(pending);
        }

        private void CloseAllOpen()
        {
            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);
        }
    }
}

Hi amusleh,

That's brilliant, thank you so much!

If you wouldn't mind, I have another thread regarding something new I'm trying in this same bot: 

@Output variable value to textbox:  23 Aug 2021, 21:40


Hi all,

I spent some time attempting to figure all of this out on my own, but no luck so far.

I've added some code snippets for reference, as the source for this bot has gotten kind of long so far.

The basic problem: to output the value of a variable to a textbox (chart object).

The code has an existing method of retrieving the value of a textbox and assigning it to a variable. That method looks like this:
 

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

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


An example of using the above method looks like this:

var _lots = GetValueFromInput(LotsInputKey, 0);

In the above example, LotsInputKey is the assigned variable of the textbox.

What I am looking for is basically the exact opposite of this; a way to set the value of a textbox equal to a variable.

I am not even entirely sure if a method would be the best way to accomplish this, which is why I'm asking

Any advice would be greatly appreciated, thanks.

@Pending Order/Fragmentation Trading Panel:  21 Aug 2021, 18:23


Hi all,

I've modified the cTrader sample Quick Trading Panel to support some extra features I wanted. The features added are as follows:

Pending orders (Both Stop & Limit).
Fragmentation of orders (Splitting total volume between the number of positions to create several smaller positions).
Close all pending orders at once.

However, I've encountered two errors with the fragmentation logic specifically. These errors are:

1. When the lot size per fragmented position is less than 1 (eg. 3 lots total over 6 positions for 0.5 lots total), I receive an error that the lot size is 0.

2. When the fragment is more than 1 only one order is opened. An example of this would be 3 lots total over 2 positions, meaning 2 positions of 1.5 lots each should be opened. Only one is opened though.

Here is the code:

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class EasyStop : 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 Price", Group = "Default trade parameters", DefaultValue = 1.17)]
        public double DefaultPrice { get; set; }

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

        [Parameter("Default Fragmentation", Group = "Default trade parameters", DefaultValue = 1)]
        public double DefaultFrag { get; set; }

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

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

        protected override void OnStart()
        {
            var tradingPanel = new TradingPanel(this, Symbol, DefaultPrice, DefaultFrag, DefaultLots, DefaultStopLossPips, DefaultTakeProfitPips);

            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 PriceInputKey = "PriceKey";
        private const string FragInputKey = "FragKey";
        private const string TakeProfitInputKey = "TPKey";
        private const string StopLossInputKey = "SLKey";
        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 defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            _robot = robot;
            _symbol = symbol;
            AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultStopLossPips, defaultTakeProfitPips));
        }

        private ControlBase CreateTradingPanel(double defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            var mainPanel = new StackPanel();

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

            var contentPanel = CreateContentPanel(defaultPrice, defaultFrag, defaultLots, defaultStopLossPips, defaultTakeProfitPips);
            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 defaultPrice, double defaultFrag, double defaultLots, double defaultStopLossPips, double defaultTakeProfitPips)
        {
            var contentPanel = new StackPanel 
            {
                Margin = 10
            };
            var grid = new Grid(9, 3);
            grid.Columns[1].SetWidthInPixels(5);

            var sellmarketButton = CreateMarketTradeButton("MARKET SELL", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(sellmarketButton, 0, 0);

            var buymarketButton = CreateMarketTradeButton("MARKET BUY", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buymarketButton, 0, 2);

            var sellstopButton = CreateStopTradeButton("SELL STOP", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(sellstopButton, 1, 0);

            var buystopButton = CreateStopTradeButton("BUY STOP", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buystopButton, 1, 2);

            var selllimitButton = CreateLimitTradeButton("SELL LIMIT", Styles.CreateSellButtonStyle(), TradeType.Sell);
            grid.AddChild(selllimitButton, 3, 0);

            var buylimitButton = CreateLimitTradeButton("BUY LIMIT", Styles.CreateBuyButtonStyle(), TradeType.Buy);
            grid.AddChild(buylimitButton, 3, 2);

            var priceInput = CreateInputWithLabel("Pending Price", defaultPrice.ToString("F2"), PriceInputKey);
            grid.AddChild(priceInput, 4, 0);

            var fragInput = CreateInputWithLabel("Order Fragmentation", defaultFrag.ToString("F2"), FragInputKey);
            grid.AddChild(fragInput, 4, 2);

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

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

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

            var closeAllPendingButton = CreateCloseAllPendingButton();
            grid.AddChild(closeAllPendingButton, 7, 0, 1, 3);

            var closeAllOpenButton = CreateCloseAllOpenButton();
            grid.AddChild(closeAllOpenButton, 8, 0, 1, 3);

            contentPanel.AddChild(grid);

            return contentPanel;
        }

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

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

            return tradeButton;
        }

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

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

            return tradeButton;
        }

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

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

            return tradeButton;
        }

        private ControlBase CreateCloseAllPendingButton()
        {
            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 Pending",
                Margin = "0 10 0 0"
            };

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

            return closeAllBorder;
        }

        private ControlBase CreateCloseAllOpenButton()
        {
            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 Open",
                Margin = "0 10 0 0"
            };

            closeButton.Click += args => CloseAllOpen();
            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 PlaceMarket(TradeType tradeType)
        {
            var _vol_usable = 0.0;
            var count = 0;
            var lots = GetValueFromInput(LotsInputKey, 0);
            if (lots <= 0)
            {
                _robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
                return;
            }

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                _vol_usable = Calc_LPT();
                var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
                var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
                var _price_usable = GetValueFromInput(PriceInputKey, 0);

                var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);
                if (count != _frag)
                {
                    _robot.ExecuteMarketOrderAsync(tradeType, _symbol.Name, _volume_units, string.Empty, stopLossPips, takeProfitPips);
                    count++;
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }

        }

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

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                _vol_usable = Calc_LPT();
                var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
                var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
                var _price_usable = GetValueFromInput(PriceInputKey, 0);

                var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);
                if (count != _frag)
                {
                    _robot.PlaceStopOrderAsync(tradeType, _symbol.Name, _volume_units, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
                    count++;
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }

        }

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

            var _frag = GetValueFromInput(FragInputKey, 0);
            if (_frag >= 1)
            {
                _vol_usable = Calc_LPT();
                var stopLossPips = GetValueFromInput(StopLossInputKey, 0);
                var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
                var _price_usable = GetValueFromInput(PriceInputKey, 0);

                var _volume_units = _symbol.QuantityToVolumeInUnits(_vol_usable);
                if (count != _frag)
                {
                    _robot.PlaceLimitOrderAsync(tradeType, _symbol.Name, _volume_units, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
                    count++;
                }
            }
            else if (_frag < 1)
            {
                _robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
                return;
            }

        }

        private double Calc_LPT()
        {
            var _lots = GetValueFromInput(LotsInputKey, 0);
            var _frag = GetValueFromInput(FragInputKey, 0);
            var result = Math.Round(_lots / _frag, 2);
            return result;
        }

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

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

        private void CloseAllPending()
        {
            foreach (var pending in _robot.PendingOrders)
                _robot.CancelPendingOrderAsync(pending);
        }

        private void CloseAllOpen()
        {
            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);
        }
    }
}

Thanks in advance,

@Custom indicator parameters question:  16 Aug 2021, 16:22


amusleh said:

Hi,

When you are using a custom indicator on a cBot you must pass a value for all of the indicator parameters, for TDI you can use it like this:

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class TDISystem : Robot
    {
        //parameters

        private TradersDynamicIndex _TDI;

        protected override void OnStart()
        {
            _TDI = Indicators.GetIndicator<TradersDynamicIndex>(Bars.ClosePrices, 13, 2, 7, 34, 2, MovingAverageType.Simple, MovingAverageType.Simple);
        }

        protected override void OnBar()
        {
            // Put your core logic here
        }

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

The parameters you pass must be in same order that is defined in indicator.

Hi,

This is perfect, thanks!

@Custom indicator parameters question:  14 Aug 2021, 13:36


Hi all,

I want to use a custom indicator that I found on cTrader.com in a bot. This is the Traders Dynamic Index (TDI.)

I referenced the indicator into the bot successfully, however, I am new to custom indicators and am not sure about the parameters I should be calling for this specific indicator (it has a lot of inner workings).

Here is the cBot source:
 

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.FullAccess)]
    public class TDISystem : Robot
    {
        //parameters

        private TradersDynamicIndex _TDI;

        protected override void OnStart()
        {
            _TDI = Indicators.GetIndicator<TradersDynamicIndex>(???);
        }

        protected override void OnBar()
        {
            // Put your core logic here
        }

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

The three question marks are the bit I am uncertain about.

Here is the indicator source:
 

using System;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Levels(32, 50, 68)]
    [Indicator(AccessRights = AccessRights.None)]
    public class TradersDynamicIndex : Indicator
    {
        private RelativeStrengthIndex _rsi;
        private MovingAverage _price;
        private MovingAverage _signal;
        private BollingerBands _bollingerBands;

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

        [Parameter("RSI Period", DefaultValue = 13)]
        public int RsiPeriod { get; set; }

        [Parameter("Price Period", DefaultValue = 2)]
        public int PricePeriod { get; set; }

        [Parameter("Signal Period", DefaultValue = 7)]
        public int SignalPeriod { get; set; }

        [Parameter("Volatility Band", DefaultValue = 34)]
        public int Volatility { get; set; }

        [Parameter("Standard Deviations", DefaultValue = 2)]
        public int StDev { get; set; }

        [Parameter("Price MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType PriceMaType { get; set; }

        [Parameter("Signal MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType SignalMaType { get; set; }

        [Output("Upper Band", LineColor = "Blue")]
        public IndicatorDataSeries Up { get; set; }

        [Output("Lower Band", LineColor = "Blue")]
        public IndicatorDataSeries Down { get; set; }

        [Output("Middle Band", LineColor = "Orange", Thickness = 2)]
        public IndicatorDataSeries Middle { get; set; }

        [Output("Price", LineColor = "Green", Thickness = 2)]
        public IndicatorDataSeries PriceSeries { get; set; }

        [Output("Signal", LineColor = "Red", Thickness = 2)]
        public IndicatorDataSeries SignalSeries { get; set; }

        protected override void Initialize()
        {
            _rsi = Indicators.RelativeStrengthIndex(Source, RsiPeriod);
            _bollingerBands = Indicators.BollingerBands(_rsi.Result, Volatility, StDev, MovingAverageType.Simple);
            _price = Indicators.MovingAverage(_rsi.Result, PricePeriod, PriceMaType);
            _signal = Indicators.MovingAverage(_rsi.Result, SignalPeriod, SignalMaType);
        }



        public override void Calculate(int index)
        {
            Up[index] = _bollingerBands.Top[index];
            Down[index] = _bollingerBands.Bottom[index];
            Middle[index] = _bollingerBands.Main[index];

            PriceSeries[index] = _price.Result[index];
            SignalSeries[index] = _signal.Result[index];

        }


    }
}



Any help as to what parameters and in which order would be appreciated, thanks.

@Stoploss algorithm working on Candles, but not Renko:  28 Jul 2021, 16:42


amusleh said:

Hi,

Can you post the cBot full code?

Hi,

Thanks for the reply, but it's not necessary. I set the stop at executing to null and it worked.

Sharing just in case someone has the same problem. 

@Stoploss algorithm working on Candles, but not Renko:  28 Jul 2021, 11:37


Hi all,

I have created a stop loss algorithm that works like this:

Initial Stop Loss = 11 pips on Execution.
Stop Loss Modified = Supertrend Last + 5 extra pips until the breakeven trigger
The breakeven trigger is 5 pips, at which point the stop is kept at breakeven for the rest of the position duration.

The algorithm works... but only on candles for some reason.

To visually explain this, I have attached some images:


 

In this image of a backtest I ran, you can see that this works exactly as intended. The breakeven requirement is never hit, thus the stop is equal to Supertrend Downtrend + 5 pips.

However, in this image:


This image comes from a demo running with the initial stop of 11 pips still intact. The red line is the actual exit at 11 pips, and the purple line is where the stop loss should have been.

Here is the logic for the stop loss:
 

if (ActiveBuy != null || ActiveSell != null)
            {
                var entryPrice = ActiveBuy != null ? ActiveBuy.EntryPrice : ActiveSell.EntryPrice;
                var sT_Stop = ActiveBuy != null ? _STrend.UpTrend.Last(1) : _STrend.DownTrend.Last(1);
                var distance = 0.0;
                var beTrigger = 5.0;
                var breakEven = ActiveBuy != null ? entryPrice + ExtraPips * Symbol.PipSize : entryPrice - ExtraPips * Symbol.PipSize;
                var _mod_SL = ActiveBuy != null ? sT_Stop + ExtraPipsStop * Symbol.PipSize : sT_Stop + ExtraPipsStop * Symbol.PipSize;

                if (ActiveBuy != null)
                {
                    distance = Symbol.Bid - entryPrice;
                    if (distance >= beTrigger * Symbol.PipSize && ActiveBuy.StopLoss != breakEven)
                    {
                        ModifyPosition(ActiveBuy, breakEven, null);
                    }
                    else if (ActiveBuy.StopLoss != _mod_SL && ActiveBuy.StopLoss != breakEven)
                    {
                        ModifyPosition(ActiveBuy, _mod_SL, null);
                    }
                }
                else if (ActiveSell != null)
                {
                    distance = entryPrice - Symbol.Ask;
                    if (distance >= beTrigger * Symbol.PipSize && ActiveSell.StopLoss != breakEven)
                    {
                        ModifyPosition(ActiveSell, breakEven, null);
                    }
                    else if (ActiveSell.StopLoss != _mod_SL && ActiveSell.StopLoss != breakEven)
                    {
                        ModifyPosition(ActiveSell, _mod_SL, null);
                    }
                }



Any advice would be greatly appreciated

Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.

No uploaded.

Warning! Executing cBots downloaded from this section may result in loss of funds. Use them at your own risk.

No uploaded.