Replies

findsameh
16 Apr 2021, 16:28 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi Sameh,

The discussion is very general and I cannot help you without knowing what you are looking at. To help you more you will need to provide us with information that will allow us to reproduce what you are looking at. We need to know the following

  1. The cBot code you are using
  2. cBot parameters and backtesting dates
  3. Screenshots showing the discrepancies.

Best Regards,

Panagiotis 

Join us on Telegram

I think sharing the bot code won't be useful at this point since we know now the historical prices do differ. You'll get different results if you backtested the bot I referred to in the first message. The difference varies from one bot to another. And do you think any change in code can cancel out the differences when the underlying data is not identical?

Here's what I can share for now (the screenshots).


@findsameh

findsameh
16 Apr 2021, 15:04

RE:

 

Not necessarily.

Best Regards,

Panagiotis 

Join us on Telegram

So basically, for the sake of this argument, if I test a bot and get a return of 110% on a live account and get 60% on the demo account; then I cannot know which result is more in line with the "real" historical prices because we don't really know what the real prices are? Just give me something in order to know how to adjust my results in accordance with this difference. I'm sure you'd agree that a return of 110% and 60% is quite a considerable discrepancy.


@findsameh

findsameh
16 Apr 2021, 13:56

RE:

PanagiotisCharalampous said:

Hi Sameh,

There are many reasons that can cause such a behavior different price feeds, different backtesting setup etc. You should check your backtesting results and figure out where are the differences. That would provide you with clues regarding the reason behind this.

Best Regards,

Panagiotis 

Join us on Telegram

But isn't the price feed the same for both accounts? And backtesting setup and parameters are all exactly the same. All I do is switch from demo to real account.


@findsameh

findsameh
31 Mar 2021, 12:14

RE: RE: RE:

amusleh said:

findsameh said:

Hello Ahmad,

Thanks for the suggestion. But with your suggested solution if you compare the result through the indicator code (Result[index]) and compare it to the result through the bot (crsi.Result[index]), you'd find that both values still don't match.

And I'm not sure why I'd need to change the indicator code to retrieve a value from indicator to bot, knowing the indicator already produces the correct values for CRSI.

Sameh

There was some issues in your indicator code, that causes issues when you use it on a cBot, like using invalid bar index.

I checked the indicator and cBot I posted and the results does match on backtest for EURUSD on Spotware cTrader beta.

Apologies, my mistake ... they do match. Thanks a lot.

Sameh


@findsameh

findsameh
30 Mar 2021, 22:05

RE:

Hello Ahmad,

Thanks for the suggestion. But with your suggested solution if you compare the result through the indicator code (Result[index]) and compare it to the result through the bot (crsi.Result[index]), you'd find that both values still don't match.

And I'm not sure why I'd need to change the indicator code to retrieve a value from indicator to bot, knowing the indicator already produces the correct values for CRSI.

Sameh


@findsameh

findsameh
28 Mar 2021, 14:51

RE:

Dear Ahmad, 

