Example #1
0
 public override dynamic Get(IEnumerable <decimal?> candles, IIndicatorOptions options = null)
 {
     throw new NotImplementedException();
 }
Example #2
0
        public override dynamic Get(IEnumerable <ICandle> source, IIndicatorOptions options = null)
        {
            // TODO: Move to options
            bool returnRaw = false;

            // Calculate our Moving Averages
            IEnumerable <decimal?> smaFastData = source.Select(x => (decimal?)((x.High + x.Low) / 2));
            List <decimal?>        smaFast     = smaFastData.Sma(5);

            IEnumerable <decimal?> smaSlowData = source.Select(x => (decimal?)((x.High + x.Low) / 2));
            List <decimal?>        smaSlow     = smaFastData.Sma(34);

            List <decimal?> result = new List <decimal?>();

            for (int i = 0; i < smaFast.Count(); i++)
            {
                if (returnRaw)
                {
                    if (!smaFast[i].HasValue || !smaSlow[i].HasValue)
                    {
                        result.Add(null);
                    }
                    else
                    {
                        result.Add(smaFast[i].Value - smaSlow[i].Value);
                    }
                }
                else
                {
                    // The last and second to last values interest us, because we're looking for a cross of these lines.
                    // If it's not the first item, we can check the previous.
                    if (i > 0)
                    {
                        decimal?smaFastLast       = smaFast[i];
                        decimal?smaSlowLast       = smaSlow[i];
                        decimal?smaFastSecondLast = smaFast[i - 1];
                        decimal?smaSlowSecondLast = smaSlow[i - 1];

                        decimal?aoSecondLast = smaFastSecondLast - smaSlowSecondLast;
                        decimal?aoLast       = smaFastLast - smaSlowLast;

                        if (aoSecondLast <= 0 && aoLast > 0)
                        {
                            result.Add(100);
                        }
                        else if (aoSecondLast >= 0 && aoLast < 0)
                        {
                            result.Add(-100);
                        }
                        else
                        {
                            result.Add(0);
                        }
                    }
                    else
                    {
                        result.Add(0);
                    }
                }
            }

            return(result);
        }
