Troubleshooting a cBot for trading by price crosses the MA

Created at 12 Apr 2019, 19:58
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!
PE

pejman101

Joined 12.04.2019

Troubleshooting a cBot for trading by price crosses the MA
12 Apr 2019, 19:58


Hello and good day everyone

I've borrowed a code that was originally designed to trade by MA crosses and modified it to operate when the price crosses a single MA but i'm getting some errors and the code doesn't compile

The original code:

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


/*
 *  POPULAR SIMPLE MOVING AVERAGES
 *
 *  The simple moving average (SMA) is the most basic of the moving averages used for trading. 
 *  The simple moving average formula is calculated by taking the average closing price of a stock over the last "x" periods.
 *  
 *  5 - SMA  - For the hyper trader.  This short of an SMA will constantly give you signals.  The best use of a 5-SMA is as a trade trigger in conjunction with a longer SMA period.
 *  10 - SMA - popular with the short-term traders.  Great swing traders and day traders.
 *  20 - SMA - the last stop on the bus for short-term traders.  Beyond 20-SMA you are basically looking at primary trends.
 *  50 - SMA - use the trader to gauge mid-term trends.
 *  200 -SMA - welcome to the world of long-term trend followers.  Most investors will look for a cross above or below this average to represent if the stock is in a bullish or bearish trend.
 *  
 */

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

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

        [Parameter("Lot Size", DefaultValue = 0.1)]
        public double LotSize { get; set; }

        [Parameter("Source SMA #1")]
        public DataSeries SourceSma1 { get; set; }

        [Parameter("Source SMA #2")]
        public DataSeries SourceSma2 { get; set; }

        [Parameter("Period SMA #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma1 { get; set; }

        [Parameter("Period SMA #2", DefaultValue = 20, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma2 { get; set; }

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = false)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 20)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 10)]
        public int TrailingStopStep { get; set; }

        #endregion

        #region Indicator declarations

        private SimpleMovingAverage _sma1 { get; set; }
        private SimpleMovingAverage _sma2 { get; set; }

        #endregion

 My code:

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

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

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

        [Parameter("Lot Size", DefaultValue = 0.1)]
        public double LotSize { get; set; }

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

        [Parameter("Period", DefaultValue = 1, MinValue = 1, MaxValue = 1000)]
        public int Periodwma { get; set; }

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }

        [Parameter("Take Profit", DefaultValue = null, MinValue = null, Step = 1)]
        public double TakeP { get; set; }

        [Parameter("Stop Loss", DefaultValue = null, MaxValue = null, Step = 1)]
        public double StopL { get; set; }
        
        [Parameter("Include Trailing Stop", DefaultValue = false)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 20)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 10)]
        public int TrailingStopStep { get; set; }

        #endregion

        #region Indicator declarations

        private WeightedMovingAverage { get; set; }

        #endregion

        #region cTrader events

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            wma = Indicators.WeightedMovingAverage(SourceSma1, PeriodsSma1);
        }

        /// <summary>
        /// This method is called every time the price changes for the symbol
        /// </summary>
        protected override void OnTick()
        {
            if (CalculateOnBar)
            {
                return;
            }

            ManagePositions();

            if (IncludeTrailingStop)
            {
                SetTrailingStop();
            }
        }

        /// <summary>
        /// This method is called at every candle (bar) close, when it has formed
        /// </summary>
        protected override void OnBar()
        {
            if (!CalculateOnBar)
            {
                return;
            }

            ManagePositions();
        }

        /// <summary>
        /// This method is called when your robot stops, can be used to clean-up memory resources.
        /// </summary>
        protected override void OnStop()
        {
            // unused
        }

        #endregion

        #region Position management

        private void ManagePositions()
        {
            if (wma.Result.LastValue.HasCrossedAbove)
            {
                // if there is no buy position open, open one and close any sell position that is open
                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }

                ClosePosition(TradeType.Sell);
            }

            // if a sell position is already open and signal is buy do nothing
            if (wma.Result.LastValue.HasCrossedBelow)
            {
                // if there is no sell position open, open one and close any buy position that is open
                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }

                ClosePosition(TradeType.Buy);
            }
        }

        /// <summary>
        /// Opens a new long position
        /// </summary>
        /// <param name="type"></param>
        private void OpenPosition(TradeType type)
        {
            // calculate volume from lot size.
            long volume = Symbol.QuantityToVolume(LotSize);

            // open a new position
            ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, StopL, TakeP);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol, type);

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

        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Sell);

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

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

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

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

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }

        #endregion

        #region Position Information

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol, type);

            if (p.Count() >= 1)
            {
                return true;
            }

            return false;
        }

        #endregion
    }
}

 

I was wondering if anyone can help me find out what am I doing wrong

Best regards


@pejman101
Replies

pejman101
12 Apr 2019, 20:01

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


