public Dictionary <BarrierDirection, decimal> GetSpacingAroundTarget(AggregateLines Lines, int BarNumber, decimal TargetValue)
        {
            Dictionary <BarrierDirection, decimal> directionSpacing = new Dictionary <BarrierDirection, decimal>();

            Dictionary <BarrierDirection, List <IAggregateLine> > linesOfSameDirection = GetLinesOfSameDirection(Lines);

            foreach (BarrierDirection key in linesOfSameDirection.Keys)
            {
                decimal?previousLineValue = null;
                decimal?spacing           = null;
                bool    isTargetReached   = false;

                foreach (IAggregateLine line in linesOfSameDirection[key].OrderBy(b => b.GetValueAt(BarNumber)))
                {
                    decimal lineCurrentValue = line.GetValueAt(BarNumber);
                    if (previousLineValue == null)
                    {
                        if (lineCurrentValue > TargetValue)
                        {
                            isTargetReached = true;
                            break;
                        }

                        previousLineValue = lineCurrentValue;
                    }
                    else
                    {
                        spacing = lineCurrentValue - previousLineValue;

                        if (lineCurrentValue > TargetValue)
                        {
                            isTargetReached = true;
                            break;
                        }

                        previousLineValue = lineCurrentValue;
                    }
                }

                if ((spacing != null) && isTargetReached)
                {
                    directionSpacing.Add(key, spacing ?? 0.0M);
                }
            }

            return(directionSpacing);
        }
        private Dictionary <BarrierDirection, List <IAggregateLine> > GetLinesOfSameDirection(AggregateLines Lines)
        {
            Dictionary <BarrierDirection, List <IAggregateLine> > linesOfSameDirection = new Dictionary <BarrierDirection, List <IAggregateLine> >();

            foreach (IAggregateLine line in Lines.Lines)
            {
                if (!linesOfSameDirection.ContainsKey(line.BarrierDirection))
                {
                    linesOfSameDirection.Add(line.BarrierDirection, new List <IAggregateLine>());
                }

                linesOfSameDirection[line.BarrierDirection].Add(line);
            }

            return(linesOfSameDirection);
        }
        /// <summary>
        /// Sets IsCongested and CongestedBoundary on the passed lines
        /// </summary>
        /// <param name="Lines"></param>
        /// <param name="BarNumber"></param>
        public void GetCongestion(ref AggregateLines Lines, int BarNumber)
        {
            Dictionary <BarrierDirection, List <IAggregateLine> > linesOfSameDirection = GetLinesOfSameDirection(Lines);

            foreach (BarrierDirection key in linesOfSameDirection.Keys)
            {
                decimal        currentLimit = Decimal.MinValue;
                IAggregateLine previousLine = null;

                bool isCongested          = false;
                bool isPreviousSetToLower = false;
                bool isPreviousSetToUpper = false;

                foreach (IAggregateLine line in linesOfSameDirection[key].OrderBy(b => b.GetValueAt(BarNumber)))
                {
                    isPreviousSetToLower = false;
                    isPreviousSetToUpper = false;
                    decimal lineCurrentValue = line.GetValueAt(BarNumber);

                    //if ((lineCurrentValue - line.ProximateDistance) <= currentLimit)
                    if ((lineCurrentValue - line.CongestionDistance) <= currentLimit)
                    {
                        if (!isCongested)
                        {
                            isPreviousSetToLower = true;
                        }

                        isCongested = true;
                    }
                    else
                    {
                        if (isCongested)
                        {
                            isPreviousSetToUpper = true;
                            isCongested          = false;
                        }
                    }

                    line.IsCongested       = isCongested;
                    line.CongestedBoundary = CongestionBoundary.NotSet;

                    if (isPreviousSetToLower)
                    {
                        previousLine.CongestedBoundary = CongestionBoundary.Lower;
                        previousLine.IsCongested       = true;
                    }

                    if (isPreviousSetToUpper)
                    {
                        previousLine.CongestedBoundary = CongestionBoundary.Upper;
                        previousLine.IsCongested       = true;
                    }

                    //currentLimit = lineCurrentValue + line.ProximateDistance;
                    currentLimit = lineCurrentValue + line.CongestionDistance;
                    previousLine = line;
                }

                // if the last line was congested then it becomes a boundary
                if (isCongested)
                {
                    previousLine.CongestedBoundary = CongestionBoundary.Upper;
                    previousLine.IsCongested       = true;
                }
            }
        }
예제 #4
0
        public override void Get(ref object Prototype, IIndicatorValues Ind)
        {
            int     atrPeriod         = (int)this.IndicatorParameters.List[0];
            decimal atrMultiple       = (decimal)this.IndicatorParameters.List[1];
            decimal proximityFraction = (decimal)this.IndicatorParameters.List[2];

            List <IAggregateLine> linesToAdd = new List <IAggregateLine>();

            decimal atr = Ind.ATR(atrPeriod)[0].Value;

            //==================
            // The ATR multiple is likely to increase the range of the lines by twice its value (TODO: a power law of sorts may work better)
            decimal approxSpacing = atr * (atrMultiple * 2.0M);
            //==================

            decimal doubleZeroIncrement = GetIncrement(approxSpacing);

            decimal proximateDistance = doubleZeroIncrement * proximityFraction;

            // TODO: need to deal with congestion differently as the proximity distance will now scale with the distance between lines
            //decimal congestionDistance = (doubleZeroIncrement * proximityFraction) * CONGESTION_FACTOR;
            decimal congestionDistance = 0.0M;


            if (doubleZeroIncrement > 0.0M)
            {
                decimal min   = Ind.Bar[0].Close - (doubleZeroIncrement * MAX_LEVELS_ABOVEANDBELOW);
                decimal max   = Ind.Bar[0].Close + (doubleZeroIncrement * MAX_LEVELS_ABOVEANDBELOW);
                decimal value = 0.0M;

                while (value < min)
                {
                    value += doubleZeroIncrement;
                }

                for (; value <= max; value += doubleZeroIncrement)
                {
                    linesToAdd.Add(new PriceLevel(
                                       Ind.Bar.CurrentBar,
                                       value,
                                       true,
                                       0,
                                       this.FailureDistanceMultiple));
                }
            }

            base.CleanLines(ref Prototype, Ind);

            foreach (IAggregateLine line in linesToAdd)
            {
                (Prototype as AggregateLines).Lines.Add(line);
            }

            // update thresholds and proximate distance / no need to update vertical threshold for double zeros
            foreach (IAggregateLine line in (Prototype as AggregateLines).Lines)
            {
                line.ProximateDistance  = proximateDistance;
                line.CongestionDistance = congestionDistance;
            }

            // get congestion // TODO: does this work as expected
            AggregateLines lines = (Prototype as AggregateLines);

            GetCongestion(ref lines, Ind.Bar[0].Number);
            Prototype = lines;
        }