Transform Indicator to Bot
Transform Indicator to Bot
11 Nov 2020, 14:39
Hi,
I am a great layman in programming and would like to help transform this wonderful indicator into a robot.
To automatically open orders, you have control over the size of the orders you are going to execute, trailing stop and time control for work.
Could anyone help with this transformation? Thanks!
This is the code:
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 Ema3Indicator : Indicator
{
private Color _textcolor;
private ExponentialMovingAverage _emaFast;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaTrend;
[Parameter("Fast EMA (periods)", Group = "Trading", DefaultValue = 9, MinValue = 1, MaxValue = 100, Step = 1)]
public int EmaPeriodsFast { get; set; }
[Parameter("Slow EMA (periods)", Group = "Trading", DefaultValue = 21, MinValue = 1, MaxValue = 100, Step = 1)]
public int EmaPeriodsSlow { get; set; }
[Parameter("Trend EMA (periods)", Group = "Trading", DefaultValue = 55, MinValue = 1, MaxValue = 100, Step = 1)]
public int EmaPeriodsTrend { get; set; }
[Parameter("Source", Group = "Trading")]
public DataSeries Source { get; set; }
[Output("EMA Fast", LineColor = "Turquoise", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries EMAFast { get; set; }
[Output("EMA Slow", LineColor = "Orange", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries EMASlow { get; set; }
[Output("EMA Trend", LineColor = "Green", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries EMATrend { get; set; }
[Output("Stoploss Level", LineColor = "#FE0000", PlotType = PlotType.DiscontinuousLine, Thickness = 1)]
public IndicatorDataSeries StoplossLevel { get; set; }
[Output("Takeprofit Level", LineColor = "#01FF01", PlotType = PlotType.DiscontinuousLine, Thickness = 1)]
public IndicatorDataSeries TakeProfitLevel { get; set; }
protected override void Initialize()
{
// Initialize and create nested indicators
_emaFast = Indicators.ExponentialMovingAverage(Source, EmaPeriodsFast);
_emaSlow = Indicators.ExponentialMovingAverage(Source, EmaPeriodsSlow);
_emaTrend = Indicators.ExponentialMovingAverage(Source, EmaPeriodsTrend);
}
public override void Calculate(int index)
{
try
{
// Set textcolor based on selected theme
if (this.Application.ColorTheme == ColorTheme.Dark)
_textcolor = Color.FromHex("#E3D5EC");
else if (this.Application.ColorTheme == ColorTheme.Light)
_textcolor = Color.Black;
// Clear all visuals
ClearAllVisuals();
// Calculate ema results
_emaFast.Calculate(index);
_emaSlow.Calculate(index);
_emaTrend.Calculate(index);
// Save calculated results
EMAFast[index] = _emaFast.Result[index];
EMASlow[index] = _emaSlow.Result[index];
EMATrend[index] = _emaTrend.Result[index];
// Determine if we need to check for bullish or bearish setup
int? bearishSetupIndex = FindBearishSetupIndex(index);
int? bullishSetupIndex = FindBullishSetupIndex(index);
if (bearishSetupIndex != null && bullishSetupIndex != null)
{
// Find most recent bullish setup
if (bullishSetupIndex.Value > bearishSetupIndex.Value)
FindLastBullishSetup(index);
else
FindLastBearishSetup(index);
}
} catch (Exception ex)
{
Print("There was an exception in the EMA3 indicator: {0}", ex.Message);
}
}
private void ClearAllVisuals()
{
// Clear all drawings
Chart.DrawText("ema3_trade", "", 0, 0, _textcolor);
Chart.DrawText("ema3_swingHighLowIndex", "", 0, 0, _textcolor);
Chart.DrawTrendLine("ema3_longPosition", 0, 0, 0, 0, _textcolor);
Chart.DrawText("ema3_trade_pips", "", 0, 0, _textcolor);
Chart.DrawText("ema3_tp", "", 0, 0, _textcolor);
Chart.DrawText("ema3_sl", "", 0, 0, _textcolor);
Chart.DrawTrendLine("ema3_swing_highlow", 0, 0, 0, 0, _textcolor);
// Clear all visualized data series
for (int i = 0; i < Bars.Count; i++)
{
StoplossLevel[i] = double.NaN;
TakeProfitLevel[i] = double.NaN;
}
}
private int? FindBearishSetupIndex(int index)
{
for (int i = index; i > 0; i--)
{
// Test if EMA's are aligned in the same direction in order of 9, 21 55
if ((_emaFast.Result[i - 1] > _emaSlow.Result[i - 1] || _emaSlow.Result[i - 1] > _emaTrend.Result[i - 1]) && _emaFast.Result[i] < _emaSlow.Result[i] && _emaSlow.Result[i] < _emaTrend.Result[i])
return i;
}
return null;
}
private int? FindBullishSetupIndex(int index)
{
for (int i = index; i > 0; i--)
{
// Test if EMA's are aligned in the same direction in order of 9, 21 55
if ((_emaFast.Result[i - 1] < _emaSlow.Result[i - 1] || _emaSlow.Result[i - 1] < _emaTrend.Result[i - 1]) && _emaFast.Result[i] > _emaSlow.Result[i] && _emaSlow.Result[i] > _emaTrend.Result[i])
return i;
}
return null;
}
private void FindLastBearishSetup(int index)
{
Chart.DrawText("ema3_trade", "", index, Bars[index].Low, _textcolor);
double? waitForPriceLevelBreak = null;
int? swingLowIndex = null;
int emaAlignedIndex = index;
int? bullFractalIndex = null;
for (; emaAlignedIndex > 0; emaAlignedIndex--)
{
// Test if EMA's are aligned in the same direction in order of 9, 21 55
if ((_emaFast.Result[emaAlignedIndex - 1] > _emaSlow.Result[emaAlignedIndex - 1] || _emaSlow.Result[emaAlignedIndex - 1] > _emaTrend.Result[emaAlignedIndex - 1]) && _emaFast.Result[emaAlignedIndex] < _emaSlow.Result[emaAlignedIndex] && _emaSlow.Result[emaAlignedIndex] < _emaTrend.Result[emaAlignedIndex])
{
// Chart.DrawIcon("EMAsAligned", ChartIconType.DownArrow, emaAlignedIndex, Bars[emaAlignedIndex].Low, Color.Yellow);
// Find the last swing low
double swingLowLevel = (Bars[emaAlignedIndex].Low + Bars[emaAlignedIndex].High) / 2;
swingLowIndex = FindLastSwingLow(swingLowLevel, emaAlignedIndex);
if (swingLowIndex != null)
{
waitForPriceLevelBreak = Bars[swingLowIndex.Value].Low;
Chart.DrawText("ema3_swingHighLowIndex", "SL (WAITING FOR TREND CONFIRMATION)", swingLowIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
Chart.DrawTrendLine("ema3_swing_highlow", swingLowIndex.Value, waitForPriceLevelBreak.Value, emaAlignedIndex, waitForPriceLevelBreak.Value, _textcolor);
break;
}
}
}
if (waitForPriceLevelBreak != null)
{
double stoplossLevel = 0;
double takeProfitLevel = 0;
int? positionOpenIndex = null;
for (int i = emaAlignedIndex; i <= index; i++)
{
Chart.DrawTrendLine("ema3_swing_highlow", swingLowIndex.Value, waitForPriceLevelBreak.Value, i, waitForPriceLevelBreak.Value, _textcolor);
if (Bars[i].Close <= waitForPriceLevelBreak.Value)
{
bullFractalIndex = FindLastBullFractal(i);
if (bullFractalIndex != null)
{
stoplossLevel = Bars[bullFractalIndex.Value].High + (5 * Symbol.PipSize);
takeProfitLevel = Bars[i].Close - Math.Abs(Bars[bullFractalIndex.Value].High - Bars[i].Close);
positionOpenIndex = i;
// SHORT
Chart.DrawText("ema3_swingHighLowIndex", "SL (TREND CONFIRMED)", swingLowIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
Chart.DrawText("ema3_trade", "SHORT", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Low, _textcolor);
}
break;
}
}
if (positionOpenIndex != null)
{
for (int i = positionOpenIndex.Value; i <= index; i++)
{
double pips = 0;
double trendlineEndPrice = 0;
if (Bars[i].Low > takeProfitLevel && Bars[i].High < stoplossLevel)
{
pips = (Bars[positionOpenIndex.Value].Close - Bars[i].Close) / Symbol.PipSize;
trendlineEndPrice = Bars[i].Close;
UpdateBearPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
}
else
{
if (Bars[i].Low <= takeProfitLevel)
{
pips = (Bars[positionOpenIndex.Value].Close - takeProfitLevel) / Symbol.PipSize;
trendlineEndPrice = takeProfitLevel;
}
else if (Bars[i].High >= stoplossLevel)
{
pips = (Bars[positionOpenIndex.Value].Close - stoplossLevel) / Symbol.PipSize;
trendlineEndPrice = stoplossLevel;
}
UpdateBearPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
break;
}
}
}
}
}
private void FindLastBullishSetup(int index)
{
Chart.DrawText("ema3_trade", "", index, Bars[index].High, _textcolor);
double? waitForPriceLevelBreak = null;
int? swingHighIndex = null;
int emaAlignedIndex = index;
int? bearFractalIndex = null;
for (; emaAlignedIndex > 0; emaAlignedIndex--)
{
// Test if EMA's are aligned in the same direction in order of 9, 21 55
if ((_emaFast.Result[emaAlignedIndex - 1] < _emaSlow.Result[emaAlignedIndex - 1] || _emaSlow.Result[emaAlignedIndex - 1] < _emaTrend.Result[emaAlignedIndex - 1]) && _emaFast.Result[emaAlignedIndex] > _emaSlow.Result[emaAlignedIndex] && _emaSlow.Result[emaAlignedIndex] > _emaTrend.Result[emaAlignedIndex])
{
// Chart.DrawIcon("EMAsAligned", ChartIconType.DownArrow, emaAlignedIndex, Bars[emaAlignedIndex].High * 1.0008, Color.Blue);
// Find the last swing high
double swingHighLevel = (Bars[emaAlignedIndex].Low + Bars[emaAlignedIndex].High) / 2;
swingHighIndex = FindLastSwingHigh(swingHighLevel, emaAlignedIndex);
if (swingHighIndex != null)
{
waitForPriceLevelBreak = Bars[swingHighIndex.Value].High;
Chart.DrawText("ema3_swingHighLowIndex", "SH (WAITING FOR TREND CONFIRMATION)", swingHighIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
Chart.DrawTrendLine("ema3_swing_highlow", swingHighIndex.Value, waitForPriceLevelBreak.Value, emaAlignedIndex, waitForPriceLevelBreak.Value, _textcolor);
break;
}
}
}
if (waitForPriceLevelBreak != null)
{
double stoplossLevel = 0;
double takeProfitLevel = 0;
int? positionOpenIndex = null;
for (int i = emaAlignedIndex; i <= index; i++)
{
Chart.DrawTrendLine("ema3_swing_highlow", swingHighIndex.Value, waitForPriceLevelBreak.Value, i, waitForPriceLevelBreak.Value, _textcolor);
if (Bars[i].Close >= waitForPriceLevelBreak.Value)
{
bearFractalIndex = FindLastBearFractal(i);
if (bearFractalIndex != null)
{
stoplossLevel = Bars[bearFractalIndex.Value].Low - (5 * Symbol.PipSize);
takeProfitLevel = Bars[i].Close + Math.Abs(Bars[i].Close - Bars[bearFractalIndex.Value].Low);
positionOpenIndex = i;
// LONG
Chart.DrawText("ema3_swingHighLowIndex", "SH (TREND CONFIRMED)", swingHighIndex.Value, waitForPriceLevelBreak.Value, _textcolor);
Chart.DrawText("ema3_trade", "LONG", positionOpenIndex.Value, Bars[positionOpenIndex.Value].High, _textcolor);
}
break;
}
}
if (positionOpenIndex != null)
{
for (int i = positionOpenIndex.Value; i <= index; i++)
{
double pips = 0;
double trendlineEndPrice = 0;
if (Bars[i].High < takeProfitLevel && Bars[i].Low > stoplossLevel)
{
pips = (Bars[i].Close - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
trendlineEndPrice = Bars[i].Close;
UpdateBullPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
}
else
{
if (Bars[i].High >= takeProfitLevel)
{
pips = (takeProfitLevel - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
trendlineEndPrice = takeProfitLevel;
}
else if (Bars[i].Low <= stoplossLevel)
{
pips = (stoplossLevel - Bars[positionOpenIndex.Value].Close) / Symbol.PipSize;
trendlineEndPrice = stoplossLevel;
}
UpdateBullPositionVisuals(positionOpenIndex, stoplossLevel, takeProfitLevel, positionOpenIndex, i, pips, trendlineEndPrice);
break;
}
}
}
}
}
private void UpdateBearPositionVisuals(int? bullFractalIndex, double stoplossLevel, double takeProfitLevel, int? positionOpenIndex, int trendlineEndIndex, double pips, double trendlineEndPrice)
{
Chart.DrawTrendLine("ema3_longPosition", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Close, trendlineEndIndex, trendlineEndPrice, _textcolor);
Chart.DrawText("ema3_trade_pips", pips.ToString("N1") + " PIPS" + (trendlineEndIndex < Bars.Count - 1 ? "\r\nCLOSED" : ""), trendlineEndIndex, trendlineEndPrice, _textcolor);
Chart.DrawText("ema3_tp", "TP", bullFractalIndex.Value, takeProfitLevel, Color.FromHex("#01FF01"));
Chart.DrawText("ema3_sl", "SL", bullFractalIndex.Value, stoplossLevel, Color.FromHex("#FE0000"));
for (int j = 0; j <= trendlineEndIndex; j++)
StoplossLevel[j] = double.NaN;
for (int j = bullFractalIndex.Value; j <= trendlineEndIndex; j++)
StoplossLevel[j] = stoplossLevel;
for (int j = 0; j <= trendlineEndIndex; j++)
TakeProfitLevel[j] = double.NaN;
for (int j = bullFractalIndex.Value; j <= trendlineEndIndex; j++)
TakeProfitLevel[j] = takeProfitLevel;
}
private void UpdateBullPositionVisuals(int? bearFractalIndex, double stoplossLevel, double takeProfitLevel, int? positionOpenIndex, int trendlineEndIndex, double pips, double trendlineEndPrice)
{
Chart.DrawTrendLine("ema3_longPosition", positionOpenIndex.Value, Bars[positionOpenIndex.Value].Close, trendlineEndIndex, trendlineEndPrice, _textcolor);
Chart.DrawText("ema3_trade_pips", pips.ToString("N1") + " PIPS" + (trendlineEndIndex < Bars.Count - 1 ? "\r\nCLOSED" : ""), trendlineEndIndex, trendlineEndPrice, _textcolor);
Chart.DrawText("ema3_tp", "TP", bearFractalIndex.Value, takeProfitLevel, Color.FromHex("#01FF01"));
Chart.DrawText("ema3_sl", "SL", bearFractalIndex.Value, stoplossLevel, Color.FromHex("#FE0000"));
for (int j = 0; j <= trendlineEndIndex; j++)
StoplossLevel[j] = double.NaN;
for (int j = bearFractalIndex.Value; j <= trendlineEndIndex; j++)
StoplossLevel[j] = stoplossLevel;
for (int j = 0; j <= trendlineEndIndex; j++)
TakeProfitLevel[j] = double.NaN;
for (int j = bearFractalIndex.Value; j <= trendlineEndIndex; j++)
TakeProfitLevel[j] = takeProfitLevel;
}
private int? FindLastSwingLow(double swingLowLevel, int startIndex)
{
// Find the start of the current swing
int startOfCurrentSwing = startIndex;
for (; startOfCurrentSwing >= 0; startOfCurrentSwing--)
{
if (Bars[startOfCurrentSwing].High > _emaFast.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].High > _emaSlow.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].High > _emaTrend.Result[startOfCurrentSwing])
break;
}
// Chart.DrawIcon("StartOfCurrentSwingIndex", ChartIconType.DownArrow, startOfCurrentSwing, Bars[startOfCurrentSwing].High * 1.0008, Color.Magenta);
// Find the previous candle that touches the swinghigh level
int previousSwing = startOfCurrentSwing;
for (; previousSwing >= 0; previousSwing--)
{
if (Bars[previousSwing].High >= swingLowLevel && Bars[previousSwing].Low <= swingLowLevel)
{
break;
}
}
//Chart.DrawIcon("StartOfPreviousSwingIndex", ChartIconType.DownArrow, previousSwing, Bars[previousSwing].High * 1.0008, Color.Yellow);
// Find the last bull fractal (=SH). The found previousSwing index will very often be the SH itself, so set the offset to 2, so that this SH can be found
return FindLastBearFractal(Math.Min(previousSwing + 2, Bars.Count - 1));
}
private int? FindLastSwingHigh(double swingHighLevel, int startIndex)
{
// Find the start of the current swing
int startOfCurrentSwing = startIndex;
for (; startOfCurrentSwing >= 0; startOfCurrentSwing--)
{
if (Bars[startOfCurrentSwing].Low < _emaFast.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].Low < _emaSlow.Result[startOfCurrentSwing] && Bars[startOfCurrentSwing].Low < _emaTrend.Result[startOfCurrentSwing])
break;
}
// Chart.DrawIcon("StartOfCurrentSwingIndex", ChartIconType.DownArrow, startOfCurrentSwing, Bars[startOfCurrentSwing].High * 1.0008, Color.Magenta);
// Find the previous candle that touches the swinghigh level
int previousSwing = startOfCurrentSwing;
for (; previousSwing >= 0; previousSwing--)
{
if (Bars[previousSwing].Low <= swingHighLevel && Bars[previousSwing].High >= swingHighLevel)
{
break;
}
}
//Chart.DrawIcon("StartOfPreviousSwingIndex", ChartIconType.DownArrow, previousSwing, Bars[previousSwing].High * 1.0008, Color.Yellow);
// Find the last bull fractal (=SH). The found previousSwing index will very often be the SH itself, so set the offset to 2, so that this SH can be found
return FindLastBullFractal(Math.Min(previousSwing + 2, Bars.Count - 1));
}
private int? FindLastBearFractal(int startIndex)
{
for (int i = startIndex; i >= 4; i--)
{
if (this.Bars[i].Low > this.Bars[i - 2].Low && this.Bars[i - 1].Low > this.Bars[i - 2].Low && this.Bars[i - 3].Low > this.Bars[i - 2].Low && this.Bars[i - 4].Low > this.Bars[i - 2].Low)
return i - 2;
}
return null;
}
private int? FindLastBullFractal(int startIndex)
{
for (int i = startIndex; i >= 4; i--)
{
if (this.Bars[i].High < this.Bars[i - 2].High && this.Bars[i - 1].High < this.Bars[i - 2].High && this.Bars[i - 3].High < this.Bars[i - 2].High && this.Bars[i - 4].High < this.Bars[i - 2].High)
return i - 2;
}
return null;
}
}
}