CBOT

Created at 12 Jul 2022, 13:00
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!
dokinya's avatar

dokinya

Joined 09.04.2018 Blocked

CBOT
12 Jul 2022, 13:00


Greetings 

Kindly assist if possible, am trying to make this cbot open trades exactly on the MA crossing, what do i need to change? thank you!

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
            Open_Price = 2
            // Open_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 = 7)]
        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 = 8)]
        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 = 1.0)]
        public double TP { get; set; }

        [Parameter("Close on the opposite signal", Group = "Trade Parameters", DefaultValue = false)]
        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.01)]
        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;
        double lastOpen;

        DateTime lastTick;

        protected override void OnTick()
        {
            if (UseBE)
                BreakEven();
            double ma = 0;
            // Put your core logic here
            if (lastTick != Bars.OpenTimes.Last(0))
            {
                if (signalType == ENUM_SIGNAL_TYPE.MA_Cross)
                {
                    lastTick = 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.Close_Price ? lastAsk : lastOpen;
                    double currPrice = priceType == ENUM_CROSS_TYPE. Close_Price ? Ask : Bars.OpenPrices.Last(0);
                    if (currPrice >= ma && prevPrice < lastMA)
                    {
                        if (CheckOrders())
                        {
                            OpenOrder(TradeType.Buy);
                        }
                        //Open Buy
                    }
                    prevPrice = priceType == ENUM_CROSS_TYPE.Open_Price ? lastBid : lastOpen;
                    currPrice = priceType == ENUM_CROSS_TYPE.Open_Price ? Bid : Bars.OpenPrices.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
        }
    }
}


Replies

firemyst
14 Jul 2022, 03:26

" am trying to make this cbot open trades exactly on the MA crossing"

This depends on when you define a MA crossing. Right now, your code doesn't check the current bar/candle to see if the MA's crossed. Rather, it checks the previous bar and the bar before that (last(1) and last(2)).

If you want it on the exact tick that it happens, then you need to check the current values of the MA against the previous bar's values. Eg, last(0) and last(1) instead of last(1) and last(2).


@firemyst

dokinya
16 Jul 2022, 10:42

RE:

firemyst said:

" am trying to make this cbot open trades exactly on the MA crossing"

This depends on when you define a MA crossing. Right now, your code doesn't check the current bar/candle to see if the MA's crossed. Rather, it checks the previous bar and the bar before that (last(1) and last(2)).

If you want it on the exact tick that it happens, then you need to check the current values of the MA against the previous bar's values. Eg, last(0) and last(1) instead of last(1) and last(2).

Thanks firemyst

i don't know how i missed that, regards it worked if you were a girl i would have kissed you, 

thanks