Replies

buccinator
30 Oct 2019, 23:56

RE:

srubtsov said:

I see you use .NET Timers in that code. It's can be a source of the problem, because of cTrader doesn't guarantee successful work with multi-thread. You can find more info on that topic: https://ctrader.com/forum/cbot-support/22079

thank you mate, i will investigate swapping out the .NET timers. i thought i sourced all my examples from the forum :/


@buccinator

buccinator
30 Oct 2019, 23:51

i see, my bad, thank you for the confirmation. i only raised this because i when i last coded (few months ago) i did not notice this behaviour. it seemed to be that the next/current OnBar() was already closed. i understand now that the next/current OnBar() is not closed until the next cycle. once again, thank you for the confirmation.


@buccinator

buccinator
28 Oct 2019, 10:00

i posted code which can replicate the issue. i came back today and saw cTrader had updated and tested hoping it was gone (as it wasnt there in previous versions). it still exists. please advise.


@buccinator

buccinator
10 Sep 2019, 02:55

TEST MACD Crossover.cs

// -------------------------------------------------------------------------------------------------
//
//    This code is a cAlgo API MACD Crossover indicator provided by njardim@email.com on Dec 2015.
//
//    Based on the original MACD Crossover indicator from cTrade.
//
// -------------------------------------------------------------------------------------------------

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.EAustraliaStandardTime, AccessRights = AccessRights.None)]
    //TimeZones.UTC
    public class TESTMACDCrossover : Indicator
    {

        public MacdCrossOver MacdCrossOver;

        [Parameter()]

        public DataSeries Source { get; set; }

        [Parameter("Adaptive (auto-color)", DefaultValue = false)]
        public bool OnAdaptive { get; set; }

        [Parameter("Verbose", DefaultValue = true)]
        public bool OnVerbose { get; set; }

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

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

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

        [Output("Histogram Up", PlotType = PlotType.Histogram, Color = Colors.DodgerBlue)]
        public IndicatorDataSeries HistogramPositive { get; set; }

        [Output("Histogram Down", PlotType = PlotType.Histogram, Color = Colors.Red)]
        public IndicatorDataSeries HistogramNegative { get; set; }

        [Output("MACD", Color = Colors.DodgerBlue, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MACD { get; set; }

        [Output("Signal", Color = Colors.Red, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries Signal { get; set; }

        protected override void Initialize()
        {

            MacdCrossOver = Indicators.MacdCrossOver(Source, LongCycle, ShortCycle, Periods);

        }

        public override void Calculate(int index)
        {
            int index2 = MarketSeries.Close.Count - 1;
            double close = MarketSeries.Close[index2];
            double high = MarketSeries.High[index2];
            double low = MarketSeries.Low[index2];
            double open = MarketSeries.Open[index2];

            if (OnAdaptive)
            {

                if (MacdCrossOver.Histogram[index] > MacdCrossOver.Histogram[index - 1])
                {
                    HistogramPositive[index] = MacdCrossOver.Histogram[index];
                }

                else if (MacdCrossOver.Histogram[index] < MacdCrossOver.Histogram[index - 1])
                {
                    HistogramNegative[index] = MacdCrossOver.Histogram[index];
                }
            }
            else
            {
                if (MacdCrossOver.Histogram[index] > 0)
                {
                    HistogramPositive[index] = MacdCrossOver.Histogram[index];
                }

                else if (MacdCrossOver.Histogram[index] < 0)
                {
                    HistogramNegative[index] = MacdCrossOver.Histogram[index];
                }
            }

            if (OnVerbose)
            {

                if (MacdCrossOver.MACD[index] > -0.0001 && MacdCrossOver.MACD[index] < 0.0001)
                {
                    if (MacdCrossOver.MACD[index] > MacdCrossOver.Signal[index])
                    {
                        ChartObjects.DrawText("Position", "Long: 0", StaticPosition.BottomCenter, Colors.DodgerBlue);
                    }
                    else
                    {
                        ChartObjects.DrawText("Position", "Short: 0", StaticPosition.BottomCenter, Colors.Red);
                    }
                }

                else if (MacdCrossOver.MACD[index] > MacdCrossOver.Signal[index])
                {
                    var nMacd = String.Format("{0}", Math.Round(MacdCrossOver.MACD[index], Symbol.Digits));
                    ChartObjects.DrawText("Position", "Long: " + nMacd, StaticPosition.BottomCenter, Colors.DodgerBlue);
                }

                else if (MacdCrossOver.MACD[index] < MacdCrossOver.Signal[index])
                {
                    var nMacd = String.Format("{0}", Math.Round(MacdCrossOver.MACD[index], Symbol.Digits));
                    ChartObjects.DrawText("Position", "Short: " + nMacd, StaticPosition.BottomCenter, Colors.Red);
                }
            }

            Signal[index] = MacdCrossOver.Signal[index];

            MACD[index] = MacdCrossOver.MACD[index];

        }
    }
}

 

TEST DMS.cs

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TESTDMS : Indicator
    {
        [Parameter("Period", DefaultValue = 14, MinValue = 1)]
        public int Period { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType MaType { get; set; }

        [Output("ADX", Color = Colors.Cyan)]
        public IndicatorDataSeries ADX { get; set; }

        [Output("DI+", Color = Colors.Green)]
        public IndicatorDataSeries DIPlus { get; set; }

        [Output("Di-", Color = Colors.Red)]
        public IndicatorDataSeries DIMinus { get; set; }

        private DataSeries high, low, close;
        private IndicatorDataSeries tr, dmPlus, dmMinus, adx;
        private MovingAverage maTr, maDmPlus, maDmMinus, maAdx;

        protected override void Initialize()
        {
            high = MarketSeries.High;
            low = MarketSeries.Low;
            close = MarketSeries.Close;

            tr = CreateDataSeries();
            dmPlus = CreateDataSeries();
            dmMinus = CreateDataSeries();
            adx = CreateDataSeries();

            maTr = Indicators.MovingAverage(tr, Period, MaType);
            maDmPlus = Indicators.MovingAverage(dmPlus, Period, MaType);
            maDmMinus = Indicators.MovingAverage(dmMinus, Period, MaType);
            maAdx = Indicators.MovingAverage(adx, Period, MaType);
        }

        public override void Calculate(int index)
        {
            if (index == 0)
            {
                tr[0] = high[0] - low[0];
                dmPlus[0] = 0;
                dmMinus[0] = 0;
            }
            else
            {
                tr[index] = Math.Max(Math.Abs(low[index] - close[index - 1]), Math.Max(Math.Abs(high[index] - close[index - 1]), high[index] - low[index]));
                dmPlus[index] = high[index] - high[index - 1] > low[index - 1] - low[index] ? Math.Max(high[index] - high[index - 1], 0) : 0;
                dmMinus[index] = low[index - 1] - low[index] > high[index] - high[index - 1] ? Math.Max(low[index - 1] - low[index], 0) : 0;

                DIPlus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmPlus.Result[index] / maTr.Result[index]);
                DIMinus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmMinus.Result[index] / maTr.Result[index]);

                adx[index] = Math.Abs((DIPlus[index] - DIMinus[index]) / (DIPlus[index] + DIMinus[index]));
                ADX[index] = adx[index] == 0 ? 50 : 100 * maAdx.Result[index];
            }
        }
    }
}

 

 

TEST BBandStopLine.cs

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


namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TESTBBandStopLine : Indicator
    {
        [Parameter()]
        public DataSeries Source { get; set; }

        [Parameter(DefaultValue = 1.5)]
        public double StDeviation { get; set; }

        [Parameter(DefaultValue = 15)]
        public int Period { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MAType { get; set; }

        [Output("Top", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        public IndicatorDataSeries Top { get; set; }

        [Output("Bottom", PlotType = PlotType.Points, Color = Colors.Green, Thickness = 4)]
        public IndicatorDataSeries Bottom { get; set; }

        private BollingerBands _bband;
        private int _flag;

        protected override void Initialize()
        {
            _bband = Indicators.BollingerBands(Source, Period, StDeviation, MAType);
        }

        public override void Calculate(int index)
        {
            Top[index] = _bband.Top[index];
            Bottom[index] = _bband.Bottom[index];

            if (MarketSeries.Close[index] > _bband.Top[index])
            {
                _flag = 1;
            }
            else if (MarketSeries.Close[index] < _bband.Bottom[index])
            {
                _flag = -1;
            }

            if (_flag == 1)
            {
                if (_bband.Bottom[index] < Bottom[index - 1])
                {
                    Bottom[index] = Bottom[index - 1];
                }
                Top[index] = double.NaN;
            }
            else if (_flag == -1)
            {
                if (_bband.Top[index] > Top[index - 1])
                {
                    Top[index] = Top[index - 1];
                }
                Bottom[index] = double.NaN;
            }
        }
    }
}

 

TEST Mk 01.cs

using System;
using System.Linq;
using System.Collections.Concurrent;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Collections.Generic;
using System.Threading;
using System.ComponentModel.DataAnnotations; //probably requries nuget install
using System.ComponentModel;
using System.Reflection;
using System.Globalization;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.EAustraliaStandardTime, AccessRights = AccessRights.FullAccess)]
    //TimeZone = TimeZones.UTC, AccessRights.FileSystem)]
    public class TEST : Robot
    {
        private string Path_TEST;
        //static string prefix_name = "MK 01: ";

        public enum MarketSeriesType
        {
            Open,
            High,
            Low,
            Close
        }

        //BBAND COPY
        //1
        //[Parameter("BBSL: Source")]
        //public DataSeries BBSL_Source { get; set; }

        [Parameter("Source", Group = "Bollinger Bands Stop Line", DefaultValue = MarketSeriesType.Close)]
        public MarketSeriesType BBSL_MarketSeriesType { get; set; }
        public DataSeries BBSL_Source;

        [Parameter("St Deviation", Group = "Bollinger Bands Stop Line", DefaultValue = 1)]
        public double BBSL_StDeviation { get; set; }

        [Parameter("Period", Group = "Bollinger Bands Stop Line", DefaultValue = 3)]
        public int BBSL_Period { get; set; }

        [Parameter("MovAvg Type", Group = "Bollinger Bands Stop Line", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType BBSL_MAType { get; set; }

        [Parameter("Plot Icon", Group = "Bollinger Bands Stop Line", DefaultValue = UnicodeString.BLACK_CIRCLE)]
        public UnicodeString BBSL_Icon { get; set; }

        [Parameter("Top: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors BBSL_TopColorKey { get; set; }
        public cAlgo.API.Color BBSL_TopColor;

        [Parameter("Bottom: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Green)]
        public cAlgo.API.Colors BBSL_BottomColorKey { get; set; }
        public cAlgo.API.Color BBSL_BottomColor;

        //[Output("BBSL: Top", PlotType = PlotType.Points, Color = Colors.Red, Thickness = 4)]
        //public IndicatorDataSeries Top { get; set; }

        //[Output("BBSL: Bottom", PlotType = PlotType.Points, Color = Colors.Green, Thickness = 4)]
        //public IndicatorDataSeries Bottom { get; set; }

        //2
        [Parameter("(2): TimeFrame", Group = "Bollinger Bands Stop Line")]
        public TimeFrame BBSL2_TimeFrame { get; set; }

        [Parameter("(2): Source", Group = "Bollinger Bands Stop Line", DefaultValue = MarketSeriesType.Close)]
        public MarketSeriesType BBSL2_MarketSeriesType { get; set; }
        public DataSeries BBSL2_Source;
        //public MarketSeries BBSL2_MarketSeries;

        [Parameter("(2): St Deviation", Group = "Bollinger Bands Stop Line", DefaultValue = 1)]
        public double BBSL2_StDeviation { get; set; }

        [Parameter("(2): Period", Group = "Bollinger Bands Stop Line", DefaultValue = 3)]
        public int BBSL2_Period { get; set; }

        [Parameter("(2): MovAvg Type", Group = "Bollinger Bands Stop Line", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType BBSL2_MAType { get; set; }

        [Parameter("(2): Plot Icon", Group = "Bollinger Bands Stop Line", DefaultValue = UnicodeString.BLACK_CIRCLE)]
        public UnicodeString BBSL2_Icon { get; set; }

        [Parameter("(2): Top: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Orange)]
        public cAlgo.API.Colors BBSL2_TopColorKey { get; set; }
        public cAlgo.API.Color BBSL2_TopColor;

        [Parameter("(2): Bottom: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Blue)]
        public cAlgo.API.Colors BBSL2_BottomColorKey { get; set; }
        public cAlgo.API.Color BBSL2_BottomColor;

        //3
        [Parameter("(3): TimeFrame", Group = "Bollinger Bands Stop Line")]
        public TimeFrame BBSL3_TimeFrame { get; set; }

        [Parameter("(3): Source", Group = "Bollinger Bands Stop Line", DefaultValue = MarketSeriesType.Close)]
        public MarketSeriesType BBSL3_MarketSeriesType { get; set; }
        public DataSeries BBSL3_Source;
        //public MarketSeries BBSL3_MarketSeries;

        [Parameter("(3): St Deviation", Group = "Bollinger Bands Stop Line", DefaultValue = 1)]
        public double BBSL3_StDeviation { get; set; }

        [Parameter("(3): Period", Group = "Bollinger Bands Stop Line", DefaultValue = 3)]
        public int BBSL3_Period { get; set; }

        [Parameter("(3): MovAvg Type", Group = "Bollinger Bands Stop Line", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType BBSL3_MAType { get; set; }

        [Parameter("(3): Plot Icon", Group = "Bollinger Bands Stop Line", DefaultValue = UnicodeString.BLACK_CIRCLE)]
        public UnicodeString BBSL3_Icon { get; set; }

        [Parameter("(3): Top: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Yellow)]
        public cAlgo.API.Colors BBSL3_TopColorKey { get; set; }
        public cAlgo.API.Color BBSL3_TopColor;

        [Parameter("(3): Bottom: Colour", Group = "Bollinger Bands Stop Line", DefaultValue = cAlgo.API.Colors.Purple)]
        public cAlgo.API.Colors BBSL3_BottomColorKey { get; set; }
        public cAlgo.API.Color BBSL3_BottomColor;
        //BBAND COPY

        //DMS COPY
        [Parameter("Period", Group = "Directional Movement System", DefaultValue = 7, MinValue = 1)]
        public int DMS_Period { get; set; }

        [Parameter("MA Type", Group = "Directional Movement System", DefaultValue = MovingAverageType.WilderSmoothing)]
        public MovingAverageType DMS_MAType { get; set; }

        [Parameter("ADX: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Yellow)]
        public cAlgo.API.Colors DMS_ADXColorKey { get; set; }
        public cAlgo.API.Color DMS_ADXColor;

        [Parameter("ADX: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS_ADXLineStyle { get; set; }

        [Parameter("ADX: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS_ADXThickness { get; set; }

        [Parameter("DI+: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Green)]
        public cAlgo.API.Colors DMS_DIPlusColorKey { get; set; }
        public cAlgo.API.Color DMS_DIPlusColor;

        [Parameter("DI+: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS_DIPlusLineStyle { get; set; }

        [Parameter("DI+: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS_DIPlusThickness { get; set; }

        [Parameter("DI-: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors DMS_DIMinusColorKey { get; set; }
        public cAlgo.API.Color DMS_DIMinusColor;

        [Parameter("DI-: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS_DIMinusLineStyle { get; set; }

        [Parameter("DI-: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS_DIMinusThickness { get; set; }

        [Parameter("Level", Group = "Directional Movement System", DefaultValue = 20, MinValue = 0)]
        public int DMS_Level { get; set; }

        [Parameter("Level: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Gray)]
        public cAlgo.API.Colors DMS_LevelColorKey { get; set; }
        public cAlgo.API.Color DMS_LevelColor;

        [Parameter("Level: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS_LevelLineStyle { get; set; }

        [Parameter("Level: Thickness", Group = "Directional Movement System", DefaultValue = 1, MinValue = 1, MaxValue = 10)]
        public int DMS_LevelThickness { get; set; }

        //[Output("DMS: ADX", Color = Colors.Cyan)]
        //public IndicatorDataSeries DMS_ADX { get; set; }

        //[Output("DMS: DI+", Color = Colors.Green)]
        //public IndicatorDataSeries DMS_DIPlus { get; set; }

        //[Output("DMS: Di-", Color = Colors.Red)]
        //public IndicatorDataSeries DMS_DIMinus { get; set; }

        //2
        [Parameter("(2): TimeFrame", Group = "Directional Movement System")]
        public TimeFrame DMS2_TimeFrame { get; set; }

        [Parameter("(2): Period", Group = "Directional Movement System", DefaultValue = 7, MinValue = 1)]
        public int DMS2_Period { get; set; }

        //[Parameter("(2): MA Type", Group = "Directional Movement System", DefaultValue = MovingAverageType.WilderSmoothing)]
        //public MovingAverageType DMS2_MAType { get; set;  }

        [Parameter("(2): ADX: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Yellow)]
        public cAlgo.API.Colors DMS2_ADXColorKey { get; set; }
        public cAlgo.API.Color DMS2_ADXColor;

        [Parameter("(2): ADX: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS2_ADXLineStyle { get; set; }

        [Parameter("(2): ADX: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS2_ADXThickness { get; set; }

        [Parameter("(2): DI+: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Green)]
        public cAlgo.API.Colors DMS2_DIPlusColorKey { get; set; }
        public cAlgo.API.Color DMS2_DIPlusColor;

        [Parameter("(2): DI+: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS2_DIPlusLineStyle { get; set; }

        [Parameter("(2): DI+: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS2_DIPlusThickness { get; set; }

        [Parameter("(2): DI-: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors DMS2_DIMinusColorKey { get; set; }
        public cAlgo.API.Color DMS2_DIMinusColor;

        [Parameter("(2): DI-: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS2_DIMinusLineStyle { get; set; }

        [Parameter("(2): DI-: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS2_DIMinusThickness { get; set; }

        [Parameter("(2): Level", Group = "Directional Movement System", DefaultValue = 20, MinValue = 0)]
        public int DMS2_Level { get; set; }

        [Parameter("(2): Level: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Gray)]
        public cAlgo.API.Colors DMS2_LevelColorKey { get; set; }
        public cAlgo.API.Color DMS2_LevelColor;

        [Parameter("(2): Level: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS2_LevelLineStyle { get; set; }

        [Parameter("(2): Level: Thickness", Group = "Directional Movement System", DefaultValue = 1, MinValue = 1, MaxValue = 10)]
        public int DMS2_LevelThickness { get; set; }

        //3
        [Parameter("(3): TimeFrame", Group = "Directional Movement System")]
        public TimeFrame DMS3_TimeFrame { get; set; }

        [Parameter("(3): Period", Group = "Directional Movement System", DefaultValue = 7, MinValue = 1)]
        public int DMS3_Period { get; set; }

        //[Parameter("(3): MA Type", Group = "Directional Movement System", DefaultValue = MovingAverageType.WilderSmoothing)]
        //public MovingAverageType DMS3_MAType { get; set;  }

        [Parameter("(3): ADX: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Yellow)]
        public cAlgo.API.Colors DMS3_ADXColorKey { get; set; }
        public cAlgo.API.Color DMS3_ADXColor;

        [Parameter("(3): ADX: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS3_ADXLineStyle { get; set; }

        [Parameter("(3): ADX: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS3_ADXThickness { get; set; }

        [Parameter("(3): DI+: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Green)]
        public cAlgo.API.Colors DMS3_DIPlusColorKey { get; set; }
        public cAlgo.API.Color DMS3_DIPlusColor;

        [Parameter("(3): DI+: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS3_DIPlusLineStyle { get; set; }

        [Parameter("(3): DI+: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS3_DIPlusThickness { get; set; }

        [Parameter("(3): DI-: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors DMS3_DIMinusColorKey { get; set; }
        public cAlgo.API.Color DMS3_DIMinusColor;

        [Parameter("(3): DI-: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS3_DIMinusLineStyle { get; set; }

        [Parameter("(3): DI-: Thickness", Group = "Directional Movement System", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int DMS3_DIMinusThickness { get; set; }

        [Parameter("(3): Level", Group = "Directional Movement System", DefaultValue = 20, MinValue = 0)]
        public int DMS3_Level { get; set; }

        [Parameter("(3): Level: Colour", Group = "Directional Movement System", DefaultValue = cAlgo.API.Colors.Gray)]
        public cAlgo.API.Colors DMS3_LevelColorKey { get; set; }
        public cAlgo.API.Color DMS3_LevelColor;

        [Parameter("(3): Level: Line Style", Group = "Directional Movement System", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle DMS3_LevelLineStyle { get; set; }

        [Parameter("(3): Level: Thickness", Group = "Directional Movement System", DefaultValue = 1, MinValue = 1, MaxValue = 10)]
        public int DMS3_LevelThickness { get; set; }
        //DMS COPY

        //MACD COPY
        [Parameter("Source", Group = "Moving Average Convergence/Divergence")]
        public DataSeries MACD_Source { get; set; }

        [Parameter("Adaptive (auto-color)", Group = "Moving Average Convergence/Divergence", DefaultValue = false)]
        public bool MACD_OnAdaptive { get; set; }

        [Parameter("Verbose", Group = "Moving Average Convergence/Divergence", DefaultValue = true)]
        public bool MACD_OnVerbose { get; set; }

        [Parameter("Long Cycle", Group = "Moving Average Convergence/Divergence", DefaultValue = 26)]
        public int MACD_LongCycle { get; set; }

        [Parameter("Short Cycle", Group = "Moving Average Convergence/Divergence", DefaultValue = 12)]
        public int MACD_ShortCycle { get; set; }

        [Parameter("Signal Periods", Group = "Moving Average Convergence/Divergence", DefaultValue = 9)]
        public int MACD_Periods { get; set; }

        [Parameter("HI+: Colour", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.Colors.DodgerBlue)]
        public cAlgo.API.Colors MACD_HiPlusColorKey { get; set; }
        public cAlgo.API.Color MACD_HiPlusColor;

        [Parameter("HI+: Line Style", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle MACD_HiPlusLineStyle { get; set; }

        [Parameter("HI+: Thickness", Group = "Moving Average Convergence/Divergence", DefaultValue = 5, MinValue = 1, MaxValue = 10)]
        public int MACD_HiPlusThickness { get; set; }

        [Parameter("HI-: Colour", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors MACD_HiMinusColorKey { get; set; }
        public cAlgo.API.Color MACD_HiMinusColor;

        [Parameter("HI-: Line Style", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.LineStyle.Solid)]
        public cAlgo.API.LineStyle MACD_HiMinusLineStyle { get; set; }

        [Parameter("HI-: Thickness", Group = "Moving Average Convergence/Divergence", DefaultValue = 5, MinValue = 1, MaxValue = 10)]
        public int MACD_HiMinusThickness { get; set; }

        [Parameter("MACD: Colour", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.Colors.DodgerBlue)]
        public cAlgo.API.Colors MACD_MACDColorKey { get; set; }
        public cAlgo.API.Color MACD_MACDColor;

        [Parameter("MACD: Line Style", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.LineStyle.Dots)]
        public cAlgo.API.LineStyle MACD_MACDLineStyle { get; set; }

        [Parameter("MACD: Thickness", Group = "Moving Average Convergence/Divergence", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int MACD_MACDThickness { get; set; }

        [Parameter("Signal: Colour", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.Colors.Red)]
        public cAlgo.API.Colors MACD_SignalColorKey { get; set; }
        public cAlgo.API.Color MACD_SignalColor;

        [Parameter("Signal: Line Style", Group = "Moving Average Convergence/Divergence", DefaultValue = cAlgo.API.LineStyle.Dots)]
        public cAlgo.API.LineStyle MACD_SignalLineStyle { get; set; }

        [Parameter("Signal: Thickness", Group = "Moving Average Convergence/Divergence", DefaultValue = 2, MinValue = 1, MaxValue = 10)]
        public int MACD_SignalThickness { get; set; }

        //[Output("MACD: Histogram Up", PlotType = PlotType.Histogram, Color = Colors.DodgerBlue)]
        //public IndicatorDataSeries MACD_HistogramPositive { get; set; }

        //[Output("MACD: Histogram Down", PlotType = PlotType.Histogram, Color = Colors.Red)]
        //public IndicatorDataSeries MACD_HistogramNegative { get; set; }

        //[Output("MACD: MACD", Color = Colors.DodgerBlue, LineStyle = LineStyle.Lines)]
        //public IndicatorDataSeries MACD_MACD { get; set; }

        //[Output("MACD: Signal", Color = Colors.Red, LineStyle = LineStyle.Lines)]
        //public IndicatorDataSeries MACD_Signal { get; set; }
        //MACD COPY

        //TEST
        string BBSL_bullet, BBSL2_bullet, BBSL3_bullet;

        [Parameter("Plot", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot { get; set; }

        [Parameter("Plot: BBSL", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_BBSL { get; set; }

        [Parameter("Plot: BBSL (2)", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_BBSL2 { get; set; }

        [Parameter("Plot: BBSL (3)", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_BBSL3 { get; set; }

        [Parameter("Plot: DMS", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_DMS { get; set; }

        [Parameter("Plot: DMS (2)", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_DMS2 { get; set; }

        [Parameter("Plot: DMS (3)", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_DMS3 { get; set; }

        [Parameter("Plot: MACD", Group = "Test", DefaultValue = true)]
        public bool TEST_Plot_MACD { get; set; }

        [Parameter("Inc. Previous", Group = "Test", DefaultValue = true)]
        public bool TEST_PlotPrevious { get; set; }

        [Parameter("DMS: Chart Scale", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS_Scale { get; set; }

        [Parameter("DMS: Chart Start Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS_Chart_Start_Y { get; set; }

        [Parameter("DMS: Chart Height Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS_Chart_Height_Y { get; set; }

        [Parameter("(2): DMS: Chart Scale", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS2_Scale { get; set; }

        [Parameter("(2): DMS: Chart Start Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS2_Chart_Start_Y { get; set; }

        [Parameter("(2): DMS: Chart Height Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS2_Chart_Height_Y { get; set; }

        [Parameter("(3): DMS: Chart Scale", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS3_Scale { get; set; }

        [Parameter("(3): DMS: Chart Start Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS3_Chart_Start_Y { get; set; }

        [Parameter("(3): DMS: Chart Height Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double DMS3_Chart_Height_Y { get; set; }

        [Parameter("MACD: Chart Scale", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double MACD_Scale { get; set; }

        [Parameter("MACD: Chart Start Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double MACD_Chart_Start_Y { get; set; }

        [Parameter("MACD: Chart Height Y", Group = "Test", DefaultValue = 0, MinValue = 0)]
        public double MACD_Chart_Height_Y { get; set; }

        private TESTBBandStopLine TEST_Ind_BBSL;
        private TESTBBandStopLine TEST_Ind_BBSL2;
        private TESTBBandStopLine TEST_Ind_BBSL3;
        private TESTDMS TEST_Ind_DMS;
        private DirectionalMovementSystem TEST_Ind_DMS2;
        private DirectionalMovementSystem TEST_Ind_DMS3;
        private TESTMACDCrossover TEST_Ind_MACD;

        private IDictionary<string, MarketSeries> TEST_MarketSeries = new Dictionary<string, MarketSeries>();

        int TEST_Plot_Chart_BarsTotal = 0;

        private readonly ConcurrentQueue<int> Queue_TEST_Calculate = new ConcurrentQueue<int>();
        private readonly ConcurrentQueue<int> Queue_TEST_CalculatePlot = new ConcurrentQueue<int>();

        //index to handle when completion failed
        private int? _OnStop_Timer_index;
        //TEST

        //BBAND
        protected void BBSL_Initialize()
        {
            BBSL_bullet = BBSL_Icon.GetDescription();
            BBSL2_bullet = BBSL2_Icon.GetDescription();
            BBSL3_bullet = BBSL3_Icon.GetDescription();

            BBSL_TopColor = cAlgo.API.Color.FromName(BBSL_TopColorKey.ToString());
            BBSL_BottomColor = cAlgo.API.Color.FromName(BBSL_BottomColorKey.ToString());
            BBSL2_TopColor = cAlgo.API.Color.FromName(BBSL2_TopColorKey.ToString());
            BBSL2_BottomColor = cAlgo.API.Color.FromName(BBSL2_BottomColorKey.ToString());
            BBSL3_TopColor = cAlgo.API.Color.FromName(BBSL2_TopColorKey.ToString());
            BBSL3_BottomColor = cAlgo.API.Color.FromName(BBSL2_BottomColorKey.ToString());

            switch (BBSL_MarketSeriesType)
            {
                case MarketSeriesType.Close:
                    BBSL_Source = MarketSeries.Close;
                    break;
                case MarketSeriesType.Open:
                    BBSL_Source = MarketSeries.Open;
                    break;
                case MarketSeriesType.High:
                    BBSL_Source = MarketSeries.High;
                    break;
                case MarketSeriesType.Low:
                    BBSL_Source = MarketSeries.Low;
                    break;
            }

            MarketSeries BBSL2_MarketSeries = TEST_getMarketSeries(BBSL2_TimeFrame);

            switch (BBSL2_MarketSeriesType)
            {
                case MarketSeriesType.Close:
                    BBSL2_Source = BBSL2_MarketSeries.Close;
                    break;
                case MarketSeriesType.Open:
                    BBSL2_Source = BBSL2_MarketSeries.Open;
                    break;
                case MarketSeriesType.High:
                    BBSL2_Source = BBSL2_MarketSeries.High;
                    break;
                case MarketSeriesType.Low:
                    BBSL2_Source = BBSL2_MarketSeries.Low;
                    break;
            }

            MarketSeries BBSL3_MarketSeries = TEST_getMarketSeries(BBSL3_TimeFrame);

            switch (BBSL3_MarketSeriesType)
            {
                case MarketSeriesType.Close:
                    BBSL3_Source = BBSL3_MarketSeries.Close;
                    break;
                case MarketSeriesType.Open:
                    BBSL3_Source = BBSL3_MarketSeries.Open;
                    break;
                case MarketSeriesType.High:
                    BBSL3_Source = BBSL3_MarketSeries.High;
                    break;
                case MarketSeriesType.Low:
                    BBSL3_Source = BBSL3_MarketSeries.Low;
                    break;
            }

            TEST_Ind_BBSL = Indicators.GetIndicator<TESTBBandStopLine>(BBSL_Source, BBSL_StDeviation, BBSL_Period, BBSL_MAType);
            TEST_Ind_BBSL2 = Indicators.GetIndicator<TESTBBandStopLine>(BBSL2_Source, BBSL2_StDeviation, BBSL2_Period, BBSL2_MAType);
            TEST_Ind_BBSL3 = Indicators.GetIndicator<TESTBBandStopLine>(BBSL3_Source, BBSL3_StDeviation, BBSL3_Period, BBSL3_MAType);
        }

        public void BBSL_Calculate(int index)
        {
            //Print("BBSL_Calculate({0})", index);

            if (TEST_Plot_BBSL)
            {
                IndicatorDataSeries BBSL_Top = TEST_Ind_BBSL.Top;
                IndicatorDataSeries BBSL_Bottom = TEST_Ind_BBSL.Bottom;

                //Chart.DrawIcon("BBSL-Top-" + index, ChartIconType.Circle, index, BBSL_Top[index], BBSL_TopColor);
                //Chart.DrawIcon("BBSL-Bottom-" + index, ChartIconType.Circle, index, BBSL_Bottom[index], BBSL_BottomColor);

                ChartObjects.DrawText("BBSL-Top-" + index, BBSL_bullet, index, BBSL_Top[index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL_TopColorKey);
                ChartObjects.DrawText("BBSL-Bottom-" + index, BBSL_bullet, index, BBSL_Bottom[index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL_BottomColorKey);
            }

            DateTime Bot_DateTime = MarketSeries.OpenTime[index];

            if (TEST_Plot_BBSL2)
            {
                MarketSeries BBSL2_MarketSeries = TEST_getMarketSeries(BBSL2_TimeFrame);
                //int BBSL2_Index = BBSL2_MarketSeries.OpenTime.GetIndexByExactTime(Bot_DateTime);
                int BBSL2_Index = BBSL2_MarketSeries.OpenTime.GetIndexByTime(Bot_DateTime);
                if (BBSL2_Index > 0)
                {
                    IndicatorDataSeries BBSL2_Top = TEST_Ind_BBSL2.Top;
                    IndicatorDataSeries BBSL2_Bottom = TEST_Ind_BBSL2.Bottom;

                    ChartObjects.DrawText("BBSL2-Top-" + BBSL2_Index, BBSL2_bullet, index, BBSL2_Top[BBSL2_Index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL2_TopColorKey);
                    ChartObjects.DrawText("BBSL2-Bottom-" + BBSL2_Index, BBSL2_bullet, index, BBSL2_Bottom[BBSL2_Index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL2_BottomColorKey);
                }
            }

            if (TEST_Plot_BBSL3)
            {
                MarketSeries BBSL3_MarketSeries = TEST_getMarketSeries(BBSL3_TimeFrame);
                //int BBSL3_Index = BBSL3_MarketSeries.OpenTime.GetIndexByExactTime(Bot_DateTime);
                int BBSL3_Index = BBSL3_MarketSeries.OpenTime.GetIndexByTime(Bot_DateTime);
                if (BBSL3_Index > 0)
                {
                    IndicatorDataSeries BBSL3_Top = TEST_Ind_BBSL3.Top;
                    IndicatorDataSeries BBSL3_Bottom = TEST_Ind_BBSL3.Bottom;

                    ChartObjects.DrawText("BBSL3-Top-" + BBSL3_Index, BBSL3_bullet, index, BBSL3_Top[BBSL3_Index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL3_TopColorKey);
                    ChartObjects.DrawText("BBSL3-Bottom-" + BBSL3_Index, BBSL3_bullet, index, BBSL3_Bottom[BBSL3_Index], VerticalAlignment.Center, HorizontalAlignment.Center, BBSL3_BottomColorKey);
                }
            }
        }
        //BBAND

        //DMS
        protected void DMS_Initialize()
        {
            DMS_ADXColor = cAlgo.API.Color.FromName(DMS_ADXColorKey.ToString());
            DMS_DIPlusColor = cAlgo.API.Color.FromName(DMS_DIPlusColorKey.ToString());
            DMS_DIMinusColor = cAlgo.API.Color.FromName(DMS_DIMinusColorKey.ToString());
            DMS_LevelColor = cAlgo.API.Color.FromName(DMS_LevelColorKey.ToString());

            DMS2_ADXColor = cAlgo.API.Color.FromName(DMS2_ADXColorKey.ToString());
            DMS2_DIPlusColor = cAlgo.API.Color.FromName(DMS2_DIPlusColorKey.ToString());
            DMS2_DIMinusColor = cAlgo.API.Color.FromName(DMS2_DIMinusColorKey.ToString());
            DMS2_LevelColor = cAlgo.API.Color.FromName(DMS2_LevelColorKey.ToString());

            DMS3_ADXColor = cAlgo.API.Color.FromName(DMS3_ADXColorKey.ToString());
            DMS3_DIPlusColor = cAlgo.API.Color.FromName(DMS3_DIPlusColorKey.ToString());
            DMS3_DIMinusColor = cAlgo.API.Color.FromName(DMS3_DIMinusColorKey.ToString());
            DMS3_LevelColor = cAlgo.API.Color.FromName(DMS3_LevelColorKey.ToString());

            MarketSeries DMS2_MarketSeries = TEST_getMarketSeries(DMS2_TimeFrame);
            MarketSeries DMS3_MarketSeries = TEST_getMarketSeries(DMS3_TimeFrame);

            TEST_Ind_DMS = Indicators.GetIndicator<TESTDMS>(DMS_Period, DMS_MAType);
            TEST_Ind_DMS2 = Indicators.DirectionalMovementSystem(DMS2_MarketSeries, DMS2_Period);
            TEST_Ind_DMS3 = Indicators.DirectionalMovementSystem(DMS3_MarketSeries, DMS3_Period);

            double Chart_Height = (Chart.TopY - Chart.BottomY) / 2;
            if (DMS_Chart_Height_Y > 0)
            {
            }
            else
            {
                DMS_Chart_Height_Y = Chart_Height;
            }
            if (DMS_Chart_Start_Y > 0)
            {
            }
            else
            {
                DMS_Chart_Start_Y = Chart.TopY + DMS_Chart_Height_Y;
            }

            if (DMS2_Chart_Height_Y > 0)
            {
            }
            else
            {
                DMS2_Chart_Height_Y = Chart_Height;
            }
            if (DMS2_Chart_Start_Y > 0)
            {
            }
            else
            {
                DMS2_Chart_Start_Y = Chart.TopY + DMS2_Chart_Height_Y;
            }

            if (DMS3_Chart_Height_Y > 0)
            {
            }
            else
            {
                DMS3_Chart_Height_Y = Chart_Height;
            }
            if (DMS3_Chart_Start_Y > 0)
            {
            }
            else
            {
                DMS3_Chart_Start_Y = Chart.TopY + DMS3_Chart_Height_Y;
            }

            double DMS_Level_y = DMS_Chart_Start_Y + ((DMS_Level * DMS_Scale / 100) * DMS_Chart_Height_Y);
            double DMS2_Level_y = DMS2_Chart_Start_Y + ((DMS2_Level * DMS2_Scale / 100) * DMS2_Chart_Height_Y);
            double DMS3_Level_y = DMS3_Chart_Start_Y + ((DMS3_Level * DMS3_Scale / 100) * DMS3_Chart_Height_Y);

            Chart.DrawHorizontalLine("DMS-Line-" + DMS_Level, DMS_Level_y, DMS_LevelColor, DMS_LevelThickness, DMS_LevelLineStyle);
            Chart.DrawHorizontalLine("DMS2-Line-" + DMS2_Level, DMS2_Level_y, DMS2_LevelColor, DMS2_LevelThickness, DMS2_LevelLineStyle);
            Chart.DrawHorizontalLine("DMS3-Line-" + DMS3_Level, DMS3_Level_y, DMS3_LevelColor, DMS3_LevelThickness, DMS3_LevelLineStyle);

            if (DMS_Scale > 0)
            {
            }
            else
            {
                DMS_Scale = TEST_Plot_getScaleMax();
            }

            if (DMS2_Scale > 0)
            {
            }
            else
            {
                DMS2_Scale = TEST_Plot_getScaleMax();
            }

            if (DMS3_Scale > 0)
            {
            }
            else
            {
                DMS3_Scale = TEST_Plot_getScaleMax();
            }
        }

        public void DMS_Calculate(int index)
        {
            DateTime Bot_DateTime = MarketSeries.OpenTime[index];

            if (index > 0)
            {
            }
            else
            {
                return;
            }

            if (TEST_Plot_DMS)
            {
                int Bot_IndexLast = index - 1;

                IndicatorDataSeries DMS_ADX = TEST_Ind_DMS.ADX;
                IndicatorDataSeries DMS_DIPlus = TEST_Ind_DMS.DIPlus;
                IndicatorDataSeries DMS_DIMinus = TEST_Ind_DMS.DIMinus;

                double DMS_DIPlus_y1 = DMS_Chart_Start_Y + ((DMS_DIPlus[Bot_IndexLast] * DMS_Scale / 100) * DMS_Chart_Height_Y);
                double DMS_DIMinus_y1 = DMS_Chart_Start_Y + ((DMS_DIMinus[Bot_IndexLast] * DMS_Scale / 100) * DMS_Chart_Height_Y);
                double DMS_ADX_y1 = DMS_Chart_Start_Y + ((DMS_ADX[Bot_IndexLast] * DMS_Scale / 100) * DMS_Chart_Height_Y);

                double DMS_DIPlus_y2 = DMS_Chart_Start_Y + ((DMS_DIPlus[index] * DMS_Scale / 100) * DMS_Chart_Height_Y);
                double DMS_DIMinus_y2 = DMS_Chart_Start_Y + ((DMS_DIMinus[index] * DMS_Scale / 100) * DMS_Chart_Height_Y);
                double DMS_ADX_y2 = DMS_Chart_Start_Y + ((DMS_ADX[index] * DMS_Scale / 100) * DMS_Chart_Height_Y);

                Chart.DrawTrendLine("DMS-ADX-" + index, Bot_IndexLast, DMS_ADX_y1, index, DMS_ADX_y2, DMS_ADXColor, DMS_ADXThickness, DMS_ADXLineStyle);
                Chart.DrawTrendLine("DMS-Plus-" + index, Bot_IndexLast, DMS_DIPlus_y1, index, DMS_DIPlus_y2, DMS_DIPlusColor, DMS_DIPlusThickness, DMS_DIPlusLineStyle);
                Chart.DrawTrendLine("DMS-Minus-" + index, Bot_IndexLast, DMS_DIMinus_y1, index, DMS_DIMinus_y2, DMS_DIMinusColor, DMS_DIMinusThickness, DMS_DIMinusLineStyle);
            }

            if (TEST_Plot_DMS2)
            {
                MarketSeries DMS2_MarketSeries = TEST_getMarketSeries(DMS2_TimeFrame);
                //int DMS2_Index = DMS2_MarketSeries.OpenTime.GetIndexByExactTime(Bot_DateTime);
                int DMS2_Index = DMS2_MarketSeries.OpenTime.GetIndexByTime(Bot_DateTime);

                if (DMS2_Index > 0)
                {
                    TEST_TimeFrame_PlotLineTrace Trace = TEST_TimeFrame_PlotLineTrace_Pre("DMS2", MarketSeries.TimeFrame, index, DMS2_MarketSeries.TimeFrame, DMS2_Index);
                    int DMS2_Bot_IndexLast = Trace.TimeFrame1_IndexLast;
                    int DMS2_IndexLast = Trace.TimeFrame2_IndexLast;

                    IndicatorDataSeries DMS2_ADX = TEST_Ind_DMS2.ADX;
                    IndicatorDataSeries DMS2_DIPlus = TEST_Ind_DMS2.DIPlus;
                    IndicatorDataSeries DMS2_DIMinus = TEST_Ind_DMS2.DIMinus;

                    double DMS2_DIPlus_y1 = DMS2_Chart_Start_Y + ((DMS2_DIPlus[DMS2_IndexLast] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);
                    double DMS2_DIMinus_y1 = DMS2_Chart_Start_Y + ((DMS2_DIMinus[DMS2_IndexLast] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);
                    double DMS2_ADX_y1 = DMS2_Chart_Start_Y + ((DMS2_ADX[DMS2_IndexLast] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);

                    double DMS2_DIPlus_y2 = DMS2_Chart_Start_Y + ((DMS2_DIPlus[DMS2_Index] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);
                    double DMS2_DIMinus_y2 = DMS2_Chart_Start_Y + ((DMS2_DIMinus[DMS2_Index] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);
                    double DMS2_ADX_y2 = DMS2_Chart_Start_Y + ((DMS2_ADX[DMS2_Index] * DMS2_Scale / 100) * DMS2_Chart_Height_Y);

                    Chart.DrawTrendLine("DMS2-ADX-" + DMS2_Index, DMS2_Bot_IndexLast, DMS2_ADX_y1, index, DMS2_ADX_y2, DMS2_ADXColor, DMS2_ADXThickness, DMS2_ADXLineStyle);
                    Chart.DrawTrendLine("DMS2-Plus-" + DMS2_Index, DMS2_Bot_IndexLast, DMS2_DIPlus_y1, index, DMS2_DIPlus_y2, DMS2_DIPlusColor, DMS2_DIPlusThickness, DMS2_DIPlusLineStyle);
                    Chart.DrawTrendLine("DMS2-Minus-" + DMS2_Index, DMS2_Bot_IndexLast, DMS2_DIMinus_y1, index, DMS2_DIMinus_y2, DMS2_DIMinusColor, DMS2_DIMinusThickness, DMS2_DIMinusLineStyle);

                    TEST_TimeFrame_PlotLineTrace_Post("DMS2", MarketSeries.TimeFrame, index, DMS2_MarketSeries.TimeFrame, DMS2_Index);
                }
            }

            if (TEST_Plot_DMS3)
            {
                MarketSeries DMS3_MarketSeries = TEST_getMarketSeries(DMS3_TimeFrame);
                //int DMS3_Index = DMS3_MarketSeries.OpenTime.GetIndexByExactTime(Bot_DateTime);
                int DMS3_Index = DMS3_MarketSeries.OpenTime.GetIndexByTime(Bot_DateTime);

                if (DMS3_Index > 0)
                {
                    TEST_TimeFrame_PlotLineTrace Trace = TEST_TimeFrame_PlotLineTrace_Pre("DMS3", MarketSeries.TimeFrame, index, DMS3_MarketSeries.TimeFrame, DMS3_Index);
                    int DMS3_Bot_IndexLast = Trace.TimeFrame1_IndexLast;
                    int DMS3_IndexLast = Trace.TimeFrame2_IndexLast;

                    IndicatorDataSeries DMS3_ADX = TEST_Ind_DMS3.ADX;
                    IndicatorDataSeries DMS3_DIPlus = TEST_Ind_DMS3.DIPlus;
                    IndicatorDataSeries DMS3_DIMinus = TEST_Ind_DMS3.DIMinus;

                    double DMS3_DIPlus_y1 = DMS3_Chart_Start_Y + ((DMS3_DIPlus[DMS3_IndexLast] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);
                    double DMS3_DIMinus_y1 = DMS3_Chart_Start_Y + ((DMS3_DIMinus[DMS3_IndexLast] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);
                    double DMS3_ADX_y1 = DMS3_Chart_Start_Y + ((DMS3_ADX[DMS3_IndexLast] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);

                    double DMS3_DIPlus_y2 = DMS3_Chart_Start_Y + ((DMS3_DIPlus[DMS3_Index] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);
                    double DMS3_DIMinus_y2 = DMS3_Chart_Start_Y + ((DMS3_DIMinus[DMS3_Index] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);
                    double DMS3_ADX_y2 = DMS3_Chart_Start_Y + ((DMS3_ADX[DMS3_Index] * DMS3_Scale / 100) * DMS3_Chart_Height_Y);

                    Chart.DrawTrendLine("DMS3-ADX-" + DMS3_Index, DMS3_Bot_IndexLast, DMS3_ADX_y1, index, DMS3_ADX_y2, DMS3_ADXColor, DMS3_ADXThickness, DMS3_ADXLineStyle);
                    Chart.DrawTrendLine("DMS3-Plus-" + DMS3_Index, DMS3_Bot_IndexLast, DMS3_DIPlus_y1, index, DMS3_DIPlus_y2, DMS3_DIPlusColor, DMS3_DIPlusThickness, DMS3_DIPlusLineStyle);
                    Chart.DrawTrendLine("DMS3-Minus-" + DMS3_Index, DMS3_Bot_IndexLast, DMS3_DIMinus_y1, index, DMS3_DIMinus_y2, DMS3_DIMinusColor, DMS3_DIMinusThickness, DMS3_DIMinusLineStyle);

                    TEST_TimeFrame_PlotLineTrace_Post("DMS3", MarketSeries.TimeFrame, index, DMS3_MarketSeries.TimeFrame, DMS3_Index);
                }
            }
        }
        //DMS

        //MACD
        protected void MACD_Initialize()
        {
            MACD_HiPlusColor = cAlgo.API.Color.FromName(MACD_HiPlusColorKey.ToString());
            MACD_HiMinusColor = cAlgo.API.Color.FromName(MACD_HiMinusColorKey.ToString());
            MACD_MACDColor = cAlgo.API.Color.FromName(MACD_MACDColorKey.ToString());
            MACD_SignalColor = cAlgo.API.Color.FromName(MACD_SignalColorKey.ToString());

            TEST_Ind_MACD = Indicators.GetIndicator<TESTMACDCrossover>(MACD_Source, MACD_OnAdaptive, MACD_OnVerbose, MACD_LongCycle, MACD_ShortCycle, MACD_Periods);

            double Chart_Height = (Chart.TopY - Chart.BottomY) / 2;
            if (MACD_Chart_Height_Y > 0)
            {
            }
            else
            {
                MACD_Chart_Height_Y = Chart_Height;
            }

            if (MACD_Chart_Start_Y > 0)
            {
            }
            else
            {
                MACD_Chart_Start_Y = Chart.BottomY - MACD_Chart_Height_Y;
            }

            if (MACD_Scale > 0)
            {
            }
            else
            {
                MACD_Scale = TEST_Plot_getScaleMin();
            }
        }

        public void MACD_Calculate(int index)
        {
            if (index > 0)
            {
            }
            else
            {
                return;
            }

            if (TEST_Plot_MACD)
            {
            }
            else
            {
                return;
            }

            IndicatorDataSeries MACD_MACD = TEST_Ind_MACD.MACD;
            IndicatorDataSeries MACD_Signal = TEST_Ind_MACD.Signal;

            double MACD_MACD_y1 = MACD_Chart_Start_Y + ((MACD_MACD[index - 1] * MACD_Scale / 100) * MACD_Chart_Height_Y);
            double MACD_Signal_y1 = MACD_Chart_Start_Y + ((MACD_Signal[index - 1] * MACD_Scale / 100) * MACD_Chart_Height_Y);

            double MACD_MACD_y2 = MACD_Chart_Start_Y + ((MACD_MACD[index] * MACD_Scale / 100) * MACD_Chart_Height_Y);
            double MACD_Signal_y2 = MACD_Chart_Start_Y + ((MACD_Signal[index] * MACD_Scale / 100) * MACD_Chart_Height_Y);

            Chart.DrawTrendLine("MACD-MACD-" + index, index - 1, MACD_MACD_y1, index, MACD_MACD_y2, MACD_MACDColor, MACD_MACDThickness, MACD_MACDLineStyle);
            Chart.DrawTrendLine("MACD-Signal-" + index, index - 1, MACD_Signal_y1, index, MACD_Signal_y2, MACD_SignalColor, MACD_SignalThickness, MACD_SignalLineStyle);

            MacdCrossOver MACD_MacdCrossOver = TEST_Ind_MACD.MacdCrossOver;

            if (MACD_OnVerbose)
            {

                if (MACD_MacdCrossOver.MACD[index] > -0.0001 && MACD_MacdCrossOver.MACD[index] < 0.0001)
                {
                    if (MACD_MacdCrossOver.MACD[index] > MACD_MacdCrossOver.Signal[index])
                    {
                        //ChartObjects.DrawText("Position", "Long: 0", StaticPosition.BottomCenter, MACD_HiPlusColorKey);
                        Chart.DrawStaticText("Position", "Long: 0", VerticalAlignment.Bottom, HorizontalAlignment.Center, MACD_HiPlusColor);
                    }
                    else
                    {
                        //ChartObjects.DrawText("Position", "Short: 0", StaticPosition.BottomCenter, MACD_HiMinusColorKey);
                        Chart.DrawStaticText("Position", "Short: 0", VerticalAlignment.Bottom, HorizontalAlignment.Center, MACD_HiMinusColor);
                    }
                }

                else if (MACD_MacdCrossOver.MACD[index] > MACD_MacdCrossOver.Signal[index])
                {
                    var nMacd = String.Format("{0}", Math.Round(MACD_MacdCrossOver.MACD[index], Symbol.Digits));
                    //ChartObjects.DrawText("Position", "Long: " + nMacd, StaticPosition.BottomCenter, MACD_HiPlusColorKey);
                    Chart.DrawStaticText("Position", "Long: " + nMacd, VerticalAlignment.Bottom, HorizontalAlignment.Center, MACD_HiPlusColor);
                }

                else if (MACD_MacdCrossOver.MACD[index] < MACD_MacdCrossOver.Signal[index])
                {
                    var nMacd = String.Format("{0}", Math.Round(MACD_MacdCrossOver.MACD[index], Symbol.Digits));
                    //ChartObjects.DrawText("Position", "Short: " + nMacd, StaticPosition.BottomCenter, MACD_HiMinusColorKey);
                    Chart.DrawStaticText("Position", "Short: " + nMacd, VerticalAlignment.Bottom, HorizontalAlignment.Center, MACD_HiMinusColor);
                }
            }

            IndicatorDataSeries MACD_HistogramPositive = TEST_Ind_MACD.HistogramPositive;
            IndicatorDataSeries MACD_HistogramNegative = TEST_Ind_MACD.HistogramNegative;

            double MACD_Up_y = MACD_Chart_Start_Y + ((MACD_HistogramPositive[index] * MACD_Scale / 100) * MACD_Chart_Height_Y);
            double MACD_Down_y = MACD_Chart_Start_Y + ((MACD_HistogramNegative[index] * MACD_Scale / 100) * MACD_Chart_Height_Y);

            ChartObjects.DrawLine("MACD-Up-" + index, index, MACD_Chart_Start_Y, index, MACD_Up_y, MACD_HiPlusColorKey, MACD_HiPlusThickness, MACD_HiPlusLineStyle);
            ChartObjects.DrawLine("MACD-Down-" + index, index, MACD_Chart_Start_Y, index, MACD_Down_y, MACD_HiMinusColorKey, MACD_HiMinusThickness, MACD_HiMinusLineStyle);
        }
        //MACD

        //STOCK BOT
        protected override void OnStart()
        {
            System.Timers.Timer BarsTotalTimer = null;

            if (TEST_Plot)
            {
                while (Chart == null)
                {
                    Thread.Sleep(1);
                }

                BarsTotalTimer = new System.Timers.Timer(1);
                BarsTotalTimer.Elapsed += TEST_OnTimedEvent_BarsTotal_Update;
                BarsTotalTimer.AutoReset = true;
                BarsTotalTimer.Enabled = true;

                Chart.ScrollChanged += TEST_Chart_ScrollChanged;
            }

            Print("(parent) {0} @ Start: {1}, Finish: {2}", MarketSeries.TimeFrame, MarketSeries.OpenTime[0], MarketSeries.OpenTime[MarketSeries.OpenTime.Count - 1]);

            TEST_Initialize();

            // seems to release cTrader app for movement during intense drawing
            // ie. our operations are still on pause until drawing is finished
            // Timer.Start(TimeSpan.FromMilliseconds(1));
            Timer.Start(new TimeSpan(1));

            //GS_test();

            if (TEST_PlotPrevious)
            {
            }
            else
            {
                return;
            }

            for (int index = 0; index < MarketSeries.Close.Count; index++)
            {
                Queue_TEST_Calculate.Enqueue(index);
                //TEST_Calculate(index);
            }

            if (TEST_Plot)
            {
                BarsTotalTimer.AutoReset = false;
                //BarsTotalTimer.Enabled = false;
            }
        }

        //this function may lose tick sequence during load
        protected override void OnTick()
        {
        }

        protected override void OnBar()
        {
            int index = MarketSeries.Close.Count - 1;

            if (Queue_TEST_Calculate.Count > 0)
            {
                Queue_TEST_Calculate.Enqueue(index);
            }
            else
            {
                TEST_Calculate(index);
            }
        }

        protected override void OnStop()
        {
            Timer.Stop();
        }
        //STOCK BOT

        //TEST
        public void TEST_Initialize()
        {
            BBSL_Initialize();
            DMS_Initialize();
            MACD_Initialize();
        }

        public void TEST_Calculate(int index)
        {
            if (TEST_Plot)
            {
                TEST_CalculatePlot(index);
            }
        }

        public void TEST_CalculatePlot(int index)
        {
            TEST_Plot_Chart_BarsTotal = Chart.BarsTotal;

            BBSL_Calculate(index);
            DMS_Calculate(index);
            MACD_Calculate(index);
        }

        private void TEST_OnTimedEvent_BarsTotal_Update(Object source, System.Timers.ElapsedEventArgs e)
        {
            TEST_Plot_Chart_BarsTotal = Chart.BarsTotal;
        }

        private static System.Timers.Timer TEST_Chart_ScrollChanged_Timer;
        bool TEST_Chart_ScrollChanged_OnTimer_Live = false;
        bool TEST_Chart_ScrollChanged_OnTimer_Finished = true;
        private void TEST_Chart_ScrollChanged_OnTimer(Object source, System.Timers.ElapsedEventArgs e)
        {
            //Print("The Elapsed event was raised at {0:HH:mm:ss.fff} {1}", e.SignalTime, source.ToString());

            TEST_Chart_ScrollChanged_OnTimer_Live = true;
            TEST_Chart_ScrollChanged_OnTimer_Finished = false;

            while (TEST_Chart_ScrollChanged_OnTimer_Live && Queue_TEST_Calculate.Count > 0)
            {
                Thread.Sleep(10);
            }

            TEST_TimeFrame_PlotLineTrace_Clear();

            for (int index = 0; TEST_Chart_ScrollChanged_OnTimer_Live && index < Chart.BarsTotal; index++)
            {
                TEST_CalculatePlot(index);
            }

            TEST_Chart_ScrollChanged_OnTimer_Live = false;
            TEST_Chart_ScrollChanged_OnTimer_Finished = true;
        }

        private void TEST_Chart_ScrollChanged(ChartScrollEventArgs obj)
        {
            if (TEST_Plot && 2 < (Chart.BarsTotal - Chart.LastVisibleBarIndex) && Chart.BarsTotal > TEST_Plot_Chart_BarsTotal)
            {
                TEST_Plot_Chart_BarsTotal = Chart.BarsTotal;
            }
            else
            {
                return;
            }

            if (TEST_Chart_ScrollChanged_Timer == null)
            {
            }
            else
            {
                if (TEST_Chart_ScrollChanged_Timer.GetType().GetRuntimeProperty("Enabled") == null)
                {
                }
                else
                {
                    TEST_Chart_ScrollChanged_Timer.Enabled = false;

                    if (TEST_Chart_ScrollChanged_OnTimer_Live)
                    {
                        TEST_Chart_ScrollChanged_OnTimer_Live = false;
                        while (!TEST_Chart_ScrollChanged_OnTimer_Finished)
                        {
                            Thread.Sleep(10);
                        }
                    }
                }
            }

            TEST_Chart_ScrollChanged_Timer = new System.Timers.Timer(1);
            TEST_Chart_ScrollChanged_Timer.Elapsed += TEST_Chart_ScrollChanged_OnTimer;
            TEST_Chart_ScrollChanged_Timer.AutoReset = false;
            TEST_Chart_ScrollChanged_Timer.Enabled = true;
        }

        protected override void OnTimer()
        {
            if (Queue_TEST_Calculate.Count > 0)
            {
            }
            else
            {
                Timer.Stop();
                return;
            }

            int index = -1;
            try
            {
                //int index;
                while (Queue_TEST_Calculate.TryDequeue(out index))
                {
                    TEST_Calculate(index);
                }
            } catch (ThreadAbortException e)
            {
                Thread.ResetAbort();

                Timer.Stop();
            }
        }

        protected void OnTimerPlot()
        {
            if (Queue_TEST_CalculatePlot.Count > 0)
            {
            }
            else
            {
                Timer.Stop();
                return;
            }

            int index = -1;
            try
            {
                //int index;
                while (Queue_TEST_CalculatePlot.TryDequeue(out index))
                {
                    TEST_CalculatePlot(index);
                }
            } catch (ThreadAbortException e)
            {
                Thread.ResetAbort();

                Timer.Stop();
            }
        }

        private MarketSeries TEST_getMarketSeries(TimeFrame timeFrame)
        {
            MarketSeries marketSeries;

            TEST_MarketSeries.TryGetValue(timeFrame.ToString(), out marketSeries);

            if (marketSeries == null)
            {
                marketSeries = MarketData.GetSeries(timeFrame);
                TEST_MarketSeries[timeFrame.ToString()] = marketSeries;
                Print("{0} @ Start: {1}, Finish: {2}", timeFrame, marketSeries.OpenTime[0], marketSeries.OpenTime[marketSeries.OpenTime.Count - 1]);
            }

            return marketSeries;
        }

        double? TEST_Plot_ScaleMax;
        public double TEST_Plot_getScaleMax()
        {
            if (TEST_Plot_ScaleMax == null)
            {
                TEST_Plot_ScaleMax = 1.75 * (1 - (((Chart.TopY - Chart.BottomY) * Symbol.PipSize) * (6 + (6 - Chart.Zoom) * 0.1)));
            }
            return (double)TEST_Plot_ScaleMax;
        }

        double? TEST_Plot_ScaleMin;
        public double TEST_Plot_getScaleMin()
        {
            if (TEST_Plot_ScaleMin == null)
            {
                TEST_Plot_ScaleMin = (100 * (100 / (Chart.TopY - Chart.BottomY))) / ((3 + ((1 / Symbol.PipSize) / 100)) * 4);
            }
            return (double)TEST_Plot_ScaleMin;
        }

        private IDictionary<string, TEST_TimeFrame_PlotLineTrace> TEST_TimeFrame_PlotLineTraces = new Dictionary<string, TEST_TimeFrame_PlotLineTrace>();
        public void TEST_TimeFrame_PlotLineTrace_Clear()
        {
            TEST_TimeFrame_PlotLineTraces = new Dictionary<string, TEST_TimeFrame_PlotLineTrace>();
        }

        public TEST_TimeFrame_PlotLineTrace TEST_TimeFrame_PlotLineTrace_Pre(string key, TimeFrame timeFrame1, int index1, TimeFrame timeFrame2, int index2)
        {
            if (TEST_TimeFrame_PlotLineTraces.ContainsKey(key))
            {
            }
            else
            {
                int TimeFrame1_IndexLast, TimeFrame2_IndexLast, TimeFrame1_IndexLastLast, TimeFrame2_IndexLastLast;
                Tuple<int, int> ret;
                MarketSeries marketSeries1 = TEST_getMarketSeries(timeFrame1);
                MarketSeries marketSeries2 = TEST_getMarketSeries(timeFrame2);
                if (timeFrame1 < timeFrame2)
                {
                    ret = TEST_MarketSeriesIndexSyncPrev(marketSeries1, marketSeries2, index1 - 1);
                    TimeFrame1_IndexLast = ret.Item1;
                    TimeFrame2_IndexLast = ret.Item2;
                    ret = TEST_MarketSeriesIndexSyncPrev(marketSeries1, marketSeries2, index1 - 2);
                    TimeFrame1_IndexLastLast = ret.Item1;
                    TimeFrame2_IndexLastLast = ret.Item2;
                }
                else
                {
                    ret = TEST_MarketSeriesIndexSyncPrev(marketSeries2, marketSeries1, index2 - 1);
                    TimeFrame1_IndexLast = ret.Item2;
                    TimeFrame2_IndexLast = ret.Item1;
                    ret = TEST_MarketSeriesIndexSyncPrev(marketSeries2, marketSeries1, index2 - 2);
                    TimeFrame1_IndexLastLast = ret.Item2;
                    TimeFrame2_IndexLastLast = ret.Item1;
                }

                TEST_TimeFrame_PlotLineTraces[key] = new TEST_TimeFrame_PlotLineTrace 
                {
                    TimeFrame1_Index = index1,
                    TimeFrame1_IndexLast = TimeFrame1_IndexLast > 0 ? TimeFrame1_IndexLast : 0,
                    TimeFrame1_IndexLastLast = TimeFrame1_IndexLastLast > 0 ? TimeFrame1_IndexLastLast : 0,
                    TimeFrame2_Index = index2,
                    TimeFrame2_IndexLast = TimeFrame2_IndexLast > 0 ? TimeFrame2_IndexLast : 0,
                    TimeFrame2_IndexLastLast = TimeFrame2_IndexLastLast > 0 ? TimeFrame2_IndexLastLast : 0
                };
            }

            TEST_TimeFrame_PlotLineTrace Trace = TEST_TimeFrame_PlotLineTraces[key];

            Trace.TimeFrame1_Index = index1;
            Trace.TimeFrame2_Index = index2;

            DateTime timeFrame1_DateTime = TEST_getMarketSeries(timeFrame1).OpenTime[index1];

            if (timeFrame1 < timeFrame2)
            {
                if (index2 > Trace.TimeFrame2_IndexLast)
                {
                    Trace.TimeFrame1_IndexLastLast = Trace.TimeFrame1_IndexLast;
                    Trace.TimeFrame1_IndexLast = index1 - 1;
                }
                else
                {
                    Trace.TimeFrame2_IndexLast = Trace.TimeFrame2_IndexLastLast;
                }
            }
            else
            {
                if (index2 > Trace.TimeFrame2_IndexLast)
                {
                }
                else
                {
                    Trace.TimeFrame2_IndexLast = Trace.TimeFrame2_IndexLastLast;
                }

                if (index1 > Trace.TimeFrame1_IndexLast)
                {
                }
                else
                {
                    Trace.TimeFrame1_IndexLast = Trace.TimeFrame1_IndexLastLast;
                }
            }

            TEST_TimeFrame_PlotLineTraces[key] = Trace;

            return Trace;
        }

        public void TEST_TimeFrame_PlotLineTrace_Post(string key, TimeFrame timeFrame1, int index1, TimeFrame timeFrame2, int index2)
        {
            if (TEST_TimeFrame_PlotLineTraces.ContainsKey(key))
            {
            }
            else
            {
                return;
            }

            TEST_TimeFrame_PlotLineTrace Trace = TEST_TimeFrame_PlotLineTraces[key];

            if (timeFrame1 < timeFrame2)
            {
                Trace.TimeFrame2_IndexLastLast = Trace.TimeFrame2_IndexLast;
                Trace.TimeFrame2_IndexLast = index2;
            }
            else
            {
                Trace.TimeFrame2_IndexLastLast = Trace.TimeFrame2_IndexLast;
                Trace.TimeFrame2_IndexLast = index2;

                Trace.TimeFrame1_IndexLastLast = Trace.TimeFrame1_IndexLast;
                Trace.TimeFrame1_IndexLast = index1;
            }

            TEST_TimeFrame_PlotLineTraces[key] = Trace;
        }

        //C# 7.0+
        //private (int index1, int index2) TEST_MarketSeriesIndexSyncNext(MarketSeries marketSeries1, MarketSeries marketSeries2, int marketSeriesIndex1)
        private Tuple<int, int> TEST_MarketSeriesIndexSyncNext(MarketSeries marketSeries1, MarketSeries marketSeries2, int marketSeriesIndex1)
        {
            int marketSeriesIndex2 = -1;

            while (0 > marketSeriesIndex2 && marketSeriesIndex1 < marketSeries1.OpenTime.Count)
            {
                DateTime dateTime = marketSeries1.OpenTime[marketSeriesIndex1];
                marketSeriesIndex2 = marketSeries2.OpenTime.GetIndexByTime(dateTime);
                marketSeriesIndex1++;
            }
            if (0 > marketSeriesIndex2)
            {
                marketSeriesIndex1 = -1;
            }
            else
            {
                marketSeriesIndex1--;
            }

            //C# 7.0+
            //return (marketSeriesIndex1, marketSeriesIndex2);
            return Tuple.Create(marketSeriesIndex1, marketSeriesIndex2);
        }

        private Tuple<int, int> TEST_MarketSeriesIndexSyncPrev(MarketSeries marketSeries1, MarketSeries marketSeries2, int marketSeriesIndex1)
        {
            int marketSeriesIndex2 = -1;

            while (0 > marketSeriesIndex2 && marketSeriesIndex1 > -1)
            {
                DateTime dateTime = marketSeries1.OpenTime[marketSeriesIndex1];
                marketSeriesIndex2 = marketSeries2.OpenTime.GetIndexByTime(dateTime);
                marketSeriesIndex1--;
            }
            if (0 > marketSeriesIndex2)
            {
                marketSeriesIndex1 = -1;
            }
            else
            {
                marketSeriesIndex1++;
            }

            return Tuple.Create(marketSeriesIndex1, marketSeriesIndex2);
        }

        private Tuple<int, int> TEST_MarketSeriesIndexSyncExactNext(MarketSeries marketSeries1, MarketSeries marketSeries2, int marketSeriesIndex1)
        {
            int marketSeriesIndex2 = -1;

            while (0 > marketSeriesIndex2 && marketSeriesIndex1 < marketSeries1.OpenTime.Count)
            {
                DateTime dateTime = marketSeries1.OpenTime[marketSeriesIndex1];
                marketSeriesIndex2 = marketSeries2.OpenTime.GetIndexByExactTime(dateTime);
                marketSeriesIndex1++;
            }
            if (0 > marketSeriesIndex2)
            {
                marketSeriesIndex1 = -1;
            }
            else
            {
                marketSeriesIndex1--;
            }

            return Tuple.Create(marketSeriesIndex1, marketSeriesIndex2);
        }

        private Tuple<int, int> TEST_MarketSeriesIndexSyncExactPrev(MarketSeries marketSeries1, MarketSeries marketSeries2, int marketSeriesIndex1)
        {
            int marketSeriesIndex2 = -1;

            while (0 > marketSeriesIndex2 && marketSeriesIndex1 > -1)
            {
                DateTime dateTime = marketSeries1.OpenTime[marketSeriesIndex1];
                marketSeriesIndex2 = marketSeries2.OpenTime.GetIndexByExactTime(dateTime);
                marketSeriesIndex1--;
            }
            if (0 > marketSeriesIndex2)
            {
                marketSeriesIndex1 = -1;
            }
            else
            {
                marketSeriesIndex1++;
            }

            return Tuple.Create(marketSeriesIndex1, marketSeriesIndex2);
        }
        //TEST

        //UTIL
        //https://www.ssec.wisc.edu/~tomw/java/unicode.html
        public int COM_StringToInt(string str)
        {
            return (int)str.ToCharArray()[0];
        }

        //https://www.ssec.wisc.edu/~tomw/java/unicode.html
        public string COM_IntToString(int dec)
        {
            return new string(new char[] 
            {
                (char)dec
            });
        }

        //https://www.ssec.wisc.edu/~tomw/java/unicode.html
        public enum UnicodeString
        {
            [Display(Name = "CIRCLED PLUS", Order = 8853, ShortName = "⊕"), Description("⊕")]
            CIRCLED_PLUS,
            [Display(Name = "CIRCLED MINUS", Order = 8854, ShortName = "⊖"), Description("⊖")]
            CIRCLED_MINUS,
            [Display(Name = "CIRCLED TIMES", Order = 8855, ShortName = "⊗"), Description("⊗")]
            CIRCLED_TIMES,
            [Display(Name = "CIRCLED DIVISION SLASH", Order = 8856, ShortName = "⊘"), Description("⊘")]
            CIRCLED_DIVISION_SLASH,
            [Display(Name = "CIRCLED DOT OPERATOR", Order = 8857, ShortName = "⊙"), Description("⊙")]
            CIRCLED_DOT_OPERATOR,
            [Display(Name = "CIRCLED RING OPERATOR", Order = 8858, ShortName = "⊚"), Description("⊚")]
            CIRCLED_RING_OPERATOR,
            [Display(Name = "CIRCLED ASTERISK OPERATOR", Order = 8859, ShortName = "⊛"), Description("⊛")]
            CIRCLED_ASTERISK_OPERATOR,
            [Display(Name = "CIRCLED EQUALS", Order = 8860, ShortName = "⊜"), Description("⊜")]
            CIRCLED_EQUALS,
            [Display(Name = "CIRCLED DASH", Order = 8861, ShortName = "⊝"), Description("⊝")]
            CIRCLED_DASH,
            [Display(Name = "APL FUNCTIONAL SYMBOL QUAD CIRCLE", Order = 9020, ShortName = "⌼"), Description("⌼")]
            APL_FUNC_SYM_QUAD_CIRCLE,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE STILE", Order = 9021, ShortName = "⌽"), Description("⌽")]
            APL_FUNC_SYM_CIRCLE_STILE,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE JOT", Order = 9022, ShortName = "⌾"), Description("⌾")]
            APL_FUNC_SYM_CIRCLE_JOT,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH", Order = 9033, ShortName = "⍉"), Description("⍉")]
            APL_FUNC_SYM_CIRCLE_BACKSLASH,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR", Order = 9052, ShortName = "⍜"), Description("⍜")]
            APL_FUNC_SYM_CIRCLE_UNDERBAR,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE STAR", Order = 9055, ShortName = "⍟"), Description("⍟")]
            APL_FUNC_SYM_CIRCLE_STAR,
            [Display(Name = "APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS", Order = 9061, ShortName = "⍥"), Description("⍥")]
            APL_FUNC_SYM_CIRCLE_DIAERESIS,
            [Display(Name = "CIRCLED HORIZONTAL BAR WITH NOTCH", Order = 9097, ShortName = "⎉"), Description("⎉")]
            CIRCLED_HORIZONTAL_BAR_W_NOTCH,
            [Display(Name = "CIRCLED TRIANGLE DOWN", Order = 9098, ShortName = "⎊"), Description("⎊")]
            CIRCLED_TRIANGLE_DOWN,
            [Display(Name = "CIRCLED DIGIT ONE", Order = 9312, ShortName = "①"), Description("①")]
            CIRCLED_DIGIT_ONE,
            [Display(Name = "CIRCLED DIGIT TWO", Order = 9313, ShortName = "②"), Description("②")]
            CIRCLED_DIGIT_TWO,
            [Display(Name = "CIRCLED DIGIT THREE", Order = 9314, ShortName = "③"), Description("③")]
            CIRCLED_DIGIT_THREE,
            [Display(Name = "CIRCLED DIGIT FOUR", Order = 9315, ShortName = "④"), Description("④")]
            CIRCLED_DIGIT_FOUR,
            [Display(Name = "CIRCLED DIGIT FIVE", Order = 9316, ShortName = "⑤"), Description("⑤")]
            CIRCLED_DIGIT_FIVE,
            [Display(Name = "CIRCLED DIGIT SIX", Order = 9317, ShortName = "⑥"), Description("⑥")]
            CIRCLED_DIGIT_SIX,
            [Display(Name = "CIRCLED DIGIT SEVEN", Order = 9318, ShortName = "⑦"), Description("⑦")]
            CIRCLED_DIGIT_SEVEN,
            [Display(Name = "CIRCLED DIGIT EIGHT", Order = 9319, ShortName = "⑧"), Description("⑧")]
            CIRCLED_DIGIT_EIGHT,
            [Display(Name = "CIRCLED DIGIT NINE", Order = 9320, ShortName = "⑨"), Description("⑨")]
            CIRCLED_DIGIT_NINE,
            [Display(Name = "CIRCLED NUMBER TEN", Order = 9321, ShortName = "⑩"), Description("⑩")]
            CIRCLED_NUMBER_TEN,
            [Display(Name = "CIRCLED NUMBER ELEVEN", Order = 9322, ShortName = "⑪"), Description("⑪")]
            CIRCLED_NUMBER_ELEVEN,
            [Display(Name = "CIRCLED NUMBER TWELVE", Order = 9323, ShortName = "⑫"), Description("⑫")]
            CIRCLED_NUMBER_TWELVE,
            [Display(Name = "CIRCLED NUMBER THIRTEEN", Order = 9324, ShortName = "⑬"), Description("⑬")]
            CIRCLED_NUMBER_THIRTEEN,
            [Display(Name = "CIRCLED NUMBER FOURTEEN", Order = 9325, ShortName = "⑭"), Description("⑭")]
            CIRCLED_NUMBER_FOURTEEN,
            [Display(Name = "CIRCLED NUMBER FIFTEEN", Order = 9326, ShortName = "⑮"), Description("⑮")]
            CIRCLED_NUMBER_FIFTEEN,
            [Display(Name = "CIRCLED NUMBER SIXTEEN", Order = 9327, ShortName = "⑯"), Description("⑯")]
            CIRCLED_NUMBER_SIXTEEN,
            [Display(Name = "CIRCLED NUMBER SEVENTEEN", Order = 9328, ShortName = "⑰"), Description("⑰")]
            CIRCLED_NUMBER_SEVENTEEN,
            [Display(Name = "CIRCLED NUMBER EIGHTEEN", Order = 9329, ShortName = "⑱"), Description("⑱")]
            CIRCLED_NUMBER_EIGHTEEN,
            [Display(Name = "CIRCLED NUMBER NINETEEN", Order = 9330, ShortName = "⑲"), Description("⑲")]
            CIRCLED_NUMBER_NINETEEN,
            [Display(Name = "CIRCLED NUMBER TWENTY", Order = 9331, ShortName = "⑳"), Description("⑳")]
            CIRCLED_NUMBER_TWENTY,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER A", Order = 9398, ShortName = "Ⓐ"), Description("Ⓐ")]
            CIRCLED_LATIN_CAPITAL_LETTER_A,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER B", Order = 9399, ShortName = "Ⓑ"), Description("Ⓑ")]
            CIRCLED_LATIN_CAPITAL_LETTER_B,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER C", Order = 9400, ShortName = "Ⓒ"), Description("Ⓒ")]
            CIRCLED_LATIN_CAPITAL_LETTER_C,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER D", Order = 9401, ShortName = "Ⓓ"), Description("Ⓓ")]
            CIRCLED_LATIN_CAPITAL_LETTER_D,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER E", Order = 9402, ShortName = "Ⓔ"), Description("Ⓔ")]
            CIRCLED_LATIN_CAPITAL_LETTER_E,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER F", Order = 9403, ShortName = "Ⓕ"), Description("Ⓕ")]
            CIRCLED_LATIN_CAPITAL_LETTER_F,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER G", Order = 9404, ShortName = "Ⓖ"), Description("Ⓖ")]
            CIRCLED_LATIN_CAPITAL_LETTER_G,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER H", Order = 9405, ShortName = "Ⓗ"), Description("Ⓗ")]
            CIRCLED_LATIN_CAPITAL_LETTER_H,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER I", Order = 9406, ShortName = "Ⓘ"), Description("Ⓘ")]
            CIRCLED_LATIN_CAPITAL_LETTER_I,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER J", Order = 9407, ShortName = "Ⓙ"), Description("Ⓙ")]
            CIRCLED_LATIN_CAPITAL_LETTER_J,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER K", Order = 9408, ShortName = "Ⓚ"), Description("Ⓚ")]
            CIRCLED_LATIN_CAPITAL_LETTER_K,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER L", Order = 9409, ShortName = "Ⓛ"), Description("Ⓛ")]
            CIRCLED_LATIN_CAPITAL_LETTER_L,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER M", Order = 9410, ShortName = "Ⓜ"), Description("Ⓜ")]
            CIRCLED_LATIN_CAPITAL_LETTER_M,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER N", Order = 9411, ShortName = "Ⓝ"), Description("Ⓝ")]
            CIRCLED_LATIN_CAPITAL_LETTER_N,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER O", Order = 9412, ShortName = "Ⓞ"), Description("Ⓞ")]
            CIRCLED_LATIN_CAPITAL_LETTER_O,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER P", Order = 9413, ShortName = "Ⓟ"), Description("Ⓟ")]
            CIRCLED_LATIN_CAPITAL_LETTER_P,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER Q", Order = 9414, ShortName = "Ⓠ"), Description("Ⓠ")]
            CIRCLED_LATIN_CAPITAL_LETTER_Q,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER R", Order = 9415, ShortName = "Ⓡ"), Description("Ⓡ")]
            CIRCLED_LATIN_CAPITAL_LETTER_R,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER S", Order = 9416, ShortName = "Ⓢ"), Description("Ⓢ")]
            CIRCLED_LATIN_CAPITAL_LETTER_S,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER T", Order = 9417, ShortName = "Ⓣ"), Description("Ⓣ")]
            CIRCLED_LATIN_CAPITAL_LETTER_T,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER U", Order = 9418, ShortName = "Ⓤ"), Description("Ⓤ")]
            CIRCLED_LATIN_CAPITAL_LETTER_U,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER V", Order = 9419, ShortName = "Ⓥ"), Description("Ⓥ")]
            CIRCLED_LATIN_CAPITAL_LETTER_V,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER W", Order = 9420, ShortName = "Ⓦ"), Description("Ⓦ")]
            CIRCLED_LATIN_CAPITAL_LETTER_W,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER X", Order = 9421, ShortName = "Ⓧ"), Description("Ⓧ")]
            CIRCLED_LATIN_CAPITAL_LETTER_X,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER Y", Order = 9422, ShortName = "Ⓨ"), Description("Ⓨ")]
            CIRCLED_LATIN_CAPITAL_LETTER_Y,
            [Display(Name = "CIRCLED LATIN CAPITAL LETTER Z", Order = 9423, ShortName = "Ⓩ"), Description("Ⓩ")]
            CIRCLED_LATIN_CAPITAL_LETTER_Z,
            [Display(Name = "CIRCLED LATIN SMALL LETTER A", Order = 9424, ShortName = "ⓐ"), Description("ⓐ")]
            CIRCLED_LATIN_SMALL_LETTER_A,
            [Display(Name = "CIRCLED LATIN SMALL LETTER B", Order = 9425, ShortName = "ⓑ"), Description("ⓑ")]
            CIRCLED_LATIN_SMALL_LETTER_B,
            [Display(Name = "CIRCLED LATIN SMALL LETTER C", Order = 9426, ShortName = "ⓒ"), Description("ⓒ")]
            CIRCLED_LATIN_SMALL_LETTER_C,
            [Display(Name = "CIRCLED LATIN SMALL LETTER D", Order = 9427, ShortName = "ⓓ"), Description("ⓓ")]
            CIRCLED_LATIN_SMALL_LETTER_D,
            [Display(Name = "CIRCLED LATIN SMALL LETTER E", Order = 9428, ShortName = "ⓔ"), Description("ⓔ")]
            CIRCLED_LATIN_SMALL_LETTER_E,
            [Display(Name = "CIRCLED LATIN SMALL LETTER F", Order = 9429, ShortName = "ⓕ"), Description("ⓕ")]
            CIRCLED_LATIN_SMALL_LETTER_F,
            [Display(Name = "CIRCLED LATIN SMALL LETTER G", Order = 9430, ShortName = "ⓖ"), Description("ⓖ")]
            CIRCLED_LATIN_SMALL_LETTER_G,
            [Display(Name = "CIRCLED LATIN SMALL LETTER H", Order = 9431, ShortName = "ⓗ"), Description("ⓗ")]
            CIRCLED_LATIN_SMALL_LETTER_H,
            [Display(Name = "CIRCLED LATIN SMALL LETTER I", Order = 9432, ShortName = "ⓘ"), Description("ⓘ")]
            CIRCLED_LATIN_SMALL_LETTER_I,
            [Display(Name = "CIRCLED LATIN SMALL LETTER J", Order = 9433, ShortName = "ⓙ"), Description("ⓙ")]
            CIRCLED_LATIN_SMALL_LETTER_J,
            [Display(Name = "CIRCLED LATIN SMALL LETTER K", Order = 9434, ShortName = "ⓚ"), Description("ⓚ")]
            CIRCLED_LATIN_SMALL_LETTER_K,
            [Display(Name = "CIRCLED LATIN SMALL LETTER L", Order = 9435, ShortName = "ⓛ"), Description("ⓛ")]
            CIRCLED_LATIN_SMALL_LETTER_L,
            [Display(Name = "CIRCLED LATIN SMALL LETTER M", Order = 9436, ShortName = "ⓜ"), Description("ⓜ")]
            CIRCLED_LATIN_SMALL_LETTER_M,
            [Display(Name = "CIRCLED LATIN SMALL LETTER N", Order = 9437, ShortName = "ⓝ"), Description("ⓝ")]
            CIRCLED_LATIN_SMALL_LETTER_N,
            [Display(Name = "CIRCLED LATIN SMALL LETTER O", Order = 9438, ShortName = "ⓞ"), Description("ⓞ")]
            CIRCLED_LATIN_SMALL_LETTER_O,
            [Display(Name = "CIRCLED LATIN SMALL LETTER P", Order = 9439, ShortName = "ⓟ"), Description("ⓟ")]
            CIRCLED_LATIN_SMALL_LETTER_P,
            [Display(Name = "CIRCLED LATIN SMALL LETTER Q", Order = 9440, ShortName = "ⓠ"), Description("ⓠ")]
            CIRCLED_LATIN_SMALL_LETTER_Q,
            [Display(Name = "CIRCLED LATIN SMALL LETTER R", Order = 9441, ShortName = "ⓡ"), Description("ⓡ")]
            CIRCLED_LATIN_SMALL_LETTER_R,
            [Display(Name = "CIRCLED LATIN SMALL LETTER S", Order = 9442, ShortName = "ⓢ"), Description("ⓢ")]
            CIRCLED_LATIN_SMALL_LETTER_S,
            [Display(Name = "CIRCLED LATIN SMALL LETTER T", Order = 9443, ShortName = "ⓣ"), Description("ⓣ")]
            CIRCLED_LATIN_SMALL_LETTER_T,
            [Display(Name = "CIRCLED LATIN SMALL LETTER U", Order = 9444, ShortName = "ⓤ"), Description("ⓤ")]
            CIRCLED_LATIN_SMALL_LETTER_U,
            [Display(Name = "CIRCLED LATIN SMALL LETTER V", Order = 9445, ShortName = "ⓥ"), Description("ⓥ")]
            CIRCLED_LATIN_SMALL_LETTER_V,
            [Display(Name = "CIRCLED LATIN SMALL LETTER W", Order = 9446, ShortName = "ⓦ"), Description("ⓦ")]
            CIRCLED_LATIN_SMALL_LETTER_W,
            [Display(Name = "CIRCLED LATIN SMALL LETTER X", Order = 9447, ShortName = "ⓧ"), Description("ⓧ")]
            CIRCLED_LATIN_SMALL_LETTER_X,
            [Display(Name = "CIRCLED LATIN SMALL LETTER Y", Order = 9448, ShortName = "ⓨ"), Description("ⓨ")]
            CIRCLED_LATIN_SMALL_LETTER_Y,
            [Display(Name = "CIRCLED LATIN SMALL LETTER Z", Order = 9449, ShortName = "ⓩ"), Description("ⓩ")]
            CIRCLED_LATIN_SMALL_LETTER_Z,
            [Display(Name = "CIRCLED DIGIT ZERO", Order = 9450, ShortName = "⓪"), Description("⓪")]
            CIRCLED_DIGIT_ZERO,
            [Display(Name = "WHITE CIRCLE", Order = 9675, ShortName = "○"), Description("○")]
            WHITE_CIRCLE,
            [Display(Name = "DOTTED CIRCLE", Order = 9676, ShortName = "◌"), Description("◌")]
            DOTTED_CIRCLE,
            [Display(Name = "CIRCLE WITH VERTICAL FILL", Order = 9677, ShortName = "◍"), Description("◍")]
            CIRCLE_WITH_VERTICAL_FILL,
            [Display(Name = "BLACK CIRCLE", Order = 9679, ShortName = "●"), Description("●")]
            BLACK_CIRCLE,
            [Display(Name = "CIRCLED WHITE STAR", Order = 10026, ShortName = "✪"), Description("✪")]
            CIRCLED_WHITE_STAR,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT ONE", Order = 10112, ShortName = "➀"), Description("➀")]
            DINGBAT_CIRCLED_SS_ONE,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT TWO", Order = 10113, ShortName = "➁"), Description("➁")]
            DINGBAT_CIRCLED_SS_TWO,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT THREE", Order = 10114, ShortName = "➂"), Description("➂")]
            DINGBAT_CIRCLED_SS_THREE,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT FOUR", Order = 10115, ShortName = "➃"), Description("➃")]
            DINGBAT_CIRCLED_SS_FOUR,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT FIVE", Order = 10116, ShortName = "➄"), Description("➄")]
            DINGBAT_CIRCLED_SS_FIVE,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT SIX", Order = 10117, ShortName = "➅"), Description("➅")]
            DINGBAT_CIRCLED_SS_SIX,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT SEVEN", Order = 10118, ShortName = "➆"), Description("➆")]
            DINGBAT_CIRCLED_SS_SEVEN,
            [Display(Name = "DINGBAT CIRCLED SANS - SERIF DIGIT EIGHT", Order = 10119, ShortName = "➇"), Description("➇")]
            DINGBAT_CIRCLED_SS_EIGHT,
            [Display(Name = "DINGBAT CIRCLED SANS-SERIF DIGIT NINE", Order = 10120, ShortName = "➈"), Description("➈")]
            DINGBAT_CIRCLED_SS_NINE,
            [Display(Name = "DINGBAT CIRCLED SANS-SERIF NUMBER TEN", Order = 10121, ShortName = "➉"), Description("➉")]
            DINGBAT_CIRCLED_SS_TEN,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE", Order = 10122, ShortName = "➊"), Description("➊")]
            DINGBAT_NEG_CIRCLED_SS_ONE,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO", Order = 10123, ShortName = "➋"), Description("➋")]
            DINGBAT_NEG_CIRCLED_SS_TWO,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE", Order = 10124, ShortName = "➌"), Description("➌")]
            DINGBAT_NEG_CIRCLED_SS_THREE,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR", Order = 10125, ShortName = "➍"), Description("➍")]
            DINGBAT_NEG_CIRCLED_SS_FOUR,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE", Order = 10126, ShortName = "➎"), Description("➎")]
            DINGBAT_NEG_CIRCLED_SS_FIVE,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX", Order = 10127, ShortName = "➏"), Description("➏")]
            DINGBAT_NEG_CIRCLED_SS_SIX,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN", Order = 10128, ShortName = "➐"), Description("➐")]
            DINGBAT_NEG_CIRCLED_SS_SEVEN,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT", Order = 10129, ShortName = "➑"), Description("➑")]
            DINGBAT_NEG_CIRCLED_SS_EIGHT,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE", Order = 10130, ShortName = "➒"), Description("➒")]
            DINGBAT_NEG_CIRCLED_SS_NINE,
            [Display(Name = "DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN", Order = 10131, ShortName = "➓"), Description("➓")]
            DINGBAT_NEG_CIRCLED_SS_TEN,
            [Display(Name = "HALFWIDTH WHITE CIRCLE", Order = 65518, ShortName = "○"), Description("○")]
            HALFWIDTH_WHITE_CIRCLE
        }

        //UTIL
    }
    public static class Extensions
    {
        /*
        public static string GetDescription2(this Enum e)
        {
            var attribute =
                e.GetType()
                    .GetTypeInfo()
                    .GetMember(e.ToString())
                    .FirstOrDefault(member => member.MemberType == MemberTypes.Field)
                    .GetCustomAttributes(typeof(DescriptionAttribute), false)
                    .SingleOrDefault()
                    as DescriptionAttribute;

            return attribute?.Description ?? e.ToString();
        }
        */

        public static string GetDescription<T>(this T e) where T : IConvertible
        {
            if (e is Enum)
            {
                Type type = e.GetType();
                Array values = System.Enum.GetValues(type);

                foreach (int val in values)
                {
                    if (val == e.ToInt32(CultureInfo.InvariantCulture))
                    {
                        MemberInfo[] memInfo = type.GetMember(type.GetEnumName(val));
                        DescriptionAttribute descriptionAttribute = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() as DescriptionAttribute;

                        if (descriptionAttribute != null)
                        {
                            return descriptionAttribute.Description;
                        }
                    }
                }
            }

            return null;
            //return string.Empty
        }

    }

    public class TEST_TimeFrame_PlotLineTrace
    {
        public int TimeFrame1_IndexLastLast { get; set; }
        public int TimeFrame1_IndexLast { get; set; }
        public int TimeFrame1_Index { get; set; }

        public int TimeFrame2_IndexLastLast { get; set; }
        public int TimeFrame2_IndexLast { get; set; }
        public int TimeFrame2_Index { get; set; }
    }
}

 

I have removed a lot of other code but this is the drawing and scroll movment to the past indexes which causes redrawing of the chart that still crashes. Im pretty certain this crash didnt happen before the last cTrader update (or i was very lucky in abusing the test with no crash).

Try on two different timeframes, one may cause the crash to happen sooner than the other eg. Hour4 or Minute. load the Bot, wait until Chart has finished drawing, then use the scroll bar to go to the far left and let the marketseries data change and another redraw to happen. after that either way or dont wait and keep moving to the past at the far left to cause a repeat of the same. sometimes it takes many marketseries data refreshes or sometimes not many at all to cause the crash. It seems if you wait for a long period of time before attempting each scroll to the past you can avoid a crash.

I assume the crash error number is internal so you guys must have some more detail about it you could share?

cheers and thanks for having a look as to what it may be, again i was testing the behaviour pretty hard before release (with no crashing) and its only started doing it recently.

 


@buccinator

buccinator
06 Sep 2019, 12:20

although this is only triggered in my bot on scrollbar event, if i try to use it as a normal user (quickly) after a redraw, i get a few attempts before crash. however if i wait a good 10+ seconds between scrollbar useage, it does not crash.


@buccinator

buccinator
06 Sep 2019, 11:42

i reverted my code to when it was all contained in the robot class (and tested OK heavily with no crashes). however i now get the same error even with the previous code, so i guess it has nothing to do with external classes or Chart.ScrollChanged at all.

 

any pointers as to what it may be? 


@buccinator

buccinator
04 Sep 2019, 11:56

RE:

admin said:

You may extend the class name of the robot you are trying to reference. 

 

//#reference: ..\Robots\test_Referenced.algo
// -------------------------------------------------------------------------------
//
//    This is a Template used as a guideline to build your own Robot. 
//    Please use the “Feedback” tab to provide us with your suggestions about cAlgo’s API.
//
// -------------------------------------------------------------------------------

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

namespace cAlgo.Robots
{
    [Robot]
    public class test_ReferenceRobot : test_Referenced
    {
        protected override void OnStart()
        {
        	base.Volume = 100;
            base.OnStart();
        }

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

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


 

// -------------------------------------------------------------------------------
//
//    This is a Template used as a guideline to build your own Robot. 
//    Please use the “Feedback” tab to provide us with your suggestions about cAlgo’s API.
//
// -------------------------------------------------------------------------------

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

namespace cAlgo.Robots
{
    [Robot]
    public class test_Referenced : Robot
    {
        [Parameter(DefaultValue = 10000, MinValue = 0)]
        public int Volume { get; set; }


        protected override void OnStart()
        {
            Print("test_Referenced Volume {0}", Volume);
        }

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

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

 


 

 

for anyone interested it doing this it seems you have to remove the [Robot] line from the base class.

https://ctrader.com/forum/calgo-support/3827?page=1


@buccinator

buccinator
30 Aug 2019, 10:08

my bot is over 2700 lines of code and it seems irrelevant as it crashed first line of code at OnStart(). 

i just tried replicating the error in a new template bot with no luck. i tried with lots of parameters and big enums thinking it would somehow change the outcome, it did not.

the workaround i originally posted works so will stick with that, i guess its a heads up if anyone else (somehow) has the same issue.

from memory i believe it was a crashed with "onstart error with null reference exception object not set to an instance of an object".

the first line of code i had in OnStart() was use of the Chart object. sorry i am unable to replicate the issue in a template bot.


@buccinator

buccinator
30 Aug 2019, 09:24

as soon as cTrader has loaded, quickly have your mouse over the blue play button for a bot, soon as it turns from greyed blue to deep blue click it. it seems to happen on most of the time on first load of cTrader.


@buccinator

buccinator
29 Aug 2019, 08:09

just an update to anyone who found this, the third step is not needed ie. updating machine.config. i am also adding the search term " google sheets " to this thread as it doesnt seem to be returning in the forum search.


@buccinator

buccinator
15 Aug 2019, 11:41

i just tried to do the same thing and no luck, do you have a work around?


@buccinator

buccinator
04 Aug 2019, 12:57

spoke too soon

well, i..

1. switched Properties>Application>Target Framework to .NET Framework 4.6.1

2. Updated NuGet packages

3. Updated machine.config from new app.config

.. and its now working.


@buccinator