Topics
14 Mar 2021, 17:53
 1806
 17
19 Jan 2021, 18:33
 1002
 4
Replies

prosteel1
09 Sep 2022, 16:39 ( Updated at: 09 Sep 2022, 16:47 )

RE: RE: RE:

jaydcrowe1989 said:

prosteel1 said:

jaydcrowe1989 said:

Hi,

Has anyone used the Fractals indicator and managed to get the latest arrow successfully? So essentially the last one?

Cheers,

Jay

Fractals are a bit strange, technically you need 5 bars to confirm a fractal, with 3 bars since the high or low minimum. I have seen the indicator but have implemented it myself instead in the way I prefer.

I don't like how the indicator works myself

The youtube channel for the inventor of the fractal is youtube.com/c/Profitunity

I know how to use it and I can see it on the chart fine. My problem is when I am trying to use it within a bot I need to get the last value and determine if it was up or down. At the moment it seems like I can get the last up and the last down but not determine what the latest value was.

Can you post the bot code or a link to which one you are using? I could have a look. 


@prosteel1

prosteel1
09 Sep 2022, 16:28 ( Updated at: 09 Sep 2022, 16:33 )

RE:

jaydcrowe1989 said:

Hi,

Has anyone used the Fractals indicator and managed to get the latest arrow successfully? So essentially the last one?

Cheers,

Jay

Fractals are a bit strange, technically you need 5 bars to confirm a fractal, with 3 bars since the high or low minimum. I have seen the indicator but have implemented it myself instead in the way I prefer.

I don't like how the indicator works myself

The youtube channel for the inventor of the fractal is youtube.com/c/Profitunity


@prosteel1

prosteel1
09 Sep 2022, 15:45

RE:

Seems to be a fair bit missing in my opinion for a properly working cbot without all sorts of bugs and strange things going on.

I would like to work with others to produce an open source cbot that actually places trades with stoploss and takeprofit correctly with all the checks to avoid all the pitfalls when things go wrong.

I am open to making this simple cbot using what I have learnt and used from this site, if others are willing to contribute. If we all contributed we could produce an open source sample cbot that works well.

 

The above CalculateRisk method is 2 lines:

protected double CalculateRisk(double stoploss)
        {
            double exactVolume = Symbol.QuantityToVolumeInUnits(Volume);
            return Symbol.NormalizeVolumeInUnits(exactVolume, RoundingMode.ToNearest);
        }

Compare that to what I have (not counting my CalculateMargin and CalculateVolume methods):

