Renko/Range Backtest

afhacker's avatar

afhacker since: 15 Oct 2015;

  11 Aug 2021, 09:40
Renko/Range Backtest

Hello,

I want to share the code that I use for backtesting Renko/Range bots on cTrader, follow the below instruction:

  1. Clone the "cAlgo.API.Extensions.Series" repo, and build it (You have to update the cAlgo.dll file reference to one located on your system before build)
  2. Reference the library on your Indicator/cBot
  3. Use the sample below to implement it on your cBot code
  4. For backtesting you have to use Tick data, it will not work on bars data
using cAlgo.API;
using cAlgo.API.Extensions.Enums;
using cAlgo.API.Extensions.Models;
using cAlgo.API.Extensions.Series;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class RenkoBot : Robot
    {
        // Use RangeBars for Range bars
        private RenkoBars _renkoBars;

        [Parameter("Size (Pips)", DefaultValue = 10)]
        public double RankoSizeInPips { get; set; }

        protected override void OnStart()
        {
            _renkoBars = new RenkoBars(RankoSizeInPips, Symbol, this);

            _renkoBars.OnBar += RenkoBars_OnBar;
        }

        protected override void OnTick()
        {
            // The Renko/Range market series OnTick method must be called on each new upcoming ticks
            _renkoBars.OnTick();
        }

        // This method is called on new Renko/Range bars, you should use this method instead of OnBar method of your Robot
        private void RenkoBars_OnBar(object sender, OhlcBar newBar, OhlcBar oldBar)
        {
            var positionsToClose = Positions.FindAll("RenkoBot");

            if (oldBar.Type == BarType.Bullish)
            {
                foreach (var position in positionsToClose)
                {
                    if (position.TradeType == TradeType.Buy) continue;

                    ClosePosition(position);
                }

                ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1000, "RenkoBot", 10, 20);
            }
            else if (oldBar.Type == BarType.Bearish)
            {
                foreach (var position in positionsToClose)
                {
                    if (position.TradeType == TradeType.Sell) continue;

                    ClosePosition(position);
                }

                ExecuteMarketOrder(TradeType.Sell, Symbol.Name, 1000, "RenkoBot", 10, 20);
            }
        }
    }
}
http://algodeveloper.com/
afhacker's avatar

afhacker since: 15 Oct 2015;

  20 Dec 2019, 17:30

It only works if you use Tick data for backtesting, and the time frame is not important it will give you the same result on all time frames.

http://algodeveloper.com/

lukasztrader since: 25 Dec 2019;

  29 Dec 2019, 23:11

Dear AlgoDeveloper,

I appreciate very much your input! I see that not only me is waiting for renko backtesting functionality in cTrader.

I tested your great work.

I tested on EURUSD and WTI. For both backtesting I set t1 (1 tick) and in backtesting settings I chose that Data: "Tick data from Server (accurate)".

In both tests, not once the code went into the 'bear' condition, the only log I received was only "BULL".:

            if (newBar.Type == BarType.Bullish)
            {
                Print("      BULL");
                //ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1000, string.Empty, 10, 20);
            }
            else if (newBar.Type == BarType.Bearish)
            {
                Print("BEAR");                
                //ExecuteMarketOrder(TradeType.Sell, Symbol.Name, 1000, string.Empty, 10, 20);
            }

Can you reproduce it at your environment and give us hint how to proceed? I am using cTrader 3.6

afhacker's avatar

afhacker since: 15 Oct 2015;

  02 Jan 2020, 12:57
RE:

lukasz.iskier said:

Dear AlgoDeveloper,

I appreciate very much your input! I see that not only me is waiting for renko backtesting functionality in cTrader.

I tested your great work.

I tested on EURUSD and WTI. For both backtesting I set t1 (1 tick) and in backtesting settings I chose that Data: "Tick data from Server (accurate)".

In both tests, not once the code went into the 'bear' condition, the only log I received was only "BULL".:

            if (newBar.Type == BarType.Bullish)
            {
                Print("      BULL");
                //ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1000, string.Empty, 10, 20);
            }
            else if (newBar.Type == BarType.Bearish)
            {
                Print("BEAR");                
                //ExecuteMarketOrder(TradeType.Sell, Symbol.Name, 1000, string.Empty, 10, 20);
            }

Can you reproduce it at your environment and give us hint how to proceed? I am using cTrader 3.6

Hi,

I fixed the issue, please clone the latest version of the library from Github.

http://algodeveloper.com/

lukasztrader since: 25 Dec 2019;

  03 Jan 2020, 00:01

Hi,

I cloned the newest version (there is a missing reference for cargo.dll, but I changed that manually).

Now, there is no bar detection - I received no logs in the console and none transaction was made.

I guess something went wrong with new change.

afhacker's avatar

afhacker since: 15 Oct 2015;

  07 Jan 2020, 23:55