Neither index-1 nor Last(1) work, both return numbers not matching any of the correct results. Below is the CRSI indicator code, followed by a simple bot to retrieve the results.

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ConnorsCRSI11 : Indicator
    {
        [Output("Main", Color = Colors.Orange)]
        public IndicatorDataSeries Result { get; set; }
        [Parameter(DefaultValue = 3.0)]
        public int rsiPeriods { get; set; }
        [Parameter(DefaultValue = 2.0)]
        public int streakPeriods { get; set; }
        [Parameter(DefaultValue = 100.0)]
        public int rocPeriods { get; set; }

        public RelativeStrengthIndex rsi;
        public int streak;
        public double avgGain1;
        public double avgLoss1;
        public double avgGain;
        public double avgLoss;
        public double rsiStreakValue = 0;
        public List<double> listOfAvgGain = new List<double>();
        public List<double> listOfAvgLoss = new List<double>();
        public List<double> listOfGain = new List<double>();
        public List<double> listOfLoss = new List<double>();
        public List<int> listOfStreaks = new List<int>();
        public int startIndex;
        public double percentRank = 0.0;

        protected override void Initialize()
        {
            rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, rsiPeriods);
            startIndex = 1;
        }
        public override void Calculate(int index)
        {
            UpDownStreak(streakPeriods, index + 1);
            RsiStreak(streakPeriods, index);
            Roc(rocPeriods, index);
            Result[index] = (rsiStreakValue + rsi.Result.LastValue + percentRank) / 3;

        }
        // crsi calculations
        public void Roc(double periods, int index)
        {
            var countRocDn = 0;
            var prevDayRoc = 0.0;
            var todayRoc = (Bars.ClosePrices[index] - Bars.ClosePrices[index - 1]) / Bars.ClosePrices[index - 1];
            for (int i = 1; i <= periods; i++)
            {
                prevDayRoc = (Bars.ClosePrices[index - i] - Bars.ClosePrices[index - i - 1]) / Bars.ClosePrices[index - i - 1];
                if (todayRoc > prevDayRoc)
                    countRocDn++;
            }
            percentRank = (countRocDn / periods) * 100;
        }
        public void UpDownStreak(int periods, int index)
        {
            int countUp = 0;
            int countDn = 0;
            int countEqual = 0;
            for (int i = 1; i < 100; i++)
                if (Bars.ClosePrices[index - i] > Bars.ClosePrices[index - i - 1])
                {
                    countUp++;
                    continue;
                }
                else
                    break;
            for (int i = 1; i < 100; i++)
                if (Bars.ClosePrices[index - i] < Bars.ClosePrices[index - i - 1])
                {
                    countDn++;
                    continue;
                }
                else
                    break;
            for (int i = 1; i < 100; i++)
                if (Bars.ClosePrices[index - i] == Bars.ClosePrices[index - i - 1])
                {
                    countEqual++;
                    continue;
                }
                else
                    break;
            if (countUp > countDn && countUp > countEqual)
            {
                streak = countUp;
                listOfStreaks.Add(countUp);
            }
            else if (countDn > countUp && countDn > countEqual)
            {
                streak = -countDn;
                listOfStreaks.Add(-countDn);
            }
            else if (countEqual > countUp && countEqual > countDn)
            {
                streak = 0;
                listOfStreaks.Add(0);
            }
            if (listOfStreaks.Count > periods)
                listOfStreaks.RemoveAt(0);
        }
        public void RsiStreak(int periods, int index)
        {
            if (listOfStreaks.Count < periods)
                return;
            double changeValue = 0;
            double rs = 0;
            List<double> listOfChangeValues = new List<double>();
            for (int i = 0; i < periods - 1; i++)
            {
                changeValue = listOfStreaks[i + 1] - listOfStreaks[i];
                if (changeValue > 0)
                {
                    listOfGain.Add(changeValue);
                    listOfLoss.Add(0);
                }
                else
                {
                    listOfLoss.Add(Math.Abs(changeValue));
                    listOfGain.Add(0);
                }
            }
            if (1 == startIndex)
            {
                avgGain1 = listOfGain.Average();
                avgLoss1 = listOfLoss.Average();
                listOfAvgGain.Add(avgGain1);
                listOfAvgLoss.Add(avgLoss1);
            }
            else
            {
                avgGain = ((listOfAvgGain[listOfAvgGain.Count - 1] * (periods - 1)) + listOfGain[listOfGain.Count - 1]) / periods;
                avgLoss = ((listOfAvgLoss[listOfAvgLoss.Count - 1] * (periods - 1)) + listOfLoss[listOfLoss.Count - 1]) / periods;
                listOfAvgGain.Add(avgGain);
                listOfAvgLoss.Add(avgLoss);
            }
            if (1 == startIndex)
            {
                startIndex = 2;
                rs = avgGain1 / avgLoss1;
                if (avgLoss1 == 0)
                    rsiStreakValue = 100;
                else
                    rsiStreakValue = 100 - (100 / (1 + rs));
            }
            else
            {
                rs = avgGain / avgLoss;
                if (avgLoss == 0)
                    rsiStreakValue = 100;
                else
                    rsiStreakValue = 100 - (100 / (1 + rs));
            }
            if (listOfLoss.Count >= periods)
                listOfLoss.RemoveAt(0);
            if (listOfGain.Count >= periods)
                listOfGain.RemoveAt(0);
            if (listOfAvgGain.Count >= periods)
                listOfAvgGain.RemoveAt(0);
            if (listOfAvgLoss.Count >= periods)
                listOfAvgLoss.RemoveAt(0);
            if (listOfStreaks.Count >= periods)
                listOfStreaks.RemoveAt(0);
        }
    }
}
===========

