на 4.1.6 воспроизводится.
public class RangeHLCandleBuilder : CandleBuilder<RangeHLCandle>
{
private decimal prevClose = 0;
public RangeHLCandleBuilder()
{
this.Container.ValuesKeepTime = new TimeSpan(1,0,0,0);
}
public RangeHLCandleBuilder(ICandleBuilderContainer container) : base(container)
{}
protected override RangeHLCandle CreateCandle(StockSharp.Algo.Candles.CandleSeries series, ICandleBuilderSourceValue value)
{
RangeHLCandle candle = new RangeHLCandle
{
Range = (decimal) series.Arg
};
FirstInitCandle(series, candle, value);
candle.OpenTime = value.Time;
candle.CloseTime = value.Time;
candle.LowTime = value.Time;
if (prevClose == 0)
return candle;
candle.OpenPrice = prevClose;
this.AddInfoLog(String.Format("Created, Open = {0}", candle.OpenPrice));
return candle;
}
public override IEnumerable<Range<DateTime>> GetSupportedRanges(CandleSeries series)
{
IEnumerable<Range<DateTime>> supportedRanges = base.GetSupportedRanges(series);
if (!supportedRanges.IsEmpty())
{
if (!(series.Arg is decimal))
{
throw new ArgumentException();
}
if (((decimal)series.Arg) <= 0)
{
throw new ArgumentOutOfRangeException();
}
}
return supportedRanges;
}
protected override bool IsCandleFinishedBeforeChange(CandleSeries series, RangeHLCandle candle, ICandleBuilderSourceValue value)
{
int i = this.Container.GetValues(series, candle).Count();
if (i == 0)
{
int k = 2/i; //проверка на дефект
}
bool firstCandle = ((candle.HighPrice - candle.LowPrice) > (decimal) candle.Arg) &&
(series.GetCandles<RangeHLCandle>().Count() == 1);
bool nextCandle = (Math.Abs(candle.OpenPrice - candle.ClosePrice) >= (decimal) candle.Arg) &&
(series.GetCandles<RangeHLCandle>().Count() > 1);
bool byDate = candle.LowTime.Date != candle.CloseTime.Date;
if ( firstCandle || nextCandle || byDate)
{
prevClose = candle.ClosePrice;
return true;
}
return false;
}
protected override void UpdateCandle(CandleSeries series, RangeHLCandle candle, ICandleBuilderSourceValue value)
{
base.UpdateCandle(series, candle, value);
candle.LowTime = candle.CloseTime;
candle.CloseTime = value.Time;
}
}
метод для создания сделок из файла:
public static List<Trade> MakeDealsFromHistory(string file)
{
List<Trade> trades = new List<Trade>();
using (StreamReader sr = new StreamReader(file))
{
String line;
int i = 0;
while ((line = sr.ReadLine()) != null)
{
if (line == "<TICKER>;<PER>;<DATE>;<TIME>;<CLOSE>;<VOL>")
continue;
i++;
string[] lines = line.Split(';');
Trade trade = new Trade
{
Id = i,
Price = Convert.ToDecimal(lines[4]),
Volume = Convert.ToInt32(lines[5])
};
trade.Time = new DateTime(Convert.ToInt32(lines[2].Substring(0, 4)),
Convert.ToInt32(lines[2].Substring(4, 2)),
Convert.ToInt32(lines[2].Substring(6, 2)),
Convert.ToInt32(lines[3].Substring(0, 2)),
Convert.ToInt32(lines[3].Substring(2, 2)),
Convert.ToInt32(lines[3].Substring(4, 2))
);
trades.Add(trade);
}
}
return trades;
}
файл со сделками прикреплю к посту.
Заметил, что с Container.ValuesKeepTime равным дню свечи очень долго строятся. Чем меньше Container.ValuesKeepTime, тем быстрее строятся. на Container.ValuesKeepTime = 1 минута баг возникает очень быстро.