RE:

lukasz.iskier said:

Hi,

I cloned the newest version (there is a missing reference for cargo.dll, but I changed that manually).

Now, there is no bar detection - I received no logs in the console and none transaction was made.

I guess something went wrong with new change.

I just tested it and it works fine, are you you are calling the onTick method of Renko series on each new tick?

This is the code I used:

using cAlgo.API;
using cAlgo.API.Extensions.Enums;
using cAlgo.API.Extensions.Models;
using cAlgo.API.Extensions.Series;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class RenkoBot : Robot
    {
        // Use RangeMarketSeries for Range bars
        private RenkoMarketSeries _renkoSeries;

        private MovingAverage _ma;

        [Parameter("Size (Pips)", DefaultValue = 10)]
        public double RankoSizeInPips { get; set; }

        protected override void OnStart()
        {
            _renkoSeries = new RenkoMarketSeries(RankoSizeInPips, Symbol, this);

            _renkoSeries.OnBar += RenkoSeries_OnBar;

            // You can initialize cTrader indicators 
            _ma = Indicators.MovingAverage(_renkoSeries.Close, 10, MovingAverageType.Exponential);
        }

        protected override void OnTick()
        {
            // The Renko/Range market series OnTick method must be called on each new up coming ticks
            _renkoSeries.OnTick();
        }

        // This method is called on new Renko/Range bars, you should use this method instead of OnBar method of your Robot
        private void RenkoSeries_OnBar(object sender, OhlcBar newBar, OhlcBar oldBar)
        {
            Print(oldBar.Type);
        }
    }
}

And Result:

http://algodeveloper.com/

liwik10297 since: 08 Jan 2020;

  08 Jan 2020, 20:30

Hi, I've tested the following code, but the indicator doesn't work properly. It returns NaN values for about 100 bars (the number of bars depend on the time frame selected).

The code:

using cAlgo.API;
using cAlgo.API.Extensions.Enums;
using cAlgo.API.Extensions.Models;
using cAlgo.API.Extensions.Series;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class RenkoBot : Robot
    {
        // Use RangeMarketSeries for Range bars
        private RenkoMarketSeries _renkoSeries;

        private MovingAverage _ma;

        [Parameter("Size (Pips)", DefaultValue = 10)]
        public double RankoSizeInPips { get; set; }

        
        protected override void OnStart()
        {
            _renkoSeries = new RenkoMarketSeries(RankoSizeInPips, Symbol, this);

            _renkoSeries.OnBar += RenkoSeries_OnBar;
            
            // You can initialize cTrader indicators 
            _ma = Indicators.MovingAverage(_renkoSeries.Close, 10, MovingAverageType.Exponential);
        }

        protected override void OnTick()
        {
            // The Renko/Range market series OnTick method must be called on each new up coming ticks
            _renkoSeries.OnTick();
            
        }

        // This method is called on new Renko/Range bars, you should use this method instead of OnBar method of your Robot
        private void RenkoSeries_OnBar(object sender, OhlcBar newBar, OhlcBar oldBar)
        {

            Print("Renko: ", _renkoSeries.Close.Last(1));
            Print("MA: ", ma.Result.Last(1));
            Print("Count", _renkoSeries.Close.Count);

        }
    }
}

lukasztrader since: 25 Dec 2019;

  11 Jan 2020, 16:00

I compared backtest Renko size 10 and real chart and the bricks and the dates are not the same. Why?

What impact does have the setting of the instance's to 1hour or 1tick?

The size of the brick size is set to 10, the backtesting setting for data is set to "Tick data from Server (accurate)".

I see that there are different values for:

var prevOpenPrice = MarketSeries.Open.Last(1);

Example:

GBPJPY, h1, m1, t1 - the renko values for prevOpenPrice are different. What is the reason for that?

afhacker's avatar

afhacker since: 15 Oct 2015;

  13 Jan 2020, 15:23
RE:

lukasz.iskier said:

I compared backtest Renko size 10 and real chart and the bricks and the dates are not the same. Why?

What impact does have the setting of the instance's to 1hour or 1tick?

The size of the brick size is set to 10, the backtesting setting for data is set to "Tick data from Server (accurate)".

I see that there are different values for:

var prevOpenPrice = MarketSeries.Open.Last(1);

Example:

GBPJPY, h1, m1, t1 - the renko values for prevOpenPrice are different. What is the reason for that?

Hi,

It differs because the counting starts from different points of time, the cTrader Renko chart is calculated on their servers and then fed to client platforms.

http://algodeveloper.com/

lukasztrader since: 25 Dec 2019;

  13 Jan 2020, 20:17

Ok, thanks.

How about those NaN values for indicators from mine screens and liwik10297 ? Do you plan to release any fix for that? Do you plan to make possible to visualize renko bricks for backtesting?