Bot to retrieve results:

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 cBotNew : Robot
    {
        [Parameter("RSI periods", Group = "CRSI", DefaultValue = 3.0, MinValue = 1)]
        public int rsiPeriods { get; set; }
        [Parameter("Up/down streak periods", Group = "CRSI", DefaultValue = 2.0, MinValue = 1)]
        public int streakPeriods { get; set; }
        [Parameter("Rate of change periods", Group = "CRSI", DefaultValue = 100.0, MinValue = 2)]
        public int rocPeriods { get; set; }

        public ConnorsCRSI11 crsi;

        protected override void OnStart()
        {
            crsi = Indicators.GetIndicator<ConnorsCRSI11>(rsiPeriods, streakPeriods, rocPeriods);
        }
        protected override void OnBar()
        {
            Print(crsi.Result.Last(1));
        }
    }
}
===========

Thanks,

Sameh


@findsameh

findsameh
14 Sep 2020, 10:47

RE:

PanagiotisCharalampous said:

Hi findsameh,

Here is the correct way to do this.

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            var trade = History.Where(x => x.PositionId == args.Position.Id).First();
            Print("Pos ID: {0} ... Close Time: {1}", trade.PositionId, TimeInUtc);
        }

Best Regards,

Panagiotis 

Join us on Telegram 

Hello Panagiotis,

This is perfect! Thank you very much.

Best regards,

Sameh


@findsameh

findsameh
14 Sep 2020, 10:29 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

findsameh said:

PanagiotisCharalampous said:

Hi Sameh,

I asked for the cBot code so that I can reproduce what you are seeing. I cannot reproduce such an issue with the cBot you posted. See below

Best Regards,

Panagiotis 

Join us on Telegram 

These are the results I got. Meaning the date/time of trade has something to do with it.

Hello Panagiotis,

Any thoughts on this? As I mentioned on Friday, if you can fix the issue with the bot I shared, I can apply it mine. The issue arises at certain dates/times and it doesn't on others, as shown in my last post.

Thanks,

Sameh


@findsameh

findsameh
11 Sep 2020, 14:32 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi Sameh,

I asked for the cBot code so that I can reproduce what you are seeing. I cannot reproduce such an issue with the cBot you posted. See below

Best Regards,

Panagiotis 

Join us on Telegram 

These are the results I got. Meaning the date/time of trade has something to do with it.


@findsameh

findsameh
11 Sep 2020, 14:12

RE:

PanagiotisCharalampous said:

Hi findsameh,

That's not what I meant. You assume that the last deal is the deal associated to the position which might not always be true. The right way is to make sure that the printed deal is the closing deal of the associated position. If you post the complete code, I can try and fix this for you.

Best Regards,

Panagiotis 

Join us on Telegram 

I can't see the point in sharing the code for the whole bot, which I can't.

Instead, something as simple as this has the same issue, I can apply your fix on my bot.

