public void FinalizeTest() { if (testCursor != null) { finalCandles = testCursor.GetCurrentQuotes(); testCursor.Close(); } testCursor = null; AccountInfo.Balance = initialTestBalance; lastTestEnd = DateTime.Now; CalcProfitForOpenOrder(); }
private static Dictionary<string, List<float>> GetTickersRates(List<string> tickers, DateTime dateStart, int intervalMinutes, List<string> errors) { var curs = new BacktestTickerCursor(); if (!curs.SetupCursor(string.Format("{0}{1}", ExecutablePath.ExecPath, TerminalEnvironment.QuoteCacheFolder), tickers, dateStart)) { errors.Add(Localizer.GetString("MessageErrorGettingQuotesFromFiles")); return null; } var rates = tickers.ToDictionary(t => t, t => new List<float>()); try { curs.MoveToTime(dateStart); // выйти на некоторую начальную точку, в которой представлены все валютные пары var lastTime = DateTime.MinValue; var quotes = new List<Cortege2<string, CandleData>>(); while (true) { if (!curs.MoveNext()) break; quotes = curs.GetCurrentQuotes(); if (quotes.Count < tickers.Count) continue; // !! lastTime = quotes[0].b.timeOpen; break; } if (quotes.Count < tickers.Count) { var nullTickers = tickers.Where(t => !quotes.Any(q => q.a == t)); errors.Add(string.Format(Localizer.GetString("MessageNoQuotesForTickers") + ": {0}", string.Join(", ", nullTickers))); return null; } // считать приращения while (curs.MoveNext()) { var newQuotes = curs.GetCurrentQuotes(); var time = newQuotes[0].b.timeOpen; if ((time - lastTime).TotalMinutes < intervalMinutes) continue; lastTime = time; for (var i = 0; i < quotes.Count; i++) { rates[quotes[i].a].Add((newQuotes[i].b.open - quotes[i].b.open)/quotes[i].b.open); } quotes = newQuotes; } } catch (Exception ex) { errors.Add(Localizer.GetString("MessageErrorReadingQuotes")); Logger.Error("GetTickersRates error", ex); } finally { curs.Close(); } if (rates.Count == 0 || rates[tickers[0]].Count == 0) errors.Add(Localizer.GetString("MessageErrorCalcDeltas")); return rates; }
/// <summary> /// переместиться на ближ. следующий момент времени в архиве из N котировок /// скормить котировки роботам /// роботы разродятся ордерами (возможно) /// /// перед вызовами MakeStep() необходимо вызвать InitiateTest /// </summary> public bool MakeStep(out DateTime modelTime, out DateTime firstRealDateOfTest) { modelTime = TimeFrom; firstRealDateOfTest = TimeFrom; var candles = testCursor.GetCurrentQuotes(); if (candles.Count == 0) { return(true); } modelTime = candles[0].b.timeOpen; if (!firstDateOfTest.HasValue) { firstDateOfTest = modelTime; } firstRealDateOfTest = firstDateOfTest.Value; if (!historyStartoffPassed && modelTime >= TimeFrom) { historyStartoffPassed = true; } var names = candles.Select(q => q.a).ToArray(); var candlesBidAsk = candles.Select(q => { var spread = DalSpot.Instance.GetAbsValue(q.a, DefaultSpreadPoints); return(new CandleDataBidAsk(q.b, spread)); } ).ToArray(); var quotes = candlesBidAsk.Select((c, i) => new QuoteData(c.close, c.closeAsk, c.timeClose)).ToArray(); // обновить хранилище котировок quotesStorage.UpdateValues(names, quotes); // проверить стопаут var isSo = tradeManager.CheckStopOut(AccountInfo.ID); if (isSo) {// закрыть все сделки по стопауту stopoutEventTimes.Add(modelTime); var idToCloseList = positions.Select(p => p.ID).ToList(); foreach (var posId in idToCloseList) { SendCloseRequest(null, AccountInfo.ID, posId, PositionExitReason.Stopout); } } // проверить отложенные и открытые ордера, маржу и плечо) for (var i = 0; i < names.Length; i++) { CheckDeals(names[i], quotes[i]); } // дать роботам котировки в работу OnQuotesReceived(names, candlesBidAsk, !historyStartoffPassed); // обновить кривые средств и экспозиции if (historyStartoffPassed) { UpdateDailyEquityExposure(modelTime.Date); } previousQuotes.UpdateValues(names, quotes); if (!testCursor.MoveNext()) { return(true); } if (timeTo < modelTime.Date) { return(true); } return(false); }
public static void OrderCalcWorkerOnDoWork(object senderWorker, DoWorkEventArgs argsWithTicker) { var worker = (BackgroundWorker) senderWorker; var ticker = (string) argsWithTicker.Argument; var account = AccountStatus.Instance.AccountData; if (account == null) return; var orders = new List<MarketOrder>(); try { // получить закрытые ордера порциями while (true) { if (worker.CancellationPending) return; var startId = orders.Count == 0 ? 0 : orders.Max(o => o.ID); var ordersPart = TradeSharpAccount.Instance.proxy.GetClosedOrders(AccountStatus.Instance.accountID, ticker, startId, 200) ?? new List<MarketOrder>(); if (ordersPart.Count == 0) break; orders.AddRange(ordersPart); } // получить открытые ордера if (worker.CancellationPending) return; List<MarketOrder> openedOrders; TradeSharpAccount.Instance.proxy.GetMarketOrders(AccountStatus.Instance.accountID, out openedOrders); if (openedOrders != null && openedOrders.Count > 0) { openedOrders = openedOrders.Where(o => o.Symbol == ticker).ToList(); if (openedOrders.Count > 0) { CalculateOpenedOrdersResult(openedOrders, account.Currency); orders.AddRange(openedOrders); } } } catch (Exception ex) { Logger.Error("Ошибка получения ордеров", ex); MessageBox.Show(Localizer.GetString("MessageErrorGettingOrders"), Localizer.GetString("TitleError"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (orders.Count == 0) return; var balanceOnDate = new BalanceAndEquitySeriesData(); var startDate = orders.Min(o => o.TimeEnter).Date; var endDate = DateTime.Now; orders.ForEach(o => { o.TimeExit = o.TimeExit ?? endDate; o.State = PositionState.Opened; }); orders = orders.Where(o => o.TimeExit.HasValue).OrderBy(o => o.TimeExit).ToList(); var balance = 0f; // установить "курсор" котировок на начало наблюдаемого отрезка var cursor = new BacktestTickerCursor(); var tickers = new List<string> {ticker}; // нужна еще валюта пересчета? bool inverse, pairsEqual; var tickerCounterDepo = DalSpot.Instance.FindSymbol(ticker, false, account.Currency, out inverse, out pairsEqual); if (!string.IsNullOrEmpty(tickerCounterDepo) && tickerCounterDepo != ticker) tickers.Add(tickerCounterDepo); cursor.SetupCursor(TerminalEnvironment.QuoteCacheFolder, tickers, startDate); try { for (var date = startDate; ; ) { if (date != endDate && DaysOff.Instance.IsDayOff(date)) { date = date.AddDays(1); continue; } for (var i = 0; i < orders.Count; i++) { if (orders[i].TimeExit > date) break; balance += orders[i].ResultDepo; orders.RemoveAt(i); i--; } // получить текущий результат по открытым на момент ордерам var equity = balance; var curDate = date; var curOrders = orders.Where(o => o.TimeEnter <= curDate).ToList(); if (curOrders.Count > 0) { cursor.MoveToTime(date); var curProfit = DalSpot.Instance.CalculateOpenedPositionsCurrentResult(curOrders, cursor.GetCurrentQuotes().ToDictionary(c => c.a, c => new QuoteData(c.b.close, c.b.close, curDate)), account.Currency); equity += curProfit; } balanceOnDate.lstBalance.Add(new TimeBalans(date, balance)); balanceOnDate.lstEquity.Add(new TimeBalans(date, equity)); if (date == endDate) break; date = date.AddDays(1); if (date > endDate) date = endDate; } } finally { cursor.Close(); } // сместить последнюю дату кривой баланса balanceOnDate.ShiftLastDate(); argsWithTicker.Result = balanceOnDate; }
private void StartRoutineDoWork(object sender, DoWorkEventArgs e) { // загрузить историю котировок и отработать старт роботов var quotesToReceive = GetUsedTickersAndStartTime(); if (quotesToReceive.Count == 0) return; var firstDate = quotesToReceive.Min(q => q.Value); if ((DateTime.Now - firstDate).TotalMinutes < MinMinutesToLoadQuotes) return; // обновить кэш котировок updateTickersCacheForRobots(quotesToReceive, 3); Logger.InfoFormat("Портфель роботов: загрузка {0} котировок c {1:dd.MM.yyyy HH:mm}", quotesToReceive.Count, firstDate); // закачать котировки и "скормить" их роботам var cursor = new BacktestTickerCursor(); // !! path !! var path = ExecutablePath.ExecPath + "\\quotes"; try { if (!cursor.SetupCursor(path, quotesToReceive.Keys.ToList(), firstDate)) { Logger.DebugFormat("Старт портфеля из {0} роботов: не удалось установить курсор, путь \"{1}\"", robots.Count, path); return; } do { var candles = cursor.GetCurrentQuotes(); if (candles.Count == 0) break; var names = candles.Select(q => q.a).ToArray(); var prices = candles.Select(q => new CandleDataBidAsk(q.b, DalSpot.Instance.GetDefaultSpread(q.a))).ToArray(); // дать роботам котировки в работу foreach (var robot in robots) { var robotEvents = robot.OnQuotesReceived(names, prices, true); if (robotEvents == null || robotEvents.Count == 0) continue; ShowRobotEventsSafe(robot, robotEvents); } } while (cursor.MoveNext()); } finally { cursor.Close(); } }