Beispiel #1
0
 private void OpenPosition(PositionDirection direction, DataSample sample, string ticker, decimal amount)
 {
     Position = new Position
     {
         OpenPrice     = sample.Candle.Close,
         Direction     = direction,
         OpenTimestamp = sample.Candle.Timestamp,
         Ticker        = ticker,
         Amount        = amount
     };
     this.OnOpenPosition(Position);
 }
Beispiel #2
0
        public SignalResult SellSignal(IList <DataSample> samples, DataSample sample, Position position)
        {
            var localMinimums = ExtremumArea.FindLocalMinimums(samples);
            var localMaximums = ExtremumArea.FindLocalMaximums(samples);

            localMinimums = ExtremumArea.FillMinimumsArea(localMinimums, localMaximums);
            localMaximums = ExtremumArea.FillMaximumsArea(localMaximums, localMinimums);

            // Проверяем, не сработал ли кастомный стоплосс с учетом максимального процента потерь
            if (position != null)
            {
                var lastExtremumForPrice = ExtremumArea.GetLastExtremumForPriceBeforeSample(localMinimums, sample, position.OpenPrice, PositionDirection.Long);
                if (lastExtremumForPrice != null)
                {
                    var stopLossExtremumPrice = lastExtremumForPrice.CurrentExtremum.Candle.Close;

                    if (sample.Candle.Close < stopLossExtremumPrice - stopLossExtremumPrice * (MaxLoosePercentage / 100))
                    {
                        //Console.WriteLine($"##Sell Signal triggered because sample.Candle.Close({sample.Candle.Close}) < stopLossExtremumPrice({stopLossExtremumPrice}) - stopLossExtremumPrice({stopLossExtremumPrice}) * (MaxLoosePercentage({MaxLoosePercentage}) / 100)");
                        return(new SignalResult()
                        {
                            SignalTriggered = true,
                            ByStopLoss = true
                        });
                    }
                }
            }

            var lastLocalMinimumPassed  = false;
            var lastLocalMaximumPassed  = false;
            var lastMaximumBeforeSample = ExtremumArea.GetLastMaximumBeforeAndWithSample(localMaximums, sample);
            var lastMinimumBeforeSample = ExtremumArea.GetLastMinimumBeforeAndWithSample(localMinimums, sample);

            if (lastMaximumBeforeSample != null && lastMinimumBeforeSample != null)
            {
                lastLocalMaximumPassed = lastMinimumBeforeSample.CurrentExtremum.Candle.Timestamp >
                                         lastMaximumBeforeSample.CurrentExtremum.Candle.Timestamp;

                //lastLocalMinimumPassed = sample.Candle.Close < lastMinimumBeforeSample.CurrentExtremum.Candle.Low;
                lastLocalMinimumPassed = sample.Candle.Close < lastMinimumBeforeSample.CurrentExtremum.Candle.Low;
            }

            //if (lastLocalMaximumPassed && lastLocalMinimumPassed)
            //Console.WriteLine($"##Sell Signal (stoploss) triggered for sample.Candle.Timestamp({sample.Candle.Timestamp}) because lastLocalMaximumPassed(minimum.Low is {lastMaximumBeforeSample.CurrentExtremum.Candle.High} maximum high is {lastMinimumBeforeSample.CurrentExtremum.Candle.Low}) and lastLocalMinimumPassed(sample.Candle.Close({sample.Candle.Close}) < lastMinimumBeforeSample.CurrentExtremum.Candle.Close({lastMinimumBeforeSample.CurrentExtremum.Candle.Close}))");

            return(new SignalResult()
            {
                ByStopLoss = false,
                SignalTriggered = lastLocalMaximumPassed && lastLocalMinimumPassed
            });
        }
Beispiel #3
0
        public SignalResult SellSignal(IList <DataSample> samples, DataSample sample, Position position)
        {
            // Проверяем, не сработал ли кастомный стоплосс с учетом максимального процента потерь
            if (position != null && sample.Candle.Close < position.OpenPrice - position.OpenPrice * (MaxLoosePercentage / 100))
            {
                return(new SignalResult()
                {
                    SignalTriggered = true,
                    ByStopLoss = true
                });
            }

            // Если MFI выходит из зоны перепроданности
            var mfiCheckPassed     = false;
            var currentSampleIndex = samples.IndexOf(sample);

            if (currentSampleIndex != 0) // Будем сверяться с предыдущим сэмплом. Для самого первого сверять не с чем, поэтому нужна такая проверка
            {
                // Проверяем, что MFI пересек 80ку
                if (((MFIIndicator)samples[currentSampleIndex - 1].Indicators["mfi"]).MFI > 80 &&
                    ((MFIIndicator)sample.Indicators["mfi"]).MFI < 80)
                {
                    mfiCheckPassed = true;
                }
            }

            // Дополнительно проверяем, что MACD гистограмма ниже, чем на прошлом сэмпле
            var macdCheckPassed = false;

            if (currentSampleIndex != 0
                ) // Будем сверяться с предыдущим сэмплом. Для самого первого сверять не с чем, поэтому нужна такая проверка
            {
                if (((MACDIndicator)samples[currentSampleIndex].Indicators["macd"]).Histogram <
                    ((MACDIndicator)samples[currentSampleIndex - 1].Indicators["macd"]).Histogram)
                {
                    macdCheckPassed = true;
                }
            }

            return(new SignalResult()
            {
                SignalTriggered = mfiCheckPassed && macdCheckPassed,
                ByStopLoss = false
            });
        }