private void CalculateRisk()
        {
            PositionRisk = 0.0;
            OrderRisk = 0.0;
            if (Positions.Count > 0)
            {
                Position[] longpositions = Positions.FindAll("Long");
                var longpos = longpositions;
                foreach (var pos in longpos)
                {
                    if (pos.Comment != "" && pos.StopLoss != null && pos.StopLoss < pos.EntryPrice)
                    {
                        double SL = Convert.ToDouble(pos.StopLoss);
                        double posrisk = 0;
                        posrisk = Math.Round((((pos.EntryPrice - SL) / Symbols.GetSymbolInfo(pos.SymbolName).PipSize) * Symbols.GetSymbolInfo(pos.SymbolName).PipValue * pos.VolumeInUnits) - (2 * pos.Commissions) - pos.Swap, 2);
                        Print("pos.SymbolName = " + pos.SymbolName + ", posrisk= " + posrisk);
                        PositionRisk += posrisk;
                    }
                }
                Position[] shortpositions = Positions.FindAll("Short");
                var shortpos = shortpositions;
                foreach (var pos in shortpos)
                {
                    if (pos.Comment != "" && pos.StopLoss != null && pos.StopLoss > pos.EntryPrice)
                    {
                        double SL = Convert.ToDouble(pos.StopLoss);
                        double posrisk = 0;
                        posrisk = Math.Round((((SL - pos.EntryPrice) / Symbols.GetSymbolInfo(pos.SymbolName).PipSize) * Symbols.GetSymbolInfo(pos.SymbolName).PipValue * pos.VolumeInUnits) - (2 * pos.Commissions) - pos.Swap, 2);
                        Print("pos.SymbolName = " + pos.SymbolName + ", posrisk = " + posrisk);
                        PositionRisk += posrisk;
                    }
                }
            }

            if (PendingOrders.Count > 0)
            {
                foreach (var order in PendingOrders)
                {
                    if (order.Comment != "")
                    {
                        var splitted = order.Comment.Split(' ');
                        double ep = Convert.ToDouble(splitted[2]);
                        double sl = Convert.ToDouble(splitted[4]);
                        double tp = Convert.ToDouble(splitted[5]);
                        if (order.TradeType == TradeType.Buy)
                        {
                            double orderrisk = 0;
                            orderrisk = Math.Round((((ep - sl) / Symbols.GetSymbolInfo(order.SymbolName).PipSize) * Symbols.GetSymbolInfo(order.SymbolName).PipValue * order.VolumeInUnits), 2);
                            Print("order.SymbolName = " + order.SymbolName + ", orderrisk = " + orderrisk);
                            OrderRisk += orderrisk;
                        }
                        if (order.TradeType == TradeType.Sell)
                        {
                            double orderrisk = 0;
                            orderrisk = Math.Round((((sl - ep) / Symbols.GetSymbolInfo(order.SymbolName).PipSize) * Symbols.GetSymbolInfo(order.SymbolName).PipValue * order.VolumeInUnits), 2);
                            Print("order.SymbolName = " + order.SymbolName + ", orderrisk = " + orderrisk);
                            OrderRisk += orderrisk;
                        }
                    }
                }
            }
        }

 

I think we are getting to a point in this community where our code is all similar and we should form an opensource focussed group to make good bots rather than the simple examples.

If anyone else is interested please say so!


@prosteel1

prosteel1
07 Sep 2022, 11:57

RE:

moorkirina said:

why was the bot START/STOP button removed from the chart window??? Now you need to waste time to exit the chart, go to the BOT tab and there slap on the button.... I use multiple charts. It got very uncomfortable...

Right Click on Chart > Viewing Options > QuickTrade Buttons

Make sure that is turned on and it should show.


@prosteel1

prosteel1
07 Sep 2022, 11:49

RE:

PanagiotisCharalampous said:

Hi there,

Obviously something has changed in the API between 4.1 and 4.2 but this does not mean it's a bug. But in order to advise where the change is, evaluate if it is a bug or an impreovement, and how address it, I need a small code sample that reproduces the problem. Unfortunately I cannot spend hours undestanding and debugging your code to figure out what is calcuated differently.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Hi Panagiotis and YC1186,

Small code sample below. The following code works, but breaks when the OnBar line is commented out.

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 a2DumptoCSVJan2022Works : Robot
    {
        [Parameter("Periods", Group = "RSI", DefaultValue = 24)]
        public int Periods { get; set; }

        private RelativeStrengthIndex RSI;
        double _RSI;
        
        protected override void OnStart()
        {
            RSI = Indicators.RelativeStrengthIndex(Bars.OpenPrices,Periods);
        }
        
        protected override void OnBar()
        {
            // Comment out following line to produce NaN
            _RSI = RSI.Result.LastValue;
        }

        protected override void OnStop()
        {
            for (var i = Periods; i <= Bars.ClosePrices.Count; i++)
            {
                Print(i + " " + RSI.Result[i-1]);
            }
        }
    }
}

 


@prosteel1

prosteel1
07 Sep 2022, 07:40 ( Updated at: 07 Sep 2022, 07:43 )

RE: RE:

jaydcrowe1989 said:

PanagiotisCharalampous said:

Hi Jay,

This happens when the stop loss falls within the spread. The only solution is to check your positions after opening and handle the situation accordingly.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

Thank you, that makes complete sense. I have noticed there is an overridable method that I can close the trade straight away if it gets triggered and the stop loss is null, so I will use this for now. It does say that this method is obsolete though?

