MACD bot inquiry

Created at 05 Feb 2022, 07:10
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
WA

waym77

Joined 22.07.2021

MACD bot inquiry
05 Feb 2022, 07:10


Hi,

I created a bot using a MACD and a 200 EMA, although I am having some problems getting the MACD to work as intended. MACD needs to work  as such:

Buy requirements:

if the price is above 200 EMA & 
if the MACD Main crosses above the Signal & 
if the MACD main is below the 0 level.

Sell is the exact opposite.

I have added a picture below to illustrate what I mean:

The green circle is where I would like the entry to happen, the white line is where it is happening.

I have also added the current code:

​
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 MACD Bot: Robot
    {
        [Parameter("Name", Group = "General", DefaultValue = "MACD Bot")]
        public string _Label { get; set; }

        [Parameter("MACD Long", Group = "MACD", DefaultValue = 26, MaxValue = 100, MinValue = 1)]
        public int _macdlong { get; set; }

        [Parameter("MACD Short", Group = "MACD", DefaultValue = 12, MaxValue = 100, MinValue = 1)]
        public int _macdshort { get; set; }

        [Parameter("MACD Signal", Group = "MACD", DefaultValue = 9, MaxValue = 100, MinValue = 1)]
        public int _macdsig { get; set; }

        [Parameter("MA Type", Group = "Moving Average", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType _matype { get; set; }

        [Parameter("MA Period", Group = "Moving Average", DefaultValue = 200, MaxValue = 1000, MinValue = 1)]
        public int _maperiod { get; set; }

        [Parameter("Reward", Group = "Risk", DefaultValue = 1.5, MaxValue = 10.0, MinValue = 0.1, Step = 0.1)]
        public double _reward { get; set; }

        [Parameter("Pip Limiter", Group = "Risk", DefaultValue = 8.0, MaxValue = 50.0, MinValue = 0.1, Step = 0.1)]
        public double _limiter { get; set; }

        [Parameter("Position Size", Group = "Risk", DefaultValue = 1.0, MaxValue = 100.0, MinValue = 0.01, Step = 0.01)]
        public double _size { get; set; }

        [Parameter("Stop Loss Buffer", Group = "Risk", DefaultValue = 1.0, MaxValue = 50.0, MinValue = 0.01, Step = 0.01)]
        public double _slbuffer { get; set; }

        public MacdCrossOver _macd;
        public MovingAverage _ma;
        private bool _macdbuy, _macdsell, _maq, _distanceq;
        public double _getsl, _gettp, _distance;

        protected override void OnStart()
        {
            _macd = Indicators.MacdCrossOver(_macdlong, _macdshort, _macdsig);
            _ma = Indicators.MovingAverage(Bars.ClosePrices, _maperiod, _matype);
            _slbuffer = 1.0;
            _distance = 0.0;
        }

        protected override void OnBar()
        {
            var _activebuy = Positions.Find(_Label, SymbolName, TradeType.Buy);
            var _activesell = Positions.Find(_Label, SymbolName, TradeType.Sell);

            var _volume = Symbol.QuantityToVolumeInUnits(_size);
            _distance = Math.Abs((_ma.Result.LastValue - Bars.ClosePrices.LastValue) / Symbol.PipSize);

            _maq = Bars.ClosePrices.Last(1) > _ma.Result.Last(1) ? true : false;
            _distanceq = _distance < _limiter ? true : false;

            if (_macd.MACD.HasCrossedAbove(_macd.Signal.Last(1), 1) && _macd.MACD.Last(1) < 0)
            {
                _macdbuy = true;
            }

            if (_macd.MACD.HasCrossedBelow(_macd.Signal.Last(1), 1) && _macd.MACD.Last(1) > 0)
            {
                _macdsell = true;
            }

            if (_activebuy == null && _maq && _distanceq && _macdbuy)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();
                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }
                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }

            if (_activesell == null && !_maq && _distanceq && _macdsell)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();
                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }
                ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }
        }
        private double GetStopLoss()
        {
            double _result = Math.Abs((_ma.Result.Last(1) - Bars.ClosePrices.Last(1)) / Symbol.PipSize);
            _result = _result + _slbuffer;
            return _result;
        }

        private double GetTakeProfit()
        {
            double result = _getsl * _reward;
            return result;
        }
    }
}

