Topics

Forum Topics not found

Replies

amusleh
18 Jun 2021, 20:11

Hi,

cTrader Automate API gives you two option for drawing on charts:

  1. Chart Controls
  2. Chart Objects

The first one is static and doesn't depend on your chart price and time axis, the second one is more dynamic and you can position it based on chart price and time axis.

For your case I thing you should use ChartText not chart controls.

To allow user to interact with your chart object (change font size, color,...) set its IsInteractive property to True.

First call the Chart.DrawText and save the returning ChartText object on a variable, then set its IsInteractive property to True:

// You can also use time instead of BarIndex
var chartText = Chart.DrawText("Text", "My text", barIndex, price, color);

chartText.IsInteractive = True;

// If you want to lock the object position and only allow user to change // text properties set its IsLocked to True

chartText.IsLocked = True;

Checkout the ChartText example on API references and if you need a more advanced sample check the Pattern Drawing indicator code.


@amusleh

amusleh
18 Jun 2021, 16:57 ( Updated at: 18 Jun 2021, 16:58 )

Hi,

You should not use Print method inside property setter method, this works fine:

using cAlgo.API;


namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Baseline : Robot
    {
        [Parameter("Risk (%)", DefaultValue = 2.0, MinValue = 1.0, MaxValue = 5.0, Step = 1.0, Group = "Risk Management")]
        public double RiskPercentage
        {
            get 
            { 
                return riskPercentage;
            }
            set 
            { 
                riskPercentage = SetRisk(value);
            }
        }


        private double riskPercentage;

        protected override void OnStart()
        {

            RiskPercentage = 4.0;
        }

        protected override void OnBar()
        {

        }

        protected override void OnTick()
        {

        }

        private double SetRisk(double value)
        {
            return value;
        }
    }
}

And Strategy is null when you access it inside setter method, that can also cause this issue, because OnStart is not called yet.


@amusleh

amusleh
16 Jun 2021, 11:53 ( Updated at: 16 Jun 2021, 11:55 )

Hi,

You can open a buy/sell market order by using ExecuteMarketOrder method, and you can pass the stop loss/take profit in Pips.

The order will be executed based on symbol bid/ask price, check the code examples of Position.

You can use OnBar method on a Renko chart to execute your orders per bar, or use the OnTick method to count the Pips by your self.


@amusleh

amusleh
14 Jun 2021, 14:33

Hi,

I created a MTF exponential moving average for you:

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MTFEMA : Indicator
    {
        private Bars _baseTimeFrameBars;

        private DataSeries _baseSeries;

        private double _multiplier;

        private bool _isInitialized;

        private int _baseTimeFramePreviousIndex;

        private double _baseTimeFramePreviousEma;

        [Parameter(DefaultValue = 14)]
        public double Periods { get; set; }

        [Parameter("Source", DefaultValue = DataSource.Close)]
        public DataSource Source { get; set; }

        [Parameter("Base Time Frame")]
        public TimeFrame BaseTimeFrame { get; set; }

        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        protected override void Initialize()
        {
            _baseTimeFrameBars = MarketData.GetBars(BaseTimeFrame);

            _baseSeries = GetSeries(Source);

            _multiplier = 2 / (Periods + 1);
        }

        public override void Calculate(int index)
        {
            var baseTimeFrameIndex = _baseTimeFrameBars.OpenTimes.GetIndexByTime(Bars[index].OpenTime);

            if (baseTimeFrameIndex < Periods) return;

            if (!_isInitialized)
            {
                Result[index] = GetAverage(baseTimeFrameIndex);

                _isInitialized = true;
            }
            else
            {
                Result[index] = (_baseTimeFrameBars[baseTimeFrameIndex].Close - _baseTimeFramePreviousEma) * _multiplier + _baseTimeFramePreviousEma;
            }

            if (baseTimeFrameIndex != _baseTimeFramePreviousIndex)
            {
                _baseTimeFramePreviousIndex = baseTimeFrameIndex;
                _baseTimeFramePreviousEma = Result[index];
            }
        }

        private double GetAverage(int index)
        {
            var lastIndex = index - Periods;

            double sum = 0;

            for (var i = index; i > lastIndex; i--)
            {
                sum += _baseSeries[i];
            }

            return sum / Periods;
        }

        private DataSeries GetSeries(DataSource dataSource)
        {
            switch (dataSource)
            {
                case DataSource.Open:
                    return _baseTimeFrameBars.OpenPrices;

                case DataSource.High:
                    return _baseTimeFrameBars.HighPrices;

                case DataSource.Low:
                    return _baseTimeFrameBars.LowPrices;

                case DataSource.Close:
                    return _baseTimeFrameBars.ClosePrices;

                case DataSource.Volume:
                    return _baseTimeFrameBars.TickVolumes;

                case DataSource.Typical:
                    return _baseTimeFrameBars.TypicalPrices;

                case DataSource.Weighted:
                    return _baseTimeFrameBars.WeightedPrices;

                case DataSource.Median:
                    return _baseTimeFrameBars.MedianPrices;

                default:
                    throw new ArgumentOutOfRangeException("dataSource");
            }
        }
    }

    public enum DataSource
    {
        Open,
        High,
        Low,
        Close,
        Volume,
        Typical,
        Median,
        Weighted
    }
}

I checked it gives same result like built-in EMA, only the last bar value might be different because it waits for bar to finish then it updates the value as it should consider other time frames data, hopefully this will help you.


@amusleh

amusleh
14 Jun 2021, 13:06

Hi,

I don't know what you are trying to do, but the correct way to work with another time frame data is what I just posted.

Do you want to calculate the exponential moving average value of another time frame? 


@amusleh

amusleh
14 Jun 2021, 12:06

Hi,

You can't use index for another time frame bars data, in your code you used the current chart bars index to get another time frame bars data: barsTF1.ClosePrices[index]

Try this:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TripleEMA : Indicator
    {
        [Parameter("EMA Fast", DefaultValue = 50)]
        public int Periods { get; set; }

        [Parameter("EMA Slow", DefaultValue = 100)]
        public int Periods1 { get; set; }

        [Parameter("EMA Trend", DefaultValue = 200)]
        public int Periods2 { get; set; }

        [Parameter("EMA Trend", DefaultValue = 100)]
        public int Periods3 { get; set; }

        [Parameter("TimeFrame", DefaultValue = "Daily")]
        public TimeFrame EMATimeframe1 { get; set; }

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

        [Output("EMA2", LineColor = "Red")]
        public IndicatorDataSeries EMA2 { get; set; }

        [Output("EMA3", LineColor = "Yellow")]
        public IndicatorDataSeries EMA3 { get; set; }

        private Bars series1;
        private Bars barsTF1;

        private ExponentialMovingAverage Ema1;
        private ExponentialMovingAverage Ema2;
        private ExponentialMovingAverage Ema3;
        private ExponentialMovingAverage Ema4;

        private IndicatorDataSeries _iDataSeries1;

        protected override void Initialize()
        {
            //series1 = MarketData.GetSeries(EMATimeframe1);
            series1 = MarketData.GetBars(EMATimeframe1);

            Ema1 = Indicators.ExponentialMovingAverage(series1.ClosePrices, Periods);
            Ema2 = Indicators.ExponentialMovingAverage(series1.ClosePrices, Periods1);
            Ema3 = Indicators.ExponentialMovingAverage(series1.ClosePrices, Periods2);

            barsTF1 = MarketData.GetBars(TimeFrame.Hour4);
            _iDataSeries1 = CreateDataSeries();

            Ema4 = Indicators.ExponentialMovingAverage(_iDataSeries1, Periods3);
        }

        public override void Calculate(int index)
        {
            var index1 = GetIndexByDate(series1, Bars.OpenTimes[index]);
            if (index1 != -1)
            {
                EMA1[index] = Ema1.Result[index1];
            }

            var index2 = GetIndexByDate(series1, Bars.OpenTimes[index]);
            if (index2 != -1)
            {
                EMA2[index] = Ema2.Result[index2];
            }

            var index3 = GetIndexByDate(series1, Bars.OpenTimes[index]);
            if (index3 != -1)
            {
                EMA3[index] = Ema3.Result[index3];
            }

            var barsTF1Index = barsTF1.OpenTimes.GetIndexByTime(Bars[index].OpenTime);

            _iDataSeries1[index] = barsTF1.ClosePrices[barsTF1Index] - (High(index) + Low(index)) / 2;

            Print("EMA : " + Ema4.Result[index]);
        }

        private int GetIndexByDate(Bars series, DateTime time)
        {
            for (int i = series.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTimes[i])
                    return i;
            }
            return -1;
        }

        private double High(int index)
        {
            double high = Bars.HighPrices[index - 10];

            for (int i = index - 10 + 1; i <= index; i++)
            {
                if (Bars.HighPrices[i] > high)
                    high = Bars.HighPrices[i];
            }

            return high;
        }

        private double Low(int index)
        {
            double low = Bars.LowPrices[index - 10];

            for (int i = index - 10 + 1; i <= index; i++)
            {
                if (Bars.LowPrices[i] < low)
                    low = Bars.LowPrices[i];
            }

            return low;
        }
    }
}

 