Beispiel #4
0
        public decimal GetStopLossPrice(IList <DataSample> samples, DataSample sample, Position position)
        {
            var          maximums = ExtremumArea.FindLocalMaximums(samples);
            var          minimums = ExtremumArea.FindLocalMinimums(samples);
            ExtremumArea lastExtremum;
            decimal      stopLossPrice = 0;

            if (position.Direction == PositionDirection.Long)
            {
                lastExtremum  = ExtremumArea.GetLastMinimumBeforeAndWithSample(minimums, sample);
                stopLossPrice = lastExtremum.CurrentExtremum.Candle.Low - (position.OpenPrice - lastExtremum.CurrentExtremum.Candle.Low) * 10; //TODO убрать хардкод
            }
            else if (position.Direction == PositionDirection.Short)
            {
                lastExtremum  = ExtremumArea.GetLastMaximumBeforeAndWithSample(maximums, sample);
                stopLossPrice = lastExtremum.CurrentExtremum.Candle.High + (lastExtremum.CurrentExtremum.Candle.High - position.OpenPrice) * 10; //TODO убрать хардкод
            }
            return(stopLossPrice);
        }
Beispiel #5
0
        private double Calculate(IList <DataSample> samples, DataSample sample)
        {
            var    result        = 0d;
            double p1            = Period + 1;
            double EMAMultiplier = Convert.ToDouble(2 / p1);
            var    indexOfCandle = samples.IndexOf(sample);

            if (indexOfCandle >= Period - 1)
            {
                EMA lastEMA = null;
                switch (Kind)
                {
                case EMAKind.Short:
                    lastEMA = samples[indexOfCandle - 1].EMAshort;
                    break;

                case EMAKind.Long:
                    lastEMA = samples[indexOfCandle - 1].EMAlong;
                    break;

                case EMAKind.Smoothing:
                    lastEMA = ((MACDIndicator)samples[indexOfCandle - 1].Indicators["macd"]).EMAForMACD;
                    break;
                }

                if (indexOfCandle == Period - 1)
                {
                    // This is our seed EMA, using SMA of EMA1 Period for EMA 1
                    result = samples.Where(a => a.Candle.Timestamp <= sample.Candle.Timestamp).OrderByDescending(a => a.Candle.Timestamp)
                             .Take(Period).Average(a => Convert.ToDouble(a.Candle.Close));
                }
                else
                {
                    result = (Convert.ToDouble(sample.Candle.Close) - lastEMA.Value) * EMAMultiplier + lastEMA.Value;
                }
            }

            return(result);
        }
Beispiel #6
0
 public static ExtremumArea GetLastExtremumForPriceBeforeSample(IList <ExtremumArea> extremums, DataSample sample, decimal price, PositionDirection direction)
 {
     return(extremums.LastOrDefault(m =>
                                    m.CurrentExtremum.Candle.Timestamp < sample.Candle.Timestamp && direction == PositionDirection.Long ? m.CurrentExtremum.Candle.High < price : m.CurrentExtremum.Candle.Low < price));
 }
Beispiel #7
0
 public static ExtremumArea GetLastMaximumBeforeAndWithSample(IList <ExtremumArea> extremums, DataSample sample)
 {
     return(extremums.LastOrDefault(m => m.CurrentExtremum.Candle.Timestamp <= sample.Candle.Timestamp));
 }
Beispiel #8
0
 /// <summary>
 /// Экспоненциальная скользящая средняя
 /// </summary>
 /// <param name="period">Период</param>
 /// <param name="candles">Набор свечей для расчета</param>
 /// <param name="candle">Свеча, для которой рассчитываем EMA</param>
 /// <param name="seedEMA">Флаг, указывающий, что высчитываем первоначальный EMA</param>
 /// <param name="kind">Тип EMA</param>
 public EMA(int period, IList <DataSample> samples, DataSample sample, EMAKind kind)
 {
     Period = period;
     Kind   = kind;
     Value  = Calculate(samples, sample);
 }
Beispiel #9
0
 public MFIIndicator(DataSample sample, IList <DataSample> samples, int mfiPeriod)
 {
     Sample    = sample;
     Samples   = samples;
     MFIPeriod = mfiPeriod;
 }