Category Trend  Published on 08/01/2018

Force Acceleration

Description

Force & Resistance acceleration using a tripple weighted moving average

For references here ths is a change to the original snake force indicator. With one difference and one addition.

- Indicator uses the HULL average which is tripple weighted instead of a standard weighted average. 
- An additional setting has been added to set the periods of the HULL average.  the snake force implementation has a default period setting of 24 and a hard coded value of 6 ( 1/4 of the periods ) as the period setter for the moving average. This implementation allows both periods to be set. 

The thinking behind the tripple weighting is to make this a more relevant indicator for higher frequency scalp trading. 

An interesting Robot algo might be to create a trade signal based on the Force or Resistance rate of change. 

All thoughts or opinions are welcome. 


using System;
using cAlgo.API;


namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None)]

    public class ForceAcceleration : Indicator
    {
        [Parameter()]
        public DataSeries Source { get; set; }

        [Parameter("Force Periods", DefaultValue = 24)]
        public int Periods { get; set; }


        [Parameter("Weighted Average Peridos", DefaultValue = 6)]
        public int WAPeriods { get; set; }

        [Output("Positive Force", Color = Colors.White, PlotType = PlotType.Histogram, Thickness = 5)]
        public IndicatorDataSeries ForceUp { get; set; }

        [Output("ForceDown", Color = Colors.Purple, PlotType = PlotType.Histogram, Thickness = 5)]
        public IndicatorDataSeries ForceDown { get; set; }

        [Output("ResistanceUp", Color = Colors.White, PlotType = PlotType.Histogram)]
        public IndicatorDataSeries ResistanceUp { get; set; }

        [Output("ResistanceDown", Color = Colors.Purple, PlotType = PlotType.Histogram)]
        public IndicatorDataSeries ResistanceDown { get; set; }

        private IndicatorDataSeries Mart;
        private HullMovingAverage iMA;

        double Force_Sum_Plus;
        double Force_Sum_Minus;
        double Force_Weight;
        double Force_Sum;

        protected override void Initialize()
        {
            Mart = CreateDataSeries();
            iMA = Indicators.GetIndicator<HullMovingAverage>(Source, WAPeriods);
        }

        public override void Calculate(int index)
        {
            int i = 0;
            int FirstPos = 0;

            if (index <= 50)
                return;

            if (Periods < 21)
                return;

            FirstPos = 1;
            if (FirstPos > index - Periods - 7)
            {
                FirstPos = index - Periods - 7;
                Mart[FirstPos + Periods] = ForceFirstCalc(FirstPos + Periods, index);

                for (i = FirstPos; i < FirstPos - Periods - 1; i++)
                    ForceNextCalc(i);
            }
            Force(FirstPos, index);
        }

        void Force(int Pos, int index)
        {
            if (Pos < 6)
                Pos = index - 6;

            Mart[Pos] = ForceFirstCalc(Pos, index);
            Drawing(Pos);
            Pos++;
            while (Pos <= index - 5)
            {
                Mart[Pos] = ForceNextCalc(Pos);
                Drawing(Pos);
                Pos++;
            }
            while (Pos < index)
            {
                Mart[Pos] = ForceFirstCalc(Pos, index);
                Drawing(Pos);
                Pos++;
            }
            if (Pos == index)
            {
                Mart[Pos] = iMA.Result.LastValue;
                Drawing(Pos);
            }
            return;
        }

        double ForcePrice(int Shift)
        {
            return MarketSeries.Close[Shift];
        }

        double ForceFirstCalc(int Shift, int index)
        {
            int w = 0;
            int j = 0;
            int i = 0;

            Force_Sum = 0.0;
            if (Shift > (index - 5))
            {
                Force_Weight = 0.0;
                i = 0;
                w = Shift - 5;
                while (w <= Shift)
                {
                    i++;
                    Force_Sum = Force_Sum + i * ForcePrice(w);
                    Force_Weight = Force_Weight + i;
                    w++;
                }
                while (w <= index)
                {
                    i--;
                    Force_Sum = Force_Sum + i * ForcePrice(w);
                    Force_Weight = Force_Weight + i;
                    w++;
                }
            }
            else
            {
                Force_Sum_Minus = 0.0;
                Force_Sum_Plus = 0.0;
                for (j = Shift + 5,i = Shift - 5,w = 1; w <= 5; j--,i++,w++)
                {
                    Force_Sum = Force_Sum + w * (ForcePrice(i) + ForcePrice(j));
                    Force_Sum_Minus = Force_Sum_Minus + ForcePrice(i);
                    Force_Sum_Plus = Force_Sum_Plus + ForcePrice(j);
                }
                Force_Sum = Force_Sum + 6 * ForcePrice(Shift);
                Force_Sum_Minus = Force_Sum_Minus + ForcePrice(Shift);
                Force_Weight = 36;
            }
            return (Force_Sum / Force_Weight);
        }

        double ForceNextCalc(int Shift)
        {
            Force_Sum_Plus = Force_Sum_Plus + ForcePrice(Shift + 5);
            Force_Sum = Force_Sum - Force_Sum_Minus + Force_Sum_Plus;
            Force_Sum_Minus = Force_Sum_Minus - ForcePrice(Shift - 6) + ForcePrice(Shift);
            Force_Sum_Plus = Force_Sum_Plus - ForcePrice(Shift);
            return Force_Sum / Force_Weight;
        }

        void Drawing(int Shift)
        {
            double Dval = 0;
            double val = 0;

            val = 5 * (Mart[Shift] - Mart[ArrayMinimum(Mart, Periods, Shift)]) / 9;
            Dval = 5 * (Mart[Shift] - Mart[Shift - 1] + Mart[ArrayMinimum(Mart, Periods, Shift - 1)] - Mart[ArrayMinimum(Mart, Periods, Shift)]) / 9;
            if (Dval > 0)
            {
                ForceUp[Shift] = val;
                ResistanceUp[Shift] = 0;
            }
            else
            {
                ForceUp[Shift] = 0;
                ResistanceUp[Shift] = val;
            }
            val = 5 * (Mart[Shift] - Mart[ArrayMaximum(Mart, Periods, Shift)]) / 9;
            Dval = 5 * (Mart[Shift] - Mart[Shift - 1] + Mart[ArrayMaximum(Mart, Periods, Shift - 1)] - Mart[ArrayMaximum(Mart, Periods, Shift)]) / 9;
            if (Dval < 0)
            {
                ForceDown[Shift] = val;
                ResistanceDown[Shift] = 0;
            }
            else
            {
                ForceDown[Shift] = 0;
                ResistanceDown[Shift] = val;
            }
            return;
        }

        int ArrayMaximum(IndicatorDataSeries array, int count = 0, int start = 0)
        {
            var result = start;
            for (var i = start - count + 1; i <= start - 1; i++)
            {
                if (array[i] > array[result])
                    result = i;
            }
            return result;
        }

        int ArrayMinimum(IndicatorDataSeries array, int count = 0, int start = 0)
        {
            var result = start;
            for (var i = start - count + 1; i <= start - 1; i++)
            {
                if (array[i] < array[result])
                    result = i;
            }
            return result;
        }

    }
}


shlbnd.ms's avatar
shlbnd.ms

Joined on 10.06.2016

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: ForceAcceleration.algo
  • Rating: 0
  • Installs: 2557
Comments
Log in to add a comment.
TO
tob_wolf · 6 years ago

Yes, it repaints the last 6 candles. Using future values it must repaint and there is no nrp-version possible, at least not without making the indicator lagging heavily and that would make it pretty useless.

shlbnd.ms's avatar
shlbnd.ms · 6 years ago

No

SI
simonv76 · 6 years ago

Is it a repainting Indicator?