back test several symbols

Created at 20 May 2020, 01:32
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!
EY

eynt

Joined 08.05.2020

back test several symbols
20 May 2020, 01:32


What if I want to back test several symbols, is there a way to run on backtest on several symbols simultaniously instead of one by one?

Thanks


@eynt
Replies

PanagiotisCharalampous
20 May 2020, 09:06

Hi Yuval,

Yes multisymbol backtesting. You can see an example below

using System;
using System.Linq;
using System.Text;
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 MultisymbolBacktesting : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        public Symbol[] MySymbols;

        protected override void OnStart()
        {
            // We get a symbol array for the following for symbols
            MySymbols = Symbols.GetSymbols("EURUSD", "GBPUSD", "USDJPY", "USDCHF");
            // We subscribe to the tick event for each symbol
            foreach (var symbol in MySymbols)
            {
                symbol.Tick += Symbol_Tick;
            }
            // We subscribe to the bar event for each symbol for the current timeframe
            foreach (var symbol in MySymbols)
            {
                var bars = MarketData.GetBars(TimeFrame, symbol.Name);
                bars.BarOpened += Bars_BarOpened;
            }
        }

        private void Bars_BarOpened(BarOpenedEventArgs obj)
        {
            // When a bar opens we check the previous bar. If the bar is bullish, we send a buy order, else we send a sell order.
            if (obj.Bars.Last(1).Close > obj.Bars.Last(1).Open)
            {
                ExecuteMarketOrder(TradeType.Buy, obj.Bars.SymbolName, 1000, "", 2, 2);
            }
            else
            {
                ExecuteMarketOrder(TradeType.Sell, obj.Bars.SymbolName, 1000, "", 2, 2);
            }
        }

        private void Symbol_Tick(SymbolTickEventArgs obj)
        {
            // On each symbol tick, we print the symbol's bid/ask prices on the chart
            var sb = new StringBuilder();
            foreach (var symbol in MySymbols)
            {
                var textLine = string.Format("{0} {1} {2}", symbol.Name, symbol.Bid, symbol.Ask);
                sb.AppendLine(textLine);
            }
            Chart.DrawStaticText("symbols", sb.ToString(), VerticalAlignment.Top, HorizontalAlignment.Left, Chart.ColorSettings.ForegroundColor);
        }

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

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

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

eynt
04 Jun 2020, 09:25

RE:

Thank you.

 

