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: colors (positive and negative values), width, height, vertical scale (PIPs), shift back and opacity.
The indicator to be shown is specified in the field 'Source'.
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 TransformDomainV11 : Indicator
{
[Parameter("Source", Group = "Main")]
public DataSeries Source { get; set; }
[Parameter("Period", Group = "Main", DefaultValue = 500, MinValue = 1)]
public int Period { get; set; }
[Parameter("Width (Even)", Group = "Grid", DefaultValue = 50, 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 = 2, MinValue = 1)]
public int Scale { get; set; }
[Parameter("Shift Back", Group = "Profile Configuration", DefaultValue = 0, MinValue = 0)]
public int Shift { get; set; }
[Parameter("Color Opacity [0-155]", Group = "Profile Configuration", DefaultValue = 50, MinValue = 0, MaxValue = 155)]
public int ColorOpacity { get; set; }
[Parameter("Positive Color", Group = "Profile Configuration", DefaultValue = "MediumSeaGreen")]
public Color PositiveColor { get; set; }
[Parameter("Negative Color", Group = "Profile Configuration", DefaultValue = "IndianRed")]
public Color NegativeColor { 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;
//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, 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)VAL((DIVZ((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, values[i].Value >= 0 ? PositiveColor : NegativeColor));
}
}
}
}
}
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) + ColorOpacity;
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 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);
}
}
}
Abstract
Joined on 08.08.2021
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: TransformDomainV11.algo
- Rating: 5
- Installs: 609
- Modified: 13/06/2023 11:30
Comments
Thank you. I've made a new way to establish position according to my likings.
Regards
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);
}
}
}
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
wow! this is very clever
20Bet je jedno z najnovších online kasín https://casinohex.sk/online-kasina/20bet/ na trhu a už sa stalo veľmi populárnym medzi hráčmi. Stránka ponúka obrovský výber slotov, živých hier s dealerom a športových stávok. Je to skvelé miesto pre tých, ktorí radi skúšajú rôzne druhy hier a stávok na jednom mieste. Okrem toho, 20Bet ponúka aj veľmi zaujímavé bonusy a akcie pre nových hráčov a verných zákazníkov. Stránka je prehľadná a jednoduchá na používanie, s rýchlymi a jednoduchými vkladmi a výbermi peňazí. Pre tých, ktorí hľadajú nové a zaujímavé online kasíno, 20Bet je určite skvelá voľba.