has crossed over help

Created at 07 Mar 2021, 15:25
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!
DU

duketv

Joined 16.09.2020

has crossed over help
07 Mar 2021, 15:25


Hi guys,

Working on a new idea and trying a very simple crossover but do not seem to able to get it to work consistenly in my backtest, perhaps you can spot the error?

My goal is to:

1. return true when price crosses and closes above MA for buy signal (and opposite for sell)

2. Return true for this instance for the next three bars or so (in case no direct overlap with other indicators)

 

I previously did this with: 

if (Bars.Last(1).Open < Sma.Result.LastValue && Bars.Last(1).Close > Sma.Result.LastValue)

{ //buy

or with:

if (Sma.Result.HasCrossedBelow(Symbol.Bid, 3));

{ //buy

but neither gives me the consistent desired result..

Any ideas are much appreciated :)


@duketv
Replies

PanagiotisCharalampous
08 Mar 2021, 09:07

Hi duketv,

Can you explain why the results are not consistent?

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

duketv
14 Mar 2021, 21:15

RE:

Dear PanagiotisCharalampous
My interpretation of 'hascrossedabove' is that after crossing, the method will return true for an x amount of bars. X being the 'int Period' from the method. However, I do see an irregular amount 'true' when I code for this.  Perhaps my understanding is of the method is wrong? I coded a small bot to illustrate, being particularly charmed by the Schaff indicator myself, but any crossing indicator will work.

Ultimately my goal is to:

1. return true when price crosses and closes above MA for buy signal (and opposite for sell)

2. Return true for this instance for the next three bars or so (in case no direct overlap with other indicators)

 

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.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }


        [Parameter(Group = "Schaff")]
        public DataSeries SourceSchaff { get; set; }

        [Parameter("Short Cycle", DefaultValue = 28, Group = "Schaff")]
        public int ShortCycle { get; set; }

        [Parameter("Long Cycle", DefaultValue = 54, Group = "Schaff")]
        public int LongCycle { get; set; }

        [Parameter("Period", DefaultValue = 15, Group = "Schaff")]
        public int SchaffPeriod { get; set; }

        [Parameter("Factor", DefaultValue = 0.5, Group = "Schaff")]
        public double Factor { get; set; }

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

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



        private SchaffTrendCycle _indi1 { get; set; }
        private SimpleMovingAverage _sma1 { get; set; }




        protected override void OnStart()
        {
            _indi1 = Indicators.GetIndicator<SchaffTrendCycle>(SourceSchaff, ShortCycle, LongCycle, SchaffPeriod, Factor);
            _sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }


        protected override void OnBar()
        {

            var SmaBuy = _sma1.Result.HasCrossedBelow(Symbol.Bid, 3);
            var SmaSell = _sma1.Result.HasCrossedAbove(Symbol.Bid, 3);
            var SchaffBuy = _indi1.Result.HasCrossedAbove(_indi1.L25, 3) && _indi1.Result.LastValue > 75;
            var SchaffSell = _indi1.Result.HasCrossedBelow(_indi1.L75, 3) && _indi1.Result.LastValue < 25;


            if (SchaffBuy == true)
            {
                Print("SchaffBuy = True");
            }

            if (SchaffSell == true)
            {
                Print("SchaffSell = True");
            }

            if (SmaBuy == true)
            {
                Print("SmaBuy = True");
            }

            if (SmaSell == true)
            {
                Print("SmaSell = True");
            }


        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@duketv

amusleh
15 Mar 2021, 09:46

RE:

duketv said:

Hi guys,

Working on a new idea and trying a very simple crossover but do not seem to able to get it to work consistenly in my backtest, perhaps you can spot the error?

My goal is to:

1. return true when price crosses and closes above MA for buy signal (and opposite for sell)

2. Return true for this instance for the next three bars or so (in case no direct overlap with other indicators)

 

I previously did this with: 

if (Bars.Last(1).Open < Sma.Result.LastValue && Bars.Last(1).Close > Sma.Result.LastValue)

{ //buy

or with:

if (Sma.Result.HasCrossedBelow(Symbol.Bid, 3));

{ //buy

but neither gives me the consistent desired result..

Any ideas are much appreciated :)

Hi,

The code above checks last MA value which is not closed yet and can change, so it can go above or below last closed bar price.

You should use Last(1) not LastValue:

if (Bars.Last(1).Open < Sma.Result.Last(1) && Bars.Last(1).Close > Sma.Result.Last(1))
{

​}

Last(1) gives you the latest closed value, and LastValue gives you the last value of series which is not closed yet and can change which will give you inconsistent results both in backtest and live.

You can use Last(2) to get the last second closed value of a series.


@amusleh

duketv
19 Mar 2021, 15:38

RE: RE:

amusleh said:

Hi,

The code above checks last MA value which is not closed yet and can change, so it can go above or below last closed bar price.

You should use Last(1) not LastValue:

if (Bars.Last(1).Open < Sma.Result.Last(1) && Bars.Last(1).Close > Sma.Result.Last(1))
{

​}

Last(1) gives you the latest closed value, and LastValue gives you the last value of series which is not closed yet and can change which will give you inconsistent results both in backtest and live.

You can use Last(2) to get the last second closed value of a series.

Thank you, That is indeed some valuable information for further coding.. A small but not unimportant detail!

Still curious how the hascrossedabove method works though? My interpretation of 'hascrossedabove' is that after crossing, the method will return true for an x amount of bars. X being the 'int Period' from the method. However, I do see an irregular amount 'true' when I code for this.


@duketv

amusleh
19 Mar 2021, 16:07

RE: RE: RE:

duketv said:

amusleh said:

Hi,

The code above checks last MA value which is not closed yet and can change, so it can go above or below last closed bar price.

You should use Last(1) not LastValue:

if (Bars.Last(1).Open < Sma.Result.Last(1) && Bars.Last(1).Close > Sma.Result.Last(1))
{

​}

Last(1) gives you the latest closed value, and LastValue gives you the last value of series which is not closed yet and can change which will give you inconsistent results both in backtest and live.

You can use Last(2) to get the last second closed value of a series.

Thank you, That is indeed some valuable information for further coding.. A small but not unimportant detail!

Still curious how the hascrossedabove method works though? My interpretation of 'hascrossedabove' is that after crossing, the method will return true for an x amount of bars. X being the 'int Period' from the method. However, I do see an irregular amount 'true' when I code for this.

You can read the documentation of HasCroossedAbove method here: 

 


@amusleh

duketv
21 Mar 2021, 16:27

RE: RE: RE: RE:

Thank you, I have read the documentation before of this method but still unclear exactly how it works. My interpretation of 'hascrossedabove' is that after crossing, the method will return true for an x amount of bars. X being the 'int Period' from the method. However, I do see an irregular amount 'true' when I code for this.

Any exact explanation is appreciated. thanks

 

amusleh said:

 

You can read the documentation of HasCroossedAbove method here: 

 


@duketv

duketv
01 Apr 2021, 14:58

hi guys,
I am still hoping someone can explain how this 'hascrossedover' function exactly works with respect to the period, because I see a variable number of 'true' returns with respect to this period
The documentation says: "HasCrossedAbove will compare the crossing dataseries to the crossed dataseries starting from the current value of the series going back the specified period"

Thank you.


@duketv

PanagiotisCharalampous
02 Apr 2021, 08:41

Hi duketv,

I think the documentation is clear. If you think there is a bug, please provide us some examples to reproduce and investigate.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

duketv
05 Apr 2021, 18:45

RE:

PanagiotisCharalampous said:

Hi duketv,

I think the documentation is clear. If you think there is a bug, please provide us some examples to reproduce and investigate.

Best Regards,

Panagiotis 

Join us on Telegram

Dear PanagiotisCharalampous ,

Thank you for taking the time to reply to this. In the below code I have added a 'print message in the log' after every cross over between the price and a simple SMA. I have set the period to 3, so I expect the method will return 3x 'true', but it doesn't. Checked on the BTC/EUR pair with actual tick data.
Can you explain this irregular amount of 'true' ?

Many thanks

 

 

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.None)]
    public class NewcBot : Robot
    {

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

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



        private SimpleMovingAverage _sma1 { get; set; }




        protected override void OnStart()
        {
            _sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }


        protected override void OnBar()
        {

            var SmaBuy = _sma1.Result.HasCrossedBelow(Symbol.Bid, 3);
            var SmaSell = _sma1.Result.HasCrossedAbove(Symbol.Bid, 3);

            if (SmaBuy == true)
            {
                Print("SmaBuy = True");
            }

            if (SmaSell == true)
            {
                Print("SmaSell = True");
            }


        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@duketv

amusleh
06 Apr 2021, 15:04

Hi,

The methods check if there was any cross in x last periods, if there was any it returns true otherwise it returns false.

If you use HasCrossedAbove with 10 as period, then it checks if is the crossing series has crossed at least one time the crossed series upward in last 10 values or not, if it did then the method returns true otherwise it returns false.

Same for HasCrossedBelow, except it checks for downward cross.

An up cross happens if a value inside crossing series goes above//equal to crossed series value and previous value of crossing series was below crossed series value.

A down cross happens if a value inside crossing series goes below//equal to crossed series value and previous value of crossing series was above crossed series value.


@amusleh

duketv
06 Apr 2021, 20:17

RE:

amusleh said:

Hi,

The methods check if there was any cross in x last periods, if there was any it returns true otherwise it returns false.

If you use HasCrossedAbove with 10 as period, then it checks if is the crossing series has crossed at least one time the crossed series upward in last 10 values or not, if it did then the method returns true otherwise it returns false.

Same for HasCrossedBelow, except it checks for downward cross.

An up cross happens if a value inside crossing series goes above//equal to crossed series value and previous value of crossing series was below crossed series value.

A down cross happens if a value inside crossing series goes below//equal to crossed series value and previous value of crossing series was above crossed series value.

 

Thanks! That is exactly how I understand it as well but that is not what I see happening.
Because if your period is set to 10 than you would see the method return true for 10 bars (if set to on bar), but instead I see an irregular amount of true returned.

In the below bot I have set it to print a message to the log, everytime the method returns true. Am i missing something or is there perhaps a bug?
 

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.None)]
    public class NewcBot : Robot
    {

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

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



        private SimpleMovingAverage _sma1 { get; set; }




        protected override void OnStart()
        {
            _sma1 = Indicators.SimpleMovingAverage(SourceSma1, PeriodsSma1);
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }


        protected override void OnBar()
        {

            var SmaBuy = _sma1.Result.HasCrossedBelow(Symbol.Bid, 3);
            var SmaSell = _sma1.Result.HasCrossedAbove(Symbol.Bid, 3);

            if (SmaBuy == true)
            {
                Print("SmaBuy = True");
            }

            if (SmaSell == true)
            {
                Print("SmaSell = True");
            }


        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@duketv

amusleh
07 Apr 2021, 11:03

Hi,

The methods works the way I explained on my previous post, just tested with this sample:

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HasCrossedSample : Indicator
    {
        private SimpleMovingAverage _fastMa, _slowMa;

        [Parameter("Type", DefaultValue = CrossType.Above)]
        public CrossType CrossType { get; set; }
        
        [Parameter("Period", DefaultValue = 10)]
        public int Period { get; set; }

        [Output("Fast MA", LineColor = "Red", Thickness = 1)]
        public IndicatorDataSeries FastMa { get; set; }

        [Output("Slow MA", LineColor = "Yellow", Thickness = 2)]
        public IndicatorDataSeries SlowMa { get; set; }

        protected override void Initialize()
        {
            _fastMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 9);
            _slowMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 20);
        }

        public override void Calculate(int index)
        {
            FastMa[index] = _fastMa.Result[index];
            SlowMa[index] = _slowMa.Result[index];

            if (!IsLastBar) return;

            Chart.DrawVerticalLine("line", index - Period, Color.Red, 2);

            if (CrossType == CrossType.Above && FastMa.HasCrossedAbove(SlowMa, Period)) Print("Crossed");
            else if (CrossType == CrossType.Below && FastMa.HasCrossedBelow(SlowMa, Period)) Print("Crossed");
        }
    }
    
    public enum CrossType
    {
        Above,
        Below
    }
}

