RSI Indicator - LastValue, Last(0), Last(1) - Not understanding why their values are as per the enclosed screenshot.

Created at 15 Mar 2020, 14:45
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!
B9

b917187

Joined 27.02.2020

RSI Indicator - LastValue, Last(0), Last(1) - Not understanding why their values are as per the enclosed screenshot.
15 Mar 2020, 14:45


Hi,

Can someone explain to me, why on this chart LastValue is more than Last (0) and Last (1)?

See 5 orange boxes in the enclosed screenshot.

Thanks

 

 


@b917187
Replies

firemyst
16 Mar 2020, 02:16 ( Updated at: 21 Dec 2023, 09:21 )

RE:

b917187 said:

Hi,

Can someone explain to me, why on this chart LastValue is more than Last (0) and Last (1)?

See 5 orange boxes in the enclosed screenshot.

Thanks

 

 

In your debug window, Result.Last(0) should be the same as Result.LastValue since they mean the same thing.

Thus, since you didn't post any other code, my initial guess is due to lazy loading of indicator values, you're not properly getting the values before you use them.

For example, somewhere before your "if" statement block, you need to do:

 

//Need to force the indicator to calculate the last value before using any of them.
//Put this before your "if" statement.
double a = _rsi.Result.Last(0);

//If the above works, great!
//Advice: Generally what I do is create a method that does nothing but the above
//for every indicator I use in a bot or another indicator. 
//Saves me from having to worry if the latest values have been calculated or not.

 

 


@firemyst

b917187
17 Mar 2020, 00:17

Hi firemyst,

Thank you.

So I created a small function as follows to get a fresh copy of the indicator values:

 

 

But the results still seem to be incorrect even though I call this function just prior to testing the values:

 

See how the rsi in the chart is visually sloping upwards, yet the last1 is higher than LastValue, which means the variables see it as going downwards, right? It returns false instead of true

 

Many thanks,


@b917187

PanagiotisCharalampous
17 Mar 2020, 08:15 ( Updated at: 21 Dec 2023, 09:21 )

RE:

b917187 said:

Hi firemyst,

Thank you.

So I created a small function as follows to get a fresh copy of the indicator values:

 

 

But the results still seem to be incorrect even though I call this function just prior to testing the values:

 

See how the rsi in the chart is visually sloping upwards, yet the last1 is higher than LastValue, which means the variables see it as going downwards, right? It returns false instead of true

 

Many thanks,

Hi there,

Can you share the complete cBot code with us?

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

