/// <summary> /// Получить тиковые исторические данные /// </summary> /// <param name="insID">Инструмент</param> /// <param name="date">Дата</param> /// <returns>Список тиков или пустой список</returns> public Task <IEnumerable <Tick> > GetTicksAsync(int insID, DateTime date) { return(Task.Factory.StartNew <IEnumerable <Tick> >(() => { var data = _tickHistoryDA.GetData(insID, date); if (data == null || data.Length == 0) { return new List <Tick>(); } var instrum = _instrumBL.GetInstrumByID(insID); if (instrum == null) { return new List <Tick>(); } AllTradesEncoding encoding = new AllTradesEncoding(instrum.Decimals); var allTradesTicks = encoding.Decode(data); if (allTradesTicks == null) { return new List <Tick>(); } return allTradesTicks.Select(t => new Tick(0, date.AddSeconds(t.Second), insID, t.Lots, t.Price)).ToList(); })); }
/// <summary> /// Инициализация графика /// </summary> /// <param name="xdChart">Данные для инициализации</param> public void Initialize(XDocument xdChart = null) { if (xdChart == null) { xdChart = new XDocument(new XElement("Chart")); } var xnSources = xdChart.Root.Element("Sources"); if (xnSources != null) { foreach (var xnSrc in xnSources.Elements()) { if (xnSrc.Name == "BarRow") { int insID = 0; string guid = xnSrc.Attribute("Id").Value; int.TryParse(xnSrc.Attribute("InsID").Value, out insID); int tf = 0; int.TryParse(xnSrc.Attribute("Tf").Value, out tf); if (insID == 0) { continue; } Instrum ins = _instrumBL.GetInstrumByID(insID); if (ins == null) { continue; } CreateBarRowSource(ins, (Timeframes)tf, guid); } } } _indicators.Clear(); var xnIndicators = xdChart.Root.Element("Indicators"); if (xnIndicators != null) { foreach (var xnIndic in xnIndicators.Elements()) { var indic = _factory.CreateIndicator(xnIndic.Name.ToString()); if (indic == null) { continue; } indic.Initialize(new XDocument(xnIndic)); AddIndicator(indic); } } }
private int GetLotSize(int insID) { if (_insID_lotSize == null) { _insID_lotSize = new Dictionary <int, int>(); } if (_insID_lotSize.ContainsKey(insID)) { return(_insID_lotSize[insID]); } else { Instrum ins = _instrumBL.GetInstrumByID(insID); if (ins != null) { _insID_lotSize.Add(ins.InsID, ins.LotSize); return(ins.LotSize); } else { _insID_lotSize.Add(insID, 1); return(1); } } }
/// <summary> /// Создание сделок при импорте /// </summary> /// <param name="accountID">Торговый счет</param> /// <param name="trades">Список сделок, которые нужно создать</param> /// <returns>Список созданных сделок (может отличаться от исходного списка)</returns> private IEnumerable <Trade> CreateTrades(int accountID, IEnumerable <Trade> trades) { sb.AppendLine("Create trades ..."); var db_trades = _accountDA.GetTrades(accountID); List <Trade> createTrades = new List <Trade>(); foreach (var trade in trades) { var found = db_trades.FirstOrDefault(r => r.BuySell == trade.BuySell && r.InsID == trade.InsID && r.LotCount == trade.LotCount && r.Price == trade.Price && r.Time == trade.Time); if (found != null) { var instrum = _instrumBL.GetInstrumByID(trade.InsID); if (instrum == null) { continue; } sb.AppendLine(string.Format("Trade already exists: {0} {1} {2} {3} {4}", instrum.Ticker, trade.Time.ToString("dd.MM.yyyy HH:mm:ss"), trade.BuySell, trade.Price.ToString(), trade.LotCount.ToString())); continue; } var order = _accountDA.CreateOrder(accountID, trade.Time, trade.InsID, trade.BuySell, trade.LotCount, trade.Price, OrderStatus.Trade, null, 0); var newTrade = _accountDA.CreateTrade(accountID, order.OrderID, trade.Time, trade.InsID, trade.BuySell, trade.LotCount, trade.Price, 0, 0); createTrades.Add(newTrade); } sb.AppendLine("Create trades complete: " + createTrades.Count.ToString()); return(createTrades); }
/// <summary> /// Загрузка исторических данных в BarRow. /// Наиболее подходящий InsStore определяется автоматически. /// </summary> /// <param name="bars">BarRow</param> /// <param name="insID">Инструмент</param> /// <param name="date1">Нач дата</param> /// <param name="date2">Кон дата</param> /// <param name="insStoreID">Поток данных для загрузки (если null, то поток будет определен автоматически)</param> /// <returns>Асинхронная задача загрузки. Общее число баров после загрузки.</returns> public async Task <int> LoadHistoryAsync(BarRow bars, int insID, DateTime date1, DateTime date2, int?insStoreID = null) { Instrum instrum = _instrumBL.GetInstrumByID(insID); if (instrum == null) { return(0); } if (insStoreID == null) { var insStore = GetLoadHistoryInsStore(insID, bars.Timeframe); if (insStore != null) { insStoreID = insStore.InsStoreID; } } if (insStoreID == null) { return(0); } int k = (int)Math.Pow(10, instrum.Decimals); var list = await _insStoreDA.GetHistoryAsync(insStoreID.Value, date1, date2); return(await Task.Run(() => { bars.SuspendEvents(); foreach (var bar in list) { DateTime time = StorageLib.ToDateTime(bar.Time); decimal openPrice = (decimal)bar.OpenPrice / k; decimal lowPrice = (decimal)(bar.OpenPrice + bar.LowDelta) / k; decimal highPrice = (decimal)(bar.OpenPrice + bar.HighDelta) / k; decimal closePrice = (decimal)(bar.OpenPrice + bar.CloseDelta) / k; bars.AddTick(time, openPrice, 0); bars.AddTick(time, lowPrice, 0); bars.AddTick(time, highPrice, 0); bars.AddTick(time, closePrice, bar.Volume); } bars.CloseLastBar(); bars.ResumeEvents(); return bars.Count; })); }
public void AddTrade(Trade trade) { var instrum = _instrumBL.GetInstrumByID(trade.InsID); if (instrum == null) { return; } PosTypes pt = trade.BuySell == BuySell.Buy ? PosTypes.Short : PosTypes.Long; int count = trade.LotCount * instrum.LotSize; var openPos = from p in _positions let srt = p.Count == count ? 0 : (p.Count > count ? 1 : 2) where p.InsID == trade.InsID && p.CloseTime == null && p.PosType == pt orderby srt ascending, p.OpenTime descending select p; foreach (var p in openPos) { if (count <= 0) { break; } if (count < p.Count) { SplitPosition(p, count); p.ClosePosition(trade.Time, trade.Price); AddPosTrade(p.PosID, trade.TradeID); count = 0; break; } else if (count == p.Count) { p.ClosePosition(trade.Time, trade.Price); AddPosTrade(p.PosID, trade.TradeID); count = 0; break; } else { p.ClosePosition(trade.Time, trade.Price); AddPosTrade(p.PosID, trade.TradeID); count -= p.Count; } } if (count > 0) { PosTypes pt1 = trade.BuySell == BuySell.Buy ? PosTypes.Long : PosTypes.Short; Position pos1 = AddPosition(trade.InsID, count, trade.Time, trade.Price, pt1); AddPosTrade(pos1.PosID, trade.TradeID); } }
public RemotePriceChart GetRemotePriceChart(int accountID, int instrumId, int timeframe, int key, int from = 0) { var instrum = _instrumBL.GetInstrumByID(instrumId); if (instrum == null) { return(null); } var cm = _chartSystem.GetChartManager(accountID, instrumId, (Timeframes)timeframe); if (cm == null) { return(null); } var chartData = cm.GetChartData(); if (chartData == null) { return(null); } if (chartData.IsDynamic) { var ls = _lsm.GetServer(); if (ls == null) { return(null); } var tps = ls.GetTickPipe().Result; if (tps == null) { return(null); } int count = _tickDisp.GetTicksCount(instrum.InsID); var ticks = tps.GetLastTicks(_tickDisp.CurrentDate, instrum, count).Result; if (ticks != null && ticks.Any()) { _tickDisp.AddTicks(ticks); } ls.DeleteTickPipe().Wait(); } return(RemotePriceChart.Generate(key, instrum.Decimals, chartData, from)); }
public bool AddInstrum(int instrumID) { var instrum = _instrumBL.GetInstrumByID(instrumID); if (instrum == null) { return(false); } if (_instrums.Any(r => r.InsID == instrumID)) { return(false); } _instrums.Add(instrum); return(true); }
public void ListInsStore() { var list = _insStoreBL.GetAllInsStores(); _console.WriteLine("InsStoreID\tInsID\tTicker\tTf\tIsEnable"); _console.WriteSeparator(); foreach (var insStore in list) { var instrum = _instrumBL.GetInstrumByID(insStore.InsID); if (instrum == null) { continue; } _console.WriteLine(string.Format("{0}\t\t{1}\t{2}\t{3}\t{4}", insStore.InsStoreID.ToString(), insStore.InsID.ToString(), instrum.Ticker, insStore.Tf.ToString(), insStore.IsEnable ? "*" : "-")); } }
public Task Generate(int accountID, Timeline timeline) { return(Task.Run(() => { _cashRow.Clear(); _portfolioRow.Clear(); _equityRow.Clear(); _prices.Clear(); var trades = _accountDA.GetTrades(accountID).OrderBy(r => r.Time).ToList(); var account = _accountDA.GetAccountByID(accountID); var cash = _accountDA.GetCash(accountID); List <EqHold> eqHoldList = new List <EqHold>(); decimal cashSumma = cash.Initial; decimal pfSumma = 0; var bd1 = timeline.GetBarDate(0); var bd2 = timeline.GetBarDate(timeline.Count - 1); if (bd1 == null || bd2 == null) { return; } DateTime date1 = bd1.Value.Start.Date; DateTime date2 = bd2.Value.NextStart.Date; // для таймфреймов day и week загрузим историю на один лишний день int tradeIdx = 0; for (int i = 0; i < timeline.Count; i++) { var barDates = timeline.GetBarDate(i); if (barDates == null) { continue; } while (tradeIdx < trades.Count && trades[tradeIdx].Time < barDates.Value.NextStart) { var trade = trades[tradeIdx]; var instrum = _instrumBL.GetInstrumByID(trade.InsID); // из кеша var tradeSumma = trade.Price * trade.LotCount * instrum.LotSize; var hold = eqHoldList.FirstOrDefault(r => r.InsID == instrum.InsID); if (trade.BuySell == BuySell.Buy) { cashSumma -= tradeSumma; if (hold != null) { hold.LotCount += trade.LotCount; } else { eqHoldList.Add(new EqHold() { InsID = instrum.InsID, LotSize = instrum.LotSize, LotCount = trade.LotCount }); } } else { cashSumma += tradeSumma; if (hold != null) { hold.LotCount -= trade.LotCount; if (hold.LotCount == 0) { eqHoldList.Remove(hold); } } else { eqHoldList.Add(new EqHold() { InsID = instrum.InsID, LotSize = instrum.LotSize, LotCount = -trade.LotCount }); } } tradeIdx++; } // вычисляем сумму портфеля на конец бара pfSumma = 0; foreach (var hold in eqHoldList) { if (!_prices.ContainsKey(hold.InsID)) { BarRow barRow = new BarRow(timeline.Timeframe, hold.InsID); _insStoreBL.LoadHistoryAsync(barRow, hold.InsID, date1, date2).Wait(); _prices.Add(hold.InsID, barRow); } var bars = _prices[hold.InsID]; var bar = bars.Bars.FirstOrDefault(r => r.Time == barDates.Value.Start); if (bar != null) { pfSumma += bar.Close * hold.LotCount * hold.LotSize; } } _cashRow.Add(cashSumma); _portfolioRow.Add(pfSumma); _equityRow.Add(cashSumma + pfSumma); } })); }
/// <summary> /// Загрузка одного потока /// </summary> /// <param name="args">Date1, Date2, [Dirty], Tf, Ticker, Ticker, ...</param> public async void HistoryDownloadAsync(List <string> args) { DateTime date1 = DateTime.Today; DateTime date2 = DateTime.Today; bool isLastDirty = false; Timeframes tf = Timeframes.Min; if (args.Count == 1) { if (args[0].Trim().ToLower() == "progress") { if (_progress != null) { ShowProgress(_progress); } else { _console.WriteLine("Нет операции"); } return; } else if (args[0].Trim().ToLower() == "cancel") { if (_cancel != null) { _cancel.Cancel(); _console.WriteLine("Операция прервана"); } else { _console.WriteLine("Нет операции"); } return; } } if (args.Count < 2) { _console.WriteError("Не указаны даты"); return; } DateTime d; if (DateTime.TryParse(args[0].Trim(), out d)) { date1 = d; } else { _console.WriteError("Неверно указана дата начала"); return; } if (DateTime.TryParse(args[1].Trim(), out d)) { date2 = d; } else { _console.WriteError("Неверно указана дата окончания"); return; } args.RemoveRange(0, 2); if (args.Count < 1) { _console.WriteError("Неверное число аргументов"); return; } if (args[0].Trim().ToLower() == "dirty") { isLastDirty = true; args.RemoveAt(0); } if (args.Count < 1) { _console.WriteError("Неверное число аргументов"); return; } Timeframes tf_; if (!Timeframes.TryParse <Timeframes>(args[0].Trim(), out tf_)) { _console.WriteError("Неверный агрумент: Timeframe"); return; } tf = tf_; args.RemoveAt(0); if (args.Count < 1) { _console.WriteError("Неверное число аргументов"); return; } List <CommonData.InsStore> insStores = new List <CommonData.InsStore>(); foreach (string ticker in args) { CommonData.InsStore insStore = _insStoreBL.GetInsStore(ticker, tf); if (insStore == null) { _console.WriteError("Не найден тикер: " + ticker); continue; } insStores.Add(insStore); } if (insStores.Count == 0) { _console.WriteError("Пустой список тикеров"); return; } if (_progress != null && _progress.IsWorking) { ShowProgress(_progress); return; } _console.WriteLine("Загрузка данных ... "); _progress = new BgTaskProgress(_syncContext, "Загрузка данных ..."); _cancel = new CancellationTokenSource(); _progress.OnStart(); int idx = 0; foreach (var insStore in insStores) { var instrum = _instrumBL.GetInstrumByID(insStore.InsID); if (instrum == null) { continue; } var p = _progress.AddChildProgress(instrum.ShortName); await _historyDownloader.DownloadAsync(insStore, date1, date2, isLastDirty, true, p, _cancel.Token); idx++; _progress.OnProgress((double)idx * 100 / insStores.Count); } _progress.OnComplete(); }
public void AddTrade_buyTrade_singleOpenLongPosition() { var ins = instrumBL.GetInstrumByID(1); PosTable table = new PosTable(instrumBL); Trade t = new Trade() { InsID = ins.InsID, OrderID = 1, Time = new DateTime(2010, 1, 1, 10, 30, 30), Price = 100m, LotCount = 5, BuySell = BuySell.Buy }; table.AddTrade(t); var positions = table.GetPositions(); Assert.Single(positions); var pos = positions.ElementAt(0); Assert.Equal(t.InsID, pos.InsID); Assert.True(pos.PosID < 0); Assert.Equal(t.Time, pos.OpenTime); Assert.Equal(t.Price, pos.OpenPrice); Assert.Equal(t.LotCount * ins.LotSize, pos.Count); Assert.Equal(PosTypes.Long, pos.PosType); Assert.Null(pos.ClosePrice); Assert.Null(pos.CloseTime); }
/// <summary> /// Асинхронная загрузка исторических данных /// </summary> /// <param name="toDate">Загрузка по эту дату включительно</param> /// <param name="isLastDirty">Данные за последний день неполные</param> /// <param name="progress">Объект управления фоновой задачей</param> /// <param name="cancel">Отмена длительной операции</param> /// <returns>Асинхронная задача загрузки</returns> public Task DownloadAllAsync(DateTime toDate, bool isLastDirty, BgTaskProgress progress, CancellationToken cancel) { return(Task.Run(() => { try { _logger.LogInformation("DownloadAll to {date}", toDate.ToString("yyyy-MM-dd")); var insStores = _insStoreBL.GetActiveInsStores(); int count = insStores.Count(); int idx = 1; if (progress != null) { progress.OnStart(count > 1); } Dictionary <CommonData.InsStore, BgTaskProgress> progresses = new Dictionary <CommonData.InsStore, BgTaskProgress>(); if (progress != null) { foreach (var ss in insStores) { string name = ""; var instrum = _instrumBL.GetInstrumByID(ss.InsID); if (instrum != null) { name = instrum.ShortName; } var child = progress.AddChildProgress(name); progresses.Add(ss, child); } } foreach (var insStore in insStores) { if (cancel.IsCancellationRequested) { if (progress != null) { progress.OnAbort(); } break; } var ssCal = _insStoreBL.GetInsStoreCalendar(insStore.InsStoreID); if (ssCal == null || ssCal.Periods == null) { continue; } DateTime fromDate; if (ssCal.Periods.Count() > 0) { var lastPeriod = ssCal.Periods.Last(); fromDate = lastPeriod.IsLastDirty ? lastPeriod.EndDate : lastPeriod.EndDate.AddDays(1); } else { fromDate = _insStoreBL.GetDefaultStartHistoryDate(toDate, insStore.Tf); } var p = progresses.ContainsKey(insStore) ? progresses[insStore] : null; DownloadAsync(insStore, fromDate, toDate, isLastDirty, true, p, cancel).Wait(); if (progress != null) { progress.OnProgress((double)idx++ / count * 100); } } if (progress != null) { if (cancel.IsCancellationRequested) { progress.OnAbort(); } else { progress.OnComplete(); } } _logger.LogInformation("DownloadAll complete."); } catch (Exception ex) { _logger.LogError(ex, "DownloadAll error."); if (progress != null) { progress.OnFault(ex); } } })); }