The sloploss and take profit can also be effected by slippage so I first correct for slippage, then for null stoploss and if still not set then close the position.

I store the stoploss etc in the comment  so I can have positions on multiple pairs. 

I don't get obsolete warnings with this.

protected override void OnStart()
        {
            Positions.Opened += PositionsOnOpened;
        }

private void PositionsOnOpened(PositionOpenedEventArgs args)
        {
            var pos = args.Position;
            if (pos.Comment != "" && pos.SymbolName == SymbolName)
            {
                var splitted = pos.Comment.Split(' ');
                int m = Convert.ToInt32(splitted[0]);
                int n = Convert.ToInt32(splitted[1]);
                double ep = Convert.ToDouble(splitted[2]);
                double ch = Convert.ToDouble(splitted[3]);
                double sl = Math.Round((Convert.ToDouble(splitted[4])), Symbol.Digits);
                double tp = Math.Round((Convert.ToDouble(splitted[5])), Symbol.Digits);
                if (pos.Label == "Long")
                    LongTradeSLPrice = sl;

                // Correct any slippage
                if (LongTRFPrice[m] > sl)
                    sl = LongTRFPrice[m];
                // Try to correct stoploss not being set correctly
                if (pos.StopLoss != sl)
                    ModifyPosition(pos, sl, tp);
                // If stoploss still not correct, close position
                if (pos.StopLoss != sl)
                    ClosePosition(pos);
            }

 


@prosteel1

prosteel1
19 Apr 2022, 18:27 ( Updated at: 19 Apr 2022, 19:03 )

RE: RE: RE: RE:

I use PendingOrders.Count and haven't seen an issue in use, it does seem to be updated as soon as an order is placed which seems to get around the delay between when an order is placed and when it is filled. Here is a roughly cropped example which you should be able to paste into your bot: If you can break it I'll be interested ;) But I think this was the solution to preventing multiple orders for me.

So regardless of code execution sequence semantics, if the point is to prevent multiple orders I believe this works because PendingOrders.Count gets updated immediately upon the placing of an order ;)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace NewcBot6
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewcBot6 : Robot
    {
        int LongTradeActive = 0;
        int ShortTradeActive = 0;

        protected override void OnStart()
        {
            Print("OnStart");
            Positions.Opened += PositionsOnOpened;
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnTick()
        {
            // Handle price updates here
            Print("OnTick");
            SetTrade();
        }

        protected override void OnStop()
        {
            // Handle cBot stop here
            Print("OnStop");
        }

        private void SetTrade()
        {
            Print("SetTrade");
            int Longpendingorders = 0;
            int Shortpendingorders = 0;
            var LabelLong = "Long";
            var LabelShort = "Short";

            if (PendingOrders.Count(x => x.Label == LabelLong) > 0)
            {
                foreach (var order in PendingOrders)
                {
                    if (order.SymbolName == SymbolName)
                        Longpendingorders = 1;
                }
            }
            if (PendingOrders.Count(x => x.Label == LabelShort) > 0)
            {
                foreach (var order in PendingOrders)
                {
                    if (order.SymbolName == SymbolName)
                        Shortpendingorders = 1;
                }
            }

            if (LongTradeActive == 0 && Longpendingorders == 0 && Positions.Find(LabelLong, SymbolName) == null && Positions.Find(LabelShort, SymbolName) == null)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, LabelLong);
            }
            
            if (ShortTradeActive == 0 && Shortpendingorders == 0 && Positions.Find(LabelLong, SymbolName) == null && Positions.Find(LabelShort, SymbolName) == null)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000, LabelShort);
            }

        }

        private void PositionsOnOpened(PositionOpenedEventArgs args)
        {
            Print("PositionsOnOpened");
            var pos = args.Position;
            if (pos.SymbolName == SymbolName)
            {
                if (pos.Label == "Long")
                {
                    LongTradeActive = 1;
                }
                if (pos.Label == "Short")
                {
                    ShortTradeActive = 1;
                }
            }
        }

        private void PositionsOnClosed(PositionClosedEventArgs args)
        {
            Print("PositionsOnClosed");
            var pos = args.Position;
            if (pos.SymbolName == SymbolName)
            {
                if (pos.Label == "Long")
                {
                    LongTradeActive = 0;
                }
                if (pos.Label == "Short")
                {
                    ShortTradeActive = 0;
                }
            }
        }
    }
}

 