​

Any help would be appreciated, thanks!


@waym77
Replies

amusleh
07 Feb 2022, 09:20

Hi,

Please try this:

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 MACDBot : Robot

    {
        [Parameter("Name", Group = "General", DefaultValue = "MACD Bot")]
        public string _Label { get; set; }

        [Parameter("MACD Long", Group = "MACD", DefaultValue = 26, MaxValue = 100, MinValue = 1)]
        public int _macdlong { get; set; }

        [Parameter("MACD Short", Group = "MACD", DefaultValue = 12, MaxValue = 100, MinValue = 1)]
        public int _macdshort { get; set; }

        [Parameter("MACD Signal", Group = "MACD", DefaultValue = 9, MaxValue = 100, MinValue = 1)]
        public int _macdsig { get; set; }

        [Parameter("MA Type", Group = "Moving Average", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType _matype { get; set; }

        [Parameter("MA Period", Group = "Moving Average", DefaultValue = 200, MaxValue = 1000, MinValue = 1)]
        public int _maperiod { get; set; }

        [Parameter("Reward", Group = "Risk", DefaultValue = 1.5, MaxValue = 10.0, MinValue = 0.1, Step = 0.1)]
        public double _reward { get; set; }

        [Parameter("Pip Limiter", Group = "Risk", DefaultValue = 8.0, MaxValue = 50.0, MinValue = 0.1, Step = 0.1)]
        public double _limiter { get; set; }

        [Parameter("Position Size", Group = "Risk", DefaultValue = 1.0, MaxValue = 100.0, MinValue = 0.01, Step = 0.01)]
        public double _size { get; set; }

        [Parameter("Stop Loss Buffer", Group = "Risk", DefaultValue = 1.0, MaxValue = 50.0, MinValue = 0.01, Step = 0.01)]
        public double _slbuffer { get; set; }

        public MacdCrossOver _macd;
        public MovingAverage _ma;
        private bool _macdbuy, _macdsell, _maq, _distanceq;
        public double _getsl, _gettp, _distance;

        protected override void OnStart()
        {
            _macd = Indicators.MacdCrossOver(_macdlong, _macdshort, _macdsig);
            _ma = Indicators.MovingAverage(Bars.ClosePrices, _maperiod, _matype);
            _slbuffer = 1.0;
            _distance = 0.0;
        }

        protected override void OnBar()
        {
            var _activebuy = Positions.Find(_Label, SymbolName, TradeType.Buy);
            var _activesell = Positions.Find(_Label, SymbolName, TradeType.Sell);

            var _volume = Symbol.QuantityToVolumeInUnits(_size);
            _distance = Math.Abs((_ma.Result.LastValue - Bars.ClosePrices.LastValue) / Symbol.PipSize);

            _maq = Bars.ClosePrices.Last(1) > _ma.Result.Last(1) ? true : false;
            _distanceq = _distance < _limiter ? true : false;

            if (_macd.MACD.HasCrossedAbove(_macd.Signal, 1) && _macd.MACD.Last(1) < 0)
            {
                _macdbuy = true;
            }

            if (_macd.MACD.HasCrossedBelow(_macd.Signal, 1) && _macd.MACD.Last(1) > 0)
            {
                _macdsell = true;
            }

            if (_activebuy == null && _maq && _distanceq && _macdbuy)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }

            if (_activesell == null && !_maq && _distanceq && _macdsell)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }
        }

        private double GetStopLoss()
        {
            double _result = Math.Abs((_ma.Result.Last(1) - Bars.ClosePrices.Last(1)) / Symbol.PipSize);
            _result = _result + _slbuffer;
            return _result;
        }

        private double GetTakeProfit()
        {
            double result = _getsl * _reward;
            return result;
        }
    }
}

I back tested it and it works fine:


@amusleh

waym77
08 Feb 2022, 19:46 ( Updated at: 21 Dec 2023, 09:22 )

RE:

amusleh said:

Hi,