@amusleh

amusleh
13 Jun 2021, 08:27

Hi,

To use WinForms on your cBot/Indicator, you have to follow these steps:

  • Add System.Windows.Forms Reference to your cBot/Indicator project
  • Change your cBot/Indicator AccessRights to FullAccess
  • Add a Windows Form to your cBot/Indicator project by right clicking on your project in VS, then select Add -> Form
  • Design your form on VS WinFroms Designer
  • To communicate between your cBot/Indicator and Form you can pass your indicator/cBot to the form via its constructor parameter, or use an adapter object
  • You must execute the Form ShowDialog method inside a separate thread, because this method blocks the thread until the form is closed you have to use a separate thread, and not use the cBot/Indicator main execution thread, also the thread must have STA ApartmentState
  • Build your cBot/Indicator project from VS not cTrader, because of the changes you made on references and adding new form, you can build it from cTrader but the first build after adding the form and making changes on project references must be done by VS

As an example you can check my WinForms Test cBot sample:  

 

Clone it from Github or download it as a zip file, extract the content on a new folder inside your cTrader cAlgo/Robots folder, it will appear in your cTrader automate cBots list, re-build it and run it.

Open it with VS to see the cBot full code.


@amusleh

amusleh
10 Jun 2021, 10:56

Hi,

You can use separate outputs for each time frame, and add Output attribute to your indicator outputs otherwise it will not work.


@amusleh

amusleh
08 Jun 2021, 12:05

Hi,

You can draw Fibonacci Expansion and Channel with our Fibonacci Drawing indicator: 

 


@amusleh

amusleh
08 Jun 2021, 12:04

Hi,

The positions collections will be updated immediately after sending a position execution request, try this sample code:

using cAlgo.API;
using cAlgo.API.Internals;
using System.Text;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class RSIRangeRobot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin);
        }

        protected override void OnTick()
        {
            foreach (var position in Positions)
            {
                var stringBuilder = new StringBuilder();

                stringBuilder.AppendFormat("Before Execution: {0}", Positions.Count);

                ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin);

                stringBuilder.AppendFormat(" | After Execution: {0}", Positions.Count);

                Print(stringBuilder);
            }
        }
    }
}

 


@amusleh

amusleh
08 Jun 2021, 11:54

Hi,

Try to put your entry code inside OnBar method, not on OnTick, right now your bot opens a new position on each tick if conditions were ok.

And put your closing code inside OnTick method, as you want to close as soon as possible when the conditions were met.


@amusleh

amusleh
08 Jun 2021, 11:46

Hi,

There are several issues on your code, I recommend you to take a look on Automate API references and multi time frame indicator samples.