@prosteel1

prosteel1
04 Jun 2021, 12:52

RE:

By using fractals.DownFractal.Count you can store the bar number in a variable and then check if it is greater than the variable.

I think this makes !double.IsNaN(fractals.DownFractal.Last(0)) not needed, so I removed it too.

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, TimeZone = TimeZones.UTC)]

    public class SKYPIPS6MAscrossCHAOS : Robot
    {
        private bool _position;
        private MovingAverage ma1;
        private MovingAverage ma2;
        private MovingAverage ma3;
        private MovingAverage ma4;
        private MovingAverage ma5;
        private MovingAverage ma6;
        private RelativeStrengthIndex rsi;
        private Fractals fractals;

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

        [Parameter("Take Profit", DefaultValue = 15, Step = 5)]
        public double Takeprofit { get; set; }

        [Parameter("Stop Loss", DefaultValue = 5, Step = 5)]
        public double Stoploss { get; set; }

        [Parameter("Fractals", DefaultValue = 5)]
        public int fractalsperiod { get; set; }

        [Parameter("RSI Periods", DefaultValue = 4)]
        public int Periods { get; set; }

        [Parameter("MA 1 Period", DefaultValue = 5, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA1Period { get; set; }

        [Parameter("MA 2 Period", DefaultValue = 8, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA2Period { get; set; }

        [Parameter("MA 3 Period", DefaultValue = 13, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA3Period { get; set; }
        [Parameter("MA 4 Period", DefaultValue = 21, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA4Period { get; set; }
        [Parameter("MA 5 Period", DefaultValue = 48, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA5Period { get; set; }

        [Parameter("MA 6 Period", DefaultValue = 150, MaxValue = 500, MinValue = 0, Step = 1)]
        public int MA6Period { get; set; }

        [Parameter("Volume", DefaultValue = 10000, MinValue = 0)]
        public int Volume { get; set; }

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }


        [Parameter("Hour To Hour", DefaultValue = false)]
        public bool HourToHour { get; set; }
        [Parameter("Start Hour", DefaultValue = 8, MaxValue = 23)]
        public int StartHour { get; set; }
        [Parameter("Stop Hour", DefaultValue = 18, MaxValue = 23)]
        public int StopHour { get; set; }
        private bool c_hour = true;
        private bool st_45 = true;

        // Added a counter
        int downfractalcount;
        int upfractalcount;



        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(Source, Periods);
            ma1 = Indicators.MovingAverage(Source, MA1Period, MAType);
            ma2 = Indicators.MovingAverage(Source, MA2Period, MAType);
            ma3 = Indicators.MovingAverage(Source, MA3Period, MAType);
            ma4 = Indicators.MovingAverage(Source, MA4Period, MAType);
            ma5 = Indicators.MovingAverage(Source, MA5Period, MAType);
            ma6 = Indicators.MovingAverage(Source, MA6Period, MAType);

            fractals = Indicators.Fractals(fractalsperiod);

            // Write the last fractal counts
            downfractalcount = fractals.DownFractal.Count;
            upfractalcount = fractals.UpFractal.Count;
        }


        protected override void OnBar()
        {
            //Print("Down " + fractals.DownFractal.Count);
            //Print("Up " + fractals.UpFractal.Count);
            c_hour = GetTradingHour();

            if (Trade.IsExecuting)
                return;

            var buy_position = Positions.Find("BUY", SymbolName);
            var sell_position = Positions.Find("SELL", SymbolName);

            if (buy_position == null && sell_position == null)
                _position = true;
            else
                _position = false;
            // Added a check for a later fractal count
            if (_position && fractals.DownFractal.Count > downfractalcount && (ma1.Result.Last(0) > ma2.Result.Last(0) && ma2.Result.Last(0) > ma3.Result.Last(0)) && c_hour && st_45 && Bars.ClosePrices.Last(1) > ma2.Result.Last(1))
            {
                Print(fractals.DownFractal.Count + " Buy, " + fractals.DownFractal.Last(0) + " " + !double.IsNaN(fractals.DownFractal.Last(0)));
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, "BUY", Stoploss, Takeprofit);
                _position = false;
            }
            // Added a check for a later fractal count
            if (_position && fractals.UpFractal.Count > upfractalcount && (ma1.Result.Last(0) < ma2.Result.Last(0) && ma2.Result.Last(0) < ma3.Result.Last(0)) && c_hour && st_45 && Bars.ClosePrices.Last(1) < ma2.Result.Last(1))
            {
                Print(fractals.UpFractal.Count + " Sell, " + fractals.UpFractal.Last(0) + " " + !double.IsNaN(fractals.UpFractal.Last(0)));
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, "SELL", Stoploss, Takeprofit);
                _position = false;
            }

            // Update the count of the last fractals
            downfractalcount = fractals.DownFractal.Count;
            upfractalcount = fractals.UpFractal.Count;


        }


        //+------------------------------------------------------------------+
        //| Get Trading hour                                                 |
        //+------------------------------------------------------------------+
        private bool GetTradingHour()
        {
            bool h_res = true;
            if (HourToHour)
            {
                if (StartHour != StopHour)
                {
                    if ((StopHour > StartHour && Time.Hour >= StartHour && Time.Hour < StopHour) || (StartHour > StopHour && (Time.Hour >= StartHour || Time.Hour < StopHour)))
                        h_res = true;
                    else
                        h_res = false;
                }
                else
                {

                    st_45 = false;
                    h_res = false;
                }
            }
            return (h_res);
        }
    }
}

 


@prosteel1

prosteel1
25 Mar 2021, 12:19 ( Updated at: 25 Mar 2021, 12:57 )

RE: RE:

prosteel1 said:

Upgrading to Windows 10 64bit seems to have resolved the errors. The above code runs fine down to Tick2, and gets most of the way on Tick1 before cTrader becomes very slow and unresponsive, however on the last test after all windows updates were installed it did complete! Yay!

I never expected cTrader to run differently on Windows 10 32bit, but Windows 64bit uses the same license so just needed a clean install. 

 

The slow and unresponsive part may have been due to a lack of ram. I doubled the ram due to excessive disk usage from page file writes and almost halved the time it took to do a full backtest. While this was completed on my full cbot running on 8 timeframes in the one cbot down to Tick6, this same excessive page file usage may have been the cause of slowness during the above test. While I still did see lots of pagefile writes, I did see an improvement which when added to the improvement from moving to 64bit windows 10 makes a good case for using 64bit windows 10 with lots of ram.

The difference I have seen running cTrader on 64bit Windows 10 compared to 32bit Windows 10 when doing long term backtesting is like night and day.

 

Conclusion: The errors I encountered were due to the limitations of 32bit Windows: Don't use 32bit Windows 10 for cTrader if your doing long term Backtesting and perhaps Optimization where the number of bars could exceed 1 million. Use 64bit Windows 10.  I note that https://www.cygwin.com/ does not recommend 32bit Windows and after spending the last 2 weeks figuring out the cause of #62080512 #62082701 & #62086147, this is probably something that should be considered - "Address space is a very limiting factor for Cygwin. These days, a full 32 bit Cygwin distro is not feasible anymore, and will in all likelihood fail in random places due to an issue with the fork(2) system call. Therefore we recommend using 32 bit Cygwin only in limited scenarios, with only a minimum of necessary packages installed, and only if there's no way to run 64 bit Cygwin instead."


@prosteel1

prosteel1
23 Mar 2021, 11:25

RE:

Upgrading to Windows 10 64bit seems to have resolved the errors. The above code runs fine down to Tick2, and gets most of the way on Tick1 before cTrader becomes very slow and unresponsive, however on the last test after all windows updates were installed it did complete! Yay!

I never expected cTrader to run differently on Windows 10 32bit, but Windows 64bit uses the same license so just needed a clean install. 

 


@prosteel1

prosteel1
22 Mar 2021, 16:09 ( Updated at: 22 Mar 2021, 16:13 )

I am currently testing a second identical windows 10 32bit desktop computer hardware wise. This will eliminate software effects. After that I will reinstall windows as 64bit and test again. This should prove a great test as to whether a 64bit OS has the proposed effect on the max number of bars accessible by a bot during backtesting. I should have results in about 30 hours.


@prosteel1

prosteel1
22 Mar 2021, 10:08 ( Updated at: 21 Dec 2023, 09:22 )

RE:

prosteel1 said:

Further testing suggests this error occurs on 32bit Windows 10 but perhaps not on 64bit Windows server 2019. Strange...

While I prepare to upgrade my 32bit system to 64bit, I've been able to replicate the error on a vps running Server 2019 64bit by running the bot on Tick1.

USDJPY crashes on bar 65,532,919 and AUDUSD crashes on 65,534,350 so the same behavior exists where there is a limit to the number of bars able to be accessed.

 

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 error : Robot
    {

        [Parameter("Timeframe", DefaultValue = "Tick10")]
        public TimeFrame tf { get; set; }

        Bars series;
        long BarLast;

        protected override void OnStart()
        {
            series = MarketData.GetBars(tf);
            BarLast = series.Count - 2;
        }
        protected override void OnStop()
        {
        }

        protected override void OnTick()
        {
            if (series.Count - 2 > BarLast)
            {
                BarLast = series.Count - 2;
                if (BarLast > 65500000)
                    Print(BarLast);
            }
        }
    }
}

 


@prosteel1

prosteel1
19 Mar 2021, 09:20

Further testing suggests this error occurs on 32bit Windows 10 but perhaps not on 64bit Windows server 2019. Strange...


@prosteel1

prosteel1
18 Mar 2021, 12:15 ( Updated at: 18 Mar 2021, 14:23 )

RE:

PanagiotisCharalampous said:

Hi prosteel1,

Unfortunately source code did not help reproducing this issue. Can you please send us some troubleshooting information the next time this happens? To do so, press Ctrl+Alt+Shift+T, paste a link to this discussion in the text box that will appear and press submit.

Best Regards,

Panagiotis 

Join us on Telegram

I'm not sure how the troubleshooting works. I ran it after the first error, then ran the bot again and just closed it, thinking it might record what happens while it runs?

I have had 100% success triggering this error with the below code and the mentioned settings earlier and shown in the screenshot for clarity. There is definetely a limit in backtesting to not be able to reference more than 1,024,000 bars on any timeframe. I have not seen this in realtime.Mode where I used Load more history to load over 15,000,000 Tick6 bars.

Please try this code with the settings I showed in the screenshot as it has never failed over about 50 tests. It does take a long tome to load the tick data for the whole period. If you didn't want to wait so long 1 or 2 years should load over the 1,024,000 bars required to throw the error.

The main issue is that I can't backtest below Tick60 over this long time period without this error being thrown, because anything below Tick60 (on AUD/USD) has more than 1,024,000 bars (EUR/USD will likely error at higher tick time frames). It's only after spending such a large amount of time testing this error that I now know the current limitations. 

 

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 error62082701 : Robot
    {

        [Parameter("Timeframe", DefaultValue = "Tick6")]
        public TimeFrame tf { get; set; }

        Bars series;
        long BarLast;

        protected override void OnStart()
        {
            series = MarketData.GetBars(tf);
            BarLast = series.Count - 2;
        }
        protected override void OnStop()
        {
        }

        protected override void OnTick()
        {
            if (series.Count - 2 > BarLast)
            {
                BarLast = series.Count - 2;
                if (BarLast > 900000)
                    Print(BarLast);
            }
        }
    }
}

 


@prosteel1

prosteel1
18 Mar 2021, 09:37 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi prosteel1,

Unfortunately source code did not help reproducing this issue. Can you please send us some troubleshooting information the next time this happens? To do so, press Ctrl+Alt+Shift+T, paste a link to this discussion in the text box that will appear and press submit.

Best Regards,

Panagiotis 

Join us on Telegram

It's submitting at the moment. I used the error62032701 cbot above. The default cbot didn't trigger it, so I might have been wrong on the default cbot.

Here is a screenshot to show the settings I used.


@prosteel1

prosteel1
18 Mar 2021, 02:40 ( Updated at: 18 Mar 2021, 10:19 )

RE:

The #62082701 error occurs when chart time frame is time based and the number of bars on a tick timeframe is just under 1,024,000

With the chart time frame set to daily, Visual mode enabled and changing the parameter timeframe, the last printed value of BarLast before the error was as below:

Parameter, BarLast

Tick1, 1021973

Tick6, 1023755

Tick10, 1023983

Tick20, 1023990

Tick50, 1023996

So looks like there is a limit on the number of Tick bars when the chart time frame is set to a time based timeframe and the cbot references a tick based timeframe. Resulting in an internal overflow of some sort. I haven't yet been able to reproduce the other error: #62080512

 

The #62086147 error occurs when chart time frame is tick based and the number of bars on a tick timeframe is just under 1,024,000

Changing the chart time frame, Visual mode enabled with the parameter timeframe set to Tick1, the last printed value of BarLast before the error was as below:

Chart, Parameter, BarLast

Tick1000, Tick1, 1023407

Tick100, Tick1, 1021973

Tick10, Tick1, 1023873

Tick1, Tick1, 1021973

So looks like there is also a limit on the number of Tick bars when the chart time frame is set to a Tick based timeframe and the cbot references a tick based timeframe. Resulting in an internal overflow of some sort.

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 error62082701 : Robot
    {

        [Parameter("Timeframe", DefaultValue = "Tick10")]
        public TimeFrame tf { get; set; }

        Bars series;
        long BarLast;

        protected override void OnStart()
        {
            series = MarketData.GetBars(tf);
            BarLast = series.Count - 2;
        }
        protected override void OnStop()
        {
        }

        protected override void OnTick()
        {
            if (series.Count - 2 > BarLast)
            {
                BarLast = series.Count - 2;
                if (BarLast > 900000)
                    Print(BarLast);
            }
        }
    }
}

 

Simplifing to a new cbot with no extra code and setting the chart timeframe to Tick 6 or similar and backtesting from 11/11/2012 also produces the error #62082701.

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; }

        protected override void OnStart()
        {
            // Put your initialization logic here
        }

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

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

 


@prosteel1

prosteel1
17 Mar 2021, 16:04 ( Updated at: 18 Mar 2021, 10:20 )

RE:

This produces the error #62082701 when backtesting from 11/11/2012 to present. using tick data from server (accurate) with visual mode turned off.

The chart timeframe is separate to the timeframe set in the parameters.

Errors occur using the following combinations of chart and parameter timeframes:

Chart, Parameter

Hour, Tick10

Daily, Tick10

Daily, T6

Minute, Tick100

No errors using the following combinations of chart and parameter timeframes:

Chart, Parameter

Hour, Tick100

Daily, Tick50

Daily, Tick60

Daily, Tick100

Tick1000, Tick100

Tick750, Tick100

 

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 error62082701 : Robot
    {

        [Parameter("Timeframe", DefaultValue = "Tick10")]
        public TimeFrame tf { get; set; }

        Bars series;
        int BarLast;

        protected override void OnStart()
        {
            series = MarketData.GetBars(tf);
            BarLast = series.Count - 3;
        }
        protected override void OnStop()
        {
        }

        protected override void OnTick()
        {
            if (series.Count - 3 > BarLast)
            {
                BarLast = series.Count - 3;
            }
        }
    }
}

 


