static void Main(string[] args)
        {
            CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

            var(sec, thresholds) = ParseArgs(args);

            var date = DateTime.Now;

            Console.WriteLine($"Now: {date:s}");

            date = date.Date.AddDays(date < date.Date.AddHours(20) ? -1 : 0);
            //date = new DateTime(2018, 10, 1);
            Console.WriteLine($"Trade date: {date:s}");

            var history = MoexApi.DownloadHistory(sec, date.AddDays(-60), date).ToArray();

            if (history.Last().Date != date)
            {
                if (MoexApi.HasCandles(sec, date))
                {
                    throw new Exception($"No history entry for {date:yyyy-MM-dd}");
                }

                Console.WriteLine($"No trades on {date:yyyy-MM-dd}");
                return;
            }

            var indicator = RocEma.Calculate(history);
            var candidate = new TurnCandidate(indicator, indicator.Count - 2);

            Console.WriteLine(candidate);

            if (candidate.IsDip(thresholds.Low))
            {
                Notify($"📈 '{sec.ID}' DIP on {date:yyyy-MM-dd}");
            }

            if (candidate.IsPeak(thresholds.High))
            {
                Notify($"📉 '{sec.ID}' PEAK on {date:yyyy-MM-dd}");
            }

            Console.WriteLine();
        }
Exemple #2
0
        static ExperimentResult RunExperiment(IReadOnlyList <Day> history, Thresholds thresholds, Action <string> logger = null)
        {
            var tradeCount = 0;
            var slipCount  = 0;

            var cash = 0m;
            var depo = new List <decimal>();

            var flowDates  = new List <DateTime>();
            var flowValues = new List <decimal>();

            for (var i = 2; i < history.Count; i++)
            {
                var isLastDay = i == history.Count - 1;
                var day       = history[i];
                var date      = day.Date.ToString("yyyy-MM-dd");
                var price     = day.Close;
                var candidate = new TurnCandidate(history, i - 1);

                if (!isLastDay && candidate.IsDip(thresholds.Low))
                {
                    var buyCount     = 1;
                    var requiredCash = buyCount * price;

                    if (cash < requiredCash)
                    {
                        var topup = requiredCash - cash;
                        flowDates.Add(day.Date);
                        flowValues.Add(topup);
                        cash += topup;
                        logger?.Invoke($"{date} Top-up {topup}");
                    }

                    cash -= requiredCash;
                    depo.AddRange(Enumerable.Repeat(price, buyCount));
                    tradeCount++;

                    logger?.Invoke($"{date} Buy {buyCount} x {price}");
                }

                if (isLastDay || candidate.IsPeak(thresholds.High))
                {
                    if (depo.Any())
                    {
                        var sellCount = depo.Count;

                        var investedValue = depo.Take(sellCount).Sum();
                        var currentValue  = sellCount * price;
                        var earning       = currentValue - investedValue;

                        if (isLastDay || earning > 0)
                        {
                            cash += currentValue;
                            depo.RemoveRange(0, sellCount);
                            tradeCount++;

                            logger?.Invoke($"{date} Sell {sellCount} x {price}, earn {earning}");
                        }
                        else
                        {
                            logger?.Invoke($"{date} Hold");
                        }
                    }
                    else
                    {
                        slipCount++;
                        logger?.Invoke($"{date} Nothing to sell");
                    }
                }
            }

            if (depo.Any())
            {
                throw new Exception();
            }

            var xirr = 0d;

            if (flowValues.Any())
            {
                flowDates.Add(history.Last().Date);
                flowValues.Add(-cash);
                xirr = Excel.FinancialFunctions.Financial.XIrr(flowValues.Select(Convert.ToDouble), flowDates);
            }

            return(new ExperimentResult(thresholds, xirr, tradeCount, slipCount));
        }