Transform Domain free

by Abstract in category Other at 20/05/2023
Description

This indicator transforms values from any indicator at the bottom of the screen into profiles in the main window. See images below.

The profiles can be customized according to your likings: color, width, height, vertical scale (PIPs) and shift back.

 

 

 

 

 In the field 'Source' is specified the indicator to be shown in the main window. 

Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.
Formula / Source Code
Language: C#
Trading Platform: cAlgocTrader
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TransformDomainV10 : Indicator
    {
        [Parameter("Source", Group = "Main")]
        public DataSeries Source { get; set; }
        [Parameter("Period", Group = "Main", DefaultValue = 1000, MinValue = 1)]
        public int Period { get; set; }
        [Parameter("Width  (Even)", Group = "Grid", DefaultValue = 100, MinValue = 10, Step = 2)]
        public int Width { get; set; }
        [Parameter("Height (Even)", Group = "Grid", DefaultValue = 1000, MinValue = 2, Step = 2)]
        public int Height { get; set; }
        [Parameter("Vertical Scale (PIPs)", Group = "Grid", DefaultValue = 1, MinValue = 1)]
        public int Scale { get; set; }
        [Parameter("Shift Back", Group = "Profile Configuration", DefaultValue = 0, MinValue = 0)]
        public int Shift { get; set; }
        [Parameter("Color", Group = "Profile Configuration", DefaultValue = "MediumSeaGreen")]
        public Color RectangleColor { get; set; }
        
        private struct PriceValue
        {
            public double Price;
            public double Value;
            public bool filled;
        }
        
        private const string LABEL = "TDOM-"; 
        
        private int initialindex, lastindex, midheight;
        private PriceValue[] values;

        protected override void Initialize()
        {
            try
            {
                lastindex = -1;
                initialindex = Bars.ClosePrices.Count - 1;
                
                //forcing even numbers
                if (Width % 2 != 0)
                    Width++;
                if (Height % 2 != 0)
                    Height++;
                
                values = new PriceValue[Height];
                midheight = (int)(Height / 2);
            } catch (Exception)
            {
                throw;
            }
        }

        public override void Calculate(int index)
        {
            try
            {
                if (!IsNumber(index))
                    return;
                
                if (index != lastindex)
                {
                    lastindex = index;
                    if (index >= initialindex)
                    {
                        double initialprice = GetInitialPrice(index, Scale);
                        if (initialprice > 0)
                        {
                            CalculateAllValues(initialprice, Scale, index);
                            double maxvalue = GetMaxAbsValue();
                            if (maxvalue > 0) ShowValues(Width, Height, maxvalue, index);
                        }
                    }
                }
            } catch (Exception)
            {
                throw;
            }
        }
        
        private void ResetArray()
        {
            for (int i = 0; i < Height; i++)
            {
                values[i].Price = 0;
                values[i].Value = 0;
                values[i].filled = false;
            }
        }
         
        private void CalculateAllValues(double initialprice, double gridpips, int index)
        {
            double currentprice;
            
            if (IsNumber(initialprice) && IsNumber(gridpips) && IsNumber(index))
            {
                ResetArray();
                
                currentprice = initialprice;
                for (int i = 0; i < midheight; i++)
                {
                    if(i > 0) currentprice = GetNextPrice(currentprice, gridpips, true);
                    CalculateValue(currentprice, i, index, Period);
                }
                
                currentprice = initialprice;
                for (int i = midheight; i < Height; i++)
                {
                    currentprice = GetNextPrice(currentprice, gridpips, false);
                    CalculateValue(currentprice, i, index, Period);
                }
            }
        }
        
        private void CalculateValue(double price, int arrayindex, int index, int period)
        {
            double accum = 0;
            int counter = 0;
            
            if (IsNumber(price) && IsNumber(arrayindex) && IsNumber(index) && IsNumber(period))
            {
                for (int i = index; i > index - period && i > 0; i--)
                {
                    if (IsNumber(Bars.HighPrices[i]) && IsNumber(Bars.LowPrices[i]))
                    {
                        if (Bars.HighPrices[i] >= price && Bars.LowPrices[i] <= price)
                        {
                            accum += VAL(Source[i]);  
                            counter++;
                        }   
                    }
                }
                
                values[arrayindex].Price = price;
                values[arrayindex].Value = counter > 0 ? accum / counter : 0;
                values[arrayindex].filled = counter > 0;
            }else{
                values[arrayindex].Price = 0;
                values[arrayindex].Value = 0;
                values[arrayindex].filled = false;
            }
        }
        
        private double GetInitialPrice(int index, int gridpip)
        {
            double ret = -1;
            
            if (IsNumber(Bars.ClosePrices[index]) && IsNumber(Symbol.PipSize) && IsNumber(gridpip))
            {
                double totalpips = GetPIPs(Bars.ClosePrices[index], Symbol.PipSize);
                if (IsNumber(totalpips) && (gridpip > 0))
                {
                    int div = (int)(totalpips / gridpip);
                    int intdiv = div * gridpip;
                    ret = Symbol.PipSize * intdiv;
                }
            }
            
            return ret;
        }
        
        private double GetNextPrice(double price, double gridpips, bool up)
        {
            double ret = -1;
            
            if (IsNumber(price) && IsNumber(gridpips) && IsNumber(Symbol.PipSize))
            {
                double pricepips = GetPIPs(price, Symbol.PipSize);
                if (IsNumber(pricepips))
                {
                    double newpricepips = up == true ? pricepips + gridpips : pricepips - gridpips;
                    ret = newpricepips * Symbol.PipSize;
                }
            }
            
            return ret;
        }
        
        private double GetMaxAbsValue()
        {
            double max = 0;
            
            for (int i = 0; i < Height; i++)
            {
                if (IsNumber(values[i].Value))
                {
                    if (Math.Abs(values[i].Value) > max) 
                        max = Math.Abs(values[i].Value);
                }
            }
            
            return max;
        }

        private bool IsNumber(double val)
        {
            return !double.IsNaN(val);
        }
        
        private double VAL(double value, double ret = 0)
        {
            if (IsNumber(value)) return value;
            else return ret;
        }
        
        private double DIVZ(double dividend, double divisor)
        {
            if ((divisor == 0) || (double.IsNaN(divisor)) || (double.IsNaN(dividend)))
                return double.NaN;
            else
                return dividend / divisor;
        }
    
        private double GetPIPs(double v0, double pipsize)
        {
            double ret = double.NaN;
    
            if (IsNumber(v0))
                ret = DIVZ(v0 - 0, pipsize);
    
            return ret;
        }
        
        //=========================================================================
        //                              SCREEN
        //=========================================================================
        
        private void ShowValues(int indexlength, int arraylength, double maxvalue, int index)
        {
            if (IsNumber(indexlength) && IsNumber(arraylength) && IsNumber(maxvalue) && IsNumber(index))
            {
                int firstindex = GetFirstIndex(indexlength, index);
                RemoveAllObjects(arraylength);
                
                for (int i = 0; i < arraylength; i++)
                {
                    if (IsNumber(values[i].Price) && IsNumber(values[i].Value))
                    {
                        if (values[i].filled)
                        {
                            int width =  (int)((values[i].Value * indexlength) / maxvalue); 
                            DrawRectangle(GetObjectName(i), firstindex, GetMargin(values[i].Price, Scale, true), firstindex + width, GetMargin(values[i].Price, Scale, false), GetGradientColor(values[i].Value, maxvalue, RectangleColor));
                        }
                    }
                }
            }
        }
        
        private double GetMargin(double price, double gridpips, bool up)
        {
            double ret = -1;
            
            if (IsNumber(price) && IsNumber(gridpips) && IsNumber(Symbol.PipSize))
            {
                double pricepips = GetPIPs(price, Symbol.PipSize);
                if (IsNumber(pricepips))
                {
                    double shiftedpricepips = up == true ? pricepips + (gridpips/2) : pricepips - (gridpips/2);
                    ret = shiftedpricepips * Symbol.PipSize;
                }
            }
            
            return ret;
        }
        
        private Color GetGradientColor(double val, double maxval, Color RectangleColor)
        {
            Color ret = RectangleColor;
            
            if (IsNumber(val) && IsNumber(maxval))
            {
                int transparency = (int)((Math.Abs(val) * 100) / maxval) + 50;
                ret = Color.FromArgb(transparency, RectangleColor);
            }
            
            return ret;
        }
        
        private int GetFirstIndex(int indexlength, int index)
        {
            return index - (indexlength) - Shift;
        }
        
        private void DrawRectangle(string name, int x1, double y1, int x2, double y2, Color color)
        {
            if (IsNumber(x1) && IsNumber(y1) && IsNumber(x2) && IsNumber(y2) && (name != null))
            {
                ChartRectangle rectangle;
                rectangle = Chart.DrawRectangle(name, x1, y1, x2, y2, color);
                rectangle.IsFilled = true;
            }
        }
        
        private string GetObjectName(int arrayindex)
        {
            return LABEL + this.InstanceId + "-" + arrayindex;
        }
        
        private void RemoveAllObjects(int arraylength)
        {
            for (int i = 0; i < arraylength; i++)
            {
                RemoveObject(GetObjectName(i));
            }
        }
        
        private void RemoveObject(string name)
        {
            ChartObject obj = Chart.FindObject(name);
            if (obj != null)
                Chart.RemoveObject(name);
        }
    }
}
Comments