@prosteel1

prosteel1
16 Mar 2021, 10:06

RE:

PanagiotisCharalampous said:

Hi prosteel1,

Can you provide us with the source code to reproduce this behavior?

Best Regards,

Panagiotis 

Join us on Telegram

Do you have any information on the potential cause of the error codes #62082701 & #62080512 ?


@prosteel1

prosteel1
16 Mar 2021, 09:53

RE:

PanagiotisCharalampous said:

Hi prosteel1,

Can you provide us with the source code to reproduce this behavior?

Best Regards,

Panagiotis 

Join us on Telegram

Yes, I think a few more days and I will be able to replicate the behavior in a simple cbot. I'll send it to you in Telegram.


@prosteel1

prosteel1
15 Mar 2021, 22:38 ( Updated at: 15 Mar 2021, 22:47 )

RE: RE: RE: RE:

rsoudani said:

prosteel1 said:

amusleh said:

rsoudani said:

Hi, i'm working on my own strategy, looks good on demo account and on firts live tests, but i can not backtest it because i need low spreads, and i have raw spread account on icmarkets, but for backtesting in cTrader i can only get tickdata from server where i cant choose spread and it seems to be much to high (i need tick data not bar data). Do you have any suggestions?

Hi,

The tick data is from your broker price feed, you can try other brokers cTrader for backtesting and using their tick data. 