I fixed some of the issues for you:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MTFGRaBCandles : Indicator
    {
        [Parameter("MA Period", DefaultValue = 300)]
        public int maPeriod { get; set; }

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

        [Parameter("Candle width", DefaultValue = 5)]
        public int CandleWidth { get; set; }

        [Parameter("Wick width", DefaultValue = 1)]
        public int WickWidth { get; set; }

        [Parameter("Above up color", DefaultValue = "LimeGreen")]
        public string AboveUpColor { get; set; }

        [Parameter("Above down color", DefaultValue = "DarkGreen")]
        public string AboveDownColor { get; set; }

        [Parameter("Middle up color", DefaultValue = "LightBlue")]
        public string MiddleUpColor { get; set; }

        [Parameter("Middle down color", DefaultValue = "DodgerBlue")]
        public string MiddleDownColor { get; set; }

        [Parameter("Below up color", DefaultValue = "Tomato")]
        public string BelowUpColor { get; set; }

        [Parameter("Below down color", DefaultValue = "Crimson")]
        public string BelowDownColor { get; set; }

        [Output("High Moving Average", Color = Colors.Red, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries HMaResult { get; set; }

        [Output("Low Moving Average", Color = Colors.LimeGreen, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries LMaResult { get; set; }

        [Output("Middle Moving Average", Color = Colors.Blue, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        private MovingAverage _Hma;
        private MovingAverage _Lma;
        private MovingAverage _ma;

        private Bars D1;

        private Color _AboveUpColor;
        private Color _AboveDownColor;
        private Color _MiddleUpColor;
        private Color _MiddleDownColor;
        private Color _BelowUpColor;
        private Color _BelowDownColor;

        protected override void Initialize()
        {
            D1 = MarketData.GetBars(TimeFrame.Daily);

            _Hma = Indicators.MovingAverage(D1.HighPrices, maPeriod, MAType);
            _Lma = Indicators.MovingAverage(D1.LowPrices, maPeriod, MAType);
            _ma = Indicators.MovingAverage(D1.ClosePrices, maPeriod, MAType);

            _AboveUpColor = GetColor(AboveUpColor);
            _AboveDownColor = GetColor(AboveDownColor);

            _MiddleUpColor = GetColor(MiddleUpColor);
            _MiddleDownColor = GetColor(MiddleDownColor);

            _BelowUpColor = GetColor(BelowUpColor);
            _BelowDownColor = GetColor(BelowDownColor);
        }

        public override void Calculate(int index)
        {
            var dailyIndex = D1.OpenTimes.GetIndexByTime(Bars[index].OpenTime);

            var open = D1.OpenPrices[dailyIndex];
            var high = D1.HighPrices[dailyIndex];
            var low = D1.LowPrices[dailyIndex];
            var close = D1.ClosePrices[dailyIndex];

            var HMA = _Hma.Result[index];
            var LMA = _Lma.Result[index];
            var MA = _ma.Result[index];

            HMaResult[index] = HMA;
            LMaResult[index] = LMA;
            MaResult[index] = MA;

            Color color = Color.Black;

            if (close > HMA)
                color = open > close ? _AboveDownColor : _AboveUpColor;

            if (close < LMA)
                color = open > close ? _BelowDownColor : _BelowUpColor;

            if (close >= LMA && close <= HMA)
                color = open > close ? _MiddleDownColor : _MiddleUpColor;

            Chart.DrawTrendLine("candle" + index, index, open, index, close, color, CandleWidth, LineStyle.Solid);
            Chart.DrawTrendLine("line" + index, index, high, index, low, color, WickWidth, LineStyle.Solid);
        }

        private Color GetColor(string colorString, int alpha = 255)
        {
            var color = colorString[0] == '#' ? Color.FromHex(colorString) : Color.FromName(colorString);

            return Color.FromArgb(alpha, color);
        }
    }
}

You can't start developing indicators/cBots without a solid knowledge of C# basics and Automate API.

If you can't develop your indicator you can post a job request or contact one of our consultants.


@amusleh

amusleh
05 Jun 2021, 19:30

RE:

traderfxmaster007 said:

Faulting application name: cTrader.exe, version: 4.0.14.48970, time stamp: 0xafdfe7f4
Faulting module name: PresentationCore.ni.dll, version: 4.8.4110.0, time stamp: 0x5de7179c
Exception code: 0xc00000fd
Fault offset: 0x0000000000350324
Faulting process id: 0x8d4
Faulting application start time: 0x01d756152ce5d722
Faulting application path: C:\Users\Administrator\AppData\Local\Apps\2.0\6PBGL0GK.DOV\JTW5VCAE.AMT\icma..ader_7ef853fc4bdbd138_0004.0000_0ba06d2b7438f083\cTrader.exe
Faulting module path: C:\windows\assembly\NativeImages_v4.0.30319_64\PresentationCore\461b892934d24d029a6ef6d42101af09\PresentationCore.ni.dll
Report Id: 44b3c76c-c45b-11eb-85ad-f15c940a3a9d

Hi,

Its not what I asked you to post, please run the cBot code I posted on my latest post and run it, when it crashed a message will appear on cTrader cBot logs tab, copy it and post it here.


@amusleh

amusleh
04 Jun 2021, 07:41

RE: RE: RE:

traderfxmaster007 said:

Sir Amusleh,

Same Error Code: 

Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object.

Hi,

Can you copy the full logs tab data and post here? that's the default cTrader error message, I need the message that the Print method shows.

Something is wrong with your ManagePositions method.

Please use the below code this time, it will display more detailed data regarding the exception:

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MiaEMARibbon : Robot
    {
        #region User defined parameters

        [Parameter("Instance Name", DefaultValue = "20 Rangers")]
        public string InstanceName { get; set; }

        [Parameter("Percentage Risk Model?", Group = "Money Management", DefaultValue = true)]
        public bool volPercentBool { get; set; }

        [Parameter("Scale Out?", Group = "Money Management", DefaultValue = true)]
        public bool ScaleOut { get; set; }

        [Parameter("Risk %", Group = "Money Management", DefaultValue = 1.5, MinValue = 1, MaxValue = 5)]
        public double volPercent { get; set; }

        [Parameter("Volume Quantity", Group = "Money Management", DefaultValue = 2000, MinValue = 1000, Step = 1000)]
        public int volQty { get; set; }

        [Parameter("StopLoss (*ATR)", Group = "Protection", DefaultValue = 1.5, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double ATRStopLoss { get; set; }

        [Parameter("TakeProfit (*ATR)", Group = "Protection", DefaultValue = 1.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double ATRTakeProfit { get; set; }

        [Parameter("BreakEven", Group = "Protection", DefaultValue = true)]
        public bool BreakEven { get; set; }

        [Parameter("BreakEvenTrigger (*ATR)", Group = "Protection", DefaultValue = 1.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TriggerPips { get; set; }

        [Parameter("Locked in Profit", Group = "Protection", DefaultValue = 3.0, MinValue = 1.0)]
        public double AddPips { get; set; }

        [Parameter("Use Trailing Stop", Group = "Protection", DefaultValue = true)]
        public bool UseTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (*ATR)", Group = "Protection", DefaultValue = 1.5, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (*ATR)", Group = "Protection", DefaultValue = 2.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TrailingStopStep { get; set; }

        [Parameter("Close on Weekend?", Group = "Filter", DefaultValue = true)]
        public bool CloseOnWeekend { get; set; }

        [Parameter("Allowable Slippage", Group = "Filter", DefaultValue = 3.0, MinValue = 0.5, Step = 0.1)]
        public double Slippage { get; set; }

        [Parameter("Max Allowable Spread", Group = "Filter", DefaultValue = 2.0, MinValue = 0.1, MaxValue = 100.0, Step = 0.1)]
        public double MaxSpread { get; set; }

        [Parameter("Calculate OnBar?", Group = "Filter", DefaultValue = true)]
        public bool CalculateOnBar { get; set; }

        #endregion User defined parameters

        #region Indicator declarations

        private ExponentialMovingAverage EMA_1 { get; set; }
        private ExponentialMovingAverage EMA_2 { get; set; }
        private ExponentialMovingAverage EMA_3 { get; set; }
        private ExponentialMovingAverage EMA_4 { get; set; }
        private ExponentialMovingAverage EMA_5 { get; set; }
        private ExponentialMovingAverage EMA_6 { get; set; }
        private ExponentialMovingAverage EMA_7 { get; set; }
        private ExponentialMovingAverage EMA_8 { get; set; }
        private ExponentialMovingAverage EMA_9 { get; set; }
        private ExponentialMovingAverage EMA_10 { get; set; }

        private AverageTrueRange ATR;

        private double SPREAD;
        private int volume;
        private string Comment;
        private int lastbar;
        private double StopLoss;
        private double TakeProfit;

        #endregion Indicator declarations

        #region Calculate Volume

        private int CalculateVolume(double stop_loss)
        {
            int result;
            switch (volPercentBool)
            {
                case true:
                    double costPerPip = (double)((int)(Symbol.PipValue * 100000));
                    double posSizeForRisk = Math.Round((Account.Balance * (volPercent / 100)) / (stop_loss * costPerPip), 2);
                    double posSizeToVol = (Math.Round(posSizeForRisk * 100000, 0));
                    Print("costperppip : $ {0}  ||  Lot : {1}  ||  Volume : {2}", costPerPip, posSizeForRisk, posSizeToVol);
                    result = (int)Symbol.NormalizeVolumeInUnits(posSizeToVol, RoundingMode.ToNearest);
                    result = result > 150000 ? 150000 : result;
                    result = result == 1000 ? 2000 : result;
                    Print("{0}% of Account Balance [ $ {1} ] used for Volume: {2}  ||  Risk : $ {3}", volPercent, Account.Balance, result, (StopLoss * costPerPip * result) / 100000);
                    break;

                default:
                    result = volQty;
                    Print("Volume Quantity Used! : {0}", result);
                    break;
            }
            return result;
        }

        #endregion Calculate Volume

        #region Standard event handlers

        /// This is called when the robot first starts, it is only called once.
        protected override void OnStart()
        {
            ATR = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            EMA_1 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 5);
            EMA_2 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 7);
            EMA_3 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 9);
            EMA_4 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 11);
            EMA_5 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 13);
            EMA_6 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 30);
            EMA_7 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 35);
            EMA_8 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 40);
            EMA_9 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 45);
            EMA_10 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);

            StopLoss = Math.Round((ATR.Result.Last(lastbar)) * ATRStopLoss / Symbol.PipSize, 0);
            TakeProfit = Math.Round((ATR.Result.Last(lastbar)) * ATRTakeProfit / Symbol.PipSize, 0);
            volume = CalculateVolume(StopLoss);
            SPREAD = Math.Round(Symbol.Spread / Symbol.PipSize, 2);
            Comment = "Chris Trend Trading ";
            if (CalculateOnBar)
                lastbar = 1;
            else
                lastbar = 0;

            // Subscribe to the Trade Closing event
            Positions.Closed += OnPositionsClosed;
        }

        /// This event handler is called every tick or every time the price changes for the symbol.
        protected override void OnTick()
        {
            try
            {
                ManagePositions();
            }
            catch (Exception ex)
            {
                Print(ex.GetLog());

                //Stop();
            }
        }

        /// a special event handler that is called each time a new bar is drawn on chart.
        /// if you want your robot to act only when the previous bar is closed, this standard handler is where you put your main trading code.
        protected override void OnBar()
        {
            try
            {
                ManagePositions();
                CloseHalf();
                MoveToBreakEven();
                SetTrailingStop();
            }
            catch (Exception ex)
            {
                Print(ex.GetLog());

                //Stop();
            }
        }

        /// a special Robot class member that handles situations with errors.
        protected override void OnError(Error error)
        {
            Print("Error Code {0}  ||  {1} {2}:{3}:{4}", error.Code, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
        }

        #endregion Standard event handlers

        #region Logic

        private void ManagePositions()
        {
            /// if there is no buy position open, open one
            if (IsPositionOpenByType(TradeType.Buy) == false && Extreme() == false && BuyEntry() == true && EntryBar() == true)
            {
                if (Trader_Bullish() == false && Investor_Bullish() == true)
                {
                    OpenPosition(TradeType.Buy);
                }
                else if (Trader_Bullish() == true && Bars.ClosePrices.Last(lastbar + 1) < Bars.OpenPrices.Last(lastbar + 1))
                {
                    OpenPosition(TradeType.Buy);
                }
            }
            /// if there is no sell position open, open one
            else if (IsPositionOpenByType(TradeType.Sell) == false && Extreme() == false && SellEntry() == true && EntryBar() == true)
            {
                if (Trader_Bearish() == false && Investor_Bearish() == true)
                {
                    OpenPosition(TradeType.Sell);
                }
                else if (Trader_Bearish() == true && Bars.ClosePrices.Last(lastbar + 1) > Bars.OpenPrices.Last(lastbar + 1))
                {
                    OpenPosition(TradeType.Sell);
                }
            }

            /// Call custom class method to Close Open Position
            if (IsPositionOpenByType(TradeType.Buy) == true && BuyExit() == true)
                ClosePosition(TradeType.Buy);
            else if (IsPositionOpenByType(TradeType.Sell) == true && SellExit() == true)
                ClosePosition(TradeType.Sell);
        }

        #endregion Logic

        #region Scale Out

        private void CloseHalf()
        {
            var positions = Positions.FindAll(InstanceName.ToString(), SymbolName);
            foreach (var position in positions)
            {
                var Secured = position.TradeType == TradeType.Buy ? position.StopLoss - position.EntryPrice : position.EntryPrice - position.StopLoss;
                var HalfVol = Math.Round(Symbol.NormalizeVolumeInUnits(((position.VolumeInUnits) / 2), RoundingMode.ToNearest), 0);
                if (ScaleOut == true && position.VolumeInUnits >= 2000 && (Secured / Symbol.PipSize) <= AddPips && position.Pips >= (ATR.Result.Last(lastbar) * ATRTakeProfit) / Symbol.PipSize)
                {
                    ClosePosition(position, HalfVol);
                    Print("[ {0} ] Scale Out {1}   ||   New Volume: {2}   ||   Gain/Loss {3} Pips / $ {4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, position.VolumeInUnits, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
                }
            }
        }

        #endregion Scale Out

        #region BreakEven

        /// Call custom class method to move StopLoss to BreakEven
        private void MoveToBreakEven()
        {
            var positions = Positions.FindAll(InstanceName.ToString(), SymbolName);
            foreach (var position in positions)
            {
                var desiredNetProfitInDepositAsset = AddPips * Symbol.PipValue * position.VolumeInUnits;
                var desiredGrossProfitInDepositAsset = desiredNetProfitInDepositAsset - position.Commissions * 2 - position.Swap;
                var quoteToDepositRate = Symbol.PipValue / Symbol.PipSize;
                var priceDifference = desiredGrossProfitInDepositAsset / (position.VolumeInUnits * quoteToDepositRate);
                var priceAdjustment = GetPriceAdjustmentByTradeType(position.TradeType, priceDifference);
                var breakEvenLevel = position.EntryPrice + priceAdjustment;
                var roundedBreakEvenLevel = RoundPrice(breakEvenLevel, position.TradeType);

                var stopposition = position.TradeType == TradeType.Buy ? position.EntryPrice - position.StopLoss : position.StopLoss - position.EntryPrice;
                if (BreakEven == true && stopposition > 0 && position.Pips >= (ATR.Result.Last(lastbar) * TriggerPips) / Symbol.PipSize)
                {
                    ModifyPosition(position, roundedBreakEvenLevel, position.TakeProfit);
                    Print("[ {0} ] Breakeven {1}   ||   {2} {3}:{4}:{5}", LastResult.Position.Id, SymbolName, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
                }
            }
        }

        #endregion BreakEven

        #region TrailingStop

        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < (ATR.Result.Last(lastbar) * TrailingStopTrigger))
                    continue;

                double newStopLossPrice = Symbol.Ask + (ATR.Result.Last(lastbar) * TrailingStopStep);
                var newStopLoss = RoundPrice(newStopLossPrice, position.TradeType);

                if (UseTrailingStop == true && (position.StopLoss == null || newStopLossPrice < position.StopLoss))
                    ModifyPosition(position, newStopLoss, position.TakeProfit);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Trailing {1}   ||   New StopLoss: {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < (ATR.Result.Last(lastbar) * TrailingStopTrigger))
                    continue;

                double newStopLossPrice = Symbol.Bid - (ATR.Result.Last(lastbar) * TrailingStopStep);
                var newStopLoss = RoundPrice(newStopLossPrice, position.TradeType);
                if (UseTrailingStop == true && (position.StopLoss == null || newStopLossPrice > position.StopLoss))
                    ModifyPosition(position, newStopLoss, position.TakeProfit);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Trailing {1}   ||   New StopLoss: {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion TrailingStop

        #region Open Trade

        /// Call custom class method to send a market order || open a new position

        private void OpenPosition(TradeType type)
        {
            var Pos = Positions.FindAll(InstanceName.ToString(), SymbolName);
            if (Pos.Count() == 0 && Server.Time.DayOfWeek <= DayOfWeek.Friday && Server.Time.Hour <= 19 && SPREAD <= MaxSpread)
            {
                if (ScaleOut)
                    ExecuteMarketRangeOrder(type, this.Symbol.Name, volume, Slippage, Symbol.Bid, InstanceName.ToString(), StopLoss, 0, Comment);
                else
                    ExecuteMarketRangeOrder(type, this.Symbol.Name, volume, Slippage, Symbol.Bid, InstanceName.ToString(), StopLoss, TakeProfit, Comment);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Open {1} {2}    ||   Volume:{3}    ||   Spread:{4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, type, SymbolName, LastResult.Position.VolumeInUnits, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion Open Trade

        #region Close Trade

        /// Standard event handler that triggers upon position closing.
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName.ToString(), SymbolName, type);
            if (p != null)
            {
                ClosePosition(p);
                Print("[ {0} ] Close {1} {2}    ||   Volume:{3}    ||   Spread:{4}   ||   Gain/Loss {5}Pips / $ {6}   ||   {7} {8}:{9}:{10}", LastResult.Position.Id, type, SymbolName, LastResult.Position.VolumeInUnits, SPREAD, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour,
                Server.Time.Minute, Server.Time.Second);
            }
            else if (CloseOnWeekend == true && p != null && Server.Time.DayOfWeek == DayOfWeek.Friday && Server.Time.Hour >= 21 && Server.Time.Minute >= 30)
            {
                ClosePosition(p);
                Print("[ {0} ] Close {1}  on Weekend   ||   Gain/Loss {1}Pips / $ {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        /// Check for opened position
        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName.ToString(), SymbolName, type);

            if (p.Count() > 0 || p.Count() != 0)
                return true;
            return false;
        }

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            // check if the position has been closed due to stoploss or takeprofit or any other(stop out etc)
            if (args.Reason == PositionCloseReason.StopLoss)
            {
                Print("[ {0} ] Stoploss Hit {1}   ||   Gain/Loss {2}Pips / $ {3}   ||   Spread:{4}   ||   {5} {6}:{7}:{8} ", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
            else if (args.Reason == PositionCloseReason.TakeProfit)
            {
                Print("[ {0} ] Take Profit Hit {1}   ||   Gain/Loss {2}Pips / $ {3}   ||   Spread:{4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion Close Trade

        #region Check for Setups

        //////////////////////////////////////////////////////////////////////////
        ///////////////////////// Check for Setups //////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        private bool Trader_Bullish()
        {
            if (EMA_1.Result.Last(lastbar) >= EMA_2.Result.Last(lastbar) && EMA_2.Result.Last(lastbar) >= EMA_3.Result.Last(lastbar) && EMA_3.Result.Last(lastbar) >= EMA_4.Result.Last(lastbar) && EMA_4.Result.Last(lastbar) >= EMA_5.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Trader_Bearish()
        {
            if (EMA_1.Result.Last(lastbar) <= EMA_2.Result.Last(lastbar) && EMA_2.Result.Last(lastbar) <= EMA_3.Result.Last(lastbar) && EMA_3.Result.Last(lastbar) <= EMA_4.Result.Last(lastbar) && EMA_4.Result.Last(lastbar) <= EMA_5.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Investor_Bullish()
        {
            if (EMA_6.Result.Last(lastbar) >= EMA_7.Result.Last(lastbar) && EMA_7.Result.Last(lastbar) >= EMA_8.Result.Last(lastbar) && EMA_8.Result.Last(lastbar) >= EMA_9.Result.Last(lastbar) && EMA_9.Result.Last(lastbar) >= EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Investor_Bearish()
        {
            if (EMA_6.Result.Last(lastbar) <= EMA_7.Result.Last(lastbar) && EMA_7.Result.Last(lastbar) <= EMA_8.Result.Last(lastbar) && EMA_8.Result.Last(lastbar) <= EMA_9.Result.Last(lastbar) && EMA_9.Result.Last(lastbar) <= EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool BuyEntry()
        {
            if (Bars.ClosePrices.Last(lastbar) > Bars.OpenPrices.Last(lastbar) && Bars.LowPrices.Last(lastbar) < EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_1.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_5.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_6.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool SellEntry()
        {
            if (Bars.ClosePrices.Last(lastbar) < Bars.OpenPrices.Last(lastbar) && Bars.HighPrices.Last(lastbar) > EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_1.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_5.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_6.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool BuyExit()
        {
            if (IsPositionOpenByType(TradeType.Buy) == true && EMA_1.Result.Last(lastbar) < EMA_2.Result.Last(lastbar) && EMA_1.Result.Last(lastbar) < EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_5.Result.Last(lastbar))
                return true;
            else if (IsPositionOpenByType(TradeType.Buy) == true && Bars.ClosePrices.Last(lastbar + 1) == Bars.LowPrices.Last(lastbar + 1) && Bars.ClosePrices.Last(lastbar + 2) == Bars.LowPrices.Last(lastbar + 2))
                return true;

            return false;
        }

        private bool SellExit()
        {
            if (IsPositionOpenByType(TradeType.Sell) == true && EMA_1.Result.Last(lastbar) > EMA_2.Result.Last(lastbar) && EMA_1.Result.Last(lastbar) > EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_5.Result.Last(lastbar))
                return true;
            else if (IsPositionOpenByType(TradeType.Sell) == true && Bars.ClosePrices.Last(lastbar + 1) == Bars.HighPrices.Last(lastbar + 1) && Bars.ClosePrices.Last(lastbar + 2) == Bars.HighPrices.Last(lastbar + 2))
                return true;
            return false;
        }

        private bool Extreme()
        {
            if (Math.Abs(EMA_1.Result.Last(lastbar) - EMA_5.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.618 || Math.Abs(EMA_5.Result.Last(lastbar) - EMA_6.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.382 || Math.Abs(EMA_6.Result.Last(lastbar) - EMA_10.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.618)
                return true;
            return false;
        }

        private bool EntryBar()
        {
            if (Math.Abs(Bars.OpenPrices.Last(lastbar) - Bars.ClosePrices.Last(lastbar)) > Math.Abs(Bars.HighPrices.Last(lastbar) - Bars.LowPrices.Last(lastbar)) * 0.618)
                return true;
            return false;
        }

        #endregion Check for Setups

        #region RoundPrice

        ////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////

        private double RoundPrice(double price, TradeType tradeType)
        {
            var multiplier = Math.Pow(10, Symbol.Digits);
            if (tradeType == TradeType.Buy)
                return Math.Ceiling(price * multiplier) / multiplier;

            return Math.Floor(price * multiplier) / multiplier;
        }

        private static double GetPriceAdjustmentByTradeType(TradeType tradeType, double priceDifference)
        {
            if (tradeType == TradeType.Buy)
                return priceDifference;

            return -priceDifference;
        }

        #endregion RoundPrice
    }

    public static class ExceptionExtensions
    {
        public static string GetLog(this Exception exception)
        {
            return exception.GetLog(null, false);
        }

        private static string GetLog(this Exception exception, string intend, bool isInnerException)
        {
            var stringBuilder = new StringBuilder();

            intend = intend ?? string.Empty;

            if (isInnerException)
            {
                stringBuilder.AppendLine();
                stringBuilder.AppendFormat("{0}InnerException:", intend);
            }
            else
            {
                var systemType = Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit";

                stringBuilder.AppendLine();
                stringBuilder.AppendFormat("OS Version: {0}", Environment.OSVersion.VersionString);
                stringBuilder.AppendLine();
                stringBuilder.AppendFormat("System Type: {0}", systemType);
            }

            stringBuilder.AppendLine();
            stringBuilder.AppendFormat("{0}Source: {1}", intend, exception.Source);
            stringBuilder.AppendLine();
            stringBuilder.AppendFormat("{0}Message: {1}", intend, exception.Message);
            stringBuilder.AppendLine();
            stringBuilder.AppendFormat("{0}TargetSite: {1}", intend, exception.TargetSite);
            stringBuilder.AppendLine();
            stringBuilder.AppendFormat("{0}Type: {1}", intend, exception.GetType());
            stringBuilder.AppendLine();

            var stackTrace = exception.GetStackTrace(intend);

            stringBuilder.AppendLine(stackTrace);

            stringBuilder.AppendLine();

            if (exception.InnerException != null)
            {
                var innerExceptionIntent = new string(' ', intend.Length + 4);

                var innerExceptionSummary = exception.InnerException.GetLog(innerExceptionIntent, true);

                stringBuilder.Append(innerExceptionSummary);
            }

            return stringBuilder.ToString();
        }

        public static string GetStackTrace(this Exception exception)
        {
            return exception.GetStackTrace(null);
        }

        private static string GetStackTrace(this Exception exception, string intend)
        {
            if (string.IsNullOrEmpty(exception.StackTrace))
            {
                return string.Empty;
            }

            var stackTrace = new StackTrace(exception, true);

            var frames = stackTrace.GetFrames();

            if (frames == null || !frames.Any())
            {
                return string.Empty;
            }

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendFormat("{0}StackTrace:", intend);
            stringBuilder.AppendLine();

            var tracesIntend = new string(' ', string.IsNullOrEmpty(intend) ? 4 : intend.Length + 4);

            foreach (var stackFram in frames)
            {
                var fileName = stackFram.GetFileName();

                fileName = !string.IsNullOrEmpty(fileName)
                    ? fileName.Substring(fileName.LastIndexOf(@"\", StringComparison.InvariantCultureIgnoreCase) + 1)
                    : string.Empty;

                stringBuilder.AppendFormat("{0}File: {1} | Line: {2} | Col: {3} | Offset: {4} | Method: {5}", tracesIntend, fileName, stackFram.GetFileLineNumber(), stackFram.GetFileColumnNumber(), stackFram.GetILOffset(), stackFram.GetMethod());

                stringBuilder.AppendLine();
            }

            return stringBuilder.ToString();
        }
    }
}

 


@amusleh

amusleh
02 Jun 2021, 18:59

RE: RE: RE: RE:

chris07 said:

Hi amusleh,

I have contacted the developer and he responded that if the line levels of the fibo tool were interactive they could all be moved individually. Thus the question is if only the outer lines can be made adjustable, like it is the case for every fibonacci tool. You apparently have done that for your own custom fibo tool. Could you give some hints on how you have achieved that? I know your code is proprietary, too, so I respect if you want to keep this "close to your vest". 

 

 

Hi,

My code is not proprietary, the indicator is open source on Github: 

 


@amusleh

amusleh
02 Jun 2021, 16:58

Hi,

I backtested your cBot and it worked fine, if cBot got stopped then it means something is wrong with your code.

Please use this cBot code instead:

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MiaEMARibbon : Robot
    {
        #region User defined parameters

        [Parameter("Instance Name", DefaultValue = "20 Rangers")]
        public string InstanceName { get; set; }

        [Parameter("Percentage Risk Model?", Group = "Money Management", DefaultValue = true)]
        public bool volPercentBool { get; set; }

        [Parameter("Scale Out?", Group = "Money Management", DefaultValue = true)]
        public bool ScaleOut { get; set; }

        [Parameter("Risk %", Group = "Money Management", DefaultValue = 1.5, MinValue = 1, MaxValue = 5)]
        public double volPercent { get; set; }

        [Parameter("Volume Quantity", Group = "Money Management", DefaultValue = 2000, MinValue = 1000, Step = 1000)]
        public int volQty { get; set; }

        [Parameter("StopLoss (*ATR)", Group = "Protection", DefaultValue = 1.5, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double ATRStopLoss { get; set; }

        [Parameter("TakeProfit (*ATR)", Group = "Protection", DefaultValue = 1.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double ATRTakeProfit { get; set; }

        [Parameter("BreakEven", Group = "Protection", DefaultValue = true)]
        public bool BreakEven { get; set; }

        [Parameter("BreakEvenTrigger (*ATR)", Group = "Protection", DefaultValue = 1.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TriggerPips { get; set; }

        [Parameter("Locked in Profit", Group = "Protection", DefaultValue = 3.0, MinValue = 1.0)]
        public double AddPips { get; set; }

        [Parameter("Use Trailing Stop", Group = "Protection", DefaultValue = true)]
        public bool UseTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (*ATR)", Group = "Protection", DefaultValue = 1.5, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (*ATR)", Group = "Protection", DefaultValue = 2.0, Step = 0.1, MinValue = 1, MaxValue = 5)]
        public double TrailingStopStep { get; set; }

        [Parameter("Close on Weekend?", Group = "Filter", DefaultValue = true)]
        public bool CloseOnWeekend { get; set; }

        [Parameter("Allowable Slippage", Group = "Filter", DefaultValue = 3.0, MinValue = 0.5, Step = 0.1)]
        public double Slippage { get; set; }

        [Parameter("Max Allowable Spread", Group = "Filter", DefaultValue = 2.0, MinValue = 0.1, MaxValue = 100.0, Step = 0.1)]
        public double MaxSpread { get; set; }

        [Parameter("Calculate OnBar?", Group = "Filter", DefaultValue = true)]
        public bool CalculateOnBar { get; set; }

        #endregion User defined parameters

        #region Indicator declarations

        private ExponentialMovingAverage EMA_1 { get; set; }
        private ExponentialMovingAverage EMA_2 { get; set; }
        private ExponentialMovingAverage EMA_3 { get; set; }
        private ExponentialMovingAverage EMA_4 { get; set; }
        private ExponentialMovingAverage EMA_5 { get; set; }
        private ExponentialMovingAverage EMA_6 { get; set; }
        private ExponentialMovingAverage EMA_7 { get; set; }
        private ExponentialMovingAverage EMA_8 { get; set; }
        private ExponentialMovingAverage EMA_9 { get; set; }
        private ExponentialMovingAverage EMA_10 { get; set; }

        private AverageTrueRange ATR;

        private double SPREAD;
        private int volume;
        private string Comment;
        private int lastbar;
        private double StopLoss;
        private double TakeProfit;

        #endregion Indicator declarations

        #region Calculate Volume

        private int CalculateVolume(double stop_loss)
        {
            int result;
            switch (volPercentBool)
            {
                case true:
                    double costPerPip = (double)((int)(Symbol.PipValue * 100000));
                    double posSizeForRisk = Math.Round((Account.Balance * (volPercent / 100)) / (stop_loss * costPerPip), 2);
                    double posSizeToVol = (Math.Round(posSizeForRisk * 100000, 0));
                    Print("costperppip : $ {0}  ||  Lot : {1}  ||  Volume : {2}", costPerPip, posSizeForRisk, posSizeToVol);
                    result = (int)Symbol.NormalizeVolumeInUnits(posSizeToVol, RoundingMode.ToNearest);
                    result = result > 150000 ? 150000 : result;
                    result = result == 1000 ? 2000 : result;
                    Print("{0}% of Account Balance [ $ {1} ] used for Volume: {2}  ||  Risk : $ {3}", volPercent, Account.Balance, result, (StopLoss * costPerPip * result) / 100000);
                    break;

                default:
                    result = volQty;
                    Print("Volume Quantity Used! : {0}", result);
                    break;
            }
            return result;
        }

        #endregion Calculate Volume

        #region Standard event handlers

        /// This is called when the robot first starts, it is only called once.
        protected override void OnStart()
        {
            ATR = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            EMA_1 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 5);
            EMA_2 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 7);
            EMA_3 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 9);
            EMA_4 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 11);
            EMA_5 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 13);
            EMA_6 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 30);
            EMA_7 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 35);
            EMA_8 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 40);
            EMA_9 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 45);
            EMA_10 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);

            StopLoss = Math.Round((ATR.Result.Last(lastbar)) * ATRStopLoss / Symbol.PipSize, 0);
            TakeProfit = Math.Round((ATR.Result.Last(lastbar)) * ATRTakeProfit / Symbol.PipSize, 0);
            volume = CalculateVolume(StopLoss);
            SPREAD = Math.Round(Symbol.Spread / Symbol.PipSize, 2);
            Comment = "Chris Trend Trading ";
            if (CalculateOnBar)
                lastbar = 1;
            else
                lastbar = 0;

            // Subscribe to the Trade Closing event
            Positions.Closed += OnPositionsClosed;
        }

        /// This event handler is called every tick or every time the price changes for the symbol.
        protected override void OnTick()
        {
            try
            {
                ManagePositions();
            }
            catch (Exception ex)
            {
                Print(ex);

                Stop();
            }
        }

        /// a special event handler that is called each time a new bar is drawn on chart.
        /// if you want your robot to act only when the previous bar is closed, this standard handler is where you put your main trading code.
        protected override void OnBar()
        {
            try
            {
                ManagePositions();
                CloseHalf();
                MoveToBreakEven();
                SetTrailingStop();
            }
            catch (Exception ex)
            {
                Print(ex);

                Stop();
            }
        }

        /// a special Robot class member that handles situations with errors.
        protected override void OnError(Error error)
        {
            Print("Error Code {0}  ||  {1} {2}:{3}:{4}", error.Code, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
        }

        #endregion Standard event handlers

        #region Logic

        private void ManagePositions()
        {
            /// if there is no buy position open, open one
            if (IsPositionOpenByType(TradeType.Buy) == false && Extreme() == false && BuyEntry() == true && EntryBar() == true)
            {
                if (Trader_Bullish() == false && Investor_Bullish() == true)
                {
                    OpenPosition(TradeType.Buy);
                }
                else if (Trader_Bullish() == true && Bars.ClosePrices.Last(lastbar + 1) < Bars.OpenPrices.Last(lastbar + 1))
                {
                    OpenPosition(TradeType.Buy);
                }
            }
            /// if there is no sell position open, open one
            else if (IsPositionOpenByType(TradeType.Sell) == false && Extreme() == false && SellEntry() == true && EntryBar() == true)
            {
                if (Trader_Bearish() == false && Investor_Bearish() == true)
                {
                    OpenPosition(TradeType.Sell);
                }
                else if (Trader_Bearish() == true && Bars.ClosePrices.Last(lastbar + 1) > Bars.OpenPrices.Last(lastbar + 1))
                {
                    OpenPosition(TradeType.Sell);
                }
            }

            /// Call custom class method to Close Open Position
            if (IsPositionOpenByType(TradeType.Buy) == true && BuyExit() == true)
                ClosePosition(TradeType.Buy);
            else if (IsPositionOpenByType(TradeType.Sell) == true && SellExit() == true)
                ClosePosition(TradeType.Sell);
        }

        #endregion Logic

        #region Scale Out

        private void CloseHalf()
        {
            var positions = Positions.FindAll(InstanceName.ToString(), SymbolName);
            foreach (var position in positions)
            {
                var Secured = position.TradeType == TradeType.Buy ? position.StopLoss - position.EntryPrice : position.EntryPrice - position.StopLoss;
                var HalfVol = Math.Round(Symbol.NormalizeVolumeInUnits(((position.VolumeInUnits) / 2), RoundingMode.ToNearest), 0);
                if (ScaleOut == true && position.VolumeInUnits >= 2000 && (Secured / Symbol.PipSize) <= AddPips && position.Pips >= (ATR.Result.Last(lastbar) * ATRTakeProfit) / Symbol.PipSize)
                {
                    ClosePosition(position, HalfVol);
                    Print("[ {0} ] Scale Out {1}   ||   New Volume: {2}   ||   Gain/Loss {3} Pips / $ {4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, position.VolumeInUnits, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
                }
            }
        }

        #endregion Scale Out

        #region BreakEven

        /// Call custom class method to move StopLoss to BreakEven
        private void MoveToBreakEven()
        {
            var positions = Positions.FindAll(InstanceName.ToString(), SymbolName);
            foreach (var position in positions)
            {
                var desiredNetProfitInDepositAsset = AddPips * Symbol.PipValue * position.VolumeInUnits;
                var desiredGrossProfitInDepositAsset = desiredNetProfitInDepositAsset - position.Commissions * 2 - position.Swap;
                var quoteToDepositRate = Symbol.PipValue / Symbol.PipSize;
                var priceDifference = desiredGrossProfitInDepositAsset / (position.VolumeInUnits * quoteToDepositRate);
                var priceAdjustment = GetPriceAdjustmentByTradeType(position.TradeType, priceDifference);
                var breakEvenLevel = position.EntryPrice + priceAdjustment;
                var roundedBreakEvenLevel = RoundPrice(breakEvenLevel, position.TradeType);

                var stopposition = position.TradeType == TradeType.Buy ? position.EntryPrice - position.StopLoss : position.StopLoss - position.EntryPrice;
                if (BreakEven == true && stopposition > 0 && position.Pips >= (ATR.Result.Last(lastbar) * TriggerPips) / Symbol.PipSize)
                {
                    ModifyPosition(position, roundedBreakEvenLevel, position.TakeProfit);
                    Print("[ {0} ] Breakeven {1}   ||   {2} {3}:{4}:{5}", LastResult.Position.Id, SymbolName, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
                }
            }
        }

        #endregion BreakEven

        #region TrailingStop

        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < (ATR.Result.Last(lastbar) * TrailingStopTrigger))
                    continue;

                double newStopLossPrice = Symbol.Ask + (ATR.Result.Last(lastbar) * TrailingStopStep);
                var newStopLoss = RoundPrice(newStopLossPrice, position.TradeType);

                if (UseTrailingStop == true && (position.StopLoss == null || newStopLossPrice < position.StopLoss))
                    ModifyPosition(position, newStopLoss, position.TakeProfit);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Trailing {1}   ||   New StopLoss: {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < (ATR.Result.Last(lastbar) * TrailingStopTrigger))
                    continue;

                double newStopLossPrice = Symbol.Bid - (ATR.Result.Last(lastbar) * TrailingStopStep);
                var newStopLoss = RoundPrice(newStopLossPrice, position.TradeType);
                if (UseTrailingStop == true && (position.StopLoss == null || newStopLossPrice > position.StopLoss))
                    ModifyPosition(position, newStopLoss, position.TakeProfit);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Trailing {1}   ||   New StopLoss: {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion TrailingStop

        #region Open Trade

        /// Call custom class method to send a market order || open a new position

        private void OpenPosition(TradeType type)
        {
            var Pos = Positions.FindAll(InstanceName.ToString(), SymbolName);
            if (Pos.Count() == 0 && Server.Time.DayOfWeek <= DayOfWeek.Friday && Server.Time.Hour <= 19 && SPREAD <= MaxSpread)
            {
                if (ScaleOut)
                    ExecuteMarketRangeOrder(type, this.Symbol.Name, volume, Slippage, Symbol.Bid, InstanceName.ToString(), StopLoss, 0, Comment);
                else
                    ExecuteMarketRangeOrder(type, this.Symbol.Name, volume, Slippage, Symbol.Bid, InstanceName.ToString(), StopLoss, TakeProfit, Comment);
                if (LastResult.IsSuccessful)
                    Print("[ {0} ] Open {1} {2}    ||   Volume:{3}    ||   Spread:{4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, type, SymbolName, LastResult.Position.VolumeInUnits, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion Open Trade

        #region Close Trade

        /// Standard event handler that triggers upon position closing.
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName.ToString(), SymbolName, type);
            if (p != null)
            {
                ClosePosition(p);
                Print("[ {0} ] Close {1} {2}    ||   Volume:{3}    ||   Spread:{4}   ||   Gain/Loss {5}Pips / $ {6}   ||   {7} {8}:{9}:{10}", LastResult.Position.Id, type, SymbolName, LastResult.Position.VolumeInUnits, SPREAD, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour,
                Server.Time.Minute, Server.Time.Second);
            }
            else if (CloseOnWeekend == true && p != null && Server.Time.DayOfWeek == DayOfWeek.Friday && Server.Time.Hour >= 21 && Server.Time.Minute >= 30)
            {
                ClosePosition(p);
                Print("[ {0} ] Close {1}  on Weekend   ||   Gain/Loss {1}Pips / $ {2}   ||   {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        /// Check for opened position
        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName.ToString(), SymbolName, type);

            if (p.Count() > 0 || p.Count() != 0)
                return true;
            return false;
        }

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            // check if the position has been closed due to stoploss or takeprofit or any other(stop out etc)
            if (args.Reason == PositionCloseReason.StopLoss)
            {
                Print("[ {0} ] Stoploss Hit {1}   ||   Gain/Loss {2}Pips / $ {3}   ||   Spread:{4}   ||   {5} {6}:{7}:{8} ", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
            else if (args.Reason == PositionCloseReason.TakeProfit)
            {
                Print("[ {0} ] Take Profit Hit {1}   ||   Gain/Loss {2}Pips / $ {3}   ||   Spread:{4}   ||   {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
            }
        }

        #endregion Close Trade

        #region Check for Setups

        //////////////////////////////////////////////////////////////////////////
        ///////////////////////// Check for Setups //////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        private bool Trader_Bullish()
        {
            if (EMA_1.Result.Last(lastbar) >= EMA_2.Result.Last(lastbar) && EMA_2.Result.Last(lastbar) >= EMA_3.Result.Last(lastbar) && EMA_3.Result.Last(lastbar) >= EMA_4.Result.Last(lastbar) && EMA_4.Result.Last(lastbar) >= EMA_5.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Trader_Bearish()
        {
            if (EMA_1.Result.Last(lastbar) <= EMA_2.Result.Last(lastbar) && EMA_2.Result.Last(lastbar) <= EMA_3.Result.Last(lastbar) && EMA_3.Result.Last(lastbar) <= EMA_4.Result.Last(lastbar) && EMA_4.Result.Last(lastbar) <= EMA_5.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Investor_Bullish()
        {
            if (EMA_6.Result.Last(lastbar) >= EMA_7.Result.Last(lastbar) && EMA_7.Result.Last(lastbar) >= EMA_8.Result.Last(lastbar) && EMA_8.Result.Last(lastbar) >= EMA_9.Result.Last(lastbar) && EMA_9.Result.Last(lastbar) >= EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool Investor_Bearish()
        {
            if (EMA_6.Result.Last(lastbar) <= EMA_7.Result.Last(lastbar) && EMA_7.Result.Last(lastbar) <= EMA_8.Result.Last(lastbar) && EMA_8.Result.Last(lastbar) <= EMA_9.Result.Last(lastbar) && EMA_9.Result.Last(lastbar) <= EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool BuyEntry()
        {
            if (Bars.ClosePrices.Last(lastbar) > Bars.OpenPrices.Last(lastbar) && Bars.LowPrices.Last(lastbar) < EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_1.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_5.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_6.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool SellEntry()
        {
            if (Bars.ClosePrices.Last(lastbar) < Bars.OpenPrices.Last(lastbar) && Bars.HighPrices.Last(lastbar) > EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_1.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_5.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_6.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_10.Result.Last(lastbar))
                return true;
            return false;
        }

        private bool BuyExit()
        {
            if (IsPositionOpenByType(TradeType.Buy) == true && EMA_1.Result.Last(lastbar) < EMA_2.Result.Last(lastbar) && EMA_1.Result.Last(lastbar) < EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) < EMA_5.Result.Last(lastbar))
                return true;
            else if (IsPositionOpenByType(TradeType.Buy) == true && Bars.ClosePrices.Last(lastbar + 1) == Bars.LowPrices.Last(lastbar + 1) && Bars.ClosePrices.Last(lastbar + 2) == Bars.LowPrices.Last(lastbar + 2))
                return true;

            return false;
        }

        private bool SellExit()
        {
            if (IsPositionOpenByType(TradeType.Sell) == true && EMA_1.Result.Last(lastbar) > EMA_2.Result.Last(lastbar) && EMA_1.Result.Last(lastbar) > EMA_3.Result.Last(lastbar) && Bars.ClosePrices.Last(lastbar) > EMA_5.Result.Last(lastbar))
                return true;
            else if (IsPositionOpenByType(TradeType.Sell) == true && Bars.ClosePrices.Last(lastbar + 1) == Bars.HighPrices.Last(lastbar + 1) && Bars.ClosePrices.Last(lastbar + 2) == Bars.HighPrices.Last(lastbar + 2))
                return true;
            return false;
        }

        private bool Extreme()
        {
            if (Math.Abs(EMA_1.Result.Last(lastbar) - EMA_5.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.618 || Math.Abs(EMA_5.Result.Last(lastbar) - EMA_6.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.382 || Math.Abs(EMA_6.Result.Last(lastbar) - EMA_10.Result.Last(lastbar)) > ATR.Result.Last(lastbar) * 1.618)
                return true;
            return false;
        }

        private bool EntryBar()
        {
            if (Math.Abs(Bars.OpenPrices.Last(lastbar) - Bars.ClosePrices.Last(lastbar)) > Math.Abs(Bars.HighPrices.Last(lastbar) - Bars.LowPrices.Last(lastbar)) * 0.618)
                return true;
            return false;
        }

        #endregion Check for Setups

        #region RoundPrice

        ////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////

        private double RoundPrice(double price, TradeType tradeType)
        {
            var multiplier = Math.Pow(10, Symbol.Digits);
            if (tradeType == TradeType.Buy)
                return Math.Ceiling(price * multiplier) / multiplier;

            return Math.Floor(price * multiplier) / multiplier;
        }

        private static double GetPriceAdjustmentByTradeType(TradeType tradeType, double priceDifference)
        {
            if (tradeType == TradeType.Buy)
                return priceDifference;

            return -priceDifference;
        }

        #endregion RoundPrice
    }
}

I added some debugging stuff, next time it stopped check the cTrader logs tab, there will be an error message, copy it and post it here.


@amusleh

amusleh
01 Jun 2021, 16:18

Hi,

I think there is an issue with rounding of Stop loss and take profit levels, you have to round them to symbol digits if its in price level.

If you can't do it by yourself you can post a job request or contact one of our consultants.


@amusleh

amusleh
01 Jun 2021, 16:16

Hi everyone,

We released the Fibonacci drawing indicator, you can download it from here: 

If you have any question or suggestion please leave a comment on indicator page, and I will reply back.


@amusleh

amusleh
31 May 2021, 07:50

RE: RE:

chris07 said:

This was a commissioned work and the creator wishes the code to remain private.

The built-in indicators do not have a problem with reloading data or changing TFs. How do they accomplish that vs the custom drawing tools?

Any input is appreciated.

 

Hi,

The reason drawings disappear is because of not being interactive, if an indicator/cBot drew something on your chart and don't make it interactive then it will disappear if indicator/cBot reloaded.

To make the indicator drawings interactive you must have access to the code.


@amusleh

amusleh
30 May 2021, 14:39

Hi,

Maybe you are running the Trading UI Demo on Any CPU mode, change it to x86, that's the only thing that can cause the chart not loading issue.

The chart works fine on my system for all brokers, I couldn't replicate the issue.


@amusleh