The sample indicator will draw a vertical line on period start, and then if fast MA crossed above/below slow MA it will print "Crossed" on log.

A cross must happen during the period values.


@amusleh

duketv
16 Apr 2021, 13:02

RE:

amusleh said:

Hi,

The methods works the way I explained on my previous post, just tested with this sample:

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HasCrossedSample : Indicator
    {
        private SimpleMovingAverage _fastMa, _slowMa;

        [Parameter("Type", DefaultValue = CrossType.Above)]
        public CrossType CrossType { get; set; }
        
        [Parameter("Period", DefaultValue = 10)]
        public int Period { get; set; }

        [Output("Fast MA", LineColor = "Red", Thickness = 1)]
        public IndicatorDataSeries FastMa { get; set; }

        [Output("Slow MA", LineColor = "Yellow", Thickness = 2)]
        public IndicatorDataSeries SlowMa { get; set; }

        protected override void Initialize()
        {
            _fastMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 9);
            _slowMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 20);
        }

        public override void Calculate(int index)
        {
            FastMa[index] = _fastMa.Result[index];
            SlowMa[index] = _slowMa.Result[index];

            if (!IsLastBar) return;

            Chart.DrawVerticalLine("line", index - Period, Color.Red, 2);

            if (CrossType == CrossType.Above && FastMa.HasCrossedAbove(SlowMa, Period)) Print("Crossed");
            else if (CrossType == CrossType.Below && FastMa.HasCrossedBelow(SlowMa, Period)) Print("Crossed");
        }
    }
    
    public enum CrossType
    {
        Above,
        Below
    }
}

The sample indicator will draw a vertical line on period start, and then if fast MA crossed above/below slow MA it will print "Crossed" on log.

A cross must happen during the period values.

Hei amusleh,

Thanks a bunch for that code! That solved the problem and showed me that you were 100% right. Hascrossedabove works as advertised. I did found out that in my code tthat the Symbol.Bid caused all the problems. I swapped it to Bars.Openprices and the problem is gone. Thanks for the support and effort!

ar SmaBuy = _sma1.Result.HasCrossedBelow(Symbol.Bid, 3);

@duketv