Category Other  Published on 08/05/2023

Simple MA System, 4xdev.com

Description

Hey-ho, great traders! 

Let us introduce the cBot with Moving Averages. This cool trading tool will help you to track the crossing of two MAs and react to the price crossing of one of the MAs.

 

Features

The Simple MA system can:

  • Check the formed bars to cross two MAs, therefore avoiding false signals.
  • Monitor the current bar and current prices for crossing one of the MAs and the price.
  • Manage positions. 
  • Calculate all the risks for the entire position.
  • Remove the Stop Loss level on the opening price after overcoming a certain distance thanks to the BreakEven option. In this case, your trade won’t be a loss-making one.

Note! If the short-term MA crosses the long-term one upwards, the trading robot enters a long position. If there is a downward crossover, the EA will enter a short position.

 

Parameters

We have equipped our EA with more than 14 additional parameters. So, you can configure the cBot according to your needs! Moreover, you can change opening conditions for Buy and Sell orders using the input parameters.

Note! Try the Simple MA system on your demo account first before going live.


 

Other Products

Ichimoku Cloud System: https://ctrader.com/algos/cbots/show/2859  

PSAR Strategy: 

ADR Custom Indicator: 

Daily H/L Custom Indicator: 

BB Trading Strategy: 

 

Contact Info

Contact us via support@4xdev.com 

Check out our cozy Telegram blog for traders: https://t.me/Forexdev  

Visit our website to find more tools and programming services: https://bit.ly/44BFRG3

Take a look at our YouTube channel: https://www.youtube.com/channel/UChsDb4Q8X2Vl5DJ7H8PzlHQ   


