Category Other  Published on 19/04/2020

Solid Horizon 2020

Description

Solid Horizon 2020 is an update to Solid Horizon indicator (https://ctrader.com/algos/indicators/show/1721) I have released around 2 years ago.
Indicator's functionality allows to make more informed trading decisions, as well as assisting in risk management.

Key features:

  • Trend Status / Momentum / Fib levels / Open Gaps monitoring
  • Position Sizing / Break-Even Calculation / PL targets / Suggested Order Levels
  • Daily / Weekly PL tracking, Visual Margin warning

It would take some time to explain all the features in detail, thus I have created a short manual available @ http://solidindicators.com/horizon/
Suggest you keep the default parameters as is and try it out with a few small sized trades on a single instrument to understand the logic behind it.

Enjoy! :)

 


/*
Solid Horizon 2020 - cTrader indicator. Code slowly evolved over 2 years.
Find it useful? Give me a shout https://ctrader.com/users/profile/17773

Usage documentation available @ http://solidindicators.com/horizon/

*/

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.ArabianStandardTime, AutoRescale = true)]
    public class SolidHorizon2020 : Indicator
    {

        // Risk coefficient, higher number means lower risk, 1000 - high risk, 5000 - low risk (default 2400)
        [Parameter("Risk coefficient", DefaultValue = 2400, MinValue = 1000, MaxValue = 5000)]
        public int re { get; set; }

        // Maximum account value for risk calculation (balance for optimum monthly trading should be half of this)
        [Parameter("Maximum account balance", DefaultValue = 100000)]
        public int rmax { get; set; }

        private int trendperiod = 30 * 12;
        private double e, v, ev, p, d, x, g, tp, pg, ttp,
        wpt, wwp, wg, od, epmx, epmn, ox, tv, f50, f38,
        f61, cp, maxv, ds, range, i, k, op, oe, ov,
        oev, og, max, min, pips, opmx, opmn, ddcoef, rp, rng;

        private bool mainup, localup, immdup, bullrange, bearrange, bullsup, bearsup, bullres, bearres, brokesup,
        brokeres, rup, rdn, closed;

        private ExponentialMovingAverage ema50, ema200;
        private RelativeStrengthIndex rsi;
        private AverageTrueRange atr;

        Colors tc, wc, rc;
        Colors pColor = Colors.SlateBlue;

        protected override void Initialize()
        {
            Positions.Closed += PositionClosed;

            epmx = 0;
            epmn = 100000;

            ema50 = Indicators.ExponentialMovingAverage(MarketSeries.Close, 50 * 12);
            ema200 = Indicators.ExponentialMovingAverage(MarketSeries.Close, 200 * 12);
            rsi = Indicators.RelativeStrengthIndex(MarketSeries.Close, 14);
        }

        private void PositionClosed(PositionClosedEventArgs args)
        {
            var pos = args.Position;
            string pl = "position" + pos.EntryTime;
            string pl2 = pl + "2";
            ChartObjects.RemoveObject(pl);
            ChartObjects.RemoveObject(pl2);
            epmx = 0;
            epmn = 100000;
        }


        public override void Calculate(int index)
        {
            e = 0;
            v = 0;
            oe = 0;
            ov = 0;
            tv = 0;

            ddcoef = (100 / ((rmax - Account.Equity) / (re * 7.5)));
            if (ddcoef < 1)
                ddcoef = 1;

            ds = (int)(((rmax - Account.Equity) / re * Account.Equity / 5) / 5000) * 5000;
            if (ds < 10000)
                ds = 10000;

            maxv = ds * 5;

            max = MarketSeries.High.Maximum(MarketSeries.High.Count / 2);
            min = MarketSeries.Low.Minimum(MarketSeries.Low.Count / 2);

            range = max - min;
            pips = range / 4;
            f50 = (max - min) * 0.5;
            f38 = (max - min) * 0.382;
            f61 = (max - min) * 0.618;

            ChartObjects.DrawHorizontalLine("mx", max, Colors.Orange, 1, LineStyle.Lines);
            ChartObjects.DrawHorizontalLine("mn", min, Colors.Orange, 1, LineStyle.Lines);
            ChartObjects.DrawHorizontalLine("f50", min + f50, Colors.OrangeRed, 1, LineStyle.DotsRare);
            ChartObjects.DrawHorizontalLine("f38", min + f38, Colors.DarkOrange, 1, LineStyle.DotsVeryRare);
            ChartObjects.DrawHorizontalLine("f61", min + f61, Colors.DarkOrange, 1, LineStyle.DotsVeryRare);

            localtrend(index);

            foreach (var position in Positions)
            {
                if (position.SymbolCode == Symbol.Code)
                {
                    ev = position.Volume;
                    tv += ev;
                    if (position.TradeType == TradeType.Sell)
                        ev = ev * -1;
                    e = e + position.EntryPrice * ev;
                    v = v + ev;

                    if (position.EntryPrice >= epmx)
                    {
                        epmx = position.EntryPrice;
                        ChartObjects.RemoveObject("pmx");
                    }

                    if (position.EntryPrice <= epmn)
                    {
                        epmn = position.EntryPrice;
                        ChartObjects.RemoveObject("pmn");
                    }
                }
            }

            p = e / v;

            if (v == 0)
            {
                p = Symbol.Bid;
                v = (int)ds;
            }

            if (Positions.Count > 0)
            {
                ov = v;
                oe = e;
            }

            tp = 0;
            wpt = 0;
            wwp = 0;
            ttp = Account.Equity / 25;
            wwp = ttp * 3;

            foreach (var ht in History)
            {
                if (ht.SymbolCode == Symbol.Code && ht.ClosingTime.Date == DateTime.Now.Date)
                    tp = tp + ht.NetProfit;
                if (ht.SymbolCode == Symbol.Code && ht.ClosingTime.Date > DateTime.Now.AddDays(-7))
                    wpt = wpt + ht.NetProfit;
            }

            opmx = epmx;
            opmn = epmn;

            foreach (var order in PendingOrders)
            {
                if (order.SymbolCode == Symbol.Code)
                {
                    oev = order.Volume;
                    if (order.TradeType == TradeType.Sell)
                        oev = oev * -1;
                    oe = oe + order.TargetPrice * oev;
                    ov = ov + oev;

                    if (order.TargetPrice >= opmx)
                        opmx = order.TargetPrice;

                    if (order.TargetPrice <= opmn)
                        opmn = order.TargetPrice;
                }
            }

            op = oe / ov;

            pg = ttp - tp;
            wg = wwp - wpt;

            d = (Account.Equity / ddcoef * Symbol.PipSize / Symbol.PipValue) / v;


            x = (Account.FreeMargin * Symbol.PipSize / Symbol.PipValue) / v;
            g = (pg * Symbol.PipSize / Symbol.PipValue) / v;
            cp = g * (tv / (ds * 5));

            od = (Account.Equity / ddcoef * Symbol.PipSize / Symbol.PipValue) / ov;

            ox = ((Account.FreeMargin + Account.UnrealizedNetProfit) * Symbol.PipSize / Symbol.PipValue) / ov;

            og = (pg * Symbol.PipSize / Symbol.PipValue) / ov;

            string be = "" + p.ToString("0.00000") + " (" + v / 1000 + ")";
            string bg = "" + v;
            string bo = "" + op.ToString("0.00000") + " (" + ov / 1000 + ")";
            string rp = "" + (int)(pg - Account.UnrealizedNetProfit) * -1;
            string de = "" + (int)(Account.Equity / ddcoef) * -1;
            string tl3 = "" + (int)(Account.Equity / ddcoef * 2) * -1;
            string tl4 = "" + (int)(Account.Equity / ddcoef * 3) * -1;
            string tl5 = "" + (int)(Account.Equity / ddcoef * 4) * -1;

            string dp = "" + (int)pg;
            string wp = "" + (int)(wg * -1 + Account.UnrealizedNetProfit);

            double up = Account.UnrealizedNetProfit;
            double ae = Account.Equity / 1000;

            string ps = "" + up.ToString("0") + " (" + ae.ToString("0.0") + "k )";
            string vi = ps + "\n" + tv / 1000 + " / " + maxv / 1000 + " (" + (int)ds / 1000 + ")";


            if (pg < 0)
                tc = Colors.DarkRed;
            else
                tc = Colors.DarkSeaGreen;

            if (wg - Account.UnrealizedNetProfit > 0)
                wc = Colors.DarkRed;
            else
                wc = Colors.DarkSeaGreen;

            if (pg - Account.UnrealizedNetProfit > 0)
                rc = Colors.DarkRed;
            else
                rc = Colors.DarkSeaGreen;

            if ((Account.UnrealizedNetProfit / pg) > (tv / (ds * 5)))
            {

                ChartObjects.DrawText("gtc", "Good to Close: " + Account.UnrealizedNetProfit.ToString("0"), StaticPosition.BottomLeft, Colors.LightYellow);
                ChartObjects.RemoveObject("vi");
            }
            else
            {
                ChartObjects.DrawText("vi", vi, StaticPosition.BottomLeft, Colors.LightYellow);
                ChartObjects.RemoveObject("gtc");
            }

            ChartObjects.DrawText("p", rp, StaticPosition.TopRight, rc);
            ChartObjects.DrawText("wpi", wp, StaticPosition.BottomRight, wc);

            ChartObjects.DrawLine("agg", index - 5, p, index + 10, p, Colors.Blue);
            ChartObjects.DrawText("aggn", be, index + 3, p, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.NavajoWhite);

            if (PendingOrders.Count > 0)
            {
                ChartObjects.DrawLine("agg o", index - 5, op, index + 10, op, Colors.MediumSeaGreen);
                ChartObjects.DrawLine("agg ou", index - 1, op + og, index + 10, op + og, Colors.MediumSeaGreen);
                ChartObjects.DrawText("aggn o", bo, index + 3, op, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.MediumSeaGreen);
                ChartObjects.DrawLine("ogg d", index - 5, op - od, index + 10, op - od, Colors.MediumSeaGreen);
                ChartObjects.DrawLine("ot d", index - 5, op - od, index + 10, op - od, Colors.SeaGreen);
                ChartObjects.DrawLine("ot25 d", index - 5, op - od * 2, index + 10, op - od * 2, Colors.SeaGreen, 1, LineStyle.DotsVeryRare);
                ChartObjects.DrawLine("ot30 d", index - 5, op - od * 3, index + 10, op - od * 3, Colors.SeaGreen, 1, LineStyle.DotsVeryRare);
                ChartObjects.DrawLine("ot50 d", index - 5, op - od * 4, index + 10, op - od * 4, Colors.SeaGreen, 1, LineStyle.DotsRare);
                ChartObjects.DrawText("ottd5", tl5, index + 6, op - od * 4, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.DarkRed);
                ChartObjects.DrawLine("ox d", index - 5, op - ox, index + 10, op - ox, Colors.IndianRed);


                if (ov > 0)
                {
                    ChartObjects.DrawLine("omn", index - 90, opmx - range, index - 60, opmx - range, Colors.ForestGreen, 1, LineStyle.DotsRare);


                    for (i = 1; (ov + ds * i) <= maxv; i++)
                    {
                        string ntl = "OPos" + i;
                        string ntl2 = ntl + "2";

                        ChartObjects.DrawLine(ntl, index - 90, opmn - pips * i, index - 60, opmn - pips * i, Colors.ForestGreen, 1, LineStyle.DotsVeryRare);
                        ChartObjects.DrawLine(ntl2, index - 70, opmn - pips * i + pips / 2, index - 60, opmn - pips * i + pips / 2, Colors.ForestGreen, 1, LineStyle.DotsVeryRare);
                    }
                }
                if (ov < 0)
                {
                    ChartObjects.DrawLine("omx", index - 90, opmn + range, index - 60, opmn + range, Colors.ForestGreen, 1, LineStyle.DotsRare);

                    for (i = 1; (ov - ds * i) >= maxv * -1; i++)
                    {
                        string ntl = "OPos" + i;
                        string ntl2 = ntl + "2";

                        ChartObjects.DrawLine(ntl, index - 90, opmx + pips * i, index - 60, opmx + pips * i, Colors.ForestGreen, 1, LineStyle.DotsVeryRare);
                        ChartObjects.DrawLine(ntl2, index - 70, opmx + pips * i - pips / 2, index - 60, opmx + pips * i - pips / 2, Colors.ForestGreen, 1, LineStyle.DotsVeryRare);
                    }
                }
                for (k = i; k < 6; k++)
                {

                    string ntl = "OPos" + k;
                    string ntl2 = ntl + "2";
                    ChartObjects.RemoveObject(ntl);
                    ChartObjects.RemoveObject(ntl2);
                }
            }
            else
            {
                ChartObjects.RemoveObject("agg o");
                ChartObjects.RemoveObject("agg ou");
                ChartObjects.RemoveObject("aggn o");
                ChartObjects.RemoveObject("ogg d");
                ChartObjects.RemoveObject("ot d");
                ChartObjects.RemoveObject("ot25 d");
                ChartObjects.RemoveObject("ot30 d");
                ChartObjects.RemoveObject("ot50 d");
                ChartObjects.RemoveObject("ox d");
                ChartObjects.RemoveObject("omx");
                ChartObjects.RemoveObject("omn");
                for (k = 1; k < 6; k++)
                {

                    string ntl = "OPos" + k;
                    string ntl2 = ntl + "2";
                    ChartObjects.RemoveObject(ntl);
                    ChartObjects.RemoveObject(ntl2);
                }
            }

            if (Positions.Count == 0)
            {
                ChartObjects.RemoveObject("agg dd");
                ChartObjects.RemoveObject("agg um");
                ChartObjects.RemoveObject("gpu");
                ChartObjects.RemoveObject("agg cp");
                ChartObjects.RemoveObject("agg d");
                ChartObjects.RemoveObject("dpd");
                ChartObjects.RemoveObject("t u");
                ChartObjects.RemoveObject("t25 u");
                ChartObjects.RemoveObject("t30 u");
                ChartObjects.RemoveObject("t50 u");
                ChartObjects.RemoveObject("ttd3");
                ChartObjects.RemoveObject("ttd4");
                ChartObjects.RemoveObject("ttd5");
                ChartObjects.RemoveObject("pmx");
                ChartObjects.RemoveObject("pmn");
                for (k = 1; k < 6; k++)
                {

                    string ntl = "Pos" + k;
                    string ntl2 = ntl + "2";
                    ChartObjects.RemoveObject(ntl);
                    ChartObjects.RemoveObject(ntl2);
                }
                if (pg > 0)
                {
                    ChartObjects.DrawText("aggt", bg, index + 5, p - g, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.Bisque);
                    ChartObjects.DrawText("aggtu", bg, index + 5, p + g, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.Bisque);
                    ChartObjects.DrawLine("agg tu", index - 1, p - g, index + 10, p - g, Colors.Bisque);
                    ChartObjects.DrawLine("agg td", index - 1, p + g, index + 10, p + g, Colors.Bisque);
                }
            }
            else
            {
                ChartObjects.RemoveObject("aggt");
                ChartObjects.RemoveObject("aggtu");
                ChartObjects.RemoveObject("agg tu");
                ChartObjects.RemoveObject("agg td");
                ChartObjects.DrawLine("agg dd", index - 5, Symbol.Bid - x, index + 10, Symbol.Bid - x, Colors.OrangeRed);
                ChartObjects.DrawLine("agg um", index - 1, p + g, index + 10, p + g, pColor);
                ChartObjects.DrawText("gpu", dp, index + 6, p + g, VerticalAlignment.Top, HorizontalAlignment.Right, tc);
                if (pg > 0)
                    ChartObjects.DrawLine("agg cp", index - 1, p + cp, index + 10, p + cp, pColor, 1, LineStyle.Dots);
                ChartObjects.DrawLine("agg d", index - 5, p - d, index + 10, p - d, pColor);
                ChartObjects.DrawText("dpd", de, index + 6, p - d, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.DarkRed);
                ChartObjects.DrawLine("t u", index - 5, p - d, index + 10, p - d, Colors.AliceBlue);
                ChartObjects.DrawLine("t25 u", index - 5, p - d * 2, index + 10, p - d * 2, Colors.AliceBlue, 1, LineStyle.DotsVeryRare);
                ChartObjects.DrawLine("t30 u", index - 5, p - d * 3, index + 10, p - d * 3, Colors.AliceBlue, 1, LineStyle.DotsVeryRare);
                ChartObjects.DrawLine("t50 u", index - 5, p - d * 4, index + 10, p - d * 4, Colors.AliceBlue, 1, LineStyle.DotsRare);
                ChartObjects.DrawText("ttd3", tl3, index + 6, p - d * 2, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.DimGray);
                ChartObjects.DrawText("ttd4", tl4, index + 6, p - d * 3, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.DimGray);
                ChartObjects.DrawText("ttd5", tl5, index + 6, p - d * 4, VerticalAlignment.Top, HorizontalAlignment.Right, Colors.DimGray);

                if (v > 0)
                {
                    ChartObjects.DrawLine("pmn", index - 90, epmx - range, index - 60, epmx - range, Colors.DarkCyan, 1, LineStyle.DotsRare);

                    for (i = 1; (v + ds * i) <= maxv; i++)
                    {
                        string ntl = "Pos" + i;
                        string ntl2 = ntl + "2";

                        ChartObjects.DrawLine(ntl, index - 90, epmn - pips * i, index - 60, epmn - pips * i, Colors.DarkCyan, 1, LineStyle.DotsVeryRare);
                        ChartObjects.DrawLine(ntl2, index - 70, epmn - pips * i + pips / 2, index - 60, epmn - pips * i + pips / 2, Colors.DarkCyan, 1, LineStyle.DotsVeryRare);
                    }
                }
                else
                {
                    ChartObjects.DrawLine("pmx", index - 90, epmn + range, index - 60, epmn + range, Colors.DarkCyan, 1, LineStyle.DotsRare);

                    for (i = 1; (v - ds * i) >= maxv * -1; i++)
                    {
                        string ntl = "Pos" + i;
                        string ntl2 = ntl + "2";

                        ChartObjects.DrawLine(ntl, index - 90, epmx + pips * i, index - 60, epmx + pips * i, Colors.DarkCyan, 1, LineStyle.DotsVeryRare);
                        ChartObjects.DrawLine(ntl2, index - 70, epmx + pips * i - pips / 2, index - 60, epmx + pips * i - pips / 2, Colors.DarkCyan, 1, LineStyle.DotsVeryRare);
                    }
                }

                for (k = i; k < 6; k++)
                {

                    string ntl = "Pos" + k;
                    string ntl2 = ntl + "2";
                    ChartObjects.RemoveObject(ntl);
                    ChartObjects.RemoveObject(ntl2);
                }
            }
        }

        private void localtrend(int li)
        {
            int count = MarketSeries.Close.Count;

            int maxIndex1 = FindNextLocalExtremum(MarketSeries.High, count - 1, true);
            int maxIndex2 = FindNextLocalExtremum(MarketSeries.High, maxIndex1 - trendperiod, true);

            int minIndex1 = FindNextLocalExtremum(MarketSeries.Low, count - 1, false);
            int minIndex2 = FindNextLocalExtremum(MarketSeries.Low, minIndex1 - trendperiod, false);

            int lastgap = FindLastGap(count);

            int startIndex = Math.Min(maxIndex2, minIndex2) - 100;
            int endIndex = count + 100;


            double mx = MarketSeries.High[maxIndex1];
            double mn = MarketSeries.Low[minIndex1];
            double diff = mx - mn;

            double gap = MarketSeries.Close[lastgap];

            Colors bull = Colors.DarkGreen;
            Colors strongbull = Colors.Green;

            Colors bear = Colors.DarkRed;
            Colors strongbear = Colors.Red;

            string marketstatus = "EMA Trend: ";

            ChartObjects.RemoveObject("rsi");
            ChartObjects.RemoveObject("rsid");
            ChartObjects.RemoveObject("rvr");
            ChartObjects.RemoveObject("suggestion");
            ChartObjects.RemoveObject("bulr");
            ChartObjects.RemoveObject("bearr");
            ChartObjects.RemoveObject("gap");
            ChartObjects.RemoveObject("gapt");

            if (ema50.Result.LastValue > ema200.Result.LastValue)
            {
                marketstatus = marketstatus + "Up\n";
                mainup = true;
            }
            else
            {
                marketstatus = marketstatus + "Down\n";
                mainup = false;
            }

            ChartObjects.DrawLine("ema50", li + 10, ema50.Result.LastValue, li + 15, ema50.Result.LastValue, Colors.LightGray, 1, LineStyle.Dots);
            ChartObjects.DrawLine("ema200", li + 5, ema200.Result.LastValue, li + 15, ema200.Result.LastValue, Colors.Gray, 2, LineStyle.Dots);

            rng = CurrentRange(14);
            ChartObjects.DrawLine("rnghigh", li + 16, Symbol.Ask + rng, li + 16, Symbol.Bid - rng, Colors.LightBlue, 1, LineStyle.DotsRare);


            if (lastgap != 0)
            {
                ChartObjects.DrawLine("gap", lastgap, gap, li + 5, gap, Colors.DarkCyan, 1, LineStyle.DotsRare);
                ChartObjects.DrawText("gapt", "\n\n\n\n\nopen gap at: " + gap, StaticPosition.TopCenter, Colors.Gray);
            }

            bearres = false;
            bullres = false;
            brokeres = false;

            bullsup = false;
            bearsup = false;
            brokesup = false;


            if (maxIndex1 < minIndex1)
            {
                // bullish retracement
                rp = (int)((Symbol.Bid - min) / diff * 100);
                marketstatus = marketstatus + "Retracing: Up (" + rp + "%)\n";

                ChartObjects.DrawLine("236", li - 45, mx - diff * 0.764, li - 1, mx - diff * 0.764, bear);
                ChartObjects.DrawLine("382", li - 45, mx - diff * 0.382, li - 1, mx - diff * 0.382, strongbear, 1);
                ChartObjects.DrawLine("500", li - 45, mx - diff * 0.5, li - 1, mx - diff * 0.5, bear, 1, LineStyle.Dots);
                ChartObjects.DrawLine("618", li - 45, mx - diff * 0.618, li - 1, mx - diff * 0.618, strongbear, 1);

                if ((mx - diff * 0.764) - Symbol.Bid < 5 * Symbol.PipSize && Symbol.Bid < (mx - diff * 0.764))
                    marketstatus = marketstatus + " (approaching resistance)\n";

                if (Symbol.Bid > (mx - diff * 0.764) && Symbol.Bid < (mx - diff * 0.5))
                {
                    marketstatus = marketstatus + " (within bearish resistance)\n";
                    bearres = true;
                }

                if (Symbol.Bid > (mx - diff * 0.5) && Symbol.Bid < (mx - diff * 0.382))
                {
                    marketstatus = marketstatus + " (within bullish resistance)\n";
                    bullres = true;
                }

                if (Symbol.Bid > (mx - diff * 0.382 + range / 10 / Symbol.PipSize))
                {
                    marketstatus = marketstatus + " (broke resistance)\n";
                    brokeres = true;
                }
                else if (Symbol.Bid > (mx - diff * 0.382))
                    marketstatus = marketstatus + " (breaking resistance)\n";

                localup = true;
            }
            else
            {
                // bearish retracement
                rp = (int)((mx - Symbol.Bid) / diff * 100);
                marketstatus = marketstatus + "Retracing: Down (" + rp + "%)\n";

                ChartObjects.DrawLine("236", li - 45, mn + diff * 0.764, li - 1, mn + diff * 0.764, bull);
                ChartObjects.DrawLine("382", li - 45, mn + diff * 0.382, li - 1, mn + diff * 0.382, strongbull, 1);
                ChartObjects.DrawLine("500", li - 45, mn + diff * 0.5, li - 1, mn + diff * 0.5, bull, 1, LineStyle.Dots);
                ChartObjects.DrawLine("618", li - 45, mn + diff * 0.618, li - 1, mn + diff * 0.618, strongbull, 1);

                if (Symbol.Bid - (mn + diff * 0.764) < 5 * Symbol.PipSize && Symbol.Bid > (mn + diff * 0.764))
                    marketstatus = marketstatus + " (approaching support)\n";

                if (Symbol.Bid < (mn + diff * 0.764) && Symbol.Bid > (mn + diff * 0.5))
                {
                    marketstatus = marketstatus + " (within bullish support)\n";
                    bullsup = true;
                }

                if (Symbol.Bid < (mn + diff * 0.5) && Symbol.Bid > (mn + diff * 0.382))
                {
                    marketstatus = marketstatus + " (within bearish support)\n";
                    bearsup = true;
                }

                if (Symbol.Bid < (mn + diff * 0.382 - range / 10 / Symbol.PipSize))
                {
                    marketstatus = marketstatus + " (broke support)\n";
                    brokesup = true;
                }
                else if (Symbol.Bid < (mn + diff * 0.382))
                    marketstatus = marketstatus + " (breaking support)\n";
                localup = false;
            }

            if (Symbol.Bid < min + f38)
            {
                marketstatus = marketstatus + "Bearish";
                immdup = false;
            }
            if (Symbol.Bid > min + f61)
            {
                marketstatus = marketstatus + "Bullish";
                immdup = true;
            }
            bullrange = false;
            bearrange = false;
            if (Symbol.Bid < min + f50 && Symbol.Bid > min + f38)
            {
                marketstatus = marketstatus + "Bearish range";
                bearrange = true;
            }
            if (Symbol.Bid > min + f50 && Symbol.Bid < min + f61)
            {
                marketstatus = marketstatus + "Bullish range";
                bullrange = true;
            }

            ChartObjects.DrawText("marketstatus", marketstatus, StaticPosition.TopCenter);

            var lastCandleHigh = MarketSeries.High.Last(1);
            var lastCandleLow = MarketSeries.Low.Last(1);
            var lastCandleOpen = MarketSeries.Open.Last(1);
            var lastCandleClose = MarketSeries.Close.Last(1);

            rup = false;
            rdn = false;

            if (lastCandleHigh - ((lastCandleHigh - lastCandleLow) * 20 / 100) < lastCandleClose)
                rup = true;

            if (lastCandleLow + ((lastCandleHigh - lastCandleLow) * 20 / 100) > lastCandleClose)
                rdn = true;

            if (rsi.Result.LastValue < 30)
                ChartObjects.DrawText("rsi", "!! OVERSOLD !!", StaticPosition.Right, Colors.Green);
            if (rsi.Result.LastValue > 70)
                ChartObjects.DrawText("rsi", "!! OVERBOUGHT !!", StaticPosition.Right, Colors.Red);

            if (rsi.Result.IsFalling() && rsi.Result.LastValue < 50)
                ChartObjects.DrawText("rsid", "\nweak - weakening\n" + rsi.Result.LastValue.ToString("0"), StaticPosition.Right, Colors.Red);
            if (rsi.Result.IsRising() && rsi.Result.LastValue < 50)
                ChartObjects.DrawText("rsid", "\nweak - strengthening\n" + rsi.Result.LastValue.ToString("0"), StaticPosition.Right, Colors.DarkGreen);
            if (rsi.Result.IsFalling() && rsi.Result.LastValue > 50)
                ChartObjects.DrawText("rsid", "\nstrong - weakening\n" + rsi.Result.LastValue.ToString("0"), StaticPosition.Right, Colors.DarkRed);
            if (rsi.Result.IsRising() && rsi.Result.LastValue > 50)
                ChartObjects.DrawText("rsid", "\nstrong - strengthening\n" + rsi.Result.LastValue.ToString("0"), StaticPosition.Right, Colors.Green);


            if ((mainup && !localup && bullsup && bullrange && rup) ^ (!mainup && immdup && brokeres && rup))
            {
                ChartObjects.DrawText("suggestion", "!! BUY !!\n\n", StaticPosition.BottomCenter, Colors.Green);
            }
            if ((!mainup && localup && bearres && bearrange && rdn) ^ (mainup && !immdup && brokesup && rdn))
            {
                ChartObjects.DrawText("suggestion", "!! SELL !!\n\n", StaticPosition.BottomCenter, Colors.Red);
            }
            if (bullres)
                ChartObjects.DrawText("bulr", "(caution - potential bullish reversal)", StaticPosition.BottomCenter, Colors.Green);
            if (bearsup)
                ChartObjects.DrawText("bearr", "(caution - potential bearish reversal)", StaticPosition.BottomCenter, Colors.Red);
        }


        private int FindNextLocalExtremum(DataSeries series, int maxIndex, bool findMax)
        {
            for (int index = maxIndex; index >= 0; index--)
            {
                if (IsLocalExtremum(series, index, findMax))
                {
                    return index;
                }
            }
            return 0;
        }

        private int FindLastGap(int maxIndex)
        {
            for (int index = maxIndex; index >= 0; index--)
            {
                closed = false;
                if ((MarketSeries.Close[index - 1] != MarketSeries.Open[index]) && (MarketSeries.Low[index] - 0.1 * Symbol.PipSize > MarketSeries.Close[index - 1]))
                {
                    int indexgap = index;
                    while (indexgap <= maxIndex)
                    {
                        if (MarketSeries.Low[indexgap] - 0.1 * Symbol.PipSize <= MarketSeries.Close[index - 1])
                        {
                            closed = true;
                            break;
                        }
                        indexgap++;
                    }
                    if (!closed)
                        return (index - 1);
                }

                if ((MarketSeries.Close[index - 1] != MarketSeries.Open[index]) && (MarketSeries.High[index] + 0.1 * Symbol.PipSize < MarketSeries.Close[index - 1]))
                {
                    int indexgap = index;
                    while (indexgap <= maxIndex)
                    {
                        if (MarketSeries.High[indexgap] + 0.1 * Symbol.PipSize >= MarketSeries.Close[index - 1])
                        {
                            closed = true;
                            break;
                        }
                        indexgap++;
                    }
                    if (!closed)
                        return (index - 1);
                }
            }
            return 0;
        }


        private bool IsLocalExtremum(DataSeries series, int index, bool findMax)
        {
            int end = Math.Min(index + trendperiod, series.Count - 1);
            int start = Math.Max(index - trendperiod, 0);

            double value = series[index];

            for (int i = start; i < end; i++)
            {
                if (findMax && value < series[i])
                    return false;

                if (!findMax && value > series[i])
                    return false;
            }
            return true;
        }

        private double CurrentRange(int rr)
        {
            atr = Indicators.AverageTrueRange(rr, MovingAverageType.Exponential);
            return atr.Result.LastValue;
        }

    }

}



SO
solid

Joined on 08.02.2018

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Solid Horizon 2020.algo
  • Rating: 5
  • Installs: 1420
  • Modified: 13/10/2021 09:54
Comments
Log in to add a comment.
SO
solid · 4 years ago

Thanks for catching that. Corrected.

reyx's avatar
reyx · 4 years ago

You have a typo in site link on description, the correct one is http://solidindicators.com/horizon/