I use a condition to check if the channel height (ChHt) is large enough compared to the spread: (ChHt > 2 * (Symbol.Ask - Symbol.Bid))

This eliminates charts during high spread events like on the market open in order to ensure there is a small of risk to return. I also keep track of the channel height of successful trades during a backtest and store the highest value which is also used as a check to eliminate big gaps creating huge charts that block trades. I run a backtest once to get the highest chart height and then run it a second time so that huge charts resulting from gaps are eliminated the second time I do a backtest.

I love ICMarkets data fyi.  From what I have seen it looks like the live spread when using the backtesting setting > Data > 'Tick data from server (accurate') does provide accurate spread, but I haven't verified it. I use the above methods to eliminate high spreads so I don't trade them.

There might be other methods to eliminating trading during high spreads, these are what I use.

Are you running your bot using OnTick() as opposed to OnBar()? Running OnBar() instread of OnTick() might result in what you are describing.

Are you consistantly using Symbol.Bid and Symbol.Ask instead of LastBar.High or whatever the old crew use now days. When you are targeting spread as a metric and running OnTick, Symbol.Bid and Symbol.Ask is where it needs to be to use the tick data and thus get the accurate spread. I struggled with this for a while too.

 

Thank you for the answer! I use both OnBar and OnTick methods in my code, and I use Symbol.Bid and Symbol.Ask as you suggest but did not take channel height into account. For the sake of clarity, could you please specify how do you calculate / where you get channel height?

Hi rsoudani,

              Nice! seems you are asking the right questions and coding using the right tools too. 

              I've been trying to find a good video to explain my method but can't find one atm. I'll keep looking for a good example, this one might suffice and explains the current moves on EUR/USD. Need to turn on closed captions and set the autotranslation to your language. 

 Basically, a channel is a consolidation channel - a move from a high to a low or visaversa. Since this is how I construct my chart heights it makes sense to discount charts when the spread is very high. As when I try to trade on charts when the spread is very high I usually get stopped out very quickly - so now I prevent most of those.

It's largely a matter of if the spread is larger than a percentage of  risk (also known as the potential loss or return - it doesn't make sense to be entering a trade where for a long trade, if the bid is at the entry level and the ask is at the take profit 2 level, we enter and immediately get profit stopped for zero profit - so we start with a sanity check and extend it to make sure the bot doesn't make silly trades :)


@prosteel1