What if each symbol loads an indicator (base on its symbol and a specific time frame. How can I access that from the Symbol_Tick? 


@eynt

john_7ko
06 Jul 2020, 14:41

RE:

PanagiotisCharalampous said:

Hi Yuval,

Yes multisymbol backtesting. You can see an example below

using System;
using System.Linq;
using System.Text;
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 MultisymbolBacktesting : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        public Symbol[] MySymbols;

        protected override void OnStart()
        {
            // We get a symbol array for the following for symbols
            MySymbols = Symbols.GetSymbols("EURUSD", "GBPUSD", "USDJPY", "USDCHF");
            // We subscribe to the tick event for each symbol
            foreach (var symbol in MySymbols)
            {
                symbol.Tick += Symbol_Tick;
            }
            // We subscribe to the bar event for each symbol for the current timeframe
            foreach (var symbol in MySymbols)
            {
                var bars = MarketData.GetBars(TimeFrame, symbol.Name);
                bars.BarOpened += Bars_BarOpened;
            }
        }

        private void Bars_BarOpened(BarOpenedEventArgs obj)
        {
            // When a bar opens we check the previous bar. If the bar is bullish, we send a buy order, else we send a sell order.
            if (obj.Bars.Last(1).Close > obj.Bars.Last(1).Open)
            {
                ExecuteMarketOrder(TradeType.Buy, obj.Bars.SymbolName, 1000, "", 2, 2);
            }
            else
            {
                ExecuteMarketOrder(TradeType.Sell, obj.Bars.SymbolName, 1000, "", 2, 2);
            }
        }

        private void Symbol_Tick(SymbolTickEventArgs obj)
        {
            // On each symbol tick, we print the symbol's bid/ask prices on the chart
            var sb = new StringBuilder();
            foreach (var symbol in MySymbols)
            {
                var textLine = string.Format("{0} {1} {2}", symbol.Name, symbol.Bid, symbol.Ask);
                sb.AppendLine(textLine);
            }
            Chart.DrawStaticText("symbols", sb.ToString(), VerticalAlignment.Top, HorizontalAlignment.Left, Chart.ColorSettings.ForegroundColor);
        }

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

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

Best Regards,

Panagiotis 

Join us on Telegram

 

 

 

How does the subscribing process work? I don't understand how it's able to keep triggering the symbol_tick function on each new tick if onstart() is only executed once when the bot starts up.


@john_7ko

PanagiotisCharalampous
06 Jul 2020, 14:51

Hi john_7ko,

It uses an Event Handler.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

jumel.donatien
28 May 2021, 02:12 ( Updated at: 21 Dec 2023, 09:22 )

RE:

Thank you PanagiotisCharalampous !

Your code is a nice solution for what I want to do!

But I have a problem to add a stochastic detection on the code, and for each Symbol in the array..

I simplified my code (below) to show you what's wrong: I want to get the "PercentK" and "PercentD" from stochastic indicator correspond to each Symbol and Print it in the cbot log.

But it doesn't work.. The four results are the same (as you can see in the results from my cbot log), so I think that the bot just get PercentK and PercentD from only one symbol (here, I think that the result correpond to USDJPY on my chart)

Could you help me please? (I m beginner but I learn!)

Thank you

using System;
using System.Linq;
using System.Text;
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 TEST : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        public Symbol[] MySymbols;

        private StochasticOscillator stochastic;


        protected override void OnStart()
        {
            // We get a symbol array for the following for symbols
            MySymbols = Symbols.GetSymbols("EURUSD", "GBPUSD", "USDJPY", "USDCHF");

            // We subscribe to the bar event for each symbol for the current timeframe
            foreach (var symbol in MySymbols)
            {
                var bars = MarketData.GetBars(TimeFrame, symbol.Name);
                bars.BarOpened += Bars_BarOpened;
            }
        }

        private void Bars_BarOpened(BarOpenedEventArgs obj)
        {
            var stoc = MarketData.GetBars(TimeFrame, obj.Bars.SymbolName);
            stochastic = Indicators.StochasticOscillator(stoc, 8, 3, 9, MovingAverageType.Simple);

            Print("For ", obj.Bars.SymbolName, ": K=", stochastic.PercentK.Last(1), " D=", stochastic.PercentD.Last(1));

            // When a bar opens we check the previous bar. If the bar is bullish, we send a buy order, else we send a sell order.
            if (obj.Bars.Last(1).Close > obj.Bars.Last(1).Open)
            {
                Print(obj.Bars.SymbolName, " is Bullish");
            }
            else
            {
                Print(obj.Bars.SymbolName, " is Bearish");
            }
        }

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

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

The results:


@jumel.donatien

jumel.donatien
29 May 2021, 00:37 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

Ok Guys, I fixed the code by myself! ;)

See the correct code bellow. It allows you to find the Stochastic PercentK and PercentD for each symbol in the array.

The solution was to get the Stochastic's results in the "void Bars_BarOpened" with those two code lines (as you can see in the code bellow):

            var stoc = MarketData.GetBars(TimeFrame, obj.Bars.SymbolName);
            stochastic = Indicators.StochasticOscillator(stoc, 14, 3, 5, MovingAverageType.Simple);

Notice that the stochastic results work only if you respect the code given by PanagiotisCharalampous, code which get bars results symbol by symbol at first.

You can see on the joined picture, the results in the log cbot .

I have now to do the same with Ichimoku.. (maybe harder!)

Do not hesitate to propose another solution if you have!

Thank you!

using System;
using System.Linq;
using System.Text;
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 TEST : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        public Symbol[] MySymbols;

        private StochasticOscillator stochastic;


        protected override void OnStart()
        {
            // We get a symbol array for the following for symbols
            MySymbols = Symbols.GetSymbols("EURUSD", "GBPUSD", "USDJPY", "USDCHF");

            // We subscribe to the bar event for each symbol for the current timeframe
            foreach (var symbol in MySymbols)
            {
                var bars = MarketData.GetBars(TimeFrame, symbol.Name);
                bars.BarOpened += Bars_BarOpened;
            }
        }

        private void Bars_BarOpened(BarOpenedEventArgs obj)
        {
            var stoc = MarketData.GetBars(TimeFrame, obj.Bars.SymbolName);
            stochastic = Indicators.StochasticOscillator(stoc, 8, 3, 9, MovingAverageType.Simple);

            Print("For ", obj.Bars.SymbolName, ": K=", stochastic.PercentK.Last(1), " D=", stochastic.PercentD.Last(1));

            // When a bar opens we check the previous bar. If the bar is bullish, we send a buy order, else we send a sell order.
            if (obj.Bars.Last(1).Close > obj.Bars.Last(1).Open)
            {
                Print(obj.Bars.SymbolName, " is Bullish");
            }
            else
            {
                Print(obj.Bars.SymbolName, " is Bearish");
            }
        }

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

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

Here are the results in the log:


@jumel.donatien