Beispiel #1
0
        public static void BuildTrack(int accountId, string targetFilePath, int intervalMinutes)
        {
            var logger = new LimitedLogger();

            var positionsOpened = new List <MarketOrder>();
            var positionClosed  = new List <MarketOrder>();
            List <BalanceChange> balances;
            string accountCurrency;

            using (var db = new TradeSharpConnection())
            {
                accountCurrency = db.ACCOUNT.First(a => a.ID == accountId).Currency;
                balances        = db.BALANCE_CHANGE.Where(bc => bc.AccountID == accountId).OrderBy(b => b.ValueDate).ToList().Select(
                    LinqToEntity.DecorateBalanceChange).ToList();
                positionsOpened = db.POSITION.Where(bc => bc.AccountID == accountId).ToList().Select(LinqToEntity.DecorateOrder).ToList();
                positionClosed  = db.POSITION_CLOSED.Where(bc => bc.AccountID == accountId).ToList().Select(LinqToEntity.DecorateOrder).ToList();
            }

            if (balances.Count < 2)
            {
                return;
            }

            var startTime = balances.Min(b => b.ValueDate);

            startTime = startTime.Date.AddMinutes(intervalMinutes *
                                                  ((int)(startTime - startTime.Date).TotalMinutes) / intervalMinutes);
            var endTime = DateTime.Now;

            var dueDeals = positionsOpened.Union(positionClosed).OrderBy(p => p.TimeEnter).ToList();

            var cursor  = new BacktestTickerCursor();
            var tickers = dueDeals.Select(p => p.Symbol).Distinct().ToList();

            startTime = TimeUtil.RoundTime(startTime, intervalMinutes);
            var track = new Strategy(startTime, (int)balances.First().SignedAmountDepo);

            try
            {
                cursor.SetupCursor(ExecutablePath.ExecPath + "\\quotes", tickers, startTime);
                decimal balance = 0;

                for (var time = startTime; time <= endTime; time = time.AddMinutes(intervalMinutes))
                {
                    if (DaysOff.Instance.IsDayOff(time))
                    {
                        continue;
                    }
                    var candles = cursor.MoveToTime(time);
                    var quotes  = candles.ToDictionary(
                        c => c.Key,
                        c => new QuoteData(c.Value.close, c.Value.close, c.Value.timeClose));

                    // учесть вводы - выводы
                    var deltaBalance = 0M;
                    var deltaDeposit = 0M;
                    var closedProfit = 0M;
                    for (var i = 0; i < balances.Count; i++)
                    {
                        if (balances[i].ValueDate > time)
                        {
                            break;
                        }
                        deltaBalance += balances[i].SignedAmountDepo;
                        if (balances[i].ChangeType == BalanceChangeType.Profit ||
                            balances[i].ChangeType == BalanceChangeType.Loss)
                        {
                            closedProfit += balances[i].SignedAmountDepo;
                        }
                        else
                        {
                            deltaDeposit += balances[i].SignedAmountDepo;
                        }
                        balances.RemoveAt(i);
                        i--;
                    }
                    balance += deltaBalance;

                    // открытый профит
                    var openProfit  = 0M;
                    var volumesDepo = new Dictionary <string, decimal>();

                    for (var i = 0; i < dueDeals.Count; i++)
                    {
                        if (dueDeals[i].TimeEnter > time)
                        {
                            break;
                        }
                        if (dueDeals[i].TimeExit.HasValue && dueDeals[i].TimeExit.Value <= time)
                        {
                            dueDeals.RemoveAt(i);
                            i--;
                            continue;
                        }
                        // профит по сделке на момент
                        var profit = DalSpot.Instance.CalculateProfitInDepoCurrency(dueDeals[i],
                                                                                    quotes,
                                                                                    accountCurrency);
                        if (profit.HasValue)
                        {
                            openProfit += (decimal)profit.Value;
                        }
                        else
                        {
                            logger.Log(LogEntryType.Error, "CONV", 20, "Невозможно конвертировать профит сделки {0}",
                                       dueDeals[i].ToStringShort() + " @" + dueDeals[i].TimeEnter.ToStringUniform());
                        }
                        // объем
                        string errStr;
                        var    volumeDepo = DalSpot.Instance.ConvertToTargetCurrency(dueDeals[i].Symbol, true,
                                                                                     accountCurrency, dueDeals[i].Volume, quotes, out errStr, true) ?? 0;
                        if (!string.IsNullOrEmpty(errStr))
                        {
                            logger.Log(LogEntryType.Error, "CONV", 20, "Невозможно конвертировать объем сделки {0}: {1}",
                                       dueDeals[i].ToStringShort() + " @" + dueDeals[i].TimeEnter.ToStringUniform(), errStr);
                        }

                        volumeDepo *= dueDeals[i].Side;

                        if (volumesDepo.ContainsKey(dueDeals[i].Symbol))
                        {
                            volumesDepo[dueDeals[i].Symbol] += volumeDepo;
                        }
                        else
                        {
                            volumesDepo.Add(dueDeals[i].Symbol, volumeDepo);
                        }
                    }

                    var sumVolumesDepo = Math.Abs(volumesDepo.Sum(v => v.Value));

                    track.AddRecord(time, balance, balance + openProfit, sumVolumesDepo, deltaDeposit, closedProfit);
                }
            }
            finally
            {
                cursor.Close();
            }

            // сохранить трек
            using (var sw = new StreamWriter(targetFilePath, false, new System.Text.UTF8Encoding(false)))
                track.Serialize(sw);
        }
        public static void BuildTrack(int accountId, string targetFilePath, int intervalMinutes)
        {
            var logger = new LimitedLogger();

            var positionsOpened = new List<MarketOrder>();
            var positionClosed = new List<MarketOrder>();
            List<BalanceChange> balances;
            string accountCurrency;

            using (var db = new TradeSharpConnection())
            {
                accountCurrency = db.ACCOUNT.First(a => a.ID == accountId).Currency;
                balances = db.BALANCE_CHANGE.Where(bc => bc.AccountID == accountId).OrderBy(b => b.ValueDate).ToList().Select(
                    LinqToEntity.DecorateBalanceChange).ToList();
                positionsOpened = db.POSITION.Where(bc => bc.AccountID == accountId).ToList().Select(LinqToEntity.DecorateOrder).ToList();
                positionClosed = db.POSITION_CLOSED.Where(bc => bc.AccountID == accountId).ToList().Select(LinqToEntity.DecorateOrder).ToList();
            }

            if (balances.Count < 2) return;

            var startTime = balances.Min(b => b.ValueDate);
            startTime = startTime.Date.AddMinutes(intervalMinutes *
                ((int) (startTime - startTime.Date).TotalMinutes) / intervalMinutes);
            var endTime = DateTime.Now;

            var dueDeals = positionsOpened.Union(positionClosed).OrderBy(p => p.TimeEnter).ToList();

            var cursor = new BacktestTickerCursor();
            var tickers = dueDeals.Select(p => p.Symbol).Distinct().ToList();
            var track = new Strategy(startTime, (int) balances.First().SignedAmountDepo);

            try
            {
                cursor.SetupCursor(ExecutablePath.ExecPath + "\\quotes", tickers, startTime);
                decimal balance = 0;

                for (var time = startTime; time <= endTime; time = time.AddMinutes(intervalMinutes))
                {
                    var candles = cursor.MoveToTime(time);
                    var quotes = candles.ToDictionary(
                        c => c.Key,
                        c => new QuoteData(c.Value.close, c.Value.close, c.Value.timeClose));

                    // учесть вводы - выводы
                    var deltaBalance = 0M;
                    var deltaDeposit = 0M;
                    var closedProfit = 0M;
                    for (var i = 0; i < balances.Count; i++)
                    {
                        if (balances[i].ValueDate > time) break;
                        deltaBalance += balances[i].SignedAmountDepo;
                        if (balances[i].ChangeType == BalanceChangeType.Profit ||
                            balances[i].ChangeType == BalanceChangeType.Loss)
                            closedProfit += balances[i].SignedAmountDepo;
                        else
                            deltaDeposit += balances[i].SignedAmountDepo;
                        balances.RemoveAt(i);
                        i--;
                    }
                    balance += deltaBalance;

                    // открытый профит
                    var openProfit = 0M;
                    var volumesDepo = new Dictionary<string, decimal>();

                    for (var i = 0; i < dueDeals.Count; i++)
                    {
                        if (dueDeals[i].TimeEnter > time) break;
                        if (dueDeals[i].TimeExit.HasValue && dueDeals[i].TimeExit.Value <= time)
                        {
                            dueDeals.RemoveAt(i);
                            i--;
                            continue;
                        }
                        // профит по сделке на момент
                        var profit = DalSpot.Instance.CalculateProfitInDepoCurrency(dueDeals[i],
                            quotes,
                            accountCurrency);
                        if (profit.HasValue)
                            openProfit += (decimal) profit.Value;
                        else
                            logger.Log(LogEntryType.Error, "CONV", 20, "Невозможно конвертировать профит сделки {0}",
                                dueDeals[i].ToStringShort() + " @" + dueDeals[i].TimeEnter.ToStringUniform());
                        // объем
                        string errStr;
                        var volumeDepo = DalSpot.Instance.ConvertToTargetCurrency(dueDeals[i].Symbol, true,
                            accountCurrency, dueDeals[i].Volume, quotes, out errStr, true) ?? 0;
                        if (!string.IsNullOrEmpty(errStr))
                            logger.Log(LogEntryType.Error, "CONV", 20, "Невозможно конвертировать объем сделки {0}: {1}",
                                dueDeals[i].ToStringShort() + " @" + dueDeals[i].TimeEnter.ToStringUniform(), errStr);

                        volumeDepo *= dueDeals[i].Side;

                        if (volumesDepo.ContainsKey(dueDeals[i].Symbol))
                            volumesDepo[dueDeals[i].Symbol] += volumeDepo;
                        else
                            volumesDepo.Add(dueDeals[i].Symbol, volumeDepo);
                    }

                    var sumVolumesDepo = Math.Abs(volumesDepo.Sum(v => v.Value));

                    track.AddRecord(time, balance, balance + openProfit, sumVolumesDepo, deltaDeposit, closedProfit);
                }
            }
            finally
            {
                cursor.Close();
            }

            // сохранить трек
            using (var sw = new StreamWriter(targetFilePath, false, new System.Text.UTF8Encoding(false)))
                track.Serialize(sw);
        }