Try top-notch trading tools — with 4xDev.

 


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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Siple_MA : Robot
    {
        public enum ENUM_TP_TYPE
        {
            Fixed = 0,
            RiskRatio = 1
        }
        public enum ENUM_RISK_SOURCE
        {
            Equity = 0,
            Balance = 1
        }

        public enum ENUM_LOT_TYPE
        {
            Fixed_Lot = 0,
            Percent = 1
        }
        public enum ENUM_CROSS_TYPE
        {
            Ask_Bid = 1,
            // Ask/Bid
            Close_Price = 0
            // Close Price
        }

        public enum ENUM_SIGNAL_TYPE
        {
            MA_Cross = 0,
            // MAs cross
            Price_Touch = 1
            // Price hits First MA
        }


        #region Input Fast MA Parameters
        [Parameter("Fast MA Type", Group = "Fast MA Parameters")]
        public MovingAverageType FastType { get; set; }

        [Parameter("Fast MA Source", Group = "Fast MA Parameters")]
        public DataSeries FastSeries { get; set; }

        [Parameter("Fast MA Period", Group = "Fast MA Parameters", DefaultValue = 10)]
        public int FastPeriods { get; set; }
        #endregion

        #region Input Slow MA Parameters
        [Parameter("Slow MA Type", Group = "Slow MA Parameters")]
        public MovingAverageType SlowType { get; set; }

        [Parameter("Slow MA Source", Group = "Slow MA Parameters")]
        public DataSeries SlowSeries { get; set; }

        [Parameter("Slow MA Period", Group = "Slow MA Parameters", DefaultValue = 60)]
        public int SlowPeriods { get; set; }
        #endregion

        #region Input Trade Parameters
        [Parameter("Label", Group = "Trade Parameters", DefaultValue = "Simple MA")]
        public string Label { get; set; }

        [Parameter("Applied price", Group = "Trade Parameters", DefaultValue = ENUM_CROSS_TYPE.Close_Price)]
        public ENUM_CROSS_TYPE priceType { get; set; }

        [Parameter("Signal Type", Group = "Trade Parameters", DefaultValue = ENUM_SIGNAL_TYPE.MA_Cross)]
        public ENUM_SIGNAL_TYPE signalType { get; set; }

        [Parameter("Take Profit type", Group = "Trade Parameters", DefaultValue = ENUM_TP_TYPE.Fixed)]
        public ENUM_TP_TYPE tpType { get; set; }

        [Parameter("Stop Loss in pips", Group = "Trade Parameters", DefaultValue = 0)]
        public double SL { get; set; }

        [Parameter("Take Profit value", Group = "Trade Parameters", DefaultValue = 0)]
        public double TP { get; set; }

        [Parameter("Close on the opposite signal", Group = "Trade Parameters", DefaultValue = true)]
        public bool oppositeClose { get; set; }

        [Parameter("Max Orders", Group = "Trade Parameters", DefaultValue = 1)]
        public int maxOrders { get; set; }

        [Parameter("Use Reverse Trade", Group = "Trade Parameters", DefaultValue = true)]
        public bool reverseTrade { get; set; }

        #endregion

        #region Input Lot Size Parameters
        [Parameter("Lot Type", Group = "Lot Size", DefaultValue = ENUM_LOT_TYPE.Fixed_Lot)]
        public ENUM_LOT_TYPE lotType { get; set; }

        [Parameter("Risk Source", Group = "Lot Size", DefaultValue = ENUM_RISK_SOURCE.Balance)]
        public ENUM_RISK_SOURCE riskSource { get; set; }

        [Parameter("Risk/Lot Value", Group = "Lot Size", DefaultValue = 0.1)]
        public double risk { get; set; }
        #endregion

        #region Input Break Even Parameters
        [Parameter("Use BreakEven", Group = "BreakEven", DefaultValue = false)]
        public bool UseBE { get; set; }
        [Parameter("BreakEven Start(pips)", Group = "BreakEven", DefaultValue = 10)]
        public double BEStart { get; set; }

        [Parameter("BreakEven Profit(pips)", Group = "BreakEven", DefaultValue = 0)]
        public double BEProfit { get; set; }
        #endregion

        private MovingAverage fastMA;
        private MovingAverage slowMA;

        protected override void OnStart()
        {
            fastMA = Indicators.MovingAverage(FastSeries, FastPeriods, FastType);
            slowMA = Indicators.MovingAverage(SlowSeries, SlowPeriods, SlowType);

            if (priceType == ENUM_CROSS_TYPE.Ask_Bid)
            {
                lastAsk = Ask;
                lastBid = Bid;
            }
            else
            {
                lastClose = Bars.ClosePrices.Last(0);
            }
            lastMA = fastMA.Result.Last(0);
            // Put your initialization logic here
        }


        double lastAsk;
        double lastBid;
        double lastClose;
        double lastMA;

        DateTime lastBar;

        protected override void OnTick()
        {
            if (UseBE)
                BreakEven();
            double ma = 0;
            // Put your core logic here
            if (lastBar != Bars.OpenTimes.Last(0))
            {
                if (signalType == ENUM_SIGNAL_TYPE.MA_Cross)
                {
                    lastBar = Bars.OpenTimes.Last(0);
                    double ma1 = fastMA.Result.Last(1);
                    double ma1prev = fastMA.Result.Last(2);
                    double ma2 = slowMA.Result.Last(1);
                    double ma2prev = slowMA.Result.Last(2);
                    int currCross = CheckCross(ma1, ma1prev, ma2, ma2prev);
                    if (currCross == 0)
                    {
                        if (oppositeClose)
                        {
                            CloseOrders(TradeType.Sell);
                        }
                        if ((CalculateOrders() < maxOrders))
                        {
                            OpenOrder(TradeType.Buy);
                        }
                    }
                    if (currCross == 1)
                    {
                        if (oppositeClose)
                        {
                            CloseOrders(TradeType.Buy);
                        }
                        if ((CalculateOrders() < maxOrders))
                        {
                            OpenOrder(TradeType.Sell);
                        }
                    }
                }
                else
                {
                    ma = fastMA.Result.Last(0);

                    double prevPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? lastAsk : lastClose;
                    double currPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? Ask : Bars.ClosePrices.Last(0);
                    if (currPrice >= ma && prevPrice < lastMA)
                    {
                        if (CheckOrders())
                        {
                            OpenOrder(TradeType.Buy);
                        }
                        //Open Buy
                    }
                    prevPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? lastBid : lastClose;
                    currPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? Bid : Bars.ClosePrices.Last(0);
                    if (currPrice <= ma && prevPrice > lastMA)
                    {
                        if (CheckOrders())
                        {
                            OpenOrder(TradeType.Sell);
                        }
                        //Open Sell
                    }
                }
            }
            lastMA = ma;
            lastAsk = Ask;
            lastBid = Bid;
            lastClose = Bars.ClosePrices.Last(0);
        }

        bool CheckOrders()
        {
            if (Positions.Find(Label, Symbol) != null)
                return false;
            return true;
        }

        int CalculateOrders()
        {
            return Positions.FindAll(Label, Symbol).Length;
        }

        void CloseOrders(TradeType type)
        {
            if (reverseTrade)
                type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;

            foreach (var pos in Positions.FindAll(Label, Symbol, type))
            {
                ClosePosition(pos);
            }
        }

        void OpenOrder(TradeType type)
        {
            if (reverseTrade)
                type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;

            double op;
            double tp = tpType == ENUM_TP_TYPE.Fixed ? TP : SL * TP;
            double sl;

            double source = riskSource == ENUM_RISK_SOURCE.Balance ? Account.Balance : Account.Equity;

            double volumeInUnits = 0;
            if (lotType == ENUM_LOT_TYPE.Fixed_Lot)
                volumeInUnits = Symbol.QuantityToVolumeInUnits(risk);
            else
                volumeInUnits = CalculateVolume(SL, risk, source);

            if (volumeInUnits == -1)
                return;
            ExecuteMarketOrder(type, SymbolName, volumeInUnits, Label, SL, TP);
        }

        private double CalculateVolume(double stopLossPips, double riskSize, double source)
        {
            // source = Account.Balance or Account.Equity
            double riskPerTrade = source * riskSize / 100;
            double totalPips = stopLossPips;

            double _volume;
            double exactVolume = riskPerTrade / (Symbol.PipValue * totalPips);
            if (exactVolume >= Symbol.VolumeInUnitsMin)
            {
                _volume = Symbol.NormalizeVolumeInUnits(exactVolume);
            }
            else
            {
                _volume = -1;
                Print("Not enough Equity to place minimum trade, exactVolume " + exactVolume + " is not >= Symbol.VolumeInUnitsMin " + Symbol.VolumeInUnitsMin);
            }
            return _volume;
        }

        int CheckCross(double v1, double v1prev, double v2, double v2prev)
        {
            if (v1prev < v2prev && v1 > v2)
                return 0;
            if (v1prev > v2prev && v1 < v2)
                return 1;
            return -1;
        }
        private void BreakEven()
        {
            if (!UseBE)
                return;

            foreach (var pos in Positions.FindAll(Label, SymbolName))
            {
                if (pos.TradeType == TradeType.Buy)
                {
                    if (Symbol.Ask >= pos.EntryPrice + BEStart * Symbol.PipSize && (pos.StopLoss < pos.EntryPrice + BEProfit * Symbol.PipSize || pos.StopLoss == null))
                    {
                        ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
                    }
                }
                if (pos.TradeType == TradeType.Sell)
                {
                    if (Symbol.Bid <= pos.EntryPrice - BEStart * Symbol.PipSize && (pos.StopLoss > pos.EntryPrice - BEProfit * Symbol.PipSize || pos.StopLoss == null))
                    {
                        ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
                    }
                }
            }
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}


4xdev.team's avatar
4xdev.team

Joined on 11.12.2019

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Simple_MA.algo
  • Rating: 2.5
  • Installs: 2091
Comments
Log in to add a comment.
RA
ralfyussefchuluc · 7 months ago

I highly recommend this setup!

RA
ralfyussefchuluc · 7 months ago

I highly recommend it! One of the best setups in this community! Simple always works! I've been using it for a week with gains every day!

4xdev.team's avatar
4xdev.team · 1 year ago

@saladine123 most likely, the Use Reverse Trade parameter is enabled. Just turn it off and everything will be fine.

4xdev.team's avatar
4xdev.team · 1 year ago

@LeonardoBaliza, we can add a third average. Please write to our support (support@4xdev.com) to clarify the cost of such a modification.

SA
saladine123 · 2 years ago

Hi,

I have just started to use your Cbot Simple MA cross and really appreciate the effort provided. I am however having an issue with MA Cross direction and execution. You mentioned in the description that if fast MA crosses up over slow MA, a buy signal should be triggered. Conversley, a fast MA crossing down Slow MA produces a sell order. However, on my system, the opposite is happening. A cross up gives sell signal and cross down gives buy signal.

Perhaps you can point me in the right direction in order to correct this?

Thanking you in advance!!

LE
LeonardoBaliza · 2 years ago

Would it be possible to add a third average? The function of this third average would be to block sell or buy trades when it was above or below the average. Example: Do not open buy trades if it is above the third average.

SA
satib62685 · 2 years ago

A basic machine works against a single load force with a single applied force. the work done on the load is equivalent to the work done by the applied force, even when friction losses are taken into account. the machine can raise the output force on kanye west black leather jacket in the load's distance travelled. the mechanical advantage is defined as the ratio of output to applied force.

SH
shamsulzoha5 · 2 years ago

All in all a good moving average system. The availability of the code allows me to modify it to my wishes. Far better than the normal moving averages. Recommended.

henrylucas2k20's avatar
henrylucas2k20 · 2 years ago

Great tool as usual I have ever used. For success trading journey you should take a look at this MA system. Thanks for 4xdev team for their great efforts.  

JU
junaidraz278 · 2 years ago

This Trading Strategy is awesome. My friend refer this and tried now loving it. If you want to be a successful trader you need to apply this must.