Example #3
0
        public override dynamic Get(IEnumerable <ICandle> source, IIndicatorOptions options = null)
        {
            CandlePatternsOptions config = options != null ? (CandlePatternsOptions)options.Options : new CandlePatternsOptions(0.05m);

            List <CandlePatternCode> result = new List <CandlePatternCode>();

            List <decimal> open  = source.Open();
            List <decimal> close = source.Close();
            List <decimal> high  = source.High();
            List <decimal> low   = source.Low();

            for (int i = 0; i < source.Count(); i++)
            {
                if (Math.Abs(open[i] - close[i]) <= (high[i] - low[i]) * config.DojiSize)
                {
                    result.Add(CandlePatternCode.DOJI);
                    continue;
                }

                if (high[i] - low[i] > 3 * (open[i] - close[i]) && (close[i] - low[i]) / (.001m + high[i] - low[i]) > 0.6m && (open[i] - low[i]) / (.001m + high[i] - low[i]) > 0.6m)
                {
                    result.Add(CandlePatternCode.BULLISH_HAMMER);
                    continue;
                }

                if (high[i] - low[i] > 3 * (open[i] - close[i]) && (high[i] - close[i]) / (.001m + high[i] - low[i]) > 0.6m && (high[i] - open[i]) / (.001m + high[i] - low[i]) > 0.6m)
                {
                    result.Add(CandlePatternCode.BEARISH_INVERTED_HAMMER);
                    continue;
                }

                // These patterns require at least 2 data points
                if (i > 0)
                {
                    if (open[i - 1] < close[i - 1] && open[i] > close[i - 1] && high[i] - Math.Max(open[i], close[i]) >= Math.Abs(open[i] - close[i]) * 3 && Math.Min(close[i], open[i]) - low[i] <= Math.Abs(open[i] - close[i]))
                    {
                        result.Add(CandlePatternCode.SHOOTING_STAR);
                        continue;
                    }

                    if (close[i - 1] > open[i - 1] && open[i] > close[i] && open[i] <= close[i - 1] && open[i - 1] <= close[i] && open[i] - close[i] < close[i - 1] - open[i - 1])
                    {
                        result.Add(CandlePatternCode.BEARISH_HARAMI);
                        continue;
                    }

                    if (open[i - 1] > close[i - 1] && close[i] > open[i] && close[i] <= open[i - 1] && close[i - 1] <= open[i] && close[i] - open[i] < open[i - 1] - close[i - 1])
                    {
                        result.Add(CandlePatternCode.BULLISH_HARAMI);
                        continue;
                    }

                    if (close[i - 1] > open[i - 1] && open[i] > close[i] && open[i] >= close[i - 1] && open[i - 1] >= close[i] && open[i] - close[i] > close[i - 1] - open[i - 1])
                    {
                        result.Add(CandlePatternCode.BEARISH_ENGULFING);
                        continue;
                    }

                    if (open[i - 1] > close[i - 1] && close[i] > open[i] && close[i] >= open[i - 1] && close[i - 1] >= open[i] && close[i] - open[i] > open[i - 1] - close[i - 1])
                    {
                        result.Add(CandlePatternCode.BULLISH_ENGULFING);
                        continue;
                    }

                    if (open[i - 1] > close[i - 1] && open[i] >= open[i - 1] && close[i] > open[i])
                    {
                        result.Add(CandlePatternCode.BULLISH_KICKER);
                        continue;
                    }

                    if (open[i - 1] < close[i - 1] && open[i] <= open[i - 1] && close[i] <= open[i])
                    {
                        result.Add(CandlePatternCode.BEARISH_KICKER);
                        continue;
                    }

                    if (close[i - 1] > open[i - 1] && (close[i - 1] + open[i - 1]) / 2 > close[i] && open[i] > close[i] && open[i] > close[i - 1] && close[i] > open[i - 1] && (open[i] - close[i]) / (.001m + (high[i] - low[i])) > 0.6m)
                    {
                        result.Add(CandlePatternCode.BEARISH_DARK_CLOUD_COVER);
                        continue;
                    }

                    // These patterns require at least 3 data points
                    if (i > 1)
                    {
                        if (close[i - 2] < open[i - 2] && Math.Max(open[i - 1], close[i - 1]) < close[i - 2] && open[i] > Math.Max(open[i - 1], close[i - 1]) && close[i] > open[i])
                        {
                            result.Add(CandlePatternCode.BULLISH_MORNING_STAR);
                            continue;
                        }

                        if (close[i - 2] > open[i - 2] && Math.Min(open[i - 1], close[i - 1]) > close[i - 2] && open[i] < Math.Min(open[i - 1], close[i - 1]) && close[i] < open[i])
                        {
                            result.Add(CandlePatternCode.BEARISH_EVENING_STAR);
                            continue;
                        }

                        if (high[i] - low[i] > 4 * (open[i] - close[i]) && (close[i] - low[i]) / (.001m + high[i] - low[i]) >= 0.75m && (open[i] - low[i]) / (.001m + high[i] - low[i]) >= 0.75m && high[i - 1] < open[i] && high[i - 2] < open[i])
                        {
                            result.Add(CandlePatternCode.BEARISH_HANGING_MAN);
                            continue;
                        }
                    }

                    if (i > 9)
                    {
                        decimal upper = high.Skip(i - 10).Take(10).OrderByDescending(x => x).ToList()[1];
                        if (close[i - 1] < open[i - 1] && open[i] < low[i - 1] && close[i] > close[i - 1] + (open[i - 1] - close[i - 1]) / 2 && close[i] < open[i - 1])
                        {
                            result.Add(CandlePatternCode.PIERCING_LINE);
                            continue;
                        }

                        decimal lower = high.Skip(i - 10).Take(10).OrderBy(x => x).ToList()[1];
                        if (low[i] == open[i] && open[i] < lower && open[i] < close[i] && close[i] > (high[i - 1] - low[i - 1]) / 2 + low[i - 1])
                        {
                            result.Add(CandlePatternCode.BULLISH_BELT);
                            continue;
                        }
                    }
                }

                result.Add(null);
            }

            return(result);
        }
