    // File Name: scstructures.h

    // Notice: Changes to existing data structures and types in this file need to consider that existing custom studies can be affected by this.  There must not be changes to existing members.

    #ifndef _SCSTRUCTURES_H_
    #define _SCSTRUCTURES_H_

    #ifndef NOMINMAX
    // If NOMINMAX is not already defined, make a note if it so that it can be
    // disabled at a later point.
    #define SC_UNDEF_NOMINMAX
    #endif

    #include <windows.h> //Main Windows SDK header file
    #include <stdio.h> //This header is for input/output including file input/output
    #include <stdarg.h>
    #include <float.h>
    #include <io.h>
    #define _USE_MATH_DEFINES
    #include <math.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    //#include "ASCILDrawGraphics.h"
    #include <algorithm>

    #include <cstdlib>
    #ifdef __GNUC__
    // cstdlib on MinGW/GCC appears to always define NOMINMAX, which is not
    // usually desired on remote builds for custom study DLLs.
    //
    // Note: we do not want do undefine NOMINMAX if it was intentionally defined
    // earlier than this include.
    #ifdef SC_UNDEF_NOMINMAX
    #undef NOMINMAX
    #endif
    #endif
    #include <csignal>
    #include <csetjmp>
    #include <cstdarg>
    #include <typeinfo>
    #include <bitset>
    #include <functional>
    #include <utility>
    #include <ctime>
    #include <cstddef>
    #include <new>
    #include <memory>
    #include <climits>
    #include <cfloat>
    #include <limits>
    #include <exception>
    #include <stdexcept>
    #include <cassert>
    #include <cerrno>
    #include <cctype>
    #include <cwctype>
    #include <cstring>
    #include <cwchar>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
    #include <set>
    #include <map>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <iterator>
    #include <cmath>
    #include <complex>
    #include <valarray>
    #include <numeric>
    #include <iosfwd>
    #include <ios>
    #include <istream>
    #include <ostream>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <streambuf>
    #include <cstdio>
    #include <cstdint>
    #include <cmath>
    #include <chrono>

    #ifndef NOMINMAX
    #ifndef max
    #define max(a,b)            (((a) > (b)) ? (a) : (b))
    #endif

    #ifndef min
    #define min(a,b)            (((a) < (b)) ? (a) : (b))
    #endif
    #endif

    #define RGB_COLOR(r,g,b)        ((uint32_t)(((uint8_t)(r)|((uint16_t)((uint8_t)(g))<<8))|(((uint32_t)(uint8_t)(b))<<16)))

    /****************************************************************************/

    #include "scconstants.h"
    #include "scdatetime.h"
    #include "SCSymbolData.h"
    #include "sccolors.h"
    #include "VAPContainer.h"
    #include "SCString.h"

    struct s_sc;// forward declaration

    typedef s_sc& SCStudyInterfaceRef;

    const int CURRENT_SC_NEW_ORDER_VERSION = 18;
    const int CURRENT_SC_ORDER_FILL_DATA_VERSION = 4;

    #define SCDLLEXPORT extern "C" __declspec(dllexport)
    #define SCDLLCALL __cdecl

    #define SCSFExport SCDLLEXPORT void SCDLLCALL  // Use SCSFExport when defining a study function

    #define SCDLLName(DLLName) \
        SCDLLEXPORT int SCDLLCALL scdll_DLLVersion() { return SC_DLL_VERSION; } \
        SCDLLEXPORT const char* SCDLLCALL scdll_DLLName() { return DLLName; }

    typedef void (SCDLLCALL* fp_ACSGDIFunction)(HWND WindowHandle, HDC DeviceContext, SCStudyInterfaceRef);

    /****************************************************************************/

    struct s_TimeAndSales
    {
        SCDateTimeMS DateTime;// UTC
        float Price = 0;
        uint32_t Volume = 0;
        float Bid = 0;
        float Ask = 0;
        uint32_t BidSize = 0;
        uint32_t AskSize = 0;

        //This will always be a value >= 1.  It is unlikely to wrap around, but it could.  It will never be 0.
        uint32_t Sequence = 0;

        int16_t UnbundledTradeIndicator = 0;
        int16_t Type = 0;
        uint32_t TotalBidDepth = 0;
        uint32_t TotalAskDepth = 0;
        int8_t TradeIndicator = 0;

        s_TimeAndSales()
        {

        }

        explicit s_TimeAndSales(int Value)
        {

        }

        s_TimeAndSales& operator *= (float Multiplier)
        {
            Price *= Multiplier;
            Bid *= Multiplier;
            Ask *= Multiplier;

            return *this;
        }

        void Clear()
        {
            *this = s_TimeAndSales();
        }

        bool operator < (const s_TimeAndSales&  Right) const
        {
            return  Sequence < Right.Sequence;
        }
    };

    class c_SCTimeAndSalesArray
    {
        private:

        protected:
            const int m_Version=1;
            s_TimeAndSales* m_p_Data = nullptr;
            int m_MaxSize = 0;
            int m_NextIndex = 0;
            int m_StartAtNext = 0;

        public:
            /*==================================================================*/
            c_SCTimeAndSalesArray()
            {
            }

            /*==================================================================*/
            ~c_SCTimeAndSalesArray()
            {
            }

            /*==================================================================*/
            //Thread safe as long as an instance of this object is only used by one thread at a time.
            int IsCreated() const
            {
                return (m_p_Data != NULL) ? 1 : 0;
            }

            /*==================================================================*/
            int MaxSize() const
            {
                return m_MaxSize;
            }

            /*==================================================================*/
            int Size() const
            {
                if (m_p_Data == NULL)
                    return 0;

                if (m_StartAtNext)
                    return m_MaxSize;  // Using the full buffer
                else
                    return m_NextIndex;  // Using only up to m_NextIndex
            }

            /*====================================================================
                This function is for backwards compatibility.
            --------------------------------------------------------------------*/
            int GetArraySize() const
            {
                return Size();
            }

            /*====================================================================
                The oldest element is at index 0, and the newest element is at
                index Size()-1.
            --------------------------------------------------------------------*/
            const s_TimeAndSales& operator [] (int Index) const
            {
                static s_TimeAndSales DefaultElement;

                if (m_p_Data == NULL)
                    return DefaultElement;

                if (Index < 0 || Index >= Size())
                    return DefaultElement;

                // Translate the index
                if (m_StartAtNext)
                {
                    Index += m_NextIndex;

                    if (Index >= m_MaxSize)
                        Index -= m_MaxSize;
                }

                return m_p_Data[Index];
            }

            /*====================================================================
                This does not copy the data, it just copies the pointer from the
                given Time and Sales array.
            --------------------------------------------------------------------*/
            c_SCTimeAndSalesArray& operator = (const c_SCTimeAndSalesArray& Rhs)
            {
                if (&Rhs == this)
                    return *this;

                m_p_Data = Rhs.m_p_Data;
                m_MaxSize = Rhs.m_MaxSize;
                m_NextIndex = Rhs.m_NextIndex;
                m_StartAtNext = Rhs.m_StartAtNext;

                return *this;
            }

            bool IsRecordIndexTrade (int Index)
            {
                return (operator[](Index).Type == SC_TS_ASK  || operator[](Index).Type  == SC_TS_BID );
            }

            SCDateTimeMS GetDateTimeOfLastTradeRecord()
            {
                int ArraySize = Size();
                if (ArraySize == 0)
                    return 0.0;

                for (int RecordIndex = ArraySize - 1; RecordIndex >= 0; RecordIndex--)
                {
                    if (IsRecordIndexTrade(RecordIndex))
                        return operator[](RecordIndex).DateTime;
                }

                return 0.0;
            }

            const uint32_t GetIndexOfLessEqualRecordAtDateTime(const SCDateTimeMS& SearchDateTime) const
            {
                if (Size() == 0)
                    return 0;

                //Perform binary search using operator[] to locate search date-time
                //Elements are in time-ascending order

                int IndexUpper = 0;
                int IndexLower = IndexUpper;
                const size_t EndIndex = Size();
                int Count = Size();

                while (Count > 0)
                {
                    const int Step = Count / 2;
                    const int TestIndex = IndexUpper + Step;

                    if (operator[](TestIndex).DateTime <= SearchDateTime)
                    {
                        IndexLower = TestIndex;
                        IndexUpper = TestIndex + 1;
                        Count -= Step + 1;
                    }
                    else
                    {
                        Count = Step;
                    }
                }

                return IndexLower;
            }

            const s_TimeAndSales& GetLessEqualRecordAtDateTime(const SCDateTimeMS& SearchDateTime) const
            {
                static s_TimeAndSales DefaultElement;

                if (Size() == 0)
                    return DefaultElement;

                uint32_t FoundIndex = GetIndexOfLessEqualRecordAtDateTime(SearchDateTime);

                return operator[](FoundIndex);
            }

            uint32_t GetRecordIndexAtGreaterThanSequenceNumber(uint32_t SequenceNumber) const
            {
                /* This function needs to perform a fast binary search of the c_SCTimeAndSalesArray
                container and return the index of the record with a sequence number greater than
                the given SequenceNumber.
                Keep in mind that  the member variables m_NextIndex, m_StartAtNext indicate what
                the first record is in the array.
                std::upper_bound  cannot be used unless we implement forward iterators on this class.
                Return -1 if the array is empty.
                If the first array element has a sequence number greater than SequenceNumber, then return 0.
                If the last array element has a sequence number less than SequenceNumber, then return the size of the array - 1.
                */

                if (Size() == 0)
                    return -1;

                if (SequenceNumber == 0)
                    return 0;

                int IndexUpper = 0;
                int Count = Size();

                while (Count > 0)
                {
                    const int Step = Count >> 1;
                    const int TestIndex = IndexUpper + Step;

                    if (operator[](TestIndex).Sequence > SequenceNumber)
                    {
                        Count = Step;
                    }
                    else
                    {
                        IndexUpper = TestIndex + 1;
                        Count -= Step + 1;
                    }

                }

                if (IndexUpper >= Size())
                    IndexUpper = Size() - 1;

                return IndexUpper;
            }

            uint32_t GetSequenceNumberOfLastElement() const
            {
                uint32_t ArraySize = Size();

                if (ArraySize == 0)
                    return 0;

                return operator[](ArraySize - 1).Sequence;
            }

            void ValidateAndCorrectPriorSequenceNumber(uint32_t& r_PriorSequenceNumber) const
            {
                //There has either been a sequence number wrap or reset back to 0 so we need to consider that.  Otherwise, we create a condition, where we do not process new time and sales data.

                if (r_PriorSequenceNumber > GetSequenceNumberOfLastElement())
                {
                    //CommonAddMessageToLog("Prior Time Sales sequence number reset", false);

                    r_PriorSequenceNumber = 0;
                }
            }
    };

    /****************************************************************************/

    class s_UseTool
    {
    public:
        static const int DEFAULT_COLOR_VALUE = 0xFF000000;

        private:
            unsigned int Size = sizeof(s_UseTool);;
        public:
            int ChartNumber = 0;
            int Unused_1 = 0;
            int LineNumber = -1;
            int ExtendLeft = -1;
            int ExtendRight = -1;
            int TransparencyLevel = -1;
            int FourthIndex = -1;
            float BeginValue = FLT_MIN;
            float EndValue = FLT_MIN;
            int Region = -1;
            uint32_t Color = DEFAULT_COLOR_VALUE;
            uint64_t Unused_2 = 0;
            int FontSize = -1;
            char ShowBeginMark = -1;
            char ShowEndMark = -1;
            int16_t IsSelected = 0;
            float RetracementLevels[ACSIL_DRAWING_MAX_LEVELS] = {};
            SCDateTimeMS BeginDateTime;
            SCDateTimeMS EndDateTime;
            SCString Text;

            DrawingTypeEnum DrawingType = DRAWING_UNKNOWN;
            uint16_t LineWidth = 0xffff;
            SubgraphLineStyles LineStyle = LINESTYLE_UNSET;

            int AddMethod = UTAM_ADD_OR_ADJUST;

        private:
            unsigned int Version = SC_DLL_VERSION;
        public:
            int ReverseTextColor = -1;

            unsigned int FontBackColor = DEFAULT_COLOR_VALUE;
            SCString FontFace;
            int FontBold = -1;
            int FontItalic = -1;
            int TextAlignment = -1;
            int UseRelativeVerticalValues = -1;

            uint32_t SecondaryColor = DEFAULT_COLOR_VALUE;
            int SquareEdge = -1;

            int DisplayHorizontalLineValue = -1;

            SCDateTimeMS ThirdDateTime;
            float ThirdValue = FLT_MIN;

            int BeginIndex = -1;
            int EndIndex = -1;
            int ThirdIndex = -1;

            uint32_t LevelColor[ACSIL_DRAWING_MAX_LEVELS] = {};
            int LevelStyle[ACSIL_DRAWING_MAX_LEVELS] = {};  // SubgraphLineStyles
            int LevelWidth[ACSIL_DRAWING_MAX_LEVELS] = {};

            int ShowTickDifference = -1;
            int ShowCurrencyValue = -1;
            int ShowPriceDifference = -1;
            int ShowPercentChange = -1;
            int ShowTimeDifference = -1;
            int ShowNumberOfBars = -1;
            int ShowAngle = -1;
            int ShowEndPointPrice = -1;
            int MultiLineLabel = -1;

            int ShowEndPointDateTime = -1;
            int ShowEndPointDate = -1;
            int ShowEndPointTime = -1;

            int ShowPercent = -1;
            int ShowPrice = -1;
            int RoundToTickSize = -1;

            int FixedSizeArrowHead = -1;
            float ArrowHeadSize = -FLT_MAX;

            int MarkerType = -1;
            int MarkerSize = -1;
            int UseBarSpacingForMarkerSize = -1;

            int TimeExpVerticals = -1;
            int TimeExpTopLabel1 = -1;
            int TimeExpTopLabel2 = -1;
            int TimeExpBottomLabel1 = -1;
            int TimeExpBottomLabel2 = -1;
            int TimeExpBasedOnTime = -1;

            int TransparentLabelBackground = -1;
            int AddAsUserDrawnDrawing = 0;

            int ShowVolume = -1;
            int DrawFromEnd = -1;
            int DrawUnderneathMainGraph = -1;

            int ShowLabels = -1;
            int ShowLabelsAtEnd = -1;
            int AllLevelsSameColorStyle = -1;

            int UseToolConfigNum = -1;

            int ShowAskBidDiffVolume = -1;

            int FlatEdge = -1;

            int DrawWithinRegion = -1;

            int VerticalText = -1;

            uint32_t TextColor = DEFAULT_COLOR_VALUE;

            int CenterText = -1;
            int CenterPriceLabels = -1;

            int NoVerticalOutline = -1;

            int AllowSaveToChartbook = -1;

            int AssociatedStudyID = 0;

            int16_t HideDrawing = -1;

            int16_t ClearExistingText = 0;

            int16_t LockDrawing = -1;

            int16_t DrawOutlineOnly = -1;

            int16_t NumCycles = -1;

            float ExtendMultiplier = -1;

            int16_t DrawMidline = -1;

            int16_t AllowCopyToOtherCharts = -1;

            //2250
            SCString Symbol;

            // 2271
            int FontUnderline = -1;

            // 2293
            int AdvancedCustomStudyAdded = 0;

            // 2545
            uint8_t UseHighResolutionForWindowRelativeCoordinates = 0;

            // Note: When adding new members, remember to update CopyAndUpdateUseToolStruct function.

            s_UseTool()
            {
                for (int Index = 0; Index < ACSIL_DRAWING_MAX_LEVELS; ++Index)
                {
                    RetracementLevels[Index] = -FLT_MAX;
                    LevelColor[Index] = DEFAULT_COLOR_VALUE;
                    LevelStyle[Index] = LINESTYLE_UNSET;
                    LevelWidth[Index] = -1;
                }
            }

            void Clear()
            {
                const s_UseTool DefaultUseTool;

                ChartNumber = DefaultUseTool.ChartNumber;
                LineNumber = DefaultUseTool.LineNumber;
                ExtendLeft = DefaultUseTool.ExtendLeft;
                ExtendRight = DefaultUseTool.ExtendRight;
                TransparencyLevel = DefaultUseTool.TransparencyLevel;
                FourthIndex = DefaultUseTool.FourthIndex;
                BeginValue = DefaultUseTool.BeginValue;
                EndValue = DefaultUseTool.EndValue;
                Region = DefaultUseTool.Region;
                Color = DefaultUseTool.Color;
                FontSize = DefaultUseTool.FontSize;
                ShowBeginMark = DefaultUseTool.ShowBeginMark;
                ShowEndMark = DefaultUseTool.ShowEndMark;
                IsSelected = DefaultUseTool.IsSelected;

                for (int LevelIndex = 0; LevelIndex < ACSIL_DRAWING_MAX_LEVELS; LevelIndex++)
                {
                    RetracementLevels[LevelIndex] = DefaultUseTool.RetracementLevels[LevelIndex];
                    LevelColor[LevelIndex] = DefaultUseTool.LevelColor[LevelIndex];
                    LevelStyle[LevelIndex] = DefaultUseTool.LevelStyle[LevelIndex];
                    LevelWidth[LevelIndex] = DefaultUseTool.LevelWidth[LevelIndex];
                }

                BeginDateTime = DefaultUseTool.BeginDateTime;
                EndDateTime = DefaultUseTool.EndDateTime;
                DrawingType = DefaultUseTool.DrawingType;
                LineWidth = DefaultUseTool.LineWidth;
                LineStyle = DefaultUseTool.LineStyle;
                AddMethod = DefaultUseTool.AddMethod;
                ReverseTextColor = DefaultUseTool.ReverseTextColor;
                FontBackColor = DefaultUseTool.FontBackColor;
                FontFace = DefaultUseTool.FontFace;
                FontBold = DefaultUseTool.FontBold;
                FontItalic = DefaultUseTool.FontItalic;
                TextAlignment = DefaultUseTool.TextAlignment;
                UseRelativeVerticalValues = DefaultUseTool.UseRelativeVerticalValues;
                SecondaryColor = DefaultUseTool.SecondaryColor;
                SquareEdge = DefaultUseTool.SquareEdge;
                DisplayHorizontalLineValue = DefaultUseTool.DisplayHorizontalLineValue;
                ThirdDateTime = DefaultUseTool.ThirdDateTime;
                ThirdValue = DefaultUseTool.ThirdValue;
                BeginIndex = DefaultUseTool.BeginIndex;
                EndIndex = DefaultUseTool.EndIndex;
                ThirdIndex = DefaultUseTool.ThirdIndex;

                ShowTickDifference = DefaultUseTool.ShowTickDifference;
                ShowCurrencyValue = DefaultUseTool.ShowCurrencyValue;
                ShowPriceDifference = DefaultUseTool.ShowPriceDifference;
                ShowPercentChange = DefaultUseTool.ShowPercentChange;
                ShowTimeDifference = DefaultUseTool.ShowTimeDifference;
                ShowNumberOfBars = DefaultUseTool.ShowNumberOfBars;
                ShowAngle = DefaultUseTool.ShowAngle;
                ShowEndPointPrice = DefaultUseTool.ShowEndPointPrice;
                MultiLineLabel = DefaultUseTool.MultiLineLabel;
                ShowEndPointDateTime = DefaultUseTool.ShowEndPointDateTime;
                ShowEndPointDate = DefaultUseTool.ShowEndPointDate;
                ShowEndPointTime = DefaultUseTool.ShowEndPointTime;
                ShowPercent = DefaultUseTool.ShowPercent;
                ShowPrice = DefaultUseTool.ShowPrice;
                RoundToTickSize = DefaultUseTool.RoundToTickSize;
                FixedSizeArrowHead = DefaultUseTool.FixedSizeArrowHead;
                ArrowHeadSize = DefaultUseTool.ArrowHeadSize;
                MarkerType = DefaultUseTool.MarkerType;
                MarkerSize = DefaultUseTool.MarkerSize;
                UseBarSpacingForMarkerSize = DefaultUseTool.UseBarSpacingForMarkerSize;
                TimeExpVerticals = DefaultUseTool.TimeExpVerticals;
                TimeExpTopLabel1 = DefaultUseTool.TimeExpTopLabel1;
                TimeExpTopLabel2 = DefaultUseTool.TimeExpTopLabel2;
                TimeExpBottomLabel1 = DefaultUseTool.TimeExpBottomLabel1;
                TimeExpBottomLabel2 = DefaultUseTool.TimeExpBottomLabel2;
                TimeExpBasedOnTime = DefaultUseTool.TimeExpBasedOnTime;
                TransparentLabelBackground = DefaultUseTool.TransparentLabelBackground;
                AddAsUserDrawnDrawing = DefaultUseTool.AddAsUserDrawnDrawing;
                ShowVolume = DefaultUseTool.ShowVolume;
                DrawFromEnd = DefaultUseTool.DrawFromEnd;
                DrawUnderneathMainGraph = DefaultUseTool.DrawUnderneathMainGraph;
                ShowLabels = DefaultUseTool.ShowLabels;
                ShowLabelsAtEnd = DefaultUseTool.ShowLabelsAtEnd;
                AllLevelsSameColorStyle = DefaultUseTool.AllLevelsSameColorStyle;
                UseToolConfigNum = DefaultUseTool.UseToolConfigNum;
                ShowAskBidDiffVolume = DefaultUseTool.ShowAskBidDiffVolume;
                FlatEdge = DefaultUseTool.FlatEdge;
                DrawWithinRegion = DefaultUseTool.DrawWithinRegion;
                VerticalText = DefaultUseTool.VerticalText;
                TextColor = DefaultUseTool.TextColor;
                CenterText = DefaultUseTool.CenterText;
                CenterPriceLabels = DefaultUseTool.CenterPriceLabels;
                NoVerticalOutline = DefaultUseTool.NoVerticalOutline;
                AllowSaveToChartbook = DefaultUseTool.AllowSaveToChartbook;
                AssociatedStudyID = DefaultUseTool.AssociatedStudyID;
                HideDrawing = DefaultUseTool.HideDrawing;
                ClearExistingText = DefaultUseTool.ClearExistingText;
                LockDrawing = DefaultUseTool.LockDrawing;
                DrawOutlineOnly = DefaultUseTool.DrawOutlineOnly;
                NumCycles = DefaultUseTool.NumCycles;
                ExtendMultiplier = DefaultUseTool.ExtendMultiplier;
                DrawMidline = DefaultUseTool.DrawMidline;
                AllowCopyToOtherCharts = DefaultUseTool.AllowCopyToOtherCharts;

                Symbol.Clear();

                FontUnderline = DefaultUseTool.FontUnderline;
                AdvancedCustomStudyAdded = DefaultUseTool.AdvancedCustomStudyAdded;

                UseHighResolutionForWindowRelativeCoordinates = DefaultUseTool.UseHighResolutionForWindowRelativeCoordinates;
            }

            unsigned int GetSize() const
            {
                return Size;
            }

            unsigned int GetVersion() const
            {
                return Version;
            }
    };

    /****************************************************************************/
    struct s_ACSTradeStatistics
    {
        static const int CURRENT_TRADESTATS_VERSION = 3;

        double ClosedProfit = 0;
        double ClosedLoss = 0;

        double TotalCommission = 0;

        double MaximumRunup = 0;
        double MaximumDrawdown = 0;

        double MaximumTradeRunup = 0;
        double MaximumTradeDrawdown = 0;
        double MaximumOpenPositionProfit = 0;
        double MaximumOpenPositionLoss = 0;
        int TotalWinningTrades = 0;
        int TotalLosingTrades = 0;
        int TotalLongTrades = 0;
        int TotalShortTrades = 0;

        double TotalWinningQuantity = 0;
        double TotalLosingQuantity = 0;
        double TotalFilledQuantity = 0;
        double LargestTradeQuantity = 0;

        double LargestWinningTrade = 0;
        double LargestLosingTrade = 0;
        int TimeInWinningTrades = 0;
        int TimeInLosingTrades = 0;

        int MaxConsecutiveWinners = 0;
        int MaxConsecutiveLosers = 0;

        int Version = CURRENT_TRADESTATS_VERSION;
        double LastTradeProfitLoss = 0;
        double LastTradeQuantity = 0;
        SCDateTime LastFillDateTime = 0;
        SCDateTime LastEntryDateTime = 0;
        SCDateTime LastExitDateTime = 0;

        double TotalBuyQuantity = 0;
        double TotalSellQuantity = 0;

        double ClosedProfitLoss() const
        {
            return ClosedProfit + ClosedLoss;
        }

        double ProfitFactor() const
        {
            return ClosedLoss == 0 ? 0 : fabs(ClosedProfit / ClosedLoss);
        }

        int TotalTrades() const
        {
            return TotalWinningTrades + TotalLosingTrades;
        }

        double TotalPercentProfitable() const
        {
            return TotalTrades() == 0 ? 0 : static_cast<double>(TotalWinningTrades) / static_cast<double>(TotalTrades());
        }

        double TotalClosedQuantity() const
        {
            return TotalWinningQuantity + TotalLosingQuantity;
        }

        double AvgQuantityPerTrade() const
        {
            return TotalTrades() == 0 ? 0 : static_cast<double>(TotalClosedQuantity()) / static_cast<double>(TotalTrades());
        }

        double AvgQuantityPerWinningTrade() const
        {
            return TotalWinningTrades == 0 ? 0 : static_cast<double>(TotalWinningQuantity) / static_cast<double>(TotalWinningTrades);
        }

        double AvgQuantityPerLosingTrade() const
        {
            return TotalLosingTrades == 0 ? 0 : static_cast<double>(TotalLosingQuantity) / static_cast<double>(TotalLosingTrades);
        }

        double AvgProfitLoss() const
        {
            return TotalTrades() == 0 ? 0 : ClosedProfitLoss() / TotalTrades();
        }

        double AvgProfit() const
        {
            return TotalWinningTrades == 0 ? 0 : ClosedProfit / TotalWinningTrades;
        }

        double AvgLoss() const
        {
            return TotalLosingTrades == 0 ? 0 : ClosedLoss / TotalLosingTrades;
        }

        double AvgProfitFactor() const
        {
            return AvgLoss() == 0 ? 0 : fabs(AvgProfit() / AvgLoss());
        }

        double LargestWinnerPercentOfProfit() const
        {
            return ClosedProfit == 0 ? 0 : LargestWinningTrade / ClosedProfit;
        }

        double LargestLoserPercentOfLoss() const
        {
            return ClosedLoss == 0 ? 0 : fabs(LargestLosingTrade / ClosedLoss);
        }

        int TimeInTrades() const
        {
            return TimeInWinningTrades + TimeInLosingTrades;
        }

        int AvgTimeInTrade() const
        {
            return TotalTrades() == 0 ? 0 : TimeInTrades() / TotalTrades();
        }

        int AvgTimeInWinningTrade() const
        {
            return TotalWinningTrades == 0 ? 0 : TimeInWinningTrades / TotalWinningTrades;
        }

        int AvgTimeInLosingTrade() const
        {
            return TotalLosingTrades == 0 ? 0 : TimeInLosingTrades / TotalLosingTrades;
        }

        void Clear()
        {
            *this = s_ACSTradeStatistics();
        }
    };

    /****************************************************************************/
    struct s_ACSTrade
    {

        SCDateTime OpenDateTime;
        SCDateTime CloseDateTime;
        int TradeType = 0; // +1=long, -1=short
        double TradeQuantity = 0;
        double MaxClosedQuantity = 0;// Max closed quantity.
        double MaxOpenQuantity = 0;
        double EntryPrice = 0;
        double ExitPrice = 0;
        double Unused = 0;
        double TradeProfitLoss = 0;
        double MaximumOpenPositionLoss = 0;
        double MaximumOpenPositionProfit = 0;
        double FlatToFlatMaximumOpenPositionProfit = 0;
        double FlatToFlatMaximumOpenPositionLoss = 0;
        double Commission = 0;
        int IsTradeClosed = 0;
        SCString Note;

        s_ACSTrade()
        {

        }

        void Clear()
        {
            *this = s_ACSTrade();
        }
    };

    /****************************************************************************/
    struct s_SCOrderFillData
    {
        int Version = CURRENT_SC_ORDER_FILL_DATA_VERSION;

        SCString Symbol;
        SCString TradeAccount;
        uint32_t InternalOrderID = 0;
        SCDateTimeMS FillDateTime = 0.0;    // Adjusted to chart time zone
        BuySellEnum BuySell = BSE_UNDEFINED;
        double Quantity = 0;
        double FillPrice = 0.0;

        SCString FillExecutionServiceID;

        double TradePositionQuantity = 0;

        int IsSimulated = 0;

        SCString OrderActionSource;
        SCString Note;

        void Clear()
        {
            *this = s_SCOrderFillData();
        }

        bool operator < (const s_SCOrderFillData& RightValue) const
        {
            return FillDateTime < RightValue.FillDateTime;
        }
    };

    /****************************************************************************/
    struct s_SCNewOrder
    {
        int Version = CURRENT_SC_NEW_ORDER_VERSION;

        int OrderType = SCT_ORDERTYPE_MARKET;

        double OrderQuantity = 0;

        double Price1 = DBL_MAX;
        double Price2 = DBL_MAX;

        uint32_t InternalOrderID = 0;

        uint32_t InternalOrderID2 = 0;

        SCString TextTag;
        SCTimeInForceEnum TimeInForce = SCT_TIF_UNSET;

        double Target1Offset = 0.0;
        uint32_t Target1InternalOrderID = 0;
        double Stop1Offset = 0.0;
        uint32_t Stop1InternalOrderID = 0;
        double OCOGroup1Quantity = 0;

        //These depend upon the parent order price or the current price in the case of a market order
        double Target1Price = 0.0;
        double Stop1Price = 0.0;

        double Target2Offset = 0.0;
        uint32_t Target2InternalOrderID = 0;
        double Stop2Offset = 0.0;
        uint32_t Stop2InternalOrderID = 0;
        double OCOGroup2Quantity = 0;
        double Target2Price = 0.0;
        double Stop2Price = 0.0;

        double Target3Offset = 0.0;
        uint32_t Target3InternalOrderID = 0;
        double Stop3Offset = 0;
        uint32_t Stop3InternalOrderID = 0;
        double OCOGroup3Quantity = 0;
        double Target3Price = 0.0;
        double Stop3Price = 0.0;

        double Target4Offset = 0.0;
        uint32_t Target4InternalOrderID = 0;
        double Stop4Offset = 0.0;
        uint32_t Stop4InternalOrderID = 0;
        double OCOGroup4Quantity = 0;
        double Target4Price = 0.0;
        double Stop4Price = 0.0;

        double Target5Offset = 0.0;
        uint32_t Target5InternalOrderID = 0;
        double Stop5Offset = 0.0;
        uint32_t Stop5InternalOrderID = 0;
        double OCOGroup5Quantity = 0;
        double Target5Price = 0.0;
        double Stop5Price = 0.0;

        double StopAllOffset = 0.0;
        uint32_t StopAllInternalOrderID = 0;
        double StopAllPrice = 0.0;

        double MaximumChaseAsPrice = 0.0;

        char AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT;
        char AttachedOrderTarget2Type = SCT_ORDERTYPE_LIMIT;
        char AttachedOrderTarget3Type = SCT_ORDERTYPE_LIMIT;
        char AttachedOrderTarget4Type = SCT_ORDERTYPE_LIMIT;
        char AttachedOrderTarget5Type = SCT_ORDERTYPE_LIMIT;

        char AttachedOrderStop1Type = SCT_ORDERTYPE_STOP;
        char AttachedOrderStop2Type = SCT_ORDERTYPE_STOP;
        char AttachedOrderStop3Type = SCT_ORDERTYPE_STOP;
        char AttachedOrderStop4Type = SCT_ORDERTYPE_STOP;
        char AttachedOrderStop5Type = SCT_ORDERTYPE_STOP;
        char AttachedOrderStopAllType = SCT_ORDERTYPE_STOP;

        double AttachedOrderMaximumChase = 0.0;
        double TrailStopStepPriceAmount = 0.0;
        double TriggeredTrailStopTriggerPriceOffset = 0.0;
        double TriggeredTrailStopTrailPriceOffset = 0.0;

        struct s_MoveToBreakEven
        {
            int Type = MOVETO_BE_ACTION_TYPE_NONE;
            int BreakEvenLevelOffsetInTicks = 0;
            int TriggerOffsetInTicks = 0;
            int TriggerOCOGroup = 0;
        };

        s_MoveToBreakEven MoveToBreakEven;

        double  StopLimitOrderLimitOffset = DBL_MAX;

        uint32_t Target1InternalOrderID_2 = 0;
        uint32_t Stop1InternalOrderID_2 = 0;
        uint32_t Target2InternalOrderID_2 = 0;
        uint32_t Stop2InternalOrderID_2 = 0;
        uint32_t Target3InternalOrderID_2 = 0;
        uint32_t Stop3InternalOrderID_2 = 0;
        uint32_t Target4InternalOrderID_2 = 0;
        uint32_t Stop4InternalOrderID_2 = 0;
        uint32_t Target5InternalOrderID_2 = 0;
        uint32_t Stop5InternalOrderID_2 = 0;
        uint32_t StopAllInternalOrderID_2 = 0;

        double Target1Offset_2 = 0.0;
        double Target1Price_2 = 0.0;
        double Stop1Offset_2 = 0.0;
        double Stop1Price_2 = 0.0;

        double Target2Offset_2 = 0.0;
        double Target2Price_2 = 0.0;
        double Stop2Offset_2 = 0.0;
        double Stop2Price_2 = 0.0;

        double Target3Offset_2 = 0.0;
        double Target3Price_2 = 0.0;
        double Stop3Offset_2 = 0.0;
        double Stop3Price_2 = 0.0;

        double Target4Offset_2 = 0.0;
        double Target4Price_2 = 0.0;
        double Stop4Offset_2 = 0.0;
        double Stop4Price_2 = 0.0;

        double Target5Offset_2 = 0.0;
        double Target5Price_2 = 0.0;
        double Stop5Offset_2 = 0.0;
        double Stop5Price_2 = 0.0;

        double StopAllOffset_2 = 0.0;
        double StopAllPrice_2 = 0.0;

        SCString Symbol;
        SCString TradeAccount;

        double StopLimitOrderLimitOffsetForAttachedOrders = DBL_MAX;

        int32_t SubmitAsHeldOrder = 0;

        double QuantityTriggeredAttachedStop_QuantityForTrigger = 0.0;

        double AttachedOrderStop1_TriggeredTrailStopTriggerPriceOffset = 0.0;
        double AttachedOrderStop1_TriggeredTrailStopTrailPriceOffset = 0.0;
        double AttachedOrderStop2_TriggeredTrailStopTriggerPriceOffset = 0.0;
        double AttachedOrderStop2_TriggeredTrailStopTrailPriceOffset = 0.0;
        double AttachedOrderStop3_TriggeredTrailStopTriggerPriceOffset = 0.0;
        double AttachedOrderStop3_TriggeredTrailStopTrailPriceOffset = 0.0;
        double AttachedOrderStop4_TriggeredTrailStopTriggerPriceOffset = 0.0;
        double AttachedOrderStop4_TriggeredTrailStopTrailPriceOffset = 0.0;
        double AttachedOrderStop5_TriggeredTrailStopTriggerPriceOffset = 0.0;
        double AttachedOrderStop5_TriggeredTrailStopTrailPriceOffset = 0.0;

        double TriggeredLimitOrStopAttachedOrderTriggerOffset = 0.0;//As a price offset

        s_MoveToBreakEven MoveToBreakEven_2;

        s_SCNewOrder()
        {
        }

        void Reset()
        {
            *this = s_SCNewOrder();
        }

        bool IsPrice1Set() const
        {
            return (Price1 != DBL_MAX);
        }

        bool IsPrice2Set() const
        {
            return (Price2 != DBL_MAX);
        }

        bool AreAttachedOrderVariablesSet() const
        {
            return Target1Offset != 0.0
                || Stop1Offset != 0.0
                || Target1Price != 0.0
                || Stop1Price != 0.0
                || StopAllOffset != 0.0;
        }
    };

    /****************************************************************************/

    struct s_SCTradeOrder
    {
        int Version = 19;//No longer used

        uint32_t InternalOrderID = 0;
        SCString Symbol;
        SCString OrderType;
        double OrderQuantity = 0;
        SCString TextTag;

        double Price1 = 0.0;
        double Price2 = 0.0;
        double AvgFillPrice = 0.0;
        int SourceChartNumber = 0;

        SCOrderStatusCodeEnum OrderStatusCode = SCT_OSC_UNSPECIFIED;

        double FilledQuantity = 0;

        uint32_t ParentInternalOrderID = 0;
        uint32_t LinkID = 0;

        SCDateTime LastActivityTime;

        OpenCloseEnum OpenClose = OCE_UNDEFINED;
        BuySellEnum BuySell = BSE_UNDEFINED;

        SCDateTime EntryDateTime;

        int OrderTypeAsInt = 0;

        double LastModifyQuantity = 0;
        double LastModifyPrice1 = 0.0;

        double LastFillPrice = 0.0;
        double LastFillQuantity = 0;

        SCString SourceChartbookFileName;

        int IsSimulated = 0;

        uint32_t TargetChildInternalOrderID = 0;
        uint32_t StopChildInternalOrderID = 0;
        uint32_t OCOSiblingInternalOrderID = 0;

        int32_t EstimatedPositionInQueue = 0;

        int32_t TriggeredTrailingStopTriggerHit = 0;

        SCString LastOrderActionSource;

        // Structure version 19
        SCString TradeAccount;

        // version 2302
        uint64_t TrueExchangeOrderID = 0;

        // version 2347
        SCTimeInForceEnum TimeInForce = SCT_TIF_UNSET;

        s_SCTradeOrder()
        {
        }

        bool IsWorking()
        {
            return IsWorkingOrderStatus(OrderStatusCode);
        }

        bool IsLimitOrder()
        {
            return (OrderTypeAsInt ==  SCT_ORDERTYPE_LIMIT
                || OrderTypeAsInt == SCT_ORDERTYPE_MARKET_IF_TOUCHED
                || OrderTypeAsInt == SCT_ORDERTYPE_LIMIT_CHASE
                || OrderTypeAsInt == SCT_ORDERTYPE_LIMIT_TOUCH_CHASE);
        }

        bool IsAttachedOrder()
        {
            return ParentInternalOrderID != 0;
        }
    };

    /****************************************************************************/
    struct s_SCPositionData
    {
        static const int CURRENT_POSITION_DATA_VERSION = 12;

        int Version = CURRENT_POSITION_DATA_VERSION;

        SCString Symbol;
        double PositionQuantity = 0;
        double AveragePrice = 0;
        double OpenProfitLoss = 0;
        double CumulativeProfitLoss = 0;
        int WinTrades = 0;
        int LoseTrades = 0;
        int TotalTrades = 0;
        double MaximumOpenPositionLoss = 0;
        double MaximumOpenPositionProfit = 0;
        double LastTradeProfitLoss = 0;

        double PositionQuantityWithAllWorkingOrders = 0;
        double PositionQuantityWithExitWorkingOrders = 0;
        int WorkingOrdersExist = 0;

        double DailyProfitLoss = 0;

        SCDateTime LastFillDateTime;
        SCDateTime LastEntryDateTime;
        SCDateTime LastExitDateTime;

        double PriceHighDuringPosition = 0;
        double DailyTotalQuantityFilled = 0;
        double PriceLowDuringPosition = 0;
        double PriorPositionQuantity = 0;
        double PositionQuantityWithExitMarketOrders = 0;

        double TotalQuantityFilled = 0;

        double LastTradeQuantity = 0;

        double TradeStatsDailyProfitLoss = 0;
        double TradeStatsDailyClosedQuantity = 0;
        double TradeStatsOpenProfitLoss = 0;
        double TradeStatsOpenQuantity = 0;

        int NonAttachedWorkingOrdersExist = 0;

        SCString TradeAccount;

        double PositionQuantityWithMarketWorkingOrders = 0;
        double PositionQuantityWithAllWorkingOrdersExceptNonMarketExits = 0;
        double PositionQuantityWithAllWorkingOrdersExceptAllExits = 0;
        double AllWorkingBuyOrdersQuantity = 0;
        double AllWorkingSellOrdersQuantity = 0;

        s_SCPositionData()
        {
        }

    };

    /****************************************************************************/

    struct s_GetOHLCOfTimePeriod
    {
        s_GetOHLCOfTimePeriod(SCDateTime StartDateTime, SCDateTime EndDateTime, float& Open, float& High, float& Low, float& Close, float& NextOpen, int& NumberOfBars, SCDateTime& TotalTimeSpan)
        :   m_Open(Open),
            m_High(High),
            m_Low(Low),
            m_Close(Close),
            m_NextOpen(NextOpen),
            m_NumberOfBars(NumberOfBars),
            m_TotalTimeSpan(TotalTimeSpan)
        {
            m_StartDateTime = StartDateTime;
            m_EndDateTime = EndDateTime;
        }

        SCDateTime m_StartDateTime;
        SCDateTime m_EndDateTime;
        float& m_Open;
        float& m_High;
        float& m_Low;
        float& m_Close;
        float& m_NextOpen;
        int& m_NumberOfBars;
        SCDateTime& m_TotalTimeSpan;
    };

    /****************************************************************************/

    typedef void (SCDLLCALL* fp_SCDLLOnArrayUsed)(int);

    template <typename T> class c_ArrayWrapper;
    template <typename T> class c_ConstArrayWrapper;

    template <typename T>
    class c_ArrayWrapper
    {
        private:
            T* m_Data;
            int m_NumElements;

            fp_SCDLLOnArrayUsed m_fp_OnArrayUsed;
            int m_OnArrayUsedParam;

            int m_NumExtendedElements;
            int m_TotalNumElements;

            T m_DefaultElement;

        public:
            c_ArrayWrapper()
            {
                ResetMembers();
            }
            explicit c_ArrayWrapper(int i)
            {
                ResetMembers();
            }
            c_ArrayWrapper(const c_ArrayWrapper& Src)
                : m_Data(Src.m_Data)
                , m_NumElements(Src.m_NumElements)
                , m_NumExtendedElements(Src.m_NumExtendedElements)
                , m_TotalNumElements(Src.m_TotalNumElements)
                , m_fp_OnArrayUsed(Src.m_fp_OnArrayUsed)
                , m_OnArrayUsedParam(Src.m_OnArrayUsedParam)
                , m_DefaultElement(0)
            {

            }

            const c_ArrayWrapper& operator = (const c_ArrayWrapper& Src)
            {
                m_Data = Src.m_Data;
                m_NumElements = Src.m_NumElements;
                m_NumExtendedElements = Src.m_NumExtendedElements;
                m_TotalNumElements = Src.m_TotalNumElements;
                m_fp_OnArrayUsed = Src.m_fp_OnArrayUsed;
                m_OnArrayUsedParam = Src.m_OnArrayUsedParam;
                m_DefaultElement = Src.m_DefaultElement;

                return *this;
            }

            void ResetMembers()
            {
                m_Data = NULL;
                m_NumElements = 0;
                m_NumExtendedElements = 0;
                m_TotalNumElements = 0;
                m_fp_OnArrayUsed = NULL;
                m_OnArrayUsedParam = 0;
                m_DefaultElement = T(0);

            }

            void AllocateArray()
            {
                if (m_Data == NULL)
                {
                    if (m_fp_OnArrayUsed != NULL)
                    {
                        // This will allocate and set up the array if it can
                        m_fp_OnArrayUsed(m_OnArrayUsedParam);
                    }
                }
            }

            T& operator [] (int Index)
            {
                return ElementAt(Index);
            }

            const T& operator [] (int Index) const
            {
                return ElementAt(Index);
            }

            T& ElementAt(int Index)
            {
                if (m_Data == NULL)
                {
                    if (m_fp_OnArrayUsed != NULL)
                    {
                        // This will allocate and set up the array if it can
                        m_fp_OnArrayUsed(m_OnArrayUsedParam);
                    }

                    if (m_Data == NULL)
                        return m_DefaultElement;
                }

                if (m_TotalNumElements == 0)
                    return m_DefaultElement;

                if (Index < 0)
                    Index = 0;

                if (Index >= m_TotalNumElements)
                    Index = m_TotalNumElements - 1;

                return m_Data[Index];
            }

            const T& ElementAt(int Index) const
            {
                if (m_Data == NULL)
                {
                    if (m_fp_OnArrayUsed != NULL)
                    {
                        // This will allocate and set up the array if it can
                        m_fp_OnArrayUsed(m_OnArrayUsedParam);
                    }

                    if (m_Data == NULL)
                        return m_DefaultElement;
                }

                if (m_TotalNumElements == 0)
                    return m_DefaultElement;

                if (Index < 0)
                    Index = 0;

                if (Index >= m_TotalNumElements)
                    Index = m_TotalNumElements - 1;

                return m_Data[Index];
            }

            T& GetAt(int Index)
            {
                return m_Data[Index];
            }

            const T& GetAt(int Index) const
            {
                return m_Data[Index];
            }

            // For Sierra Chart internal use only.
            void InternalSetArray(T* DataPointer, int Size, int NumExtendedElements = 0)
            {
                m_NumElements = Size;
                m_NumExtendedElements = NumExtendedElements;

                if (m_NumElements == 0)
                    m_TotalNumElements = 0;
                else
                    m_TotalNumElements = m_NumElements + m_NumExtendedElements;

                m_Data = DataPointer;
            }

            // For Sierra Chart internal use only
            void InternalSetOnUsed(fp_SCDLLOnArrayUsed OnArrayUsed, int Param)
            {
                m_fp_OnArrayUsed = OnArrayUsed;
                m_OnArrayUsedParam = Param;
            }

            int GetArraySize() const
            {
                return m_NumElements;
            }

            int GetExtendedArraySize() const
            {
                return m_TotalNumElements;//m_NumElements + m_NumExtendedElements;
            }

            // This should only be used when absolutely necessary and you know what
            // you are doing with it.
            T* GetPointer()
            {
                //Returns non-constant data pointer which can be used for rapidly setting blocks of data
                return m_Data;
            }
            const T* GetPointer() const
            {
                return m_Data;
            }

        friend class c_ConstArrayWrapper<T>;
    };

    template <typename T>
    class c_ConstArrayWrapper
    {
        private:
            const T* m_Data;
            int m_NumElements;

            fp_SCDLLOnArrayUsed m_OnArrayUsed;
            int m_OnArrayUsedParam;

            int m_NumExtendedElements;
            int m_TotalNumElements;

            T m_DefaultElement;

        public:
            c_ConstArrayWrapper()
                : m_Data(NULL)
                , m_NumElements(0)
                , m_NumExtendedElements(0)
                , m_TotalNumElements(0)
                , m_OnArrayUsed(NULL)
                , m_OnArrayUsedParam(0)
                , m_DefaultElement(0)
            {

            }
            explicit c_ConstArrayWrapper(int i)
                : m_Data(NULL)
                , m_NumElements(0)
                , m_NumExtendedElements(0)
                , m_TotalNumElements(0)
                , m_OnArrayUsed(NULL)
                , m_OnArrayUsedParam(0)
                , m_DefaultElement(0)
            {

            }
            c_ConstArrayWrapper(const c_ConstArrayWrapper& Src)
                : m_Data(Src.m_Data)
                , m_NumElements(Src.m_NumElements)
                , m_NumExtendedElements(Src.m_NumExtendedElements)
                , m_TotalNumElements(Src.m_TotalNumElements)
                , m_OnArrayUsed(Src.m_OnArrayUsed)
                , m_OnArrayUsedParam(Src.m_OnArrayUsedParam)
                , m_DefaultElement(0)
            {

            }

            c_ConstArrayWrapper(const c_ArrayWrapper<T>& Src)
                : m_Data(Src.m_Data)
                , m_NumElements(Src.m_NumElements)
                , m_NumExtendedElements(Src.m_NumExtendedElements)
                , m_TotalNumElements(Src.m_TotalNumElements)
                , m_OnArrayUsed(Src.m_OnArrayUsed)
                , m_OnArrayUsedParam(Src.m_OnArrayUsedParam)
                , m_DefaultElement(0)
            {

            }

            ~c_ConstArrayWrapper()
            {
            }

            const c_ConstArrayWrapper& operator = (const c_ConstArrayWrapper& Src)
            {
                m_Data = Src.m_Data;
                m_NumElements = Src.m_NumElements;
                m_NumExtendedElements = Src.m_NumExtendedElements;
                m_TotalNumElements = Src.m_TotalNumElements;
                m_OnArrayUsed = Src.m_OnArrayUsed;
                m_OnArrayUsedParam = Src.m_OnArrayUsedParam;
                m_DefaultElement = Src.m_DefaultElement;

                return *this;
            }
            const c_ConstArrayWrapper& operator = (const c_ArrayWrapper<T>& Src)
            {
                m_Data = Src.m_Data;
                m_NumElements = Src.m_NumElements;
                m_NumExtendedElements = Src.m_NumExtendedElements;
                m_TotalNumElements = Src.m_TotalNumElements;
                m_OnArrayUsed = Src.m_OnArrayUsed;
                m_OnArrayUsedParam = Src.m_OnArrayUsedParam;
                m_DefaultElement = Src.m_DefaultElement;

                return *this;
            }

            const T& operator [] (int Index) const
            {
                return ElementAt(Index);
            }

            const T& ElementAt(int Index) const
            {
                if (m_Data == NULL)
                {
                    if (m_OnArrayUsed != NULL)
                        m_OnArrayUsed(m_OnArrayUsedParam);  // This will allocate and set up the array if it can

                    if (m_Data == NULL)
                        return m_DefaultElement;
                }

                if (m_TotalNumElements == 0)
                    return m_DefaultElement;

                if (Index < 0)
                    Index = 0;

                if (Index >= m_TotalNumElements)
                    Index = m_TotalNumElements - 1;

                return m_Data[Index];
            }

            // For Sierra Chart internal use only
            void InternalSetArray(const T* DataPointer, int Size, int NumExtendedElements = 0)
            {
                m_NumElements = Size;
                m_NumExtendedElements = NumExtendedElements;

                if (m_NumElements == 0)
                    m_TotalNumElements = 0;
                else
                    m_TotalNumElements = m_NumElements + m_NumExtendedElements;

                m_Data = DataPointer;
            }

            // For Sierra Chart internal use only
            void InternalSetOnUsed(fp_SCDLLOnArrayUsed OnArrayUsed, int Param)
            {
                m_OnArrayUsed = OnArrayUsed;
                m_OnArrayUsedParam = Param;
            }

            int GetArraySize() const
            {
                return m_NumElements;
            }

            int GetExtendedArraySize() const
            {
                return m_TotalNumElements; //m_NumElements + m_NumExtendedElements;
            }

            // This should only be used when absolutely necessary and you know what
            // you are doing with it.
            const T* GetPointer() const
            {
                return m_Data;
            }

            friend class c_ArrayWrapper<T>;
    };

    /****************************************************************************/

    class SCDateTimeArray
        : public c_ArrayWrapper<SCDateTime>
    {
        public:
            /*====================================================================
                Days since 1899-12-30.
            --------------------------------------------------------------------*/
            int DateAt(int Index) const
            {
                return ElementAt(Index).GetDate();
            }
            /*====================================================================
                Seconds since midnight.
            --------------------------------------------------------------------*/
            int TimeAt(int Index) const
            {
                return ElementAt(Index).GetTimeInSeconds();
            }

            /*====================================================================
                Returns the date that was set.
            --------------------------------------------------------------------*/
            int SetDateAt(int Index, int Date)
            {
                ElementAt(Index) = SCDateTime(Date, TimeAt(Index));
                return Date;
            }
            /*====================================================================
                Returns the time that was set.
            --------------------------------------------------------------------*/
            int SetTimeAt(int Index, int Time)
            {
                ElementAt(Index) = SCDateTime(DateAt(Index), Time);
                return Time;
            }
    };

    typedef SCDateTimeArray &SCDateTimeArrayRef;
    typedef c_ArrayWrapper<uint16_t> SCUShortArray;
    typedef c_ArrayWrapper<unsigned int> SCUIntArray;
    typedef c_ArrayWrapper<unsigned int>& SCUIntArrayRef;
    typedef c_ArrayWrapper<SCUIntArray> SCUIntArrayArray;
    typedef c_ArrayWrapper<float> SCFloatArray;
    typedef c_ArrayWrapper<uint32_t> SCColorArray;
    typedef c_ArrayWrapper<uint32_t>& SCColorArrayRef;
    typedef c_ConstArrayWrapper<uint16_t> SCConstUShortArray;
    typedef c_ConstArrayWrapper<char> SCConstCharArray;

    typedef c_ArrayWrapper<float> SCConstFloatArray;

    typedef c_ArrayWrapper<SCFloatArray>& SCBaseDataRef;
    typedef c_ArrayWrapper<float>& SCFloatArrayRef;
    typedef c_ArrayWrapper<float>& SCConstFloatArrayRef;
    typedef const c_ArrayWrapper<float>& SCFloatArrayInRef;

    typedef c_ArrayWrapper<SCConstFloatArray> SCConstFloatArrayArray;
    typedef c_ArrayWrapper<SCFloatArray> SCFloatArrayArray;

    typedef c_ArrayWrapper<SCString> SCStringArray;

    class SCGraphData
        : public SCFloatArrayArray
    {
        private:
            SCFloatArray BaseData[SC_SUBGRAPHS_AVAILABLE];

        public:
            SCGraphData()
            {
                InternalSetArray(BaseData, SC_SUBGRAPHS_AVAILABLE);
            }

            SCFloatArrayRef InternalAccessBaseDataArray(int Index)
            {
                if (Index < 0)
                    return BaseData[0];

                if (Index >= SC_SUBGRAPHS_AVAILABLE)
                    return BaseData[SC_SUBGRAPHS_AVAILABLE - 1];

                return BaseData[Index];
            }
    };

    /****************************************************************************/
    struct s_SCSubgraph_260
    {
        SCString Name;

        unsigned int PrimaryColor = 0;
        unsigned int SecondaryColor = 0;
        unsigned int SecondaryColorUsed = 0;  // boolean

        uint16_t DrawStyle = 0;
        SubgraphLineStyles LineStyle = LINESTYLE_SOLID;
        uint16_t LineWidth = 0;
        unsigned char UseLabelsColor = 0;  // Line label Name/Value
        unsigned char DisplayNameValueInDataLine = 0;

        SCFloatArray Data;  // Array of data values
        SCColorArray DataColor;  // Array of colors for each of the data elements

        SCFloatArrayArray Arrays;  // Array of extra arrays

        unsigned char IncludeInStudySummary = 0;
        unsigned char UseStudySummaryCellBackgroundColor = 0;
        unsigned char AutoColoring = 0;  // boolean

        int GraphicalDisplacement = 0;

        int DrawZeros = 0;  // boolean

        // This controls whether the Subgraph name and value are displayed in the Values windows and on the Region Data Line.
        uint16_t DisplayNameValueInWindowsFlags = 0;

        unsigned int LineLabel = 0;  // Line label Name/Value
        int ExtendedArrayElementsToGraph = 0;

        SCString TextDrawStyleText;

        float GradientAngleUnit = 0;
        float GradientAngleMax = 0;

        SCString ShortName;
        uint32_t StudySummaryCellBackgroundColor = 0;
        SCString StudySummaryCellText;
        uint32_t LabelsColor = 0;
        unsigned char IncludeInSpreadsheet = 0;
        unsigned char UseTransparentLabelBackground = 0;
        char Reserve[40] = {};

        s_SCSubgraph_260()
        {
        }

        // This constructor is so this struct can work as an c_ArrayWrapper element
        explicit s_SCSubgraph_260(int Integer)
        {

        }

        float& operator [] (int Index)
        {
            return Data[Index];
        }

        operator SCFloatArray& ()
        {
            return Data;
        }
    };

    typedef c_ArrayWrapper<s_SCSubgraph_260> SCSubgraph260Array;
    typedef s_SCSubgraph_260& SCSubgraph260Ref;
    typedef s_SCSubgraph_260& SCSubgraphRef;

    /****************************************************************************/
    struct s_ChartStudySubgraphValues
    {
        int ChartNumber = 0;
        int StudyID = 0;
        int SubgraphIndex = 0;
    };

    struct s_SCInput_145
    {
        SCString Name;

        unsigned char ValueType = 0;
        unsigned char Unused1 = 0;
        uint16_t DisplayOrder = 0;
        #pragma pack(push, 4)  // This is necessary otherwise data items larger that 4 bytes will throw off the alignment and size of the union
        union
        {
            unsigned int IndexValue;
            float FloatValue;
            unsigned int BooleanValue;
            struct
            {
                double DateTimeValue;  // SCDateTime
                unsigned int TimeZoneValue;
            };

            int IntValue;
            unsigned int ColorValue;
            s_ChartStudySubgraphValues ChartStudySubgraphValues;
            double DoubleValue;
            struct
            {
                bool StringModified;
                const char* StringValue;
            };

            unsigned char ValueBytes[16] = {};
        };

        union
        {
            float FloatValueMin;
            double DateTimeValueMin;  // SCDateTime
            int IntValueMin;
            double DoubleValueMin;

            unsigned char ValueBytesMin[16] = {};
        };

        union
        {
            float FloatValueMax;
            double DateTimeValueMax;  // SCDateTime
            int IntValueMax;
            double DoubleValueMax;

            unsigned char ValueBytesMax[16] = {};
        };
        #pragma pack(pop)

        // Do not use or modify these.  For internal use only
        int InputIndex = 0;
        void (SCDLLCALL* InternalSetCustomStrings)(int InputIndex, const char* CustomStrings) = NULL;
        const char* SelectedCustomInputString = NULL;

        void (SCDLLCALL* InternalSetDescription)(int InputIndex, const char* Description) = NULL;

        char Reserve[48] = {};

        s_SCInput_145()
        {
        }

        explicit s_SCInput_145(int Integer)
        {
        }

        void Clear()
        {
            *this = s_SCInput_145();
        }

        bool UsesStringValue() const
        {
            return ValueType == STRING_VALUE
                || ValueType == PATH_AND_FILE_NAME_VALUE
                || ValueType == FIND_SYMBOL_VALUE;
        }

        unsigned int GetIndex() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return IndexValue;

                case FLOAT_VALUE:  // FloatValue
                return static_cast<unsigned int>((FloatValue < 0.0f) ? (FloatValue - 0.5f) : (FloatValue + 0.5f));

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? 1 : 0;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return 0;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return static_cast<unsigned int>(IntValue);

                case COLOR_VALUE:  // ColorValue
                return static_cast<unsigned int>(ColorValue);

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0;

                case DOUBLE_VALUE:  // DoubleValue
                return static_cast<unsigned int>((DoubleValue < 0.0) ? (DoubleValue - 0.5f) : (DoubleValue + 0.5f));

                case TIME_WITH_TIMEZONE_VALUE:
                return TimeZoneValue;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0;

                default:
                case NO_VALUE:
                return 0;
            }
        }

        float GetFloat() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return static_cast<float>(IndexValue);

                case FLOAT_VALUE:  // FloatValue
                return FloatValue;

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? 1.0f : 0.0f;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return 0.0f;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return static_cast<float>(IntValue);

                case COLOR_VALUE:  // ColorValue
                return 0.0f;

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0.0f;

                case DOUBLE_VALUE:  // DoubleValue
                return static_cast<float>(DoubleValue);

                case TIME_WITH_TIMEZONE_VALUE:
                return 0.0f;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0.0f;

                default:
                case NO_VALUE:
                return 0.0f;
            }
        }

        unsigned int GetBoolean() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return (IndexValue != 0) ? 1 : 0;

                case FLOAT_VALUE:  // FloatValue
                return (FloatValue != 0.0f) ? 1 : 0;

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? 1 : 0;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return (DateTimeValue != 0) ? 1 : 0;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return (IntValue != 0) ? 1 : 0;

                case COLOR_VALUE:  // ColorValue
                return (ColorValue != 0) ? 1 : 0;

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0;

                case DOUBLE_VALUE:  // DoubleValue
                return (DoubleValue != 0.0) ? 1 : 0;

                case TIME_WITH_TIMEZONE_VALUE:
                return (DateTimeValue != 0) ? 1 : 0;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0;

                default:
                case NO_VALUE:
                return 0;
            }
        }

        SCDateTime GetDateTime() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return 0.0;

                case FLOAT_VALUE:  // FloatValue
                return 0.0;

                case YESNO_VALUE:  // BooleanValue
                return 0.0;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return DateTimeValue;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return 0.0;

                case COLOR_VALUE:  // ColorValue
                return 0.0;

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0.0;

                case DOUBLE_VALUE:  // DoubleValue
                return 0.0;

                case TIME_WITH_TIMEZONE_VALUE:
                return DateTimeValue;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0.0;

                default:
                case NO_VALUE:
                return 0.0;
            }
        }

        int GetInt() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return static_cast<int>(IndexValue);

                case FLOAT_VALUE:  // FloatValue
                return static_cast<int>((FloatValue < 0.0f) ? (FloatValue - 0.5f) : (FloatValue + 0.5f));

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? 1 : 0;

                case DATE_VALUE:  // DateTimeValue
                return SCDateTime(DateTimeValue).GetDate();

                case TIME_VALUE:  // DateTimeValue
                return SCDateTime(DateTimeValue).GetTimeInSeconds();

                case DATETIME_VALUE:  // DateTimeValue
                return 0;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return IntValue;

                case COLOR_VALUE:  // ColorValue
                return static_cast<int>(ColorValue);

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0;

                case DOUBLE_VALUE:  // DoubleValue
                return static_cast<int>((DoubleValue < 0.0) ? (DoubleValue - 0.5) : (DoubleValue + 0.5));

                case TIME_WITH_TIMEZONE_VALUE:
                return SCDateTime(DateTimeValue).GetTimeInSeconds();

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0;

                default:
                case NO_VALUE:
                return 0;
            }
        }

        unsigned int GetColor() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return static_cast<unsigned int>(IndexValue);

                case FLOAT_VALUE:  // FloatValue
                return 0;

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? RGB(255,255,255) : 0;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return 0;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return static_cast<unsigned int>(IntValue);

                case COLOR_VALUE:  // ColorValue
                return ColorValue;

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0;

                case DOUBLE_VALUE:  // DoubleValue
                return 0;

                case TIME_WITH_TIMEZONE_VALUE:
                return 0;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0;

                default:
                case NO_VALUE:
                return 0;
            }
        }

        double GetDouble() const
        {
            switch (ValueType)
            {
                case OHLC_VALUE:  // IndexValue
                case STUDYINDEX_VALUE:  // IndexValue
                case SUBGRAPHINDEX_VALUE:  // IndexValue
                case MOVAVGTYPE_VALUE:  // IndexValue
                case TIME_PERIOD_LENGTH_UNIT_VALUE:
                case STUDYID_VALUE:  // IndexValue
                case CANDLESTICK_PATTERNS_VALUE:
                case CUSTOM_STRING_VALUE:
                case TIMEZONE_VALUE:  // IndexValue
                case ALERT_SOUND_NUMBER_VALUE:
                return static_cast<double>(IndexValue);

                case FLOAT_VALUE:  // FloatValue
                return static_cast<double>(FloatValue);

                case YESNO_VALUE:  // BooleanValue
                return (BooleanValue != 0) ? 1.0 : 0.0;

                case DATE_VALUE:  // DateTimeValue
                case TIME_VALUE:  // DateTimeValue
                case DATETIME_VALUE:  // DateTimeValue
                return DateTimeValue;

                case INT_VALUE:  // IntValue
                case CHART_NUMBER:
                return static_cast<double>(IntValue);

                case COLOR_VALUE:  // ColorValue
                return 0.0;

                case CHART_STUDY_SUBGRAPH_VALUES:
                case STUDY_SUBGRAPH_VALUES:
                case CHART_STUDY_VALUES:
                return 0.0;

                case DOUBLE_VALUE:  // DoubleValue
                return DoubleValue;

                case TIME_WITH_TIMEZONE_VALUE:
                return DateTimeValue;

                case STRING_VALUE:
                case PATH_AND_FILE_NAME_VALUE:
                case FIND_SYMBOL_VALUE:
                return 0.0;

                default:
                case NO_VALUE:
                return 0.0;
            }
        }

        unsigned int GetInputDataIndex() const
        {
            unsigned int InputDataIndex = GetIndex();

            if (InputDataIndex > SC_SUBGRAPHS_AVAILABLE - 1)
                InputDataIndex = SC_SUBGRAPHS_AVAILABLE - 1;

            return InputDataIndex;
        }

        unsigned int GetStudyIndex() const
        {
            return GetIndex();
        }

        unsigned int GetSubgraphIndex() const
        {
            unsigned int SubgraphIndex;
            if (ValueType == CHART_STUDY_SUBGRAPH_VALUES
                || ValueType == STUDY_SUBGRAPH_VALUES)
            {
                SubgraphIndex = static_cast<unsigned int>(ChartStudySubgraphValues.SubgraphIndex);
            }
            else
                SubgraphIndex = GetIndex();

            if (SubgraphIndex > SC_SUBGRAPHS_AVAILABLE - 1)
                SubgraphIndex = SC_SUBGRAPHS_AVAILABLE - 1;

            return SubgraphIndex;
        }

        unsigned int GetMovAvgType() const
        {
            unsigned int MovAvgTypeValue = GetIndex();
            if (MovAvgTypeValue >= MOVAVGTYPE_NUMBER_OF_AVERAGES)
                MovAvgTypeValue = 0;
            return MovAvgTypeValue;
        }

        unsigned int GetTimePeriodType() const
        {
            return GetIndex();
        }

        unsigned int GetAlertSoundNumber() const
        {
            return GetIndex();
        }

        unsigned int GetCandleStickPatternIndex() const
        {
            return GetIndex();
        }

        unsigned int GetStudyID() const
        {
            if (ValueType == CHART_STUDY_SUBGRAPH_VALUES
                || ValueType == STUDY_SUBGRAPH_VALUES
                || ValueType == CHART_STUDY_VALUES)
            {
                return static_cast<unsigned int>(ChartStudySubgraphValues.StudyID);
            }
            else
                return GetIndex();
        }

        unsigned int GetYesNo() const
        {
            return GetBoolean();
        }

        int GetDate() const
        {
            return GetDateTime().GetDate();
        }

        int GetTime() const
        {
            return GetDateTime().GetTimeInSeconds();
        }

        int GetTimeInMilliseconds() const
        {
            return GetDateTime().GetTimeInMilliseconds();
        }

        void GetChartStudySubgraphValues(int& ChartNumber, int& StudyID, int& SubgraphIndex) const
        {
            ChartNumber = ChartStudySubgraphValues.ChartNumber;
            StudyID = ChartStudySubgraphValues.StudyID;
            SubgraphIndex = ChartStudySubgraphValues.SubgraphIndex;
        }

        s_ChartStudySubgraphValues GetChartStudySubgraphValues() const
        {
            return ChartStudySubgraphValues;
        }

        int GetChartNumber()
        {
            if (ValueType == CHART_STUDY_SUBGRAPH_VALUES
                || ValueType == CHART_STUDY_VALUES)
            {
                return ChartStudySubgraphValues.ChartNumber;
            }
            else if (ValueType == CHART_NUMBER)
                return IntValue;
            else
                return GetInt();
        }

        const SCString GetSelectedCustomString()
        {
            SCString TempString;
            if(SelectedCustomInputString != NULL)
                TempString = SelectedCustomInputString;

            return TempString;
        }

        TimeZonesEnum GetTimeZone()
        {
            unsigned int TimeZone = TIMEZONE_NOT_SPECIFIED;

            if (ValueType == TIMEZONE_VALUE)
                TimeZone = GetIndex();
            else if (ValueType == TIME_WITH_TIMEZONE_VALUE)
                TimeZone = TimeZoneValue;

            if (TimeZone >= NUM_TIME_ZONES)
                TimeZone = TIMEZONE_NOT_SPECIFIED;

            return static_cast<TimeZonesEnum>(TimeZone);
        }

        const char* GetString() const
        {
            if (UsesStringValue() && StringValue != NULL)
                return StringValue;

            return "Unset";
        }

        const char* GetPathAndFileName()
        {
            if (UsesStringValue() && StringValue != NULL)
                return StringValue;

            return "";
        }

        const char* GetSymbol()
        {
            if (UsesStringValue() && StringValue != NULL)
                return StringValue;

            return "";
        }

        s_SCInput_145& SetInputDataIndex(unsigned int Value)
        {
            ValueType = OHLC_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetStudyIndex(unsigned int Value)
        {
            ValueType = STUDYINDEX_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetSubgraphIndex(unsigned int Value)
        {
            ValueType = SUBGRAPHINDEX_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetMovAvgType(unsigned int Value)
        {
            ValueType = MOVAVGTYPE_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetTimePeriodType(unsigned int Value)
        {
            ValueType = TIME_PERIOD_LENGTH_UNIT_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetFloat(float Value)
        {
            ValueType = FLOAT_VALUE;
            FloatValue = Value;
            return *this;
        }

        s_SCInput_145& SetYesNo(unsigned int Value)
        {
            ValueType = YESNO_VALUE;
            BooleanValue = (Value != 0)?1:0;
            return *this;
        }

        s_SCInput_145& SetDate(int Value)
        {
            ValueType = DATE_VALUE;
            SCDateTime DateValue(Value, 0);
            DateTimeValue = DateValue.GetAsDouble();
            return *this;
        }

        s_SCInput_145& SetTime(int Value)
        {
            ValueType = TIME_VALUE;
            SCDateTime TimeValue(0, Value);
            DateTimeValue = TimeValue.GetAsDouble();

            return *this;
        }

        s_SCInput_145& SetTimeAsSCDateTime(const SCDateTime& Time)
        {
            ValueType = TIME_VALUE;
            DateTimeValue = Time.GetTimeAsDouble();
            return *this;
        }

        s_SCInput_145& SetDateTime(const SCDateTime& Value)
        {
            ValueType = DATETIME_VALUE;
            DateTimeValue = Value.GetAsDouble();
            return *this;
        }

        s_SCInput_145& SetInt(int Value)
        {
            ValueType = INT_VALUE;
            IntValue = Value;
            return *this;
        }

        s_SCInput_145& SetIntWithoutTypeChange(int Value)
        {
            switch (ValueType)
            {
            case OHLC_VALUE:  // IndexValue
            case STUDYINDEX_VALUE:  // IndexValue
            case SUBGRAPHINDEX_VALUE:  // IndexValue
            case MOVAVGTYPE_VALUE:  // IndexValue
            case TIME_PERIOD_LENGTH_UNIT_VALUE:
            case STUDYID_VALUE:  // IndexValue
            case CANDLESTICK_PATTERNS_VALUE:
            case CUSTOM_STRING_VALUE:
            case TIMEZONE_VALUE:  // IndexValue
            case ALERT_SOUND_NUMBER_VALUE:
                IndexValue = Value;
                break;

            case FLOAT_VALUE:  // FloatValue
                FloatValue = static_cast<float>(Value);
                break;

            case YESNO_VALUE:  // BooleanValue
                BooleanValue = ((Value != 0.0) ? 1 : 0);
                break;

            case DATE_VALUE:  // DateTimeValue
            case TIME_VALUE:  // DateTimeValue
            case DATETIME_VALUE:  // DateTimeValue
                DateTimeValue = static_cast<double>(Value);
                break;

            case INT_VALUE:  // IntValue
            case CHART_NUMBER:
                IntValue = Value;
                break;

            case COLOR_VALUE:  // ColorValue
                ColorValue = static_cast<unsigned int>(Value);
                break;

            case CHART_STUDY_SUBGRAPH_VALUES:
            case STUDY_SUBGRAPH_VALUES:
            case CHART_STUDY_VALUES:
                break;

            case DOUBLE_VALUE:  // DoubleValue
                DoubleValue = static_cast<double>(Value);
                break;

            case TIME_WITH_TIMEZONE_VALUE:
                DateTimeValue = static_cast<double>(Value);
                break;

            case STRING_VALUE:
            case PATH_AND_FILE_NAME_VALUE:
            case FIND_SYMBOL_VALUE:
                break;

            default:
            case NO_VALUE:
                break;
            }

            return *this;
        }

        s_SCInput_145& SetStudyID(unsigned int Value)
        {
            ValueType = STUDYID_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetColor(unsigned int Color)
        {
            ValueType = COLOR_VALUE;
            ColorValue = Color;
            return *this;
        }

        s_SCInput_145& SetColor(unsigned char Red, unsigned char Green, unsigned char Blue)
        {
            return SetColor(RGB(Red, Green, Blue));
        }

        s_SCInput_145& SetAlertSoundNumber(unsigned int Value)
        {
            ValueType = ALERT_SOUND_NUMBER_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetCandleStickPatternIndex(unsigned int Value)
        {
            ValueType = CANDLESTICK_PATTERNS_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetChartStudySubgraphValues(int ChartNumber, int StudyID, int SubgraphIndex)
        {
            ValueType = CHART_STUDY_SUBGRAPH_VALUES;
            ChartStudySubgraphValues.ChartNumber = ChartNumber;
            ChartStudySubgraphValues.StudyID = StudyID;
            ChartStudySubgraphValues.SubgraphIndex = SubgraphIndex;
            return *this;
        }

        s_SCInput_145& SetChartNumber(int ChartNumber)
        {
            ValueType = CHART_NUMBER;
            IntValue = ChartNumber;
            return *this;
        }

        s_SCInput_145& SetStudySubgraphValues(int StudyID, int SubgraphIndex)
        {
            ValueType = STUDY_SUBGRAPH_VALUES;
            ChartStudySubgraphValues.StudyID = StudyID;
            ChartStudySubgraphValues.SubgraphIndex = SubgraphIndex;
            return *this;
        }

        s_SCInput_145& SetChartStudyValues(int ChartNumber, int StudyID)
        {
            ValueType = CHART_STUDY_VALUES;
            ChartStudySubgraphValues.ChartNumber = ChartNumber;
            ChartStudySubgraphValues.StudyID = StudyID;
            return *this;
        }

        s_SCInput_145& SetCustomInputIndex(unsigned int Value)
        {
            ValueType = CUSTOM_STRING_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetDouble(double Value)
        {
            ValueType = DOUBLE_VALUE;
            DoubleValue = Value;
            return *this;
        }

        s_SCInput_145& SetDoubleWithoutTypeChange(double Value)
        {
            switch (ValueType)
            {
            case OHLC_VALUE:  // IndexValue
            case STUDYINDEX_VALUE:  // IndexValue
            case SUBGRAPHINDEX_VALUE:  // IndexValue
            case MOVAVGTYPE_VALUE:  // IndexValue
            case TIME_PERIOD_LENGTH_UNIT_VALUE:
            case STUDYID_VALUE:  // IndexValue
            case CANDLESTICK_PATTERNS_VALUE:
            case CUSTOM_STRING_VALUE:
            case TIMEZONE_VALUE:  // IndexValue
            case ALERT_SOUND_NUMBER_VALUE:
                IndexValue = static_cast<int>(Value);
                break;

            case FLOAT_VALUE:  // FloatValue
                FloatValue = static_cast<float>(Value);
                break;

            case YESNO_VALUE:  // BooleanValue
                BooleanValue = ((Value != 0.0) ? 1 : 0);
                break;

            case DATE_VALUE:  // DateTimeValue
            case TIME_VALUE:  // DateTimeValue
            case DATETIME_VALUE:  // DateTimeValue
                DateTimeValue = Value;
                break;

            case INT_VALUE:  // IntValue
            case CHART_NUMBER:
                IntValue = static_cast<int>(Value);
                break;

            case COLOR_VALUE:  // ColorValue
                ColorValue = static_cast<unsigned int>(Value);
                break;

            case CHART_STUDY_SUBGRAPH_VALUES:
            case STUDY_SUBGRAPH_VALUES:
            case CHART_STUDY_VALUES:
                break;

            case DOUBLE_VALUE:  // DoubleValue
                DoubleValue = Value;
                break;

            case TIME_WITH_TIMEZONE_VALUE:
                DateTimeValue = Value;
                break;

            case STRING_VALUE:
            case PATH_AND_FILE_NAME_VALUE:
            case FIND_SYMBOL_VALUE:
                break;

            default:
            case NO_VALUE:
                break;
            }

            return *this;
        }

        s_SCInput_145& SetTimeZone(TimeZonesEnum Value)
        {
            ValueType = TIMEZONE_VALUE;
            IndexValue = Value;
            return *this;
        }

        s_SCInput_145& SetTimeWithTimeZone(int ValueTime, TimeZonesEnum ValueTimeZone)
        {
            ValueType = TIME_WITH_TIMEZONE_VALUE;
            DateTimeValue = SCDateTime(0, ValueTime).GetTimeAsDouble();
            TimeZoneValue = ValueTimeZone;
            return *this;
        }

        s_SCInput_145& SetString(const char* Value)
        {
            ClearString();

            size_t StringLength = 0;
            if (Value != NULL)
                StringLength = strlen(Value);

            if (StringLength != 0)
            {
                size_t NumBytes = StringLength + 1;

                char* NewString = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes);

                if (NewString != NULL)
                {
                    #if __STDC_WANT_SECURE_LIB__
                    strcpy_s(NewString, NumBytes, Value);
                    #else
                    strcpy(NewString, Value);
                    #endif
                    StringValue = NewString;
                }
            }

            ValueType = STRING_VALUE;

            //if (StringLength > 0 && StringValue != NULL)
                StringModified = true;

            return *this;
        }

        void ClearString()
        {
            if (UsesStringValue() && StringModified && StringValue != NULL)
                HeapFree(GetProcessHeap(), 0, (char*)StringValue);

            StringModified = false;

            StringValue = NULL;
        }

        s_SCInput_145& SetPathAndFileName(const char* PathAndFileName)
        {
            SetString(PathAndFileName);
            ValueType = PATH_AND_FILE_NAME_VALUE;
            return *this;
        }

        s_SCInput_145& SetSymbol(const char* Symbol)
        {
            SetString(Symbol);
            ValueType = FIND_SYMBOL_VALUE;
            return *this;
        }

        void SetFloatLimits(float Min, float Max)
        {
            FloatValueMin = Min;
            FloatValueMax = Max;
        }

        void SetDateTimeLimits(SCDateTime Min, SCDateTime Max)
        {
            DateTimeValueMin = Min.GetAsDouble();
            DateTimeValueMax = Max.GetAsDouble();
        }

        void SetIntLimits(int Min, int Max)
        {
            IntValueMin = Min;
            IntValueMax = Max;
        }

        void SetDoubleLimits(double Min, double Max)
        {
            DoubleValueMin = Min;
            DoubleValueMax = Max;
        }

        void SetCustomInputStrings(const char* p_CustomStrings)
        {
            if(InternalSetCustomStrings != NULL)
            {
                InternalSetCustomStrings(InputIndex, p_CustomStrings);
                ValueType = CUSTOM_STRING_VALUE;
            }
        }

        void SetDescription(const char* Description)
        {
            if(InternalSetDescription != NULL && Description != NULL)
                InternalSetDescription(InputIndex, Description);
        }
    };

    typedef c_ArrayWrapper<s_SCInput_145> SCInput145Array;
    typedef s_SCInput_145& SCInputRef;

    /****************************************************************************/

    struct s_Parabolic
    {
        s_Parabolic(SCBaseDataRef BaseDataIn, SCSubgraphRef Out, SCDateTimeArrayRef BaseDateTimeIn, int Index, float InStartAccelFactor, float InAccelIncrement, float InMaxAccelFactor, unsigned int InAdjustForGap, int InputDataHighIndex = SC_HIGH, int InputDataLowIndex = SC_LOW)
            : m_BaseDataIn(BaseDataIn),
            m_Out(Out),
            m_BaseDateTimeIn(BaseDateTimeIn),
            m_Index(Index),
            m_InStartAccelFactor(InStartAccelFactor),
            m_InAccelIncrement(InAccelIncrement),
            m_InMaxAccelFactor(InMaxAccelFactor),
            m_InAdjustForGap(InAdjustForGap),
            m_InputDataHighIndex(InputDataHighIndex),
            m_InputDataLowIndex(InputDataLowIndex)
        {
        }

        SCBaseDataRef m_BaseDataIn;
        SCSubgraphRef m_Out;
        SCDateTimeArrayRef m_BaseDateTimeIn;
        int m_Index;
        float m_InStartAccelFactor;
        float m_InAccelIncrement;
        float m_InMaxAccelFactor;
        unsigned int m_InAdjustForGap;
        int m_InputDataHighIndex;
        int m_InputDataLowIndex;

        inline float BaseDataHigh(int Index)
        {
            return m_BaseDataIn[m_InputDataHighIndex][Index];

        }

        inline float BaseDataLow(int Index)
        {
            return m_BaseDataIn[m_InputDataLowIndex][Index];
        }
    };

    /****************************************************************************/

    struct s_NumericInformationGraphDrawTypeConfig
    {
        static const int NUMBER_OF_THRESHOLDS = 3;
        uint32_t TextBackgroundColor = COLOR_BLACK;
        bool TransparentTextBackground = true;
        bool LabelsOnRight = false;
        bool AllowLabelOverlap = false;
        bool DrawGridlines = true;
        int GridlineStyleSubgraphIndex = -1;
        int FontSize = 0;
        bool ShowPullback = false;
        bool Unused = false;
        bool HideLabels = false;
        char Reserved = 0;
        int ValueFormat[SC_SUBGRAPHS_AVAILABLE] = {};
        int SubgraphOrder[SC_SUBGRAPHS_AVAILABLE] = {};
        bool ColorBackgroundBasedOnValuePercent = false;
        int DetermineMaxMinForBackgroundColoringFrom = 0;
        float HighestValue[SC_SUBGRAPHS_AVAILABLE] = {};
        float LowestValue[SC_SUBGRAPHS_AVAILABLE] = {};
        float PercentCompareThresholds[NUMBER_OF_THRESHOLDS] = {};
        uint32_t Range3UpColor = COLOR_BLACK;
        uint32_t Range2UpColor = COLOR_BLACK;
        uint32_t Range1UpColor = COLOR_BLACK;
        uint32_t Range0UpColor = COLOR_BLACK;
        uint32_t Range0DownColor = COLOR_BLACK;
        uint32_t Range1DownColor = COLOR_BLACK;
        uint32_t Range2DownColor = COLOR_BLACK;
        uint32_t Range3DownColor = COLOR_BLACK;
        bool DifferentPullbackAndLabelsColor = false;
        uint32_t PullbackAndLabelsColor = COLOR_WHITE;
        bool ColorPullbackBackgroundBasedOnPositiveNegative = false;
        bool UseDefaultNumberFormattingForAllSubgraphs = false;
        std::vector<float> DailyHighestValue[SC_SUBGRAPHS_AVAILABLE]; //cannot safely be used by ACSIL
        std::vector<float> DailyLowestValue[SC_SUBGRAPHS_AVAILABLE]; //cannot safely be used by ACSIL
        SCDateTimeMS DateTimeOfHigh;
        SCDateTimeMS DateTimeOfLow;
        int VolumeDisplayMultiplierIndex = 0;

        s_NumericInformationGraphDrawTypeConfig()
        {
            for (int Index = 0; Index < SC_SUBGRAPHS_AVAILABLE; Index++)
            {
                SubgraphOrder[Index] = Index;
                ValueFormat[Index] =  VALUEFORMAT_INHERITED;
                HighestValue[Index] = -FLT_MAX;
                LowestValue[Index] = FLT_MAX;
            }

        }
    };

    /****************************************************************************/

    struct s_ACSOpenChartParameters
    {
        int Version = 5;
        int PriorChartNumber = 0;  // This gets checked first, 0 is unknown

        ChartDataTypeEnum ChartDataType = NO_DATA_TYPE;
        SCString Symbol;

        IntradayBarPeriodTypeEnum IntradayBarPeriodType = IBPT_DAYS_MINS_SECS;
        int IntradayBarPeriodLength = 0;

        SCDateTime SessionStartTime;
        SCDateTime SessionEndTime;
        SCDateTime EveningSessionStartTime;
        SCDateTime EveningSessionEndTime;

        int DaysToLoad = 0;

        int IntradayBarPeriodParm2 = 0;
        int IntradayBarPeriodParm3 = 0;

        int IntradayBarPeriodParm4 = 0;

        HistoricalChartBarPeriodEnum HistoricalChartBarPeriod
            = HISTORICAL_CHART_PERIOD_DAYS;

        int ChartLinkNumber = 0;

        int ContinuousFuturesContractOption = CFCO_NONE;  // ContinuousFuturesContractOptionsEnum

        int LoadWeekendData = 1;

        int HistoricalChartBarPeriodLengthInDays = 1;

        int UseEveningSession = 1;
        int HideNewChart = 0;

        int16_t AlwaysOpenNewChart = 0;
        int16_t IsNewChart = 0;
        int16_t IncludeColumnsWithNoData = 0;
        int16_t UpdatePriorChartNumberParametersToMatch = 0;

        SCString ChartTimeZone;
        int UseExactMatchForDaysToLoad = 0;

    };

    namespace n_ACSIL
    {

    struct s_BarPeriod
    {
        ChartDataTypeEnum ChartDataType = NO_DATA_TYPE;
        IntradayBarPeriodTypeEnum IntradayChartBarPeriodType = IBPT_DAYS_MINS_SECS;
        int IntradayChartBarPeriodParameter1 = 0;
        int IntradayChartBarPeriodParameter2 = 0;
        int IntradayChartBarPeriodParameter3 = 0;
        int IntradayChartBarPeriodParameter4 = 0;
        HistoricalChartBarPeriodEnum HistoricalChartBarPeriodType = HISTORICAL_CHART_PERIOD_DAYS;
        int HistoricalChartDaysPerBar = 0;
        SCString ACSILCustomChartStudyName;

        s_BarPeriod()
        {
        }

        int AreRangeBars()
        {
            return
                (IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_STANDARD
                    || IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_NEWBAR_ON_RANGEMET
                    || IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_TRUE
                    || IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_FILL_GAPS
                    || IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_OPEN_EQUAL_CLOSE
                    || IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_NEW_BAR_ON_RANGE_MET_OPEN_EQUALS_PRIOR_CLOSE
                )
                ? 1 : 0;
        }

        int AreRenkoBars()
        {
            return
                (IntradayChartBarPeriodType == IBPT_RENKO_IN_TICKS
                    || IntradayChartBarPeriodType == IBPT_FLEX_RENKO_IN_TICKS
                    || IntradayChartBarPeriodType == IBPT_FLEX_RENKO_IN_TICKS_INVERSE_SETTINGS
                    || IntradayChartBarPeriodType == IBPT_ALIGNED_RENKO
                )
                ? 1 : 0;
        }

    };

    struct s_ChartSessionTimes
    {
        SCDateTime StartTime;
        SCDateTime EndTime;
        SCDateTime EveningStartTime;
        SCDateTime EveningEndTime;

        int UseEveningSessionTimes = 0;
        int NewBarAtSessionStart = 0;
        int LoadWeekendDataSetting = 0;
    };

    struct s_HTTPHeader
    {
        SCString Name;
        SCString Value;
    };

    struct s_WriteBarAndStudyDataToFile
    {
        int StartingIndex = 0;
        SCString OutputPathAndFileName;
        int IncludeHiddenStudies = 0;
        int IncludeHiddenSubgraphs = 0;
        int AppendOnlyToFile = 0;
        int IncludeLastBar = 0;
        int UseUTCTime = 0;
        int WriteStudyData = 1;
        int UseTabDelimiter = 0;//0 means use commas
    };

    struct s_LineUntilFutureIntersection
    {
        int StartBarIndex = 0;

        //This variable can be set to the chart bar index where the future intersection line needs to stop. Once this is set to a nonzero value, the line stops at that index and does not extend. When EndBarIndex is set, the ending chart bar index is controlled by the study directly.
        int EndBarIndex = 0;

        int LineIDForBar = 0;
        float LineValue = 0;
        float LineValue2ForRange = 0;
        int UseLineValue2 = 0;
        uint32_t LineColor = 0;
        uint16_t LineWidth = 0;
        uint16_t LineStyle = 0;
        int DrawValueLabel = 0;
        int DrawNameLabel = 0;
        SCString NameLabel;
        int AlwaysExtendToEndOfChart = 0;
        int TransparencyLevel = 50;
        int PerformCloseCrossoverComparison = 0;
    };

    struct s_StudyProfileInformation
    {
        SCDateTime m_StartDateTime;
        int64_t m_NumberOfTrades = 0;
        int64_t m_Volume = 0;
        int64_t m_BidVolume = 0;
        int64_t m_AskVolume = 0;

        int m_TotalTPOCount = 0;

        float m_OpenPrice = 0;
        float m_HighestPrice = 0;
        float m_LowestPrice = 0;
        float m_LastPrice = 0;

        float m_TPOMidpointPrice = 0;
        float m_TPOMean = 0;
        float m_TPOStdDev = 0;
        float m_TPOErrorOfMean = 0;
        float m_TPOPOCPrice = 0;
        float m_TPOValueAreaHigh = 0;
        float m_TPOValueAreaLow = 0;
        int64_t m_TPOCountAbovePOC = 0;
        int64_t m_TPOCountBelowPOC = 0;

        float m_VolumeMidpointPrice = 0;
        float m_VolumePOCPrice = 0;
        float m_VolumeValueAreaHigh = 0;
        float m_VolumeValueAreaLow = 0;
        int64_t m_VolumeAbovePOC = 0;
        int64_t m_VolumeBelowPOC = 0;
        double m_POCAboveBelowVolumeImbalancePercent = 0;
        int64_t m_VolumeAboveLastPrice = 0;
        int64_t m_VolumeBelowLastPrice = 0;
        int64_t m_BidVolumeAbovePOC = 0;
        int64_t m_BidVolumeBelowPOC = 0;
        int64_t m_AskVolumeAbovePOC = 0;
        int64_t m_AskVolumeBelowPOC = 0;
        int64_t m_VolumeTimesPriceInTicks = 0;
        int64_t m_TradesTimesPriceInTicks = 0;
        int64_t m_TradesTimesPriceSquaredInTicks = 0;

        float m_IBRHighPrice = 0;
        float m_IBRLowPrice = 0;

        float m_OpeningRangeHighPrice = 0;
        float m_OpeningRangeLowPrice = 0;

        float m_VolumeWeightedAveragePrice = 0;
        int m_MaxTPOBlocksCount = 0;

        int m_TPOCountMaxDigits = 0;

        uint8_t m_ColumnsDisplayStyle = 0;

        bool m_EveningSession = false;

        float m_AverageSubPeriodRange = 0;
        int32_t m_RotationFactor = 0;

        int64_t m_VolumeAboveTPOPOC = 0;
        int64_t m_VolumeBelowTPOPOC = 0;
        SCDateTime m_EndDateTime;

        uint32_t m_BeginIndex = 0;
        uint32_t m_EndIndex = 0;
    };

    struct s_TradeStatistics
    {
        double ClosedTradesProfitLoss = 0;
        double ClosedTradesTotalProfit = 0;
        double ClosedTradesTotalLoss = 0;
        double ProfitFactor = 0;
        double EquityPeak = 0;
        double EquityValley = 0;
        double MaximumRunup = 0;
        double MaximumDrawdown = 0;
        double MaximumFlatToFlatTradeOpenProfit = 0;
        double MaximumFlatToFlatTradeOpenLoss = 0;
        double AverageTradeOpenProfit = 0;
        double AverageTradeOpenLoss = 0;
        double AverageWinningTradeOpenProfit = 0;
        double AverageWinningTradeOpenLoss = 0;
        double AverageLosingTradeOpenProfit = 0;
        double AverageLosingTradeOpenLoss = 0;
        double MaximumTradeOpenProfit = 0;
        double MaximumTradeOpenLoss = 0;
        double HighestPriceDuringPositions = 0;
        double LowestPriceDuringPositions = 0;
        double TotalCommissions = 0;
        int32_t TotalTrades = 0;
        int32_t TotalFlatToFlatTrades = 0;
        int32_t TotalFilledQuantity = 0;
        double PercentProfitable = 0;
        double FlatToFlatPercentProfitable = 0;
        int32_t WinningTrades = 0;
        int32_t WinningFlatToFlatTrades = 0;
        int32_t LosingTrades = 0;
        int32_t LosingFlatToFlatTrades = 0;
        int32_t LongTrades = 0;
        int32_t LongFlatToFlatTrades = 0;
        int32_t ShortTrades = 0;
        int32_t ShortFlatToFlatTrades = 0;
        double AverageTradeProfitLoss = 0;
        double AverageFlatToFlatTradeProfitLoss = 0;
        double AverageWinningTrade = 0;
        double AverageFlatToFlatWinningTrade = 0;
        double AverageLosingTrade = 0;
        double AverageFlatToFlatLosingTrade = 0;
        double AverageProfitFactor = 0;
        double AverageFlatToFlatProfitFactor = 0;
        double LargestWinningTrade = 0;
        double LargestFlatToFlatWinningTrade = 0;
        double LargestLosingTrade = 0;
        double LargestFlatToFlatLosingTrade = 0;
        double LargestWinnerPercentOfProfit = 0;
        double LargestFlatToFlatWinnerPercentOfProfit = 0;
        double LargestLoserPercentOfLoss = 0;
        double LargestFlatToFlatLoserPercentOfLoss = 0;
        int32_t MaxConsecutiveWinners = 0;
        int32_t MaxConsecutiveLosers = 0;
        int32_t AverageTimeInTrades = 0;// In seconds
        int32_t AverageTimeInWinningTrades = 0;// In seconds
        int32_t AverageTimeInLosingTrades = 0;// In seconds
        int32_t LongestHeldWinningTrade = 0;// In seconds
        int32_t LongestHeldLosingTrade = 0;// In seconds
        int32_t TotalQuantity = 0;
        int32_t WinningQuantity = 0;
        int32_t LosingQuantity = 0;
        float AverageQuantityPerTrade = 0;
        float AverageQuantityPerFlatToFlatTrade = 0;
        float AverageQuantityPerWinningTrade = 0;
        float AverageQuantityPerFlatToFlatWinningTrade = 0;
        float AverageQuantityPerLosingTrade = 0;
        float AverageQuantityPerFlatToFlatLosingTrade = 0;
        int32_t LargestTradeQuantity = 0;
        int32_t LargestFlatToFlatTradeQuantity = 0;
        int32_t MaximumOpenPositionQuantity = 0;
        double LastTradeProfitLoss = 0;
        int32_t LastTradeQuantity = 0;
        int32_t NumberOfOpenTrades = 0;
        int32_t OpenTradesOpenQuantity = 0;
        double OpenTradesAverageEntryPrice = 0;
        SCDateTime  LastFillDateTime;
        SCDateTime  LastEntryDateTime;
        SCDateTime  LastExitDateTime;
        int32_t TotalBuyQuantity = 0;
        int32_t TotalSellQuantity = 0;

        double ClosedFlatToFlatTradesProfitLoss = 0;
    };

    struct s_ChartReplayParameters
    {
        int ChartNumber = 0;
        float ReplaySpeed = 1;
        SCDateTimeMS StartDateTime;
        int SkipEmptyPeriods = 0;
        n_ACSIL::ChartReplayModeEnum ReplayMode = REPLAY_MODE_UNSET;
        int ClearExistingTradeSimulationDataForSymbolAndTradeAccount = 1;
        n_ACSIL::ChartsToReplayEnum ChartsToReplay = CHARTS_TO_REPLAY_UNSET;
    };

    struct s_AddStudy
    {
        // The chart number to add the study to.  This needs to be within the
        // same Chartbook as the study function which is adding the study.
        int ChartNumber = 0;

        // The configured study identifier to add if it is a built-in study.  The
        // study identifiers are specified in c_Graph::Configure.  When adding an
        // advanced custom study this needs to be zero. The study identifiers will
        // be visible in an upcoming release through the Study Settings window.
        int StudyID = 0;

        // In the case of when adding an advanced custom study, this string
        // specifies the DLL filename without extension, followed by a dot (.)
        // character, and the function name to be added.  When both StudyID and
        // CustomStudyFileAndFunctionName have not been set and are at default
        // values, then sc.AddStudy returns 0.

        // This method can also be used to add built-in studies. In this case
        // the DLL file name and function name can be determined through the
        // DLLName.FunctionName setting in the Study Settings window for the
        // study. Example: SierraChartStudies_64.scsf_MovingAverageBlock
        SCString CustomStudyFileAndFunctionName;

        // This will be set as the short name for the added study.  This can be
        // used to get the ID for the study later using sc.GetStudyIDByName.
        SCString ShortName;
    };

    struct s_MarketOrderData
    {
        t_MarketDataQuantity OrderQuantity = 0;
        uint64_t OrderID = 0;
    };

    struct s_TradeAccountDataFields
    {
        SCString m_TradeAccount;
        uint8_t m_IsSimulated = 0;
        SCString m_CurrencyCode;
        double m_CurrentCashBalance = 0;
        uint64_t m_TransactionIdentifierForCashBalanceAdjustment = 0;
        double m_AvailableFundsForNewPositions = 0;
        double m_MarginRequirement = 0;
        double m_MarginRequirementFull = 0;
        double m_MarginRequirementFullPositionsOnly = 0;
        double m_PeakMarginRequirement = 0;
        double m_AccountValue = 0;
        double m_OpenPositionsProfitLoss = 0;
        double m_DailyProfitLoss = 0;
        double m_CalculatedDailyNetLossLimitInAccountCurrency = 0;
        double m_TrailingAccountValueAtWhichToNotAllowNewPositions = 0;
        uint8_t m_DailyNetLossLimitHasBeenReached =  0;
        uint8_t m_IsUnderRequiredMargin = 0;
        uint8_t m_IsUnderRequiredAccountValue =  0;
        uint8_t m_TradingIsDisabled = 0;
        uint8_t m_ClosePositionsAtEndOfDay = 0;
        SCString m_Description;
    };

    struct s_GraphicsColor
    {
        union u_Color
        {
            uint32_t RawColor = RGB(0, 0, 0);
            struct
            {
                uint8_t Red;
                uint8_t Green;
                uint8_t Blue;
                uint8_t Alpha;
            }s_RgbColor;
        };
    };

    struct s_GraphicsPen
    {
        enum class e_PenStyle
        {
            PEN_STYLE_SOLID
            , PEN_STYLE_DASH
            , PEN_STYLE_DOT
            , PEN_STYLE_DASHDOT
            , PEN_STYLE_DASHDOTDOT
            , PEN_STYLE_NULL
        }
        PenStyle = e_PenStyle::PEN_STYLE_SOLID;

        s_GraphicsColor PenColor;
    };

    struct s_GraphicsBrush
    {
        enum e_BrushStyle
        {
            BRUSH_STYLE_NULL,
            BRUSH_STYLE_SOLID,
            BRUSH_STYLE_PATTERN
        }
        BrushType = BRUSH_STYLE_NULL;
        s_GraphicsColor BrushColor;
        std::vector<unsigned char> BrushBitPattern;
        int Width = 0;
        int Height = 0;
    };

    struct s_GraphicsFont
    {
        SCString FontFaceName;
        int FontHeight = 0;
        int FontWeight = 0;
        bool FontIsItalic = false;
        bool FontIsUnderline = false;
        int FontAngle = 0;
    };

    struct s_GraphicsRectangle
    {
        int    Left = 0;
        int    Top = 0;
        int    Right = 0;
        int    Bottom = 0;
    };

    struct s_GraphicsPoint
    {
        int X = 0;
        int Y = 0;
    };

    }  // namespace n_ACSIL

    #endif