public static List <CandleData> MakeQuotes(DateTime timeHistStart, DateTime timeHistEnd, DateSpan[] serverGaps) { // подготовить список котировок для "клиента" и "сервера" var allCandles = new List <CandleData>(); var index = 0; for (var time = timeHistStart; time <= timeHistEnd; time = time.AddMinutes(1)) { // проверить попадание в дырку на сервере if (serverGaps.Any(g => g.IsIn(time))) { continue; } if (DaysOff.Instance.IsDayOff(time)) { continue; } var o = (float)Math.Sin((index++) / 15.0); var candle = new CandleData(o, o + 0.001f, o - 0.003f, o - 0.001f, time, time.AddMinutes(1)); allCandles.Add(candle); } return(allCandles); }
private ChartItem CandleData2MultiItem(CandleData cd, CandleData?cdPre, ChartItemType type) { if (type == ChartItemType.Linear) { return(new MultipleChartItem() { Value = cd.close, Date = cd.DateTime, ValueChange = (cd.close - cdPre.Value.close) / cdPre.Value.close, Values = new List <double>(invalidValues), ValueChanges = new List <double>(invalidValues) }); } else if (type == ChartItemType.Candle) { return(new StockValuesItem() { Date = cd.DateTime, High = cd.high, Low = cd.low, Open = cd.open, Close = cd.close, CloseChange = cdPre != null ? (cd.close - cdPre.Value.close) / cdPre.Value.close : 0, Values = new List <double>(invalidValues), ValueChanges = new List <double>(invalidValues) }); } else { return(null); } }
private ChartItem CandleData2Item(CandleData cd, CandleData?cdPre, bool isStock) { if (isStock) { return(new StockItem() { Date = cd.DateTime, High = cd.high, Low = cd.low, Open = cd.open, Close = cd.close, CloseChange = cdPre != null ? (cd.close - cdPre.Value.close) / cdPre.Value.close : 0 }); } else { return(new VolumnItem() { Date = cd.DateTime, Volumn = cd.amount, Turnover = cd.money, IsRaise = cd.open < cd.close }); } }
private List <MultipleChartItem> FromStock(Stock stock, int valueCount = 0) { if (valueCount != 0) { invalidValues = new double[valueCount]; for (int i = 0; i < valueCount; i++) { invalidValues[i] = ChartItemCollection.valueNA; } } List <MultipleChartItem> cItems = new List <MultipleChartItem>(stock.DataCount); CandleData cdPre = stock.Items.FirstOrDefault(); foreach (var cd in stock.Items) { cItems.Add(new MultipleChartItem() { Value = cd.close, Date = cd.DateTime, ValueChange = (cd.close - cdPre.close) / cdPre.close, Values = valueCount != 0 ? new List <double>(invalidValues) : null, ValueChanges = valueCount != 0 ? new List <double>(invalidValues) : null }); cdPre = cd; } return(cItems); }
/// <summary> /// Получить элемент /// </summary> /// <param name="time"></param> /// <param name="addNew"></param> /// <returns></returns> public override HVolume GetElement(DateTime time, bool addNew = false) { var timeElement = CandleData.GetTimeCandle(time, periodTimeFrame); lock (syncLock) { if (lastSearchedElement.NotIsNull()) { if (lastSearchedElement.Time == timeElement) { return(lastSearchedElement); } lastSearchedElement = default; } var element = Collection.FirstOrDefault(c => c.Time == timeElement); if (element.NotIsNull()) { lastSearchedElement = element; return(lastSearchedElement); } else if (addNew) { var newElement = new HVolume(timeElement); Collection.Add(newElement); Collection = Collection.OrderByDescending(c => c.Time).ToList(); lastSearchedElement = newElement; } } return(lastSearchedElement); }
/// <summary> /// на асинхронное обновление котировки /// </summary> public void ProcessQuotesByIndicators(CandleData updatedCandle, List <CandleData> newCandles) { foreach (var indi in indicators) { indi.OnCandleUpdated(updatedCandle, newCandles); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (newCandles == null) { return; } if (newCandles.Count == 0) { return; } if (tickerData == null) { return; } // дополнить списки tickerData foreach (var ticker in tickerData) { var list = ticker.Value; var quote = QuoteStorage.Instance.ReceiveValue(ticker.Key); var lastPrice = quote != null ? (double)quote.bid : list.Count > 0 ? list[list.Count - 1] : 0; list.AddRange(newCandles.Select(t => lastPrice)); } BuildSeries(owner, false); }
private int CheckEnterCondition(string symbol, CandleData candle) { if (Math.Abs(candle.open - candle.close) < 0.000001) { return(0); } var candlesList = storedCandles[symbol]; candlesList.Add(candle); if (candlesList.Length < candlesList.MaxQueueLength) { return(0); // [A] список для вычисления Б-линджера еще не заполнен } var bollingerList = bollingerSignalHistory[symbol]; if (bollingerList.Any(x => x != 0)) { bollingerList.Add(0); return(0); } // [A] по-хорошему надо завести RestrictedQueue из кортежей: // 1) close 2) (close - open) * (close - open) // ... и вычислять средние значения close и корень из среднего значения (close - open) * (close - open) // Вычислений - возведений в квадрат - будет меньше var average = candlesList.Average(x => x.close); var v = Math.Sqrt(candlesList.Average(x => (x.close - x.open) * (x.close - x.open))); var high = average + v * (float)BollingerCoeff; var low = average - v * (float)BollingerCoeff; var signal = candle.close <low ? 1 : candle.close> high ? -1 : 0; bollingerList.Add(signal); return(signal); }
public bool MoveToTime(DateTime time, out CandleData candle) { candle = null; if (stream == null) { return(false); } if (currentCandle == null) { return(false); } if (time < currentCandle.timeClose) { stream.BaseStream.Position = 0; stream.DiscardBufferedData(); Reset(); if (currentCandle.timeClose > time) { return(false); } } while (currentCandle != null) { if (nextCandle != null && nextCandle.timeClose > time) { candle = currentCandle; return(true); } currentCandle = nextCandle; nextCandle = ReadCandle(nextCandle); } return(false); }
public void TestPackedCandleStream() { var stream = new PackedCandleStream( srcCandles.Select( c => new CandleDataPacked { timeOpen = c.timeOpen, open = c.open, HLC = c.GetHlcOffset16(VersePointValue), close = c.close }).ToList(), true); var parsedCandles = stream.GetCandles().Select(c => { var candle = new CandleData { timeOpen = c.timeOpen, open = c.open, close = c.close }; candle.MakeHlcFromOffset16(c.HLC, VersePointValue); return(candle); }).ToList(); for (var candleIndex = 0; candleIndex < srcCandles.Count; candleIndex++) { var candle = srcCandles[candleIndex]; var parsedCandle = parsedCandles[candleIndex]; Assert.AreEqual(candle.high, parsedCandle.high, 0.000001, "TestPackedCandleStream: ParseLine error (high)"); Assert.AreEqual(candle.low, parsedCandle.low, 0.000001, "TestPackedCandleStream: ParseLine error (low)"); Assert.AreEqual(candle.close, parsedCandle.close, 0.000001, "TestPackedCandleStream: ParseLine error (close)"); } }
public void DoCheckCommonStop(CandleData candle, List <MarketOrder> orders, List <string> events) { if ((Side == PriceSide.Выше && candle.close < (float)StopLevel) || (Side == PriceSide.Ниже && candle.close > (float)StopLevel)) { return; } var eventStr = string.Format("Условный стоп сделок закрытие свечи на {0} ({1} отметки {2})", candle.close.ToStringUniformPriceFormat(), Side.ToString().ToLower(), StopLevel.ToStringUniformPriceFormat()); events.Add(eventStr); Logger.Info(eventStr); foreach (var order in orders) { // проверить - у ордера не должно быть индивидуальной цены закрытия if (OverrideIndividualStop) { if (!string.IsNullOrEmpty(order.Comment)) { if (regConStop.IsMatch(order.Comment.Replace(',', '.'))) { continue; } } } // закрыть ордер CloseMarketOrder(order.ID); } }
/// <summary> /// Пересекает ли переданная свеча облако на заданном диапазоне свечей /// </summary> /// <param name="candle">Свеча, посчитанная по главному таймфрейму (M30)</param> private bool CloudIntersection(CandleData candle) { // от переданной свечи отступаем назад на средний промежуток времени (periodM) // считаем там 2 точки облака (SenkouA и SenkouB) // проверяем - пересекает ли их свеча var firstCandleDataPeriodL = shiftBackPoints.Take(PeriodL).ToList(); var kijunPoints = firstCandleDataPeriodL.Skip(firstCandleDataPeriodL.Count - PeriodM).ToList(); //TODO тут может быть исключение, есть PeriodL < PeriodM var kijunShift = (kijunPoints.Min(x => x.close) + kijunPoints.Max(x => x.close)) / 2; var tencanPoints = firstCandleDataPeriodL.Skip(firstCandleDataPeriodL.Count - PeriodS).ToList(); var tencanShift = (tencanPoints.Min(x => x.close) + tencanPoints.Max(x => x.close)) / 2; var senkouA = (tencanShift + kijunShift) / 2; var senkouB = (firstCandleDataPeriodL.Min(x => x.close) + firstCandleDataPeriodL.Max(x => x.close)) / 2; if (candle.high > senkouA && senkouA > candle.low) { return(true); } if (candle.high > senkouB && senkouB > candle.low) { return(true); } var up = senkouA > senkouB ? senkouA : senkouB; var dn = senkouA > senkouB ? senkouB : senkouA; return(up > candle.close && candle.close > dn); }
/// <summary> /// /// </summary> public override void EachCandle(int index, CandleData can, int count) { if (countPainted < Levels.Count) { Paint(); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (/*DisplayedOrders == OrderType.Рыночный && */ ShowComments || ShowCurrent) { UpdateProfit(); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (newCandles.Count > 0) { BuildSeries(owner); } }
/// <summary> /// склеить свечи m1, прочитанные из БД либо из файла с теми, /// что хранятся в AtomCandleStorage /// </summary> private static void MergeQuotes(string smb, List <CandleData> quotes) { // прочитать котировки из файла (локальный кеш) var filePath = string.Format("{0}{1}\\{2}.quote", ExecutablePath.ExecPath, TerminalEnvironment.QuoteCacheFolder, smb); var srcQuotes = AtomCandleStorage.Instance.GetAllMinuteCandles(smb); // склеить их с новыми котировками var newQuotes = quotes; if (srcQuotes != null && srcQuotes.Count > 0) { CandleData.MergeCandlesFineGrained(ref srcQuotes, quotes); newQuotes = srcQuotes; } // обновить хранилище AtomCandleStorage.Instance.RewriteCandles(smb, newQuotes); // сохранить склеенные котировки в файл try { CandleData.SaveInFile(filePath, smb, newQuotes); } catch (Exception ex) { Logger.ErrorFormat(Localizer.GetString("MessageErrorSavingQuotesInFileFmt"), filePath, ex); MessageBox.Show(string.Format(Localizer.GetString("MessageErrorSavingQuotesInFileFmt"), filePath, ex.Message), Localizer.GetString("TitleError"), MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public CandleForDb(int ticker, int pointCost, CandleData candle) { this.ticker = ticker; time = candle.timeOpen; open = candle.open; HLC = candle.GetHlcOffset16(pointCost); }
/// <summary> /// Отрисовать индекс на графике /// </summary> /// <param name="isHigh">тру - если фрактал верха</param> /// <param name="candle">текущая свеча</param> /// <param name="index">индекс текущей свечи</param> private void DrawIndi(bool isHigh, CandleData candle, int index) { //? Из за недостатка комментариев я не очень понял какие поля зачему нужны у этого класса // Думаю, что ты и так знаешь, но классы которыми нужно оперировать при отрисовке, надо бы описать в документации /* А * Конечно, надо :) */ var tip = new AsteriskTooltip("fractal", string.Empty) { Price = isHigh ? (candle.high + offset) : (candle.low - offset), CandleIndex = index, //DateStart = candle.timeOpen,//? Что это и нужно ли здесь Sign = "", //? Что это и нужно ли здесь Shape = isHigh ? AsteriskTooltip.ShapeType.ГалкаВверх : AsteriskTooltip.ShapeType.ГалкаВниз, ColorFill = isHigh ? clArrowHigh : clArrowLow, ColorLine = Color.Black, ColorText = Color.Black, Radius = 6 //? Что это и нужно ли здесь }; /* А * Sign - текст, выводимый посередине * Radius - каждая фигурка задана в "векторной" форме, Radius задает ее измерение (ширину, вроде) в пикс., пропорционально меняется другое измерение * DateStart можно не указывать, если задан CandleIndex */ series.data.Add(tip); }
// private const string TableNameQuote = "QUOTE"; /// <summary> /// получает котировки (свечи m1) по всем торгуемым активам на момент /// времени t меньше либо равный time /// </summary> public static Dictionary <string, CandleData> GetCandlesOnTime(DateTime?time) { var candles = new Dictionary <string, CandleData>(); var cmdText = time.HasValue ? "WITH e AS ( select ticker, MAX([date]) as 'mxdate' from QUOTE where [date] <= '" + time.Value.ToString("yyyyMMdd HH:mm") + "' group by ticker ) select q.* " + "FROM e join QUOTE q on q.ticker = e.ticker and q.date = e.mxdate" : "WITH e AS ( select ticker, MAX([date]) as 'mxdate' from QUOTE group by ticker ) select q.* " + "FROM e join QUOTE q on q.ticker = e.ticker and q.date = e.mxdate"; var cmd = new SqlCommand(cmdText); var values = new object[4]; try { using (var conn = MakeSqlConnection()) { cmd.Connection = conn; conn.Open(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { if (reader.GetValues(values) != values.Length) { continue; } var ticker = (Int16)values[0]; var symbol = DalSpot.Instance.GetSymbolByFXICode(ticker); if (string.IsNullOrEmpty(symbol)) { continue; } var pointValue = DalSpot.Instance.GetPrecision10(symbol); var candle = new CandleData { timeOpen = (DateTime)values[1], open = (float)(double)values[2], }; var hlc = (int)values[3]; candle.MakeHlcFromOffset(hlc, pointValue); candles.Add(symbol, candle); } } } } catch (Exception ex) { Logger.Error("GetCandlesOnTime() - ошибка доступа к БД котировок", ex); } return(candles); }
public void UpdateQuotes(List <TickerQuoteData> quotes) { var candlesToSave = new List <Cortege2 <int, CandleData> >(); var nowTime = GetDateTimeWoSeconds(DateTime.Now); foreach (var q in quotes) { int ticker; if (!tickerCodeBySymbol.TryGetValue(q.Ticker, out ticker)) { logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info, LogMsgTickerCodeMissed, 1000 * 30, "[{0}] code is missed - can not store", q.Ticker); continue; } if (q.bid <= 0) { logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info, LogMsgTickerBidWrong, 1000 * 30, "[{0}] bid is not valid - can not store", q.Ticker); continue; } // обновить свечу CandleData candle; if (!lastCandles.TryGetValue(ticker, out candle)) { continue; } if (candle == null) { candle = new CandleData(q.bid, q.bid, q.bid, q.bid, nowTime, nowTime); candlesToSave.Add(new Cortege2 <int, CandleData>(ticker, candle)); lastCandles[ticker] = candle; continue; } if (candle.high < q.bid) { candle.high = q.bid; } if (candle.low > q.bid) { candle.low = q.bid; } candle.close = q.bid; if (candle.timeOpen != nowTime) { candlesToSave.Add(new Cortege2 <int, CandleData>(ticker, candle)); candle = new CandleData(q.bid, q.bid, q.bid, q.bid, nowTime, nowTime); lastCandles[ticker] = candle; } } // сохранить новые свечки if (candlesToSave.Count > 0) { CandleStoreStream.Instance.EnqueueCandles(candlesToSave); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (newCandles.Count != 0) { // добавилась крайняя свеча графика Calculation(); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (updatedCandle == null && (newCandles == null || newCandles.Count == 0)) { return; } // проверить на мин. интервал и обновить график }
public CandleForTable(CandleData c) { Time = c.timeOpen; Open = c.open; High = c.high; Low = c.low; Close = c.close; }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (updatedCandle == null && (newCandles == null || newCandles.Count == 0)) { return; } BuildSeries(owner); }
public KosherCandle(CandleData candle) { TimeOpen = candle.timeOpen; Open = candle.open; Close = candle.close; High = candle.high; Low = candle.low; }
/// <summary> /// Обработчик новой свечи в тайм врейме /// </summary> /// <param name="taimFrame"></param> /// <param name="candle"></param> public void ProcessEventNewCandle(int timeFrame, CandleData candle) { //MAverage.Calculate(Candels.VerticalLines); Indicators.ForEach((ind) => { ((Indicator)ind).NewCandleInTimeFrame(timeFrame, candle); }); }
public async Task GetPreviousMonthCryptoCandles(string cryptoSymbol) { double seconds = this.dateTime.Now.DateTimeInstance.ConvertToUnixTimestamp(); double secondsPrevoiusMonth = this.dateTime.Now.AddMonths(-1).DateTimeInstance.ConvertToUnixTimestamp(); string res = await this.httpClient.GetStringAsync($"https://finnhub.io/api/v1/crypto/candle?symbol=BINANCE:{cryptoSymbol}&resolution=1&from={secondsPrevoiusMonth}&to={seconds}&token={"test"}").ConfigureAwait(false); CandleData candleData = JsonConvert.DeserializeObject <CandleData>(res); }
/// <summary> /// Содержит главную логику робота по анализу свечей и принятия решений о заключении сделок. Этот метод открытый, потому что он используется при /// тестировании робота. /// </summary> public void CandlesAnalysisAndTrade(CandleData candle, bool isHistoryStartOff) { if (virtualDeal != null) { var virtDealResult = DalSpot.Instance.GetPointsValue(ticker, virtualDeal.Side * (candle.close - virtualDeal.PriceEnter)); virtualResults.DequeueLast(); virtualResults.Add(virtDealResult); } var currentSign = Math.Sign(queueFast.Average() - queueSlow.Average()); // Вычисляем текущее расположение скользящих средних try { if (prevSign == 0 || prevSign == currentSign) { return; } // СС пересеклись // Считаем средней результат виртуальных сделок var avgVirtualResult = virtualResults.Length == 0 ? 0 : virtualResults.Average(); // Если следний редультат виртуальных сделок не входит в диапазон "не торговать", то высчитываем знак текущей сделки maDifSign = Math.Abs(avgVirtualResult) < unknownUnitProfit ? 0 : Math.Sign(avgVirtualResult); // "На будущее" запоминаем текущую стуацию, для расчёта виртуальных сделок на следующих итерациях virtualDeal = new MarketOrder { PriceEnter = candle.close, Side = currentSign }; virtualResults.Add(0); // тут будет результат новой сделки на следующей итерации // пересечение скользящих средних произошло не на истории if (!isHistoryStartOff) { List <MarketOrder> orders; robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders); var tradeSide = deriveSiteFromHistory ? currentSign * maDifSign : currentSign; Trade(candle, orders, tradeSide); } } finally { prevSign = currentSign; if (debugAction != null) { debugAction(new RobotMAInnerState { maDifSign = maDifSign, maValueFast = queueFast.Average(), maValueSlow = queueSlow.Average(), lastCandle = candle, }, candle.timeClose); } } }
public static List <CandleData> ReadTopNumCandles(string symbol, int count, DateTime dateStart, DateTime dateEnd) { var candles = new List <CandleData>(); var ticker = DalSpot.Instance.GetFXICodeBySymbol(symbol); if (ticker == 0) { return(candles); } var pointValue = DalSpot.Instance.GetPrecision10(symbol); var cmdText = string.Format("select top({0}) date, [open], HLC from QUOTE where ticker={1} and " + "date between '{2:yyyyMMdd HH:mm}' and '{3:yyyyMMdd HH:mm}'", count, ticker, dateStart, dateEnd); var cmd = new SqlCommand(cmdText); var values = new object[3]; try { using (var connection = new SqlConnection(connectionString)) { cmd.Connection = connection; connection.Open(); using (var reader = cmd.ExecuteReader()) { CandleData previousCandle = null; while (reader.Read()) { if (reader.GetValues(values) != values.Length) { continue; } var candle = new CandleData { timeOpen = (DateTime)values[0], open = (float)(double)values[1], }; var hlc = (int)values[2]; candle.MakeHlcFromOffset16(hlc, pointValue); if (previousCandle != null) { previousCandle.close = candle.open; previousCandle.high = Math.Max(candle.open, previousCandle.high); previousCandle.low = Math.Min(candle.open, previousCandle.low); } previousCandle = candle; candles.Add(candle); } } } } catch (Exception ex) { Logger.Error("ReadTopNumCandles() error", ex); } return(candles); }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (updatedCandle == null && newCandles.Count == 0) { return; } // построить индюк BuildSeries(owner); }