Please try this:

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 MACDBot : Robot

    {
        [Parameter("Name", Group = "General", DefaultValue = "MACD Bot")]
        public string _Label { get; set; }

        [Parameter("MACD Long", Group = "MACD", DefaultValue = 26, MaxValue = 100, MinValue = 1)]
        public int _macdlong { get; set; }

        [Parameter("MACD Short", Group = "MACD", DefaultValue = 12, MaxValue = 100, MinValue = 1)]
        public int _macdshort { get; set; }

        [Parameter("MACD Signal", Group = "MACD", DefaultValue = 9, MaxValue = 100, MinValue = 1)]
        public int _macdsig { get; set; }

        [Parameter("MA Type", Group = "Moving Average", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType _matype { get; set; }

        [Parameter("MA Period", Group = "Moving Average", DefaultValue = 200, MaxValue = 1000, MinValue = 1)]
        public int _maperiod { get; set; }

        [Parameter("Reward", Group = "Risk", DefaultValue = 1.5, MaxValue = 10.0, MinValue = 0.1, Step = 0.1)]
        public double _reward { get; set; }

        [Parameter("Pip Limiter", Group = "Risk", DefaultValue = 8.0, MaxValue = 50.0, MinValue = 0.1, Step = 0.1)]
        public double _limiter { get; set; }

        [Parameter("Position Size", Group = "Risk", DefaultValue = 1.0, MaxValue = 100.0, MinValue = 0.01, Step = 0.01)]
        public double _size { get; set; }

        [Parameter("Stop Loss Buffer", Group = "Risk", DefaultValue = 1.0, MaxValue = 50.0, MinValue = 0.01, Step = 0.01)]
        public double _slbuffer { get; set; }

        public MacdCrossOver _macd;
        public MovingAverage _ma;
        private bool _macdbuy, _macdsell, _maq, _distanceq;
        public double _getsl, _gettp, _distance;

        protected override void OnStart()
        {
            _macd = Indicators.MacdCrossOver(_macdlong, _macdshort, _macdsig);
            _ma = Indicators.MovingAverage(Bars.ClosePrices, _maperiod, _matype);
            _slbuffer = 1.0;
            _distance = 0.0;
        }

        protected override void OnBar()
        {
            var _activebuy = Positions.Find(_Label, SymbolName, TradeType.Buy);
            var _activesell = Positions.Find(_Label, SymbolName, TradeType.Sell);

            var _volume = Symbol.QuantityToVolumeInUnits(_size);
            _distance = Math.Abs((_ma.Result.LastValue - Bars.ClosePrices.LastValue) / Symbol.PipSize);

            _maq = Bars.ClosePrices.Last(1) > _ma.Result.Last(1) ? true : false;
            _distanceq = _distance < _limiter ? true : false;

            if (_macd.MACD.HasCrossedAbove(_macd.Signal, 1) && _macd.MACD.Last(1) < 0)
            {
                _macdbuy = true;
            }

            if (_macd.MACD.HasCrossedBelow(_macd.Signal, 1) && _macd.MACD.Last(1) > 0)
            {
                _macdsell = true;
            }

            if (_activebuy == null && _maq && _distanceq && _macdbuy)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }

            if (_activesell == null && !_maq && _distanceq && _macdsell)
            {
                _getsl = GetStopLoss();
                _gettp = GetTakeProfit();

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }
        }

        private double GetStopLoss()
        {
            double _result = Math.Abs((_ma.Result.Last(1) - Bars.ClosePrices.Last(1)) / Symbol.PipSize);
            _result = _result + _slbuffer;
            return _result;
        }

        private double GetTakeProfit()
        {
            double result = _getsl * _reward;
            return result;
        }
    }
}

I back tested it and it works fine:

Hi Amusleh,

 

Thanks so much for your help so far.

However, I'm still having problems with the same thing.

Please see my example below:

The purple line is where the entry is supposed to be. I'm not sure how to fix this.

Thanks in advance,


@waym77

amusleh
09 Feb 2022, 08:25 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

waym77 said:

Hi Amusleh,

 

Thanks so much for your help so far.

However, I'm still having problems with the same thing.

Please see my example below:

The purple line is where the entry is supposed to be. I'm not sure how to fix this.

Thanks in advance,

Hi,

You used global variables for saving results of some functions instead of local variables, that was the issue.

Try this:

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

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

    {
        [Parameter("Name", Group = "General", DefaultValue = "MACD Bot")]
        public string _Label { get; set; }

        [Parameter("MACD Long", Group = "MACD", DefaultValue = 26, MaxValue = 100, MinValue = 1)]
        public int _macdlong { get; set; }

        [Parameter("MACD Short", Group = "MACD", DefaultValue = 12, MaxValue = 100, MinValue = 1)]
        public int _macdshort { get; set; }

        [Parameter("MACD Signal", Group = "MACD", DefaultValue = 9, MaxValue = 100, MinValue = 1)]
        public int _macdsig { get; set; }

        [Parameter("MA Type", Group = "Moving Average", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType _matype { get; set; }

        [Parameter("MA Period", Group = "Moving Average", DefaultValue = 200, MaxValue = 1000, MinValue = 1)]
        public int _maperiod { get; set; }

        [Parameter("Reward", Group = "Risk", DefaultValue = 1.5, MaxValue = 10.0, MinValue = 0.1, Step = 0.1)]
        public double _reward { get; set; }

        [Parameter("Pip Limiter", Group = "Risk", DefaultValue = 8.0, MaxValue = 50.0, MinValue = 0.1, Step = 0.1)]
        public double _limiter { get; set; }

        [Parameter("Position Size", Group = "Risk", DefaultValue = 1.0, MaxValue = 100.0, MinValue = 0.01, Step = 0.01)]
        public double _size { get; set; }

        [Parameter("Stop Loss Buffer", Group = "Risk", DefaultValue = 1.0, MaxValue = 50.0, MinValue = 0.01, Step = 0.01)]
        public double _slbuffer { get; set; }

        public MacdCrossOver _macd;
        public MovingAverage _ma;

        protected override void OnStart()
        {
            _macd = Indicators.MacdCrossOver(_macdlong, _macdshort, _macdsig);
            _ma = Indicators.MovingAverage(Bars.ClosePrices, _maperiod, _matype);
            _slbuffer = 1.0;
        }

        protected override void OnBar()
        {
            var _activebuy = Positions.Find(_Label, SymbolName, TradeType.Buy);
            var _activesell = Positions.Find(_Label, SymbolName, TradeType.Sell);

            var _volume = Symbol.QuantityToVolumeInUnits(_size);
            var _distance = Math.Abs((_ma.Result.LastValue - Bars.ClosePrices.LastValue) / Symbol.PipSize);

            var _maq = Bars.ClosePrices.Last(1) > _ma.Result.Last(1) ? true : false;
            var _distanceq = _distance < _limiter ? true : false;

            var _macdbuy = false;
            var _macdsell = false;

            if (_macd.MACD.Last(1) > _macd.Signal.Last(1) && _macd.MACD.Last(2) < _macd.Signal.Last(2) && _macd.MACD.Last(1) < 0)
            {
                _macdbuy = true;
            }

            if (_macd.MACD.Last(1) < _macd.Signal.Last(1) && _macd.MACD.Last(2) > _macd.Signal.Last(2) && _macd.MACD.Last(1) > 0)
            {
                _macdsell = true;
            }

            if (_activebuy == null && _maq && _distanceq && _macdbuy)
            {
                var _getsl = GetStopLoss();
                var _gettp = GetTakeProfit(_getsl);

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }

            if (_activesell == null && !_maq && _distanceq && _macdsell)
            {
                var _getsl = GetStopLoss();
                var _gettp = GetTakeProfit(_getsl);

                if (_activesell != null)
                {
                    ClosePosition(_activesell);
                }

                ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _Label, _getsl, _gettp);
            }
        }

        private double GetStopLoss()
        {
            return Math.Abs((_ma.Result.Last(1) - Bars.ClosePrices.Last(1)) / Symbol.PipSize) + _slbuffer;
        }

        private double GetTakeProfit(double stopLoss)
        {
            return stopLoss * _reward;
        }
    }
}

 


@amusleh