using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        int barCounter;
        protected override void OnStart()
        {
            Positions.Closed += OnPositionsClosed;
        }
        protected override void OnBar()
        {
            barCounter++;
            if (barCounter == 1)
            {
                ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000, "label", 10, 10);
            }
            if (barCounter == 2)
            {
                ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000, "label", 10, 10);
            }
            if (barCounter == 5)
            {
                foreach (var pos in Positions)
                {
                    ClosePosition(pos);
                }
            }
        }
        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            var lastTrade = History[History.Count - 1];
            Print("Pos ID: {0} ... Close Time: {1}", lastTrade.PositionId, TimeInUtc);
        }
    }
}

Thanks,

Sameh


@findsameh

findsameh
11 Sep 2020, 13:43 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi findsameh,

It would be better to use the associated PositionID to make the association instead of the index.

Best Regards,

Panagiotis 

Join us on Telegram 

Dear Panagiotis, 

I used the "better" approach, but that didn't work either:

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            var position = args.Position;
            var lastTrade = History[History.Count - 1];
            Print("Pos ID: {0} ... Close Time: {1}", lastTrade.PositionId, TimeInUtc);
        }

Is there a "right" way as opposed to a "better" way?


@findsameh

findsameh
11 Sep 2020, 12:42 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi findsameh,

The position id is not the same with the closing deal id that is displayed in History. You are associating different trades.

Best Regards,

Panagiotis 

Join us on Telegram 

 

Dear Panagiotis,

Thank you for your reply. I tried to associate ID with Closing Deal ID with this:

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            var position = args.Position;
            var lastTrade = History[History.Count - 1];
            Print("Pos ID: {0} ... Close Time: {1}", lastTrade.ClosingDealId, TimeInUtc);
        }

But again when there are 2 positions (13 & 14) closing at the same time, only the latter position's Closing Deal ID is returned (14) for both 13 & 14, as shown in attached.

Pls let me know what can be done.

Thanks,

Sameh


@findsameh

findsameh
16 Jun 2020, 22:21

RE: RE:

findsameh said:

PanagiotisCharalampous said:

Hi Sameh,

Can you post a cBot that reproduces these crashes so that we can check?

Best Regards,

Panagiotis 

Join us on Telegram

 

Dear Panagiotis,