mirk0 - May 20, 2023 @ 23:20

wow! this is very clever

Abstract - May 21, 2023 @ 00:45

Thank you!

I've uploaded a new version in order  to force even numbers for some parameters.

For a better performance, try to establish the parameter "Height" to 500 or 1000. If you don't do it, some extreme values will be missed,

Regards

mirk0 - May 21, 2023 @ 17:42

Made a right side version with the help of OpenAI haha

 

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


namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TransformDomainV2RightSide : Indicator
    {
        [Parameter("Source", Group = "Main")]
        public DataSeries Source { get; set; }
        [Parameter("Period", Group = "Main", DefaultValue = 1000, MinValue = 1)]
        public int Period { get; set; }
        [Parameter("Width", Group = "Grid", DefaultValue = 100, MinValue = 10, Step = 2)]
        public int Width { get; set; }
        [Parameter("Height", Group = "Grid", DefaultValue = 1000, MinValue = 2, Step = 2)]
        public int Height { get; set; }
        [Parameter("Scale", Group = "Grid", DefaultValue = 20, MinValue = 1)]
        public int Scale { get; set; }
        [Parameter("Shift", Group = "Configuration", DefaultValue = -100)]
        public int Shift { get; set; }
        [Parameter("Color", Group = "Configuration", DefaultValue = "MediumSeaGreen")]
        public Color RectangleColor { get; set; }
        
        private struct PriceValue
        {
            public double Price;
            public double Value;
            public bool filled;
        }
        
        private int initialindex, lastindex, midheight;
        private PriceValue[] values;

        protected override void Initialize()
        {
            try
            {
                lastindex = -1;
                initialindex = Bars.ClosePrices.Count - 1; 
                values = new PriceValue[Height];
                midheight = Height / 2;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public override void Calculate(int index)
        {
            try
            {
                if (!IsNumber(index))
                    return;
                
                if (index != lastindex)
                {
                    lastindex = index;
                    if (index >= initialindex)
                    {
                        double initialprice = GetInitialPrice(index, Scale);
                        if (initialprice > 0)
                        {
                            CalculateAllValues(initialprice, Scale, index);
                            double maxvalue = GetMaxValue();
                            if (maxvalue > 0) ShowValues(Width, Height, maxvalue, index);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
        
        private void ResetArray()
        {
            for (int i = 0; i < Height; i++)
            {
                values[i].Price = 0;
                values[i].Value = 0;
                values[i].filled = false;
            }
        }
         
        private void CalculateAllValues(double initialprice, double gridpips, int index)
        {
            double currentprice;
            
            if (IsNumber(initialprice) && IsNumber(gridpips) && IsNumber(index))
            {
                ResetArray();
                
                currentprice = initialprice;
                for (int i = 0; i < midheight; i++)
                {
                    if(i > 0) currentprice = GetNextPrice(currentprice, gridpips, true);
                    CalculateValue(currentprice, i, index, Period);
                }
                
                currentprice = initialprice;
                for (int i = midheight; i < Height; i++)
                {
                    currentprice = GetNextPrice(currentprice, gridpips, false);
                    CalculateValue(currentprice, i, index, Period);
                }
            }
        }
        
        private void CalculateValue(double price, int arrayindex, int index, int period)
        {
            double accum = 0;
            int counter = 0;
            
            if (IsNumber(price) && IsNumber(arrayindex) && IsNumber(index) && IsNumber(period))
            {
                for (int i = index; i > index - period; i--)
                {
                    if (IsNumber(Bars.HighPrices[i]) && IsNumber(Bars.LowPrices[i]))
                    {
                        if (Bars.HighPrices[i] >= price && Bars.LowPrices[i] <= price)
                        {
                            accum += Source[i];  
                            counter++;
                        }   
                    }
                }
                
                values[arrayindex].Price = price;
                values[arrayindex].Value = counter > 0 ? accum / counter : 0;
                values[arrayindex].filled = counter > 0;
            }
            else
            {
                values[arrayindex].Price = 0;
                values[arrayindex].Value = 0;
                values[arrayindex].filled = false;
            }
        }
        
        private double GetInitialPrice(int index, int gridpip)
        {
            double ret = -1;
            
            if (IsNumber(Bars.ClosePrices[index]) && IsNumber(Symbol.PipSize) && IsNumber(gridpip))
            {
                double totalpips = GetPIPs(Bars.ClosePrices[index], Symbol.PipSize);
                if (IsNumber(totalpips) && (gridpip > 0))
                {
                    double div = totalpips / gridpip;
                    int intdiv = (int)(div * gridpip);
                    ret = Symbol.PipSize * intdiv;
                }
            }
            
            return ret;
        }
        
        private double GetNextPrice(double price, double gridpips, bool up)
        {
            double ret = -1;
            
            if (IsNumber(price) && IsNumber(gridpips) && IsNumber(Symbol.PipSize))
            {
                double pricepips = GetPIPs(price, Symbol.PipSize);
                if (IsNumber(pricepips))
                {
                    double newpricepips = up == true ? pricepips + gridpips : pricepips - gridpips;
                    ret = newpricepips * Symbol.PipSize;
                }
            }
            
            return ret;
        }
        
        private double GetMaxValue()
        {
            double max = 0;
            
            for (int i = 0; i < Height; i++)
            {
                if (IsNumber(values[i].Value))
                {
                    if (values[i].Value > max) 
                        max = values[i].Value;
                }
            }
            
            return max;
        }

        private bool IsNumber(double val)
        {
            return !double.IsNaN(val);
        }
        
        private double DIVZ(double dividend, double divisor)
        {
            if ((divisor == 0) || (double.IsNaN(divisor)) || (double.IsNaN(dividend)))
                return double.NaN;
            else
                return dividend / divisor;
        }
    
        private double GetPIPs(double v0, double pipsize)
        {
            double ret = double.NaN;
    
            if (IsNumber(v0))
                ret = DIVZ(v0 - 0, pipsize);
    
            return ret;
        }
        
        //=========================================================================
        //                              SCREEN
        //=========================================================================
        
        private void ShowValues(int indexlength, int arraylength, double maxvalue, int index)
        {
            int firstindex = GetFirstIndex(indexlength, index);
            RemoveAllObjects(arraylength);
            
            for (int i = 0; i < arraylength; i++)
            {
                if (IsNumber(values[i].Price) && IsNumber(values[i].Value))
                {
                    if (values[i].filled)
                    {
                        int width =  (int)((values[i].Value * indexlength) / maxvalue); 
                        string objectname = "PD-" + this.InstanceId + "-" + i;  
                        DrawRectangle(objectname, firstindex - width, GetMargin(values[i].Price, Scale, true), firstindex, GetMargin(values[i].Price, Scale, false), GetGradientColor(values[i].Value, maxvalue, RectangleColor));
                    }
                }
            }
        }
        
        private double GetMargin(double price, double gridpips, bool up)
        {
            double ret = -1;
            
            if (IsNumber(price) && IsNumber(gridpips) && IsNumber(Symbol.PipSize))
            {
                double pricepips = GetPIPs(price, Symbol.PipSize);
                if (IsNumber(pricepips))
                {
                    double shiftedpricepips = up == true ? pricepips + (gridpips/2) : pricepips - (gridpips/2);
                    ret = shiftedpricepips * Symbol.PipSize;
                }
            }
            
            return ret;
        }
        
        private Color GetGradientColor(double val, double maxval, Color RectangleColor)
        {
            Color ret = RectangleColor;
            
            int transparency = (int)((val * 100) / maxval) + 50;
            ret = Color.FromArgb(transparency, RectangleColor);
            
            return ret;
        }
        
        private int GetFirstIndex(int indexlength, int index)
        {
            return index - Shift;
        }
        
        private void DrawRectangle(string name, int x1, double y1, int x2, double y2, Color color)
        {
            ChartRectangle rectangle;
            rectangle = Chart.DrawRectangle(name, x1, y1, x2, y2, color);
            rectangle.IsFilled = true;
        }
        
        private void RemoveAllObjects(int arraylength)
        {
            for (int i = 0; i < arraylength; i++)
            {
                string objectname = "PD-" + this.InstanceId + "-" + i;
                RemoveObject(objectname);
            }
        }
        
        private void RemoveObject(string name)
        {
            ChartObject obj = Chart.FindObject(name);
            if (obj != null)
                Chart.RemoveObject(name);
        }
    }
}

Abstract - May 21, 2023 @ 22:30

Thank you. I've made a new way to establish position according to my likings.

Regards

5