/*
 *  POPULAR SIMPLE MOVING AVERAGES
 *
 *  The simple moving average (SMA) is the most basic of the moving averages used for trading. 
 *  The simple moving average formula is calculated by taking the average closing price of a stock over the last "x" periods.
 *  
 *  5 - SMA  - For the hyper trader.  This short of an SMA will constantly give you signals.  The best use of a 5-SMA is as a trade trigger in conjunction with a longer SMA period.
 *  10 - SMA - popular with the short-term traders.  Great swing traders and day traders.
 *  20 - SMA - the last stop on the bus for short-term traders.  Beyond 20-SMA you are basically looking at primary trends.
 *  50 - SMA - use the trader to gauge mid-term trends.
 *  200 -SMA - welcome to the world of long-term trend followers.  Most investors will look for a cross above or below this average to represent if the stock is in a bullish or bearish trend.
 *  
 */

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

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

        [Parameter("Lot Size", DefaultValue = 0.1)]
        public double LotSize { get; set; }

        [Parameter("Source SMA #1")]
        public DataSeries SourceSma1 { get; set; }

        [Parameter("Source SMA #2")]
        public DataSeries SourceSma2 { get; set; }

        [Parameter("Period SMA #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma1 { get; set; }

        [Parameter("Period SMA #2", DefaultValue = 20, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma2 { get; set; }

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }

        [Parameter("Include Trailing Stop", DefaultValue = false)]
        public bool IncludeTrailingStop { get; set; }

        [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 20)]
        public int TrailingStopTrigger { get; set; }

        [Parameter("Trailing Stop Step (pips)", DefaultValue = 10)]
        public int TrailingStopStep { get; set; }

        #endregion

        #region Indicator declarations

        private SimpleMovingAverage _sma1 { get; set; }
        private SimpleMovingAverage _sma2 { get; set; }

        #endregion

        #region cTrader events

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            _sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
            _sma2 = Indicators.SimpleMovingAverage(SourceSma2, PeriodsSma2);
        }

        /// <summary>
        /// This method is called every time the price changes for the symbol
        /// </summary>
        protected override void OnTick()
        {
            if (CalculateOnBar)
            {
                return;
            }

            ManagePositions();

            if (IncludeTrailingStop)
            {
                SetTrailingStop();
            }
        }

        /// <summary>
        /// This method is called at every candle (bar) close, when it has formed
        /// </summary>
        protected override void OnBar()
        {
            if (!CalculateOnBar)
            {
                return;
            }

            ManagePositions();
        }

        /// <summary>
        /// This method is called when your robot stops, can be used to clean-up memory resources.
        /// </summary>
        protected override void OnStop()
        {
            // unused
        }

        #endregion

        #region Position management

        private void ManagePositions()
        {
            if (_sma1.Result.LastValue > _sma2.Result.LastValue)
            {
                // if there is no buy position open, open one and close any sell position that is open
                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }

                ClosePosition(TradeType.Sell);
            }

            // if a sell position is already open and signal is buy do nothing
            if (_sma1.Result.LastValue < _sma2.Result.LastValue)
            {
                // if there is no sell position open, open one and close any buy position that is open
                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }

                ClosePosition(TradeType.Buy);
            }
        }

        /// <summary>
        /// Opens a new long position
        /// </summary>
        /// <param name="type"></param>
        private void OpenPosition(TradeType type)
        {
            // calculate volume from lot size.
            long volume = Symbol.QuantityToVolume(LotSize);

            // open a new position
            ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, null, null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol, type);

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

        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Sell);

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

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Ask + TrailingStopStep * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

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

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

                if (distance < TrailingStopTrigger * Symbol.PipSize)
                    continue;

                double newStopLossPrice = Symbol.Bid - TrailingStopStep * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }

        #endregion

        #region Position Information

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol, type);

            if (p.Count() >= 1)
            {
                return true;
            }

            return false;
        }

        #endregion
    }
}

The compelete original code


@pejman101

... Deleted by UFO ...

PanagiotisCharalampous
14 Apr 2019, 13:26

Hi pejman101,

There are several errors in your code. See below

 

        #region Indicator declarations
 
        private WeightedMovingAverage { get; set; }
 
        #endregion

?

You don't declare any parameter name here

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            wma = Indicators.WeightedMovingAverage(SourceSma1, PeriodsSma1);
        }

PeriodsSma1 is not defined anywhere

 

 if (wma.Result.LastValue.HasCrossedAbove)
            {
                // if there is no buy position open, open one and close any sell position that is open
                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }
 
                ClosePosition(TradeType.Sell);
            }
 
            // if a sell position is already open and signal is buy do nothing
            if (wma.Result.LastValue.HasCrossedBelow)
            {
                // if there is no sell position open, open one and close any buy position that is open
                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }
 
                ClosePosition(TradeType.Buy);
            }

?HasCrossedAbove and HasCrossedBelow are not used properly. See here and here how to use them.

 

Best Regards,

Panagiotis


@PanagiotisCharalampous

pejman101
14 Apr 2019, 19:57

RE:

Panagiotis Charalampous said:

Hi pejman101,

There are several errors in your code. See below

 

        #region Indicator declarations
 
        private WeightedMovingAverage { get; set; }
 
        #endregion

?

You don't declare any parameter name here

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            wma = Indicators.WeightedMovingAverage(SourceSma1, PeriodsSma1);
        }

PeriodsSma1 is not defined anywhere

 

 if (wma.Result.LastValue.HasCrossedAbove)
            {
                // if there is no buy position open, open one and close any sell position that is open
                if (!IsPositionOpenByType(TradeType.Buy))
                {
                    OpenPosition(TradeType.Buy);
                }
 
                ClosePosition(TradeType.Sell);
            }
 
            // if a sell position is already open and signal is buy do nothing
            if (wma.Result.LastValue.HasCrossedBelow)
            {
                // if there is no sell position open, open one and close any buy position that is open
                if (!IsPositionOpenByType(TradeType.Sell))
                {
                    OpenPosition(TradeType.Sell);
                }
 
                ClosePosition(TradeType.Buy);
            }

?HasCrossedAbove and HasCrossedBelow are not used properly. See here and here how to use them.

 

Best Regards,

Panagiotis

Thank you very much for your time and help!

I fixed all the issues accordingly and it works perfectly now!


@pejman101