CandleSeries и WeightedIndexSecurity
Умеет ли CandleSeries работать с BasketSecurity и его производными (например, WeightedIndexSecurity)? Теста ради написал простой обработчик свечек (см. ниже). Если в этом коде в строке
Код
_series = new CandleSeries(typeof(TimeFrameCandle), Security, TimeFrame)
в качестве Security использовать WeightedIndexSecurity, то _series всегда будет пустым. При этом новые свечки в обработчик приходят исправно, и строка _message заполняется данными, которые выводятся в лог. SMA также рассчиывается (под отладчиком видно некоторые осмысленные значения), однако корректность расчета пока не проверял - для начала хочется уяснить про CandleSeries.
Если в качестве Security указать обыкновенный инструмент (т.е. StockSharp.BusinessEntities.Security) - _candles заполняется отлично.
Вопрос: умеет ли CandleSeries работать с WeightedIndexSecurity? Для чего это надо - например, к арбитражной стратегии прикрутить скользящую среднюю. Удобнее всего это делать через свечки, да и унификации хочется с кодом, который работает с единичными инструментами.
Собственно, код:
Код
class WeightedSmaCandleStrategy : BasePortfolioStrategy
{
public TimeSpan TimeFrame { get; set; }
public int Length;
private CandleSeries _series;
DateTime strategyStartTime;
private SimpleMovingAverage Sma;
protected override void OnStarted()
{
if (TimeFrame == null)
throw new ApplicationException("Не задан таймфрейм!");
if (Length <= 0)
throw new ApplicationException("Не задан период скользящей средней!");
strategyStartTime = DateTime.Now;
base.OnStarted();
Sma = new SimpleMovingAverage() { Length = Length };
_series = new CandleSeries(typeof(TimeFrameCandle), Security, TimeFrame); // Если Security - это WeightedIndexSecurity, то _series не заполняется
_series.WorkingTime = WorkingTime;
_series
.WhenCandlesFinished()
.Do(ProcessCandle)
.Apply(this);
TraderBuilder.CandleManager.Start(_series);
}
private void ProcessCandle(Candle candle)
{
// если наша стратегия в процессе остановки
if (ProcessState == ProcessStates.Stopping)
{
// отменяем активные заявки
CancelActiveOrders();
return;
}
bool _canTrade = true;
Sma.Process(candle);
string _message;
// Исторические свечки просто запоминаем
if (candle.CloseTime < StartedTime)
{
_message = string.Format("Историческая свечка: Time: {0} O:{1} H:{1} L:{2} C:{3}", candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice);
_canTrade = false;
//return;
}
else
_message = string.Format("Реальная свечка: Time: {0} O:{1} H:{1} L:{2} C:{3}", candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice);
var _seriesCount = _series.GetCandleCount(); // В случае с WeightedIndexSecurity здесь всегда возвращается 0
var _smaValue = Sma.GetCurrentValue();
if (_seriesCount < Length)
{
//this.AddInfoLog(string.Format("GetCandleCount < Length. GetCandleCount = {0} Length = {1}", _seriesCount, Length));
//return;
_canTrade = false;
}
else
{
_message = string.Concat(_message, string.Format(" SMA={0}", _smaValue));
}
this.AddInfoLog(_message);
var _previousCandle = _series.GetCandle<TimeFrameCandle>(1);
if (_previousCandle != null)
{
if (candle.ClosePrice > _smaValue && _previousCandle.ClosePrice < _smaValue)
{
this.AddInfoLog("Пересечение снизу! CC={0} PC={1} SMA={2}", candle.ClosePrice, _previousCandle.ClosePrice, _smaValue);
if (_canTrade)
{
var _buyOrder = new Order()
{
Type = OrderTypes.Market,
Direction = OrderDirections.Buy,
Volume = Position != 0 ? 2 : 1
};
RegisterOrder(_buyOrder);
}
}
if (candle.ClosePrice < _smaValue && _previousCandle.ClosePrice > _smaValue)
{
this.AddInfoLog("Пересечение сверху! CC={0} PC={1} SMA={2}", candle.ClosePrice, _previousCandle.ClosePrice, _smaValue);
if (_canTrade)
{
var _sellOrder = new Order()
{
Type = OrderTypes.Market,
Direction = OrderDirections.Sell,
Volume = Position != 0 ? 2 : 1
};
RegisterOrder(_sellOrder);
}
}
}
}