public CandleDataBidAsk(CandleData candle, float spread) : base(candle) { openAsk = open + spread; highAsk = high + spread; lowAsk = low + spread; closeAsk = close + spread; }
public void MoveNext() { if (stream == null || nextCandle == null) return; currentCandle = nextCandle; nextCandle = ReadCandle(nextCandle); }
private List <CandleData> GetCandles(BarSettings timeframe, string symbol, DateTime date, int candlesCount) { var startTime = timeframe.GetDistanceTime(candlesCount, -1, date); var minuteCandles = AtomCandleStorage.Instance.GetAllMinuteCandles(symbol, startTime, date) ?? new List <CandleData>(); var packer = new CandlePacker(timeframe); var candles = new List <CandleData>(); foreach (var minuteCandle in minuteCandles) { var candle = packer.UpdateCandle(minuteCandle); if (candle != null) { candles.Add(candle); } } var tail = minuteCandles.Where(x => x.timeOpen > candles.Last().timeClose).ToArray(); if (tail.Length > 0) { float open = tail.First().open; float close = tail.Last().close; float high = tail.Max(x => x.high); float low = tail.Min(x => x.low); DateTime timeOpen = tail.First().timeOpen; DateTime timeClose = tail.Last().timeClose; var currentCandel = new CandleData(open, high, low, close, timeOpen, timeClose); candles.Add(currentCandel); } return(candles); }
private void MakeNewCandle(float price, DateTime time) { DateTime startTime; CandleCloseTime = GetLastCandleClose(time, out startTime); currentCandle = new CandleData(price, price, price, price, startTime, time); }
public CandleData UpdateCandle(CandleData minuteCandle) { var time = minuteCandle.timeClose; if (CurrentCandle == null) { MakeNewCandle(minuteCandle); } else { if (time > CandleCloseTime) { var candle = CloseCandle(minuteCandle); return(candle); } // обновить уровни свечи CurrentCandle.timeClose = time; CurrentCandle.close = minuteCandle.close; if (minuteCandle.high > CurrentCandle.high) { CurrentCandle.high = minuteCandle.high; } if (minuteCandle.low < CurrentCandle.low) { CurrentCandle.low = minuteCandle.low; } } // коррекция свечи? return(null); }
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; }
/// <summary> /// Вызывает хранимую процедуру 'GetLastQuote' или 'FindQuote' /// </summary> public QuoteData GetQuoteStoredProc(string ticker, DateTime? start = null) { if (string.IsNullOrEmpty(ticker)) return null; SqlConnection conn = null; SqlDataReader rdr = null; var tickerId = DalSpot.Instance.GetFXICodeBySymbol(ticker); var date = default(DateTime); var open = -1f; var lhc = -1; try { var connectionString = ConfigurationManager.ConnectionStrings["QuoteBase"].ConnectionString; conn = new SqlConnection(connectionString); conn.Open(); var procName = start.HasValue ? "FindQuote" : "GetLastQuote"; var cmd = new SqlCommand(procName, conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.Add(new SqlParameter("@ticker", tickerId)); if (start.HasValue) cmd.Parameters.Add(new SqlParameter("@date", start.Value)); rdr = cmd.ExecuteReader(); while (rdr.Read()) { if (!int.TryParse(rdr["ticker"].ToString(), out tickerId)) return null; if (!DateTime.TryParse(rdr["date"].ToString(), out date)) return null; if (!float.TryParse(rdr["open"].ToString(), out open)) return null; if (!int.TryParse(rdr["HLC"].ToString(), out lhc)) return null; } } catch (Exception ex) { Logger.Error("Ошибка в методе GetQuoteStoredProc", ex); return null; } finally { if (conn != null) { conn.Close(); } if (rdr != null) { rdr.Close(); } } var candelDataPacked = new CandleDataPacked { HLC = lhc, open = open, timeOpen = date, close = open // default }; var candleData = new CandleData(candelDataPacked, DalSpot.Instance.GetPrecision10(ticker)); var useOpen = start.HasValue && date == start.Value; return GetQuoteWithDefaultSpread(candleData, ticker, useOpen); }
public CandleDataBidAsk(CandleData candleBid, CandleData candleAsk) : base(candleBid) { openAsk = candleAsk.open; highAsk = candleAsk.high; lowAsk = candleAsk.low; closeAsk = candleAsk.close; }
private void MakeNewCandle(CandleData candle) { var time = candle.timeClose; DateTime startTime; CandleCloseTime = GetLastCandleClose(time, out startTime); currentCandle = new CandleData(candle.open, candle.high, candle.low, candle.close, startTime, time); }
public CandleData(CandleData spec) { open = spec.open; high = spec.high; close = spec.close; low = spec.low; timeOpen = spec.timeOpen; timeClose = spec.timeClose; customColor = spec.customColor; }
public void LoadFromFiles(string quoteDir) { foreach (var fileName in Directory.GetFiles(quoteDir, "*.quote")) { // получить название торгуемого актива var symbol = Path.GetFileNameWithoutExtension(fileName); if (string.IsNullOrEmpty(symbol)) { continue; } symbol = symbol.ToUpper(); // прочитать файл List <CandleData> fileCandles; try { fileCandles = CandleData.LoadFromFile(fileName, symbol); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.LoadFromFiles({0}): {1}", symbol, ex); continue; } if (fileCandles == null || fileCandles.Count == 0) { continue; } if (!locker.TryEnterWriteLock(LockTimeout)) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.LoadFromFiles({0}): невозможно получить доступ на запись", symbol); continue; } // записать в словарь try { if (candles.ContainsKey(symbol)) { candles [symbol] = new ThreadSafeCandleList(fileCandles); } else { candles.Add(symbol, new ThreadSafeCandleList(fileCandles)); } } finally { locker.ExitWriteLock(); } } }
// 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; }
private static CandleFileFormat GetCandleFileFormat(StreamReader sr) { bool?isHexFormat = null; try { while (!sr.EndOfStream) { var line = sr.ReadLine(); if (string.IsNullOrEmpty(line)) { continue; } if (!isHexFormat.HasValue) { isHexFormat = line.ToIntSafe() != null; if (isHexFormat.Value) { continue; } } var parts = line.Split(new [] { ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); if (isHexFormat.Value) { // 0401 1.32030 7FFF801D if (parts.Length != 3) { return(CandleFileFormat.Misformatted); } var format = parts[2].Length == 6 ? CandleFileFormat.Hex : CandleFileFormat.Hex16; DateTime? date = new DateTime(2000, 1, 1); CandleData prev = null; var candle = ParseLine(line, ref date, 4, ref prev); return(candle == null ? CandleFileFormat.Misformatted : format); } // 20150101 00:00;1.21500;1.21527 CandleData prevCandle = null; var quote = ParseQuote(line, ref prevCandle); return(quote == null ? CandleFileFormat.Misformatted : CandleFileFormat.Quote); } } finally { sr.DiscardBufferedData(); sr.BaseStream.Seek(0, SeekOrigin.Begin); sr.BaseStream.Position = 0; } return(CandleFileFormat.Misformatted); }
public void FlushInFiles(string quoteFilesDir) { // получить копию словаря if (!locker.TryEnterReadLock(LockTimeout)) { return; } Dictionary <string, ThreadSafeCandleList> deepCopyCandles; try { deepCopyCandles = candles.ToDictionary(p => p.Key, p => p.Value); } finally { locker.ExitReadLock(); } try { Directory.CreateDirectory(quoteFilesDir); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.FlushInFiles()", ex); } // по каждому тикеру - сохранить свечки в файл foreach (var pair in deepCopyCandles) { var symbol = pair.Key; var list = pair.Value; var candlesByTicker = list.GetAllCandles(); if (candlesByTicker == null || deepCopyCandles.Count == 0) { return; } var path = quoteFilesDir + "\\" + symbol + ".quote"; try { CandleData.SaveInFile(path, symbol, candlesByTicker); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.FlushInFiles({0}): {1}", symbol, ex); } } }
/// <summary> /// Завершить формирование свечки /// </summary> private CandleData CloseCandle(float price, DateTime time) { var completed = new CandleData { open = CurrentCandle.open, close = CurrentCandle.close, high = CurrentCandle.high, low = CurrentCandle.low, timeOpen = CurrentCandle.timeOpen, timeClose = CandleCloseTime, }; MakeNewCandle(price, time); return(completed); }
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 static List <CandleData> LoadFromFile(string filePath, string symbol) { var precision = DalSpot.Instance.GetPrecision10(symbol); var candles = new List <CandleData>(); CandleData previousCandle = null; DateTime? date = null; var countErrorsLeft = 25; using (var sr = new StreamReader(filePath, Encoding.ASCII)) { var format = GetCandleFileFormat(sr); if (format == CandleFileFormat.Misformatted) { return(new List <CandleData>()); } while (!sr.EndOfStream) { var line = sr.ReadLine(); var oldDate = date; var candle = (format == CandleFileFormat.Hex || format == CandleFileFormat.Hex16) ? ParseLine(line, ref date, precision, ref previousCandle) : ParseQuote(line, ref previousCandle); if (candle == null) { if (!oldDate.HasValue && date.HasValue) { continue; } if (oldDate.HasValue && date.HasValue && oldDate.Value != date.Value) { continue; } countErrorsLeft--; if (countErrorsLeft <= 0) { break; } } else // prevent adding nulls { candles.Add(candle); } } } return(candles); }
public void FlushInFile(string quoteFilesDir, string symbol) { // получить копию словаря if (!locker.TryEnterReadLock(LockTimeout)) { return; } ThreadSafeCandleList candlesBySymbol; try { if (!candles.TryGetValue(symbol, out candlesBySymbol)) { return; } } finally { locker.ExitReadLock(); } var lstCandles = candlesBySymbol.GetAllCandles(); if (lstCandles == null || lstCandles.Count == 0) { return; } // по каждому тикеру - сохранить свечки в файл var path = quoteFilesDir + "\\" + symbol + ".quote"; try { Directory.CreateDirectory(quoteFilesDir); CandleData.SaveInFile(path, symbol, lstCandles); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.FlushInFile({0}): {1}", symbol, ex); } }
public void TestHlcFormat() { var candleData = new CandleData { open = (float) 1.2345, high = (float) 1.2355, low = (float) 1.2335, close = (float) 1.2344 }; var offset = candleData.GetHlcOffset(VersePointValue); Assert.AreEqual(0x7E7589, offset, "TestHlcFormat: GetHlcOffset error"); var line = candleData.GetHlcOffsetHEX(VersePointValue); Assert.AreEqual("7E7589", line, "TestHlcFormat: GetHlcOffsetHEX error"); var offset16 = candleData.GetHlcOffset16(VersePointValue); Assert.AreEqual(0x7F9B8063, offset16, "TestHlcFormat: GetHlcOffset16 error"); var line16 = candleData.GetHlcOffsetHEX16(VersePointValue); Assert.AreEqual("7F9B8063", line16, "TestHlcFormat: GetHlcOffsetHEX16 error"); var candle = new CandleData {open = candleData.open}; candle.MakeHlcFromOffset(offset, VersePointValue); Assert.AreEqual(candleData.high, candle.high, 0.00001, "TestHlcFormat: MakeHlcFromOffset error (high)"); Assert.AreEqual(candleData.low, candle.low, 0.00001, "TestHlcFormat: MakeHlcFromOffset error (low)"); Assert.AreEqual(candleData.close, candle.close, 0.00001, "TestHlcFormat: MakeHlcFromOffset error (close)"); candle.MakeHlcFromOffsetHEX(line, VersePointValue); Assert.AreEqual(candleData.high, candle.high, 0.00001, "TestHlcFormat: MakeHlcFromOffsetHEX error (high)"); Assert.AreEqual(candleData.low, candle.low, 0.00001, "TestHlcFormat: MakeHlcFromOffsetHEX error (low)"); Assert.AreEqual(candleData.close, candle.close, 0.00001, "TestHlcFormat: MakeHlcFromOffsetHEX error (close)"); candle.MakeHlcFromOffset16(offset16, VersePointValue); Assert.AreEqual(candleData.high, candle.high, 0.00001, "TestHlcFormat: MakeHlcFromOffset16 error (high)"); Assert.AreEqual(candleData.low, candle.low, 0.00001, "TestHlcFormat: MakeHlcFromOffset16 error (low)"); candle.MakeHlcFromOffsetHEX16(line16, VersePointValue); Assert.AreEqual(candleData.high, candle.high, 0.00001, "TestHlcFormat: MakeHlcFromOffset16 error (high)"); Assert.AreEqual(candleData.low, candle.low, 0.00001, "TestHlcFormat: MakeHlcFromOffset16 error (low)"); }
public static CandleData ParseQuote(string line, ref CandleData previousCandle) { // 20150101 00:00;1.21500;1.21527 var parts = line.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 3) { return(null); } try { var dateTime = DateTime.ParseExact(parts[0], "yyyyMMdd HH:mm", CultureInfo.InvariantCulture); var bid = parts[1].ToFloatUniform(); var open = previousCandle == null ? bid : previousCandle.close; previousCandle = new CandleData(open, Math.Max(open, bid), Math.Min(open, bid), bid, dateTime, dateTime.AddMinutes(1)); return(previousCandle); } catch { return(null); } }
public void Setup() { // Mock для словаря метаданных TradeSharpDictionary.Initialize(MoqTradeSharpDictionary.Mock); MakeGaps(); // подготовить список котировок для "клиента" и "сервера" var allCandles = new List<CandleData>(); var clientCandles = new List<CandleData>(); var index = 0; for (var time = timeHistStart; time <= timeNow; 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); if (time > timeFileEnd) continue; // проверить попадание в дырку на клиенте if (clientGaps.Any(g => g.IsIn(time))) continue; clientCandles.Add(candle); } // поместить его в "локальное хранилище" AtomCandleStorage.Instance.RewriteCandles(Ticker, clientCandles); // инициализировать хранилище котировок moq = MoqQuoteStorage.MakeMoq(new Dictionary<string, List<CandleData>> { {Ticker, allCandles} }); QuoteStorage.Initialize(moq.Object); }
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); } }
public void OnCandleUpdated(CandleData updatedCandle, List<CandleData> newCandles) { if (newCandles != null) if (newCandles.Count > 0) BuildSeries(owner); }
public Cortege2 <DateTime, DateTime>?LoadFromFile(string quoteDir, string symbol) { if (string.IsNullOrEmpty(quoteDir)) { throw new ArgumentException("LoadFromFile - директория пуста", "quoteDir"); } if (string.IsNullOrEmpty(symbol)) { throw new ArgumentException("LoadFromFile - котировка не указана", "symbol"); } var fileName = quoteDir + "\\" + symbol + ".quote"; if (!File.Exists(fileName)) { return(null); } // прочитать файл List <CandleData> fileCandles; try { fileCandles = CandleData.LoadFromFile(fileName, symbol); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.LoadFromFile({0}): {1}", symbol, ex); return(null); } if (fileCandles == null || fileCandles.Count == 0) { return(null); } if (!locker.TryEnterWriteLock(LockTimeout)) { Logger.ErrorFormat("Ошибка в AtomCandleStorage.LoadFromFile({0}): невозможно получить доступ на запись", symbol); return(null); } // записать в словарь var dates = new Cortege2 <DateTime, DateTime>(fileCandles[0].timeOpen, fileCandles[fileCandles.Count - 1].timeOpen); try { if (candles.ContainsKey(symbol)) { candles[symbol] = new ThreadSafeCandleList(fileCandles); } else { candles.Add(symbol, new ThreadSafeCandleList(fileCandles)); } } finally { locker.ExitWriteLock(); } return(dates); }
private void Reset() { fileDate = null; currentCandle = null; nextCandle = null; currentCandle = ReadCandle(null); if (currentCandle == null) { stream.Close(); stream = null; currentCandle = null; fileName = null; return; } startTime = currentCandle.timeClose; nextCandle = ReadCandle(currentCandle); }
private CandleData ReadCandle(CandleData candle) { while (true) { if (stream.EndOfStream) return null; var fileLine = stream.ReadLine(); if (string.IsNullOrEmpty(fileLine)) continue; candle = CandleData.ParseLine(fileLine, ref fileDate, precision, ref candle); if (candle != null) break; } return candle; }
private CandleData CloseCandle(CandleData minuteCandle) { var completed = new CandleData { open = CurrentCandle.open, close = CurrentCandle.close, high = CurrentCandle.high, low = CurrentCandle.low, timeOpen = CurrentCandle.timeOpen, timeClose = CandleCloseTime, }; MakeNewCandle(minuteCandle); return completed; }
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; }
/// <summary> /// Распаковка и обработка архива Forexite /// </summary> private static Dictionary<int, List<CandleData>> ParseForexiteFile(string zipFilePath, int shiftHours, List<string> symbolsToStore) { var candles = new Dictionary<int, List<CandleData>>(); string unpackedFileName; // таки распаковать файл котировок try { var fileNames = CompressionHelper.UnzipFile(zipFilePath, Path.GetDirectoryName(zipFilePath)); if (fileNames.Count == 0) return candles; unpackedFileName = fileNames[0]; } catch (Exception ex) { Logger.Error("Error while decompressing file from Forexite", ex); return candles; } // распаковка закончена, теперь заполняем коллекции QRHistory try { using (var sr = File.OpenText(unpackedFileName)) { // пропускаем заголовок var input = sr.ReadLine(); if (string.IsNullOrEmpty(input)) return candles; while ((input = sr.ReadLine()) != null) { // разбираем строку var index = input.IndexOf(","); var index1 = index; var symbol = input.Substring(0, index); //symbol = FullTradeCurrencyNameFromForexiteFormat(symbol); if (!symbolsToStore.Contains(symbol)) continue; var code = DalSpot.Instance.GetFXICodeBySymbol(symbol); if (code == 0) continue; // куда сохранять List<CandleData> currentList; if (!candles.TryGetValue(code, out currentList)) { currentList = new List<CandleData>(); candles.Add(code, currentList); } index1 = input.IndexOf(",", index + 1); var strDate = input.Substring(index + 1, index1 - index - 1); index = index1; index1 = input.IndexOf(",", index + 1); var strTime = input.Substring(index + 1, index1 - index - 1); index = index1; index1 = input.IndexOf(",", index + 1); var strOpen = input.Substring(index + 1, index1 - index - 1); index = index1; index1 = input.IndexOf(",", index + 1); var strHigh = input.Substring(index + 1, index1 - index - 1); index = index1; index1 = input.IndexOf(",", index + 1); var strLow = input.Substring(index + 1, index1 - index - 1); var strClose = input.Substring(index1 + 1, input.Length - index1 - 1); var quote = new CandleData(); var date = string.Format("{0}/{1}/{2}", strDate.Substring(0, 4), strDate.Substring(4, 2), strDate.Substring(6, 2)); var provider = new NumberFormatInfo {NumberDecimalSeparator = "."}; quote.timeOpen = Convert.ToDateTime(date); quote.timeOpen = quote.timeOpen.AddHours(Convert.ToDouble(strTime.Substring(0, 2))); quote.timeOpen = quote.timeOpen.AddMinutes(Convert.ToDouble(strTime.Substring(2, 2))); quote.timeOpen = quote.timeOpen.AddSeconds(Convert.ToDouble(strTime.Substring(4, 2))); // QuoteRoom поставляет в GMT+1 quote.timeOpen = quote.timeOpen.AddHours(shiftHours); // преобразуем в локальный формат quote.timeOpen = quote.timeOpen.ToLocalTime(); quote.open = Convert.ToSingle(strOpen, provider); quote.high = Convert.ToSingle(strHigh, provider); quote.low = Convert.ToSingle(strLow, provider); quote.close = Convert.ToSingle(strClose, provider); currentList.Add(quote); } } } catch (Exception ex) { Logger.Error("Error while parsing Forexite file", ex); } // удалить оба файла try { File.Delete(zipFilePath); File.Delete(unpackedFileName); } catch (Exception ex) { Logger.Error("Error while finally deleting Forexite files", ex); } return candles; }
/// <summary> /// проверить условия защиты либо по диверам, либо - по Фибоначчи /// прошерстить все таймфреймы, на каждом ТФ - все диверы /// проверить, выполняется ли условие на защиту покупок или продаж /// </summary> private void CheckProtectTrigger( List<MarketOrder> orders, QuoteData curQuote, List<RobotHint> hints, bool isHistoryStartOff, CandleData newCandle) { if (diversToProtect.Count == 0 && fibonacciProtect.Count == 0) return; var protectConditions = new StringBuilder(); int diverSign = CheckProtectByDivers(curQuote, isHistoryStartOff, protectConditions); if (diverSign == 0) diverSign = CheckProtectByFibos(protectConditions, orders, newCandle); if (diverSign == 0) return; // защищаем сделки с указанным знаком var protectSide = (DealType) diverSign; // создать новый список защиты // старый либо актуализируется, либо игнорируется orders = orders.Where(o => o.Side == (int)protectSide).ToList(); if (orders.Count == 0) return; var newProtectList = new ProtectList { orderIds = orders.Select(o => o.ID).ToList(), side = protectSide }; if (protectList != null) if (newProtectList.AreEqual(protectList)) return; protectList = newProtectList; // добавить маркер на график if (ShowProtectEventMarker) { var eventTitle = protectSide == DealType.Buy ? string.Format("Защита {0} покупок", orders.Count) : string.Format("Защита {0} продаж", orders.Count); var eventText = "Условия: " + protectConditions; hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), eventText, eventTitle, "p", curQuote.bid) { Time = curQuote.time, ColorFill = Color.Yellow, ColorLine = Color.Black, RobotHintType = RobotHint.HintType.Коментарий //diverSign > 0 // ? RobotHint.HintType.Покупка // : RobotHint.HintType.Продажа }); } //Logger.InfoFormat("CheckProtectTrigger: защита сделок [{0}] типа {1}", // string.Join(", ", protectList.orderIds), protectList.side); }
public bool ReadCandlesFromFile(CandleByTicker candles, string path, out int timeframe) { timeframe = 0; using (var sr = new FileStream(path, FileMode.Open, FileAccess.Read)) { var header = sr.ReadStruct<HstFileHeader>(); if (!header.HasValue) return false; var mt4StartDate = new DateTime(1970, 1, 1); timeframe = header.Value.period; while (true) { var record = sr.ReadStruct<HstFileRecord>(); if (!record.HasValue) break; var candle = new CandleData { timeOpen = mt4StartDate.AddSeconds(record.Value.ctm), open = (float)record.Value.open, high = (float)record.Value.high, low = (float)record.Value.low, close = (float)record.Value.close }; candle.timeClose = candle.timeOpen.AddMinutes(candles.Timeframe); candles.candles.Add(candle); } } if (candles.candles.Count > 0) candles.StartTime = candles.candles.Min(c => c.timeOpen); return true; }
private int CheckProtectByFibos(StringBuilder conditions, List<MarketOrder> orders, CandleData newCandle) { if (newCandle == null) return 0; if (fibonacciProtect.Count == 0 || orders.Count == 0) return 0; var dealSign = orders[0].Side; foreach (var fibo in fibonacciProtect) { // получить точки ЗЗ, проверить условие (уровень Фибо или коррекции) if (FiboLevelReached(-dealSign, fibo.ZigZagThreshold, fibo.FiboLevel, fibo.ZigZagSource, fibo.MaxPointsToFibo, fibo.MaxCandlesFromLevel)) { if (ShowProtectEventMarker) conditions.AppendFormat("Защита по ЗЗ ({0:f1}%, {1:f3})", fibo.ZigZagThreshold, fibo.FiboLevel); return dealSign; } } return 0; }
public static void LoadCandlesSilent( Dictionary <string, Cortege2 <DateTime, DateTime> > tickersToUpload, QuoteStorageProxy quoteStorage, string quoteFolder, int minMinutesOfGap) { const int daysInRequest = 5, minDaysInRequest = 2; foreach (var ticker in tickersToUpload) { var pointCost = DalSpot.Instance.GetPrecision10(ticker.Key); var filePath = string.Format("{0}\\{1}.quote", ExecutablePath.ExecPath + quoteFolder, ticker.Key); DateTime?lastDateStore = null; DateTime?oldStart = null, oldEnd = null; bool endsUpNewLine; if (File.Exists(filePath)) { GetFirstAndLastFileDates(filePath, out oldStart, out oldEnd, out endsUpNewLine); } else { var dirName = Path.GetDirectoryName(filePath); if (!Directory.Exists(dirName)) { try { Directory.CreateDirectory(dirName); } catch (Exception ex) { Logger.Error(String.Format("Невозможно создать каталог котировок \"{0}\": {1}", dirName, ex)); throw; } } } if (oldStart.HasValue && oldEnd.HasValue) { var deltaStart = (oldStart.Value - ticker.Value.a).TotalMinutes; var deltaEnd = (ticker.Value.b - oldEnd.Value).TotalMinutes; if (deltaStart <= minMinutesOfGap && deltaEnd <= minMinutesOfGap) { continue; } if (deltaStart <= minMinutesOfGap) { lastDateStore = oldEnd.Value; } } var dateLast = DateTime.Now; for (var dateStart = lastDateStore.HasValue ? lastDateStore.Value.AddMinutes(1) : ticker.Value.a; dateStart < ticker.Value.b;) { var dateEnd = dateStart.AddDays(daysInRequest); if ((dateLast - dateEnd).TotalDays < minDaysInRequest) { dateEnd = dateLast; } // запрос List <CandleData> curCandles = null; var numFaultsLeft = 2; while (numFaultsLeft > 0) { // попытка подгрузить котировки try { var packedQuotes = quoteStorage.GetMinuteCandlesPacked(ticker.Key, dateStart, dateEnd); if (packedQuotes != null && packedQuotes.count > 0) { var denseCandles = packedQuotes.GetCandles(); if (denseCandles != null && denseCandles.Count > 0) { curCandles = denseCandles.Select(c => new CandleData(c, pointCost)).ToList(); } } } catch (Exception ex) { Logger.ErrorFormat("Ошибка закачки котировок {0} c {1:dd.MM.yyyy}: {2}", ticker.Key, dateStart, ex.Message); curCandles = null; } if (curCandles == null) { // попытка неуспешна - еще одна? numFaultsLeft--; if (numFaultsLeft > 0) { continue; } break; } break; } if (curCandles != null && curCandles.Count > 0) { // записать в файл прочитанные из БД котировки try { var existData = CandleData.LoadFromFile(filePath, ticker.Key); if (existData != null && existData.Count > 0) { CandleData.MergeCandles(ref curCandles, existData, true); } } catch (Exception ex) { Logger.ErrorFormat("QuoteCacheManager.LoadQuotesSilent() - ошибка чтения / склейки котировок \"{0}\": {1}", filePath, ex); } try { CandleData.SaveInFile(filePath, ticker.Key, curCandles); } catch (Exception ex) { Logger.ErrorFormat("QuoteCacheManager.LoadQuotesSilent() - ошибка сохранения котировок \"{0}\": {1}", filePath, ex); } } dateStart = dateEnd; } } }
public void OnCandleUpdated(CandleData updatedCandle, List<CandleData> newCandles) { BuildSeries(owner); }
/// <summary> /// на асинхронное обновление котировки /// </summary> public void ProcessQuotesByIndicators(CandleData updatedCandle, List<CandleData> newCandles) { foreach (var indi in indicators) { indi.OnCandleUpdated(updatedCandle, newCandles); } }
/// <summary> /// пересчитать индикатор для последней добавленной свечки /// </summary> public void OnCandleUpdated(CandleData updatedCandle, List<CandleData> newCandles) { if (newCandles.Count == 0) return; BuildSeries(owner); }
private string MakeInsertCommand(CandleData candle, int ticker) { int pointCost; if (!pointCostByTicker.TryGetValue(ticker, out pointCost)) return string.Empty; return string.Format("exec {0} @ticker={1}, @date='{2:yyyyMMdd HH:mm}', " + "@open={3}, @HLC={4}", ProcUpsertQuoteRecord, ticker, candle.timeOpen, candle.open.ToStringUniform(), candle.GetHlcOffset16(pointCost)); //return string.Format("if exists (select * from QUOTE where ticker={0} and date='{1:yyyyMMdd HH:mm}') begin " + // " update QUOTE set [open]={2}, HLC={3} end else begin " + // "insert into QUOTE (ticker, date, [open], HLC) values (" + // "{0}, '{1:yyyyMMdd HH:mm}', {2}, {3}) end", // ticker, // candle.timeOpen, candle.open.ToStringUniform(), candle.GetHlcOffset(pointCost)); }
public CandleData UpdateCandle(CandleData minuteCandle) { var time = minuteCandle.timeClose; if (CurrentCandle == null) MakeNewCandle(minuteCandle); else { if (time > CandleCloseTime) { var candle = CloseCandle(minuteCandle); return candle; } // обновить уровни свечи CurrentCandle.timeClose = time; CurrentCandle.close = minuteCandle.close; if (minuteCandle.high > CurrentCandle.high) CurrentCandle.high = minuteCandle.high; if (minuteCandle.low < CurrentCandle.low) CurrentCandle.low = minuteCandle.low; } // коррекция свечи? return null; }
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 (newCandles == null) return; if (newCandles.Count == 0) return; }
private static void ProcessUnzippedFile(string path) { //L,EUR,GBP,CHF,JPY,EURGBP,EURCHF,EURJPY,GBPCHF,GBPJPY,CHFJPY,CAD,EURCAD,AUD,AUDJPY,NZD,NZDJPY,XAU,XAG //S,EUR //D,41275 //1,1.3184,1.3184,1.3184,1.3184 using (var sr = new StreamReader(path, Encoding.ASCII)) { var firstLine = sr.ReadLine(); var tickers = firstLine.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).Select( GetTickerFullName).ToList(); var streams = tickers.ToDictionary(t => t, t => new StreamWriter( path + "." + t, false, Encoding.ASCII)); try { StreamWriter currentStream = null; var curDay = new DateTime(); DateTime? lastSavedDate = null; while (!sr.EndOfStream) { var line = sr.ReadLine(); if (string.IsNullOrEmpty(line)) continue; if (line.StartsWith("S,")) { var currentTicker = GetTickerFullName(line.Substring("S,".Length)); currentStream = streams[currentTicker]; continue; } if (line.StartsWith("D,")) { var dayPart = line.Substring("D,".Length).ToInt(); curDay = new DateTime(1900, 1, 1).AddDays(dayPart); lastSavedDate = null; continue; } if (currentStream == null) continue; var lineParts = line.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); var time = curDay.AddMinutes(lineParts[0].ToInt()); var open = lineParts[1].ToFloatUniform(); var high = lineParts[2].ToFloatUniform(); var low = lineParts[3].ToFloatUniform(); var close = lineParts[4].ToFloatUniform(); var candle = new CandleData(open, high, low, close, time, time.AddMinutes(1)); var pointCost = open < 20 ? 10000 : open < 70 ? 1000 : 100; if (lastSavedDate == null || lastSavedDate.Value != curDay) { lastSavedDate = curDay; currentStream.WriteLine(lastSavedDate.Value.ToString("ddMMyyyy"), curDay); } currentStream.WriteLine("{0} {1} {2}", candle.timeOpen.ToString("HHmm"), candle.open.ToStringUniformPriceFormat(true), candle.GetHlcOffsetHEX16(pointCost)); } } finally { foreach (var stream in streams) stream.Value.Close(); } } }
public static CandleData ParseLine(string line, ref DateTime?date, int precision, ref CandleData previousCandle) { if (string.IsNullOrEmpty(line)) { return(null); } if (line.Length == 8) { try { date = DateTime.ParseExact(line, "ddMMyyyy", CultureInfo.InvariantCulture); } catch { } return(null); } if (!date.HasValue) { return(null); } var parts = line.Split(fileLineSeparators, StringSplitOptions.RemoveEmptyEntries); /*if (parts.Length != 3) * return null;*/ try { var hour = parts[0].Substring(0, 2).ToInt(); var minute = parts[0].Substring(2, 2).ToInt(); var time = date.Value.AddMinutes(minute + hour * 60); var open = parts[1].ToFloatUniform(); var hlc = parts[2]; var candle = new CandleData { open = open, timeOpen = time, timeClose = time.AddMinutes(1) }; if (hlc.Length == 6) { candle.MakeHlcFromOffsetHEX(hlc, precision); previousCandle = null; } else if (hlc.Length == 8) { candle.MakeHlcFromOffsetHEX16(hlc, precision); candle.close = candle.open; // default value if (previousCandle != null) { previousCandle.close = candle.open; previousCandle.high = Math.Max(previousCandle.high, candle.open); previousCandle.low = Math.Min(previousCandle.low, candle.open); } previousCandle = candle; } else // format error { candle.high = candle.open; candle.low = candle.open; candle.close = candle.open; } return(candle); } catch { return(null); } }