Thank you for your reply. Here's a part of the bot that generates the high number of events (under Events tab) which will eventually cause a crash or a freeze of the platform until the events list is populated, This will be reproduced best when running the default parameters for a 2 year backtest or more.

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class toTest : Robot
    {
        [Parameter("Volume", Group = "Trade Parameters", DefaultValue = 10000)]
        public int volume { get; set; }
        [Parameter("Max positions", Group = "Trade Parameters", DefaultValue = 1, MinValue = 0)]
        public int maxPos { get; set; }
        [Parameter("SL (pips)", Group = "Trade Parameters", DefaultValue = 20, MinValue = 0)]
        public double sl { get; set; }
        [Parameter("TP (pips)", Group = "Trade Parameters", DefaultValue = 20, MinValue = 0)]
        public double tp { get; set; }
        [Parameter("No. of evaluated bars", Group = "Trade Parameters", DefaultValue = 30, MinValue = 6)]
        public int evaluatedBars { get; set; }
        [Parameter("Modify SL & TP?", Group = "Modify Stop Loss & Take Profit", DefaultValue = true)]
        public bool modifySlTp { get; set; }
        [Parameter("ATR (14) multiplier", Group = "Modify Stop Loss & Take Profit", DefaultValue = 1)]
        public double atrMultiplier { get; set; }

        string botLabel = "Bot_test";
        private List<double> listOfResPoints = new List<double>();
        private List<double> listOfSupPoints = new List<double>();
        AverageTrueRange atr;
        SimpleMovingAverage sma;
        int countModifiedTpSl;
        double currentAskOnTick;
        double currentBidOnTick;
        double newTp;
        double newSl;

        protected override void OnStart()
        {
            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            sma = Indicators.SimpleMovingAverage(Bars.ClosePrices, 14);
        }
        protected override void OnTick()
        {
            currentAskOnTick = Symbol.Ask;
            currentBidOnTick = Symbol.Bid;
            Trades();
            // modifies sl & tp
            if (modifySlTp == true)
            {
                ModifyStopLossTakeProfit();
            }
        }
        private void ModifyStopLossTakeProfit()
        {
            foreach (var _pos in Positions)
            {
                if (_pos.TradeType == TradeType.Buy)
                {
                    newTp = currentBidOnTick + (atr.Result.LastValue * atrMultiplier);
                    newSl = currentBidOnTick - (atr.Result.LastValue * atrMultiplier);
                    _pos.ModifyTakeProfitPrice(newTp);
                    _pos.ModifyStopLossPrice(newSl);
                    countModifiedTpSl++;
                }
                else
                {
                    newTp = currentAskOnTick - (atr.Result.LastValue * atrMultiplier);
                    newSl = currentAskOnTick + (atr.Result.LastValue * atrMultiplier);
                    _pos.ModifyTakeProfitPrice(newTp);
                    _pos.ModifyStopLossPrice(newSl);
                    countModifiedTpSl++;
                }
            }
        }
        private void Trades()
        {
            if (Positions.Count >= maxPos)
                return;
            var currentResValue = ResLineValue(evaluatedBars);
            var currentSupValue = SupLineValue(evaluatedBars);
            List<double> listOfHighs = new List<double>();
            List<double> listOfLows = new List<double>();

            for (int i = 5; i <= evaluatedBars; i++)
            {
                listOfHighs.Add(Bars.HighPrices.Last(i));
                listOfLows.Add(Bars.LowPrices.Last(i));
            }
            // opens long position
            if (currentBidOnTick > currentResValue &&
                sma.Result.IsRising())
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, botLabel, sl, tp);
            }
            else
            // opens short position
            if (currentBidOnTick < currentSupValue &&
                sma.Result.IsFalling())
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, botLabel, sl, tp);
            }
            listOfHighs.Clear();
            listOfLows.Clear();
        }
        // resistance lines
        private double ResLineValue(int evaluatedBars)
        {
            listOfResPoints.Clear();
            for (int i = 5; i < evaluatedBars + 5; i++)
            {
                var resPoint = Bars.HighPrices.Last(i);
                // populates resistance points
                listOfResPoints.Add(resPoint);
            }
            var resLine = listOfResPoints.Max();
            return resLine;
        }
        // support lines
        private double SupLineValue(int evaluatedBars)
        {
            listOfSupPoints.Clear();
            for (int i = 5; i < evaluatedBars + 5; i++)
            {
                var supPoint = Bars.LowPrices.Last(i);
                // populates support points
                listOfSupPoints.Add(supPoint);
            }
            var supLine = listOfSupPoints.Min();
            return supLine;
        }
        protected override void OnStop()
        {
            Print("No. of times SL & TP modified: {0}", countModifiedTpSl);
        }
    }
}

 

Dear Panagiotis,

Pls let me know if there's a way to fix the above.

Thank you,

Sameh


@findsameh

findsameh
11 Jun 2020, 08:10

RE:

PanagiotisCharalampous said:

Hi Sameh,

Can you post a cBot that reproduces these crashes so that we can check?

Best Regards,

Panagiotis 

Join us on Telegram

 

Dear Panagiotis,