b917187
17 Mar 2020, 18:22

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 RSITest : Robot
    {
        #region User defined parameters


        // ************************************************************
        // Debug Mode
        [Parameter("Debug Mode", DefaultValue = false)]
        public bool DebugMode { get; set; }
        // ************************************************************

        // ************************************************************
        // Used by Main Functional Elements
        [Parameter("RSI Open Active", DefaultValue = true)]
        public bool rsiOpenParamActive { get; set; }
        [Parameter("RSI Close Active", DefaultValue = true)]
        public bool rsiCloseParamActive { get; set; }
        [Parameter("RSI Overbought", DefaultValue = 70, MinValue = 1, MaxValue = 200)]
        public int _rsi_overbought_val { get; set; }
        [Parameter("RSI Oversold", DefaultValue = 30, MinValue = 1, MaxValue = 200)]
        public int _rsi_oversold_val { get; set; }


        // ************************************************************


        [Parameter("Instance Name", DefaultValue = "001")]
        public string InstanceName { get; set; }
        [Parameter("Lot Size", DefaultValue = 0.1)]
        public double LotSize { get; set; }
        [Parameter("Calculate OnBar", DefaultValue = true)]
        public bool CalculateOnBar { get; set; }

        // ************************************************************
        // Used by Built-in RSI Indicator

        [Parameter("Period RSI #1", DefaultValue = 14, MinValue = 1, MaxValue = 100)]
        public int PeriodRsi1 { get; set; }
        [Parameter("Source RSI #1")]
        public DataSeries SourceRsi1 { get; set; }
        // ************************************************************

        #endregion

        #region Indicator declarations
        private double rsilast1;
        private double rsilastvalue;
        // ************************************************************
        // Used by Built-in RSI Indicator
        private RelativeStrengthIndex _rsi { get; set; }
        private bool _rsiOversold { get; set; }
        private bool _rsiOverbought { 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

            // ************************************************************
            // Used by Built-in RSI Indicator
            _rsi = Indicators.RelativeStrengthIndex(SourceRsi1, PeriodRsi1);
            // ************************************************************
        }

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

            if (CalculateOnBar)
            {
                return;
            }
            else
            {
                ManagePositions();
            }

        }

        /// <summary>
        /// This method is called at every candle (bar) close, when it has formed
        /// </summary>
        protected override void OnBar()
        {
            if (!CalculateOnBar)
            {
                return;
            }
            else
            {
                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()
        {
            ManageBuyPositions();
            ManageSellPositions();

        }

        private void ManageBuyPositions()
        {
            setRSIOverboughtOversold();
            if (!IsPositionOpenByType(TradeType.Buy) && rsiOpenLongConditionsMet())
            {
                if (!DebugMode)
                {
                    OpenPosition(TradeType.Buy);
                    _rsiOversold = false;
                }
                else
                {
                }
            }
            // if there is a BUY position open            
            else if (IsPositionOpenByType(TradeType.Buy) && (!DebugMode))
            {
                if (rsiCloseLongConditionsMet())
                {
                    ClosePosition(TradeType.Buy);
                    return;
                }
            }
            else
            {
            }
        }

        private void ManageSellPositions()
        {

            if (!IsPositionOpenByType(TradeType.Sell) && rsiOpenShortConditionsMet())
            {
                if (!DebugMode)
                {
                    OpenPosition(TradeType.Sell);
                    _rsiOverbought = false;
                }
                else
                {
                }
            }
            else if (IsPositionOpenByType(TradeType.Sell) && !DebugMode)
            {
                if (rsiCloseShortConditionsMet())
                {
                    ClosePosition(TradeType.Sell);
                    return;
                }
            }
            else
            {
            }

        }


        private void setRSIOverboughtOversold()
        {
            if (_rsiOverbought == false)
            {
                if (_rsi.Result.Last(0) > _rsi_overbought_val)
                {
                    _rsiOverbought = true;
                }
            }
            else if (_rsiOversold == false)
            {
                if (_rsi.Result.Last(0) < _rsi_oversold_val)
                {
                    _rsiOversold = true;
                }
            }
            else
            {
                //do nothing
            }
        }

        //*******************************************************************************************************
        private bool rsiOpenLongConditionsMet()
        {
            if (rsiOpenParamActive == false)
            {
                return true;
            }
            else
            {
                if (_rsiOversold && _rsi.Result.Last(1) < _rsi.Result.LastValue)
                {
                    return true;
                }

                else
                {
                    return false;
                }
            }
        }


        private bool rsiOpenShortConditionsMet()
        {
            if (rsiOpenParamActive == false)
            {
                return true;
            }
            else
            {

                // Going down
                if (_rsiOverbought && _rsi.Result.Last(1) > _rsi.Result.LastValue)
                {
                    return true;
                }

                else
                {
                    return false;
                }
            }
        }
        //*******************************************************************************************************

        private bool rsiCloseLongConditionsMet()
        {
            calclatestrsivalues();
            if (rsiCloseParamActive == false)
            {
                return false;
            }
            else
            {
                // going down
                if (rsilast1 > rsilastvalue)
                {
                    return true;
                }

                else
                {
                    return false;
                }
            }
        }


        private bool rsiCloseShortConditionsMet()
        {
            calclatestrsivalues();
            if (rsiCloseParamActive == false)
            {
                return false;
            }
            else
            {
                // going up
                if (rsilast1 < rsilastvalue)
                {
                    return true;
                }

                else
                {
                    return false;
                }
            }
        }


        //*******************************************************************************************************

        public void calclatestrsivalues()
        {
            rsilast1 = _rsi.Result.Last(1);
            rsilastvalue = _rsi.Result.LastValue;
        }

        //*******************************************************************************************************

        private void OpenPosition(TradeType type)
        {
            // calculate volume from lot size.
            double volume = Symbol.QuantityToVolumeInUnits(LotSize);

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

        private void ClosePosition(TradeType type)
        {
            var p = Positions.Find(InstanceName, this.Symbol.Name, type);

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

        #endregion

        #region Position Information


        private bool IsPositionOpenByType(TradeType type)
        {
            var p = Positions.FindAll(InstanceName, Symbol.Name, type);

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

            return false;
        }

        #endregion
    }
}
 


@b917187

b917187
17 Mar 2020, 18:23

RE:

Here you go. Thanks for looking


@b917187

PanagiotisCharalampous
18 Mar 2020, 08:17

Hi b917187,

I tried this several times but I cannot reproduce such a behavior. I have also noticed that in your Watch the values are not refreshed (greyed). Can you please confirm you are comparing the latest values?

 Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

b917187
18 Mar 2020, 12:48 ( Updated at: 21 Dec 2023, 09:21 )

RE:

PanagiotisCharalampous said:

Hi b917187,

I tried this several times but I cannot reproduce such a behavior. I have also noticed that in your Watch the values are not refreshed (greyed). Can you please confirm you are comparing the latest values?

 Best Regards,

Panagiotis 

Join us on Telegram

 

Hi Panagiotis,

So maybe this will help us sync up. I am backtesting EURUSD on the 1 minute chart. The test is on 16th February 2020 as shown below and the test condition is hit immediately as soon as you start backtesting.

Thanks for the tip about the "refresh" button... I wasn't aware of that.  Its good to know but it does not solve the problem as not only were the watched variables showing a problem, but the code was also mirroring that problem - go going down the "true" path when it should have been the "false" patch and vice versa.

So here is a new test at the start of the 16th Feb.

My first question here is:

a) When Are you seeing the same values for LastValue and Last(1) when it falls into that "return true" in the "rsiOpenShortConditionsMet" method? Maybe you could post your screenshot if it shows different?

b) Are these two values meant to be the same? It seems to me they should not be the same. Looking at the rsi indicator on the chart, it seems Last(1) should be a lot lower than LastValue?

Note: I have refreshed the watched values... they are no longer grey.

Many thanks


@b917187

b917187
20 Mar 2020, 11:01

Hello,

Is anyone able to help with this?

The question is really the core of all these indicators. Why do Last (1) and LastValue return unexpected values?

Thanks


@b917187

PanagiotisCharalampous
20 Mar 2020, 11:32

Hi b917187,

I have checked this and there is no issue. Your check seems to take place as soon as the bar changes. At that moment the LastValue will be almost identical to the previous value since the close price of both bars is the same. Maybe you intended to check Last(1) and Last(2)?

 Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

b917187
26 Mar 2020, 22:45

RE:

PanagiotisCharalampous said:

Hi b917187,

I have checked this and there is no issue. Your check seems to take place as soon as the bar changes. At that moment the LastValue will be almost identical to the previous value since the close price of both bars is the same. Maybe you intended to check Last(1) and Last(2)?

 Best Regards,

Panagiotis 

Join us on Telegram

 

Thank you. That was it - a combination of not refreshing the Watch values and not using Last(1) and Last(2)

 


@b917187