Example #4
0
        public override dynamic Get(IEnumerable <ICandle> source, IIndicatorOptions options = null)
        {
            try
            {
                IchimokuOptions config = options != null ? (IchimokuOptions)options.Options : new IchimokuOptions(20, 60, 120, 30);

                List <decimal> highs  = source.Select(x => x.High).ToList();
                List <decimal> lows   = source.Select(x => x.Low).ToList();
                List <decimal> closes = source.Select(x => x.Close).ToList();

                var ichi = new IchimokuItem
                {
                    TenkanSen   = Donchian(source, config.ConversionLinePeriod, highs, lows),
                    KijunSen    = Donchian(source, config.BaseLinePeriod, highs, lows),
                    SenkouSpanB = Donchian(source, config.LaggingSpanPeriods, highs, lows),
                    SenkouSpanA = new List <decimal?>()
                };


                // SenkouSpanA is calculated...
                for (int i = 0; i < ichi.TenkanSen.Count; i++)
                {
                    if (ichi.TenkanSen[i].HasValue && ichi.KijunSen[i].HasValue)
                    {
                        ichi.SenkouSpanA.Add((ichi.TenkanSen[i].Value + ichi.KijunSen[i].Value) / 2);
                    }
                    else
                    {
                        ichi.SenkouSpanA.Add(null);
                    }
                }

                // Add the displacement for the cloud
                for (int i = 0; i < config.Displacement; i++)
                {
                    ichi.SenkouSpanA.Insert(0, null);
                    ichi.SenkouSpanB.Insert(0, null);
                }

                // Add the ChikouSpan
                ichi.ChikouSpan = new List <decimal?>();

                // Add the displacement for the lagging span
                var displacedCloses = closes.Skip(config.Displacement).ToList();

                for (int i = 0; i < closes.Count; i++)
                {
                    if (i < closes.Count - config.Displacement)
                    {
                        ichi.ChikouSpan.Add(displacedCloses[i]);
                    }
                    else
                    {
                        ichi.ChikouSpan.Add(null);
                    }
                }

                return(ichi);
            }
            catch (Exception ex)
            {
                throw new Exception("Could not calculate ichimoku cloud");
            }
        }
Example #5
0
        public override dynamic Get(IEnumerable <ICandle> source, IIndicatorOptions options = null)
        {
            PivotLowOptions config = options != null ? (PivotLowOptions)options.Options : new PivotLowOptions(4, 2, false);

            List <decimal?> result = new List <decimal?>();

            for (int i = 0; i < source.Count(); i++)
            {
                if (i < config.BarsLeft + config.BarsRight)
                {
                    result.Add(null);
                    continue;
                }

                bool           isPivot      = true;
                List <ICandle> subSet       = source.Skip(i - config.BarsLeft - config.BarsRight).Take(config.BarsLeft + config.BarsRight + 1).ToList();
                ICandle        valueToCheck = subSet[config.BarsLeft];

                // Check if the [barsLeft] bars left of what we're checking all have lower highs or equal
                for (int leftPivot = 0; leftPivot < config.BarsLeft; leftPivot++)
                {
                    if (subSet[leftPivot].Low < valueToCheck.Low)
                    {
                        isPivot = false;
                        break;
                    }
                }

                // If it's still a pivot by this point, carry on checking the right side...
                if (isPivot)
                {
                    // If the [barsRight] right side all have lower highs, it's a pivot!
                    for (int rightPivot = config.BarsLeft + 1; rightPivot < subSet.Count; rightPivot++)
                    {
                        if (subSet[rightPivot].Low <= valueToCheck.Low)
                        {
                            isPivot = false;
                            break;
                        }
                    }

                    // If it's a pivot
                    if (isPivot)
                    {
                        result.Add(valueToCheck.Low);
                    }
                    else
                    {
                        result.Add(null);
                    }
                }
                else
                {
                    result.Add(null);
                }
            }

            if (config.FillNullValues)
            {
                return(FillPivotNulls(result));
            }

            return(result);
        }