/// <summary> /// take candles by instrument /// взять свечи по инструменту /// </summary> /// <param name="security"> short security name/короткое название бумаги</param> /// <param name="timeSpan">timeframe/таймФрейм</param> /// <returns>failure will return null/в случае неудачи вернётся null</returns> public List <Candle> GetQuikLuaCandleHistory(Security security, TimeSpan timeSpan) { try { lock (_getCandlesLocker) { if (timeSpan.TotalMinutes > 1440 || timeSpan.TotalMinutes < 1) { return(null); } CandleInterval tf = CandleInterval.M5; if (Convert.ToInt32(timeSpan.TotalMinutes) == 1) { tf = CandleInterval.M1; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 2) { tf = CandleInterval.M2; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 5) { tf = CandleInterval.M5; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 10) { tf = CandleInterval.M10; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 15) { tf = CandleInterval.M15; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 20) { tf = CandleInterval.M20; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 30) { tf = CandleInterval.M30; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 60) { tf = CandleInterval.H1; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 120) { tf = CandleInterval.H2; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 240) { tf = CandleInterval.H4; } else if (Convert.ToInt32(timeSpan.TotalMinutes) == 1440) { tf = CandleInterval.D1; } #region MyRegion _candles = null; var needSec = security; if (needSec != null) { _candles = new List <Candle>(); string classCode = needSec.NameClass; var allCandlesForSec = QuikLua.Candles.GetAllCandles(classCode, needSec.Name.Split('_')[0], tf).Result; for (int i = 0; i < allCandlesForSec.Count; i++) { if (allCandlesForSec[i] != null) { Candle newCandle = new Candle(); newCandle.Close = allCandlesForSec[i].Close; newCandle.High = allCandlesForSec[i].High; newCandle.Low = allCandlesForSec[i].Low; newCandle.Open = allCandlesForSec[i].Open; newCandle.Volume = allCandlesForSec[i].Volume; if (i == allCandlesForSec.Count - 1) { newCandle.State = CandleState.None; } else { newCandle.State = CandleState.Finished; } newCandle.TimeStart = new DateTime(allCandlesForSec[i].Datetime.year, allCandlesForSec[i].Datetime.month, allCandlesForSec[i].Datetime.day, allCandlesForSec[i].Datetime.hour, allCandlesForSec[i].Datetime.min, allCandlesForSec[i].Datetime.sec); _candles.Add(newCandle); } } } #endregion return(_candles); } } catch (Exception error) { SendLogMessage(error.ToString(), LogMessageType.Error); return(null); } }
private void UpDateTickTimeFrame(DateTime time, decimal price, decimal volume, bool canPushUp) { if (CandlesAll != null && CandlesAll.Count > 0 && CandlesAll[CandlesAll.Count - 1] != null && CandlesAll[CandlesAll.Count - 1].TimeStart > time) {// если пришли старые данные return; } if (CandlesAll == null) { // пришла первая сделка CandlesAll = new List <Candle>(); DateTime timeNextCandle = time; if (_timeFrameSpan.TotalMinutes >= 1) { timeNextCandle = time.AddSeconds(-time.Second); while (timeNextCandle.Minute % _timeFrameSpan.TotalMinutes != 0) { timeNextCandle = timeNextCandle.AddMinutes(-1); } while (timeNextCandle.Second != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } else { while (timeNextCandle.Second % _timeFrameSpan.TotalSeconds != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle candle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleStates.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(candle); if (canPushUp) { UpdateChangeCandle(); } _lastCandleTickCount = 1; return; } if (CandlesAll != null && _lastCandleTickCount >= _countTickInCandle) { // если пришли данные из новой свечки if (CandlesAll[CandlesAll.Count - 1].State != CandleStates.Finished) { // если последнюю свечку ещё не закрыли и не отправили CandlesAll[CandlesAll.Count - 1].State = CandleStates.Finished; if (canPushUp) { UpdateFinishCandle(); } } DateTime timeNextCandle = time; while (timeNextCandle.Second % _timeFrameSpan.TotalSeconds != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle newCandle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleStates.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(newCandle); if (canPushUp) { UpdateChangeCandle(); } _lastCandleTickCount = 1; return; } if (CandlesAll != null && _lastCandleTickCount < _countTickInCandle) { // если пришли данные внутри свечи _lastCandleTickCount++; CandlesAll[CandlesAll.Count - 1].Volume += volume; CandlesAll[CandlesAll.Count - 1].Close = price; if (CandlesAll[CandlesAll.Count - 1].High < price) { CandlesAll[CandlesAll.Count - 1].High = price; } if (CandlesAll[CandlesAll.Count - 1].Low > price) { CandlesAll[CandlesAll.Count - 1].Low = price; } if (canPushUp) { UpdateChangeCandle(); } } }
/// <summary> /// build candles /// собрать свечи /// </summary> /// <param name="oldCandles"></param> /// <param name="needTf"></param> /// <param name="oldTf"></param> /// <returns></returns> private List <Candle> BuildCandles(List <Candle> oldCandles, int needTf, int oldTf) { List <Candle> newCandles = new List <Candle>(); int index; if (needTf == 120) { index = oldCandles.FindIndex(can => can.TimeStart.Hour % 2 == 0); } else if (needTf == 1440) { index = oldCandles.FindIndex(can => can.TimeStart.Hour == 10 && can.TimeStart.Minute == 0 && can.TimeStart.Second == 0); for (int i = index; i < oldCandles.Count; i++) { if (oldCandles[i].TimeStart.Hour == 10 && oldCandles[i].TimeStart.Minute == 0 && oldCandles[i].TimeStart.Second == 0) { if (newCandles.Count != 0) { newCandles[newCandles.Count - 1].State = CandleState.Finished; } newCandles.Add(new Candle()); newCandles[newCandles.Count - 1].State = CandleState.None; newCandles[newCandles.Count - 1].Open = oldCandles[i].Open; newCandles[newCandles.Count - 1].TimeStart = oldCandles[i].TimeStart; newCandles[newCandles.Count - 1].Low = Decimal.MaxValue; } if (newCandles.Count == 0) { continue; } newCandles[newCandles.Count - 1].High = oldCandles[i].High > newCandles[newCandles.Count - 1].High ? oldCandles[i].High : newCandles[newCandles.Count - 1].High; newCandles[newCandles.Count - 1].Low = oldCandles[i].Low < newCandles[newCandles.Count - 1].Low ? oldCandles[i].Low : newCandles[newCandles.Count - 1].Low; newCandles[newCandles.Count - 1].Close = oldCandles[i].Close; newCandles[newCandles.Count - 1].Volume += oldCandles[i].Volume; } return(newCandles); } else { index = oldCandles.FindIndex(can => can.TimeStart.Minute % needTf == 0); } int count = needTf / oldTf; int counter = 0; Candle newCandle = new Candle(); for (int i = index; i < oldCandles.Count; i++) { counter++; if (counter == 1) { newCandle = new Candle(); newCandle.Open = oldCandles[i].Open; newCandle.TimeStart = oldCandles[i].TimeStart; newCandle.Low = Decimal.MaxValue; } newCandle.High = oldCandles[i].High > newCandle.High ? oldCandles[i].High : newCandle.High; newCandle.Low = oldCandles[i].Low < newCandle.Low ? oldCandles[i].Low : newCandle.Low; newCandle.Volume += oldCandles[i].Volume; if (counter == count) { newCandle.Close = oldCandles[i].Close; newCandle.State = CandleState.Finished; newCandles.Add(newCandle); counter = 0; } if (i == oldCandles.Count - 1 && counter != count) { newCandle.Close = oldCandles[i].Close; newCandle.State = CandleState.Started; newCandles.Add(newCandle); } } return(newCandles); }
/// <summary> /// обновить свечи с обычным ТФ /// </summary> private void UpDateSimpleTimeFrame(DateTime time, decimal price, decimal volume, bool canPushUp) { //if (From > trade.Time) //{ // return; // } if (CandlesAll != null && CandlesAll.Count > 0 && CandlesAll[CandlesAll.Count - 1] != null && CandlesAll[CandlesAll.Count - 1].TimeStart > time) { // если пришли старые данные return; } if (CandlesAll == null) { // пришла первая сделка CandlesAll = new List <Candle>(); DateTime timeNextCandle = time; if (_timeFrameSpan.TotalMinutes >= 1) { timeNextCandle = time.AddSeconds(-time.Second); while (timeNextCandle.Minute % _timeFrameSpan.TotalMinutes != 0) { timeNextCandle = timeNextCandle.AddMinutes(-1); } while (timeNextCandle.Second != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } else { while (timeNextCandle.Second % _timeFrameSpan.TotalSeconds != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle candle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleStates.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(candle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll[CandlesAll.Count - 1].TimeStart.Add(_timeFrameSpan + _timeFrameSpan) <= time && _setForeign) { // произошёл пропуск данных в результате клиринга или перерыва в торгах SetForeign(time); } if (CandlesAll != null && CandlesAll[CandlesAll.Count - 1].TimeStart < time && CandlesAll[CandlesAll.Count - 1].TimeStart.Add(_timeFrameSpan) <= time || CandlesAll[CandlesAll.Count - 1].TimeStart.Day != time.Day) { // если пришли данные из новой свечки if (CandlesAll[CandlesAll.Count - 1].State != CandleStates.Finished) { // если последнюю свечку ещё не закрыли и не отправили CandlesAll[CandlesAll.Count - 1].State = CandleStates.Finished; if (canPushUp) { UpdateFinishCandle(); ; } } DateTime timeNextCandle = time; if (_timeFrameSpan.TotalMinutes >= 1) { timeNextCandle = time.AddSeconds(-time.Second); while (timeNextCandle.Minute % _timeFrameSpan.TotalMinutes != 0) { timeNextCandle = timeNextCandle.AddMinutes(-1); } while (timeNextCandle.Second != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } else { while (timeNextCandle.Second % _timeFrameSpan.TotalSeconds != 0) { timeNextCandle = timeNextCandle.AddSeconds(-1); } } while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle newCandle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleStates.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(newCandle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll != null && CandlesAll[CandlesAll.Count - 1].TimeStart <= time && CandlesAll[CandlesAll.Count - 1].TimeStart.Add(_timeFrameSpan) > time) { // если пришли данные внутри свечи CandlesAll[CandlesAll.Count - 1].Volume += volume; CandlesAll[CandlesAll.Count - 1].Close = price; if (CandlesAll[CandlesAll.Count - 1].High < price) { CandlesAll[CandlesAll.Count - 1].High = price; } if (CandlesAll[CandlesAll.Count - 1].Low > price) { CandlesAll[CandlesAll.Count - 1].Low = price; } if (canPushUp) { UpdateChangeCandle(); } } }
/// <summary> /// обновить свечи по объёму в свече /// </summary> private void UpDateVolumeTimeFrame(DateTime time, decimal price, decimal volume, bool canPushUp) { if (CandlesAll != null && CandlesAll.Count > 0 && CandlesAll[CandlesAll.Count - 1] != null && CandlesAll[CandlesAll.Count - 1].TimeStart > time) {// если пришли старые данные return; } if (CandlesAll == null) { // пришла первая сделка CandlesAll = new List <Candle>(); DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle candle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(candle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll != null && CandlesAll[CandlesAll.Count - 1].Volume >= _timeFrameBuilder.VolumeToCloseCandleInVolumeType) { // если пришли данные из новой свечки if (CandlesAll[CandlesAll.Count - 1].State != CandleState.Finished) { // если последнюю свечку ещё не закрыли и не отправили CandlesAll[CandlesAll.Count - 1].State = CandleState.Finished; if (canPushUp) { UpdateFinishCandle(); } } DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle newCandle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(newCandle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll != null) { // если пришли данные внутри свечи CandlesAll[CandlesAll.Count - 1].Volume += volume; CandlesAll[CandlesAll.Count - 1].Close = price; if (CandlesAll[CandlesAll.Count - 1].High < price) { CandlesAll[CandlesAll.Count - 1].High = price; } if (CandlesAll[CandlesAll.Count - 1].Low > price) { CandlesAll[CandlesAll.Count - 1].Low = price; } if (canPushUp) { UpdateChangeCandle(); } } }
/// <summary> /// обновить свечи с дельтой /// </summary> private void UpDateDeltaTimeFrame(DateTime time, decimal price, decimal volume, bool canPushUp, Side side) { // Формула кумулятивной дельты //Delta= ∑_i▒vBuy- ∑_i▒vSell if (CandlesAll != null && CandlesAll.Count > 0 && CandlesAll[CandlesAll.Count - 1] != null && CandlesAll[CandlesAll.Count - 1].TimeStart > time) {// если пришли старые данные return; } if (CandlesAll == null) { // пришла первая сделка CandlesAll = new List <Candle>(); DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle candle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(candle); if (canPushUp) { UpdateChangeCandle(); } return; } if (side == Side.Buy) { _currentDelta += volume; } else { _currentDelta -= volume; } if (CandlesAll != null && Math.Abs(_currentDelta) >= _timeFrameBuilder.DeltaPeriods) { // если пришли данные из новой свечки _currentDelta = 0; if (CandlesAll[CandlesAll.Count - 1].State != CandleState.Finished) { // если последнюю свечку ещё не закрыли и не отправили CandlesAll[CandlesAll.Count - 1].State = CandleState.Finished; if (canPushUp) { UpdateFinishCandle(); } } DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle newCandle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(newCandle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll != null) { // если пришли данные внутри свечи CandlesAll[CandlesAll.Count - 1].Volume += volume; CandlesAll[CandlesAll.Count - 1].Close = price; if (CandlesAll[CandlesAll.Count - 1].High < price) { CandlesAll[CandlesAll.Count - 1].High = price; } if (CandlesAll[CandlesAll.Count - 1].Low > price) { CandlesAll[CandlesAll.Count - 1].Low = price; } if (canPushUp) { UpdateChangeCandle(); } } }
private void UpDateRencoTimeFrame(DateTime time, decimal price, decimal volume, bool canPushUp) { if (CandlesAll != null && CandlesAll.Count > 0 && CandlesAll[CandlesAll.Count - 1] != null && CandlesAll[CandlesAll.Count - 1].TimeStart > time) {// если пришли старые данные return; } if (CandlesAll == null) { _rencoStartPrice = price; _rencoLastSide = Side.None; // пришла первая сделка CandlesAll = new List <Candle>(); DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle candle = new Candle() { Close = price, High = price, Low = price, Open = price, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(candle); if (canPushUp) { UpdateChangeCandle(); } return; } decimal renDist = _timeFrameBuilder.RencoPunktsToCloseCandleInRencoType; if ( (_rencoLastSide == Side.None && Math.Abs(_rencoStartPrice - price) >= renDist) || (_rencoLastSide == Side.Buy && price - _rencoStartPrice >= renDist) || (_rencoLastSide == Side.Buy && _rencoStartPrice - price >= renDist * 2) || (_rencoLastSide == Side.Sell && _rencoStartPrice - price >= renDist) || (_rencoLastSide == Side.Sell && price - _rencoStartPrice >= renDist * 2) ) { // если пришли данные из новой свечки Candle lastCandle = CandlesAll[CandlesAll.Count - 1]; if ( (_rencoLastSide == Side.None && price - _rencoStartPrice >= renDist) || (_rencoLastSide == Side.Buy && price - _rencoStartPrice >= renDist) ) { _rencoLastSide = Side.Buy; _rencoStartPrice = _rencoStartPrice + renDist; lastCandle.High = _rencoStartPrice; } else if ( (_rencoLastSide == Side.None && _rencoStartPrice - price >= renDist) || (_rencoLastSide == Side.Sell && _rencoStartPrice - price >= renDist) ) { _rencoLastSide = Side.Sell; _rencoStartPrice = _rencoStartPrice - renDist; lastCandle.Low = _rencoStartPrice; } else if ( _rencoLastSide == Side.Buy && _rencoStartPrice - price >= renDist * 2) { _rencoLastSide = Side.Sell; lastCandle.Open = _rencoStartPrice - renDist; _rencoStartPrice = _rencoStartPrice - renDist * 2; lastCandle.Low = _rencoStartPrice; } else if ( _rencoLastSide == Side.Sell && price - _rencoStartPrice >= renDist * 2) { _rencoLastSide = Side.Buy; lastCandle.Open = _rencoStartPrice + renDist; _rencoStartPrice = _rencoStartPrice + renDist * 2; lastCandle.High = _rencoStartPrice; } lastCandle.Close = _rencoStartPrice; if (_timeFrameBuilder.RencoIsBuildShadows == false) { if (lastCandle.IsUp) { lastCandle.Low = lastCandle.Open; lastCandle.High = lastCandle.Close; } else { lastCandle.High = lastCandle.Open; lastCandle.Low = lastCandle.Close; } } if (CandlesAll[CandlesAll.Count - 1].State != CandleState.Finished) { // если последнюю свечку ещё не закрыли и не отправили CandlesAll[CandlesAll.Count - 1].State = CandleState.Finished; if (canPushUp) { UpdateFinishCandle(); } } DateTime timeNextCandle = time; while (timeNextCandle.Millisecond != 0) { timeNextCandle = timeNextCandle.AddMilliseconds(-1); } Candle newCandle = new Candle() { Close = _rencoStartPrice, High = _rencoStartPrice, Low = _rencoStartPrice, Open = _rencoStartPrice, State = CandleState.Started, TimeStart = timeNextCandle, Volume = volume }; CandlesAll.Add(newCandle); if (canPushUp) { UpdateChangeCandle(); } return; } if (CandlesAll != null) { // если пришли данные внутри свечи CandlesAll[CandlesAll.Count - 1].Volume += volume; CandlesAll[CandlesAll.Count - 1].Close = price; if (CandlesAll[CandlesAll.Count - 1].High < price) { CandlesAll[CandlesAll.Count - 1].High = price; } if (CandlesAll[CandlesAll.Count - 1].Low > price) { CandlesAll[CandlesAll.Count - 1].Low = price; } if (canPushUp) { UpdateChangeCandle(); } } }
public static List <Candle> Merge(this List <Candle> oldCandles, List <Candle> candlesToMerge) { if (candlesToMerge == null || candlesToMerge.Count == 0) { return(oldCandles); } if (oldCandles.Count == 0) { oldCandles.AddRange(candlesToMerge); return(oldCandles); } if (candlesToMerge[0].TimeStart < oldCandles[0].TimeStart && candlesToMerge[candlesToMerge.Count - 1].TimeStart >= oldCandles[oldCandles.Count - 1].TimeStart) { // начало массива в новых свечках раньше. Конец позже. Перезаписываем полностью oldCandles.Clear(); oldCandles.AddRange(candlesToMerge); return(oldCandles); } // смотрим более ранние свечи в новой серии List <Candle> newCandles = new List <Candle>(); int indexLastInsertCandle = 0; for (int i = 0; i < candlesToMerge.Count; i++) { if (candlesToMerge[i].TimeStart < oldCandles[0].TimeStart) { newCandles.Add(candlesToMerge[i]); } else { indexLastInsertCandle = i; break; } } newCandles.AddRange(oldCandles); // обновляем последнюю свечку в старых данных if (newCandles.Count != 0) { Candle lastCandle = candlesToMerge.Find(c => c.TimeStart == newCandles[newCandles.Count - 1].TimeStart); if (lastCandle != null) { newCandles[newCandles.Count - 1] = lastCandle; } } // вставляем новые свечи в середину объединённого массива for (int i = indexLastInsertCandle; i < candlesToMerge.Count; i++) { Candle candle = candlesToMerge[i]; for (int i2 = 1; i2 < newCandles.Count - 1; i2++) { if (candle.TimeStart > newCandles[i2].TimeStart && candle.TimeStart < newCandles[i2 - 1].TimeStart) { newCandles.Insert(i2 + 1, candle); break; } } } // вставляем новые свечи в конец объединённого массива for (int i = 0; i < candlesToMerge.Count; i++) { Candle candle = candlesToMerge[i]; if (candle.TimeStart > newCandles[newCandles.Count - 1].TimeStart) { newCandles.Add(candle); } } oldCandles.Clear(); oldCandles.AddRange(newCandles); return(oldCandles); }