Thank you for your reply. Here's a part of the bot that generates the high number of events (under Events tab) which will eventually cause a crash or a freeze of the platform until the events list is populated, This will be reproduced best when running the default parameters for a 2 year backtest or more.

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class toTest : Robot
    {
        [Parameter("Volume", Group = "Trade Parameters", DefaultValue = 10000)]
        public int volume { get; set; }
        [Parameter("Max positions", Group = "Trade Parameters", DefaultValue = 1, MinValue = 0)]
        public int maxPos { get; set; }
        [Parameter("SL (pips)", Group = "Trade Parameters", DefaultValue = 20, MinValue = 0)]
        public double sl { get; set; }
        [Parameter("TP (pips)", Group = "Trade Parameters", DefaultValue = 20, MinValue = 0)]
        public double tp { get; set; }
        [Parameter("No. of evaluated bars", Group = "Trade Parameters", DefaultValue = 30, MinValue = 6)]
        public int evaluatedBars { get; set; }
        [Parameter("Modify SL & TP?", Group = "Modify Stop Loss & Take Profit", DefaultValue = true)]
        public bool modifySlTp { get; set; }
        [Parameter("ATR (14) multiplier", Group = "Modify Stop Loss & Take Profit", DefaultValue = 1)]
        public double atrMultiplier { get; set; }

        string botLabel = "Bot_test";
        private List<double> listOfResPoints = new List<double>();
        private List<double> listOfSupPoints = new List<double>();
        AverageTrueRange atr;
        SimpleMovingAverage sma;
        int countModifiedTpSl;
        double currentAskOnTick;
        double currentBidOnTick;
        double newTp;
        double newSl;

        protected override void OnStart()
        {
            atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
            sma = Indicators.SimpleMovingAverage(Bars.ClosePrices, 14);
        }
        protected override void OnTick()
        {
            currentAskOnTick = Symbol.Ask;
            currentBidOnTick = Symbol.Bid;
            Trades();
            // modifies sl & tp
            if (modifySlTp == true)
            {
                ModifyStopLossTakeProfit();
            }
        }
        private void ModifyStopLossTakeProfit()
        {
            foreach (var _pos in Positions)
            {
                if (_pos.TradeType == TradeType.Buy)
                {
                    newTp = currentBidOnTick + (atr.Result.LastValue * atrMultiplier);
                    newSl = currentBidOnTick - (atr.Result.LastValue * atrMultiplier);
                    _pos.ModifyTakeProfitPrice(newTp);
                    _pos.ModifyStopLossPrice(newSl);
                    countModifiedTpSl++;
                }
                else
                {
                    newTp = currentAskOnTick - (atr.Result.LastValue * atrMultiplier);
                    newSl = currentAskOnTick + (atr.Result.LastValue * atrMultiplier);
                    _pos.ModifyTakeProfitPrice(newTp);
                    _pos.ModifyStopLossPrice(newSl);
                    countModifiedTpSl++;
                }
            }
        }
        private void Trades()
        {
            if (Positions.Count >= maxPos)
                return;
            var currentResValue = ResLineValue(evaluatedBars);
            var currentSupValue = SupLineValue(evaluatedBars);
            List<double> listOfHighs = new List<double>();
            List<double> listOfLows = new List<double>();

            for (int i = 5; i <= evaluatedBars; i++)
            {
                listOfHighs.Add(Bars.HighPrices.Last(i));
                listOfLows.Add(Bars.LowPrices.Last(i));
            }
            // opens long position
            if (currentBidOnTick > currentResValue &&
                sma.Result.IsRising())
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, botLabel, sl, tp);
            }
            else
            // opens short position
            if (currentBidOnTick < currentSupValue &&
                sma.Result.IsFalling())
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, botLabel, sl, tp);
            }
            listOfHighs.Clear();
            listOfLows.Clear();
        }
        // resistance lines
        private double ResLineValue(int evaluatedBars)
        {
            listOfResPoints.Clear();
            for (int i = 5; i < evaluatedBars + 5; i++)
            {
                var resPoint = Bars.HighPrices.Last(i);
                // populates resistance points
                listOfResPoints.Add(resPoint);
            }
            var resLine = listOfResPoints.Max();
            return resLine;
        }
        // support lines
        private double SupLineValue(int evaluatedBars)
        {
            listOfSupPoints.Clear();
            for (int i = 5; i < evaluatedBars + 5; i++)
            {
                var supPoint = Bars.LowPrices.Last(i);
                // populates support points
                listOfSupPoints.Add(supPoint);
            }
            var supLine = listOfSupPoints.Min();
            return supLine;
        }
        protected override void OnStop()
        {
            Print("No. of times SL & TP modified: {0}", countModifiedTpSl);
        }
    }
}

 


@findsameh