I am using the dataloader to load all ticks for the bar that I am currently evaluating. Additionally, I am converting this to a lambda series so that it can be referenced through indicators who take iseries. Nice undocumented feature of the API.
There is a problem here. If you load the volume indicator which operates off of the bars stored volume and compute against the tick volume they do not match. The reason for this is that the bars in this case (range bars) could overlap in ticks. i.e. The end time of the previous bar and start time of the current bar could share ticks that happen in the same second.
Internally MC makes use of TickID to distinguish ticks that happen on the same second. This should somehow be used here. Perhaps a property of Bars.TickIdStart[barsAgo] and Bars.TickIdEnd[barsAgo] needs to be added? Otherwise it appears to be impossible to get your tick data to match your bar data. This is a big issue for tick precise indicators.
Code: Select all
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Linq;
using PowerLanguage.Function;
namespace PowerLanguage.Indicator{
public class _Test : IndicatorObject {
public _Test(object _ctx):base(_ctx){}
private IPlotObject plot1;
private ISeries<float> barVolume;
private ManualResetEventSlim _waitHandler = new ManualResetEventSlim(false);
private List<Bar[]> tickBuckets = new List<Bar[]>();
protected override void Create() {
// create variable objects, function objects, plot objects etc.
plot1 = AddPlot(new PlotAttributes("", EPlotShapes.Line, Color.Red));
}
protected override void StartCalc() {
barVolume = new Lambda<float>(barsBack =>
{
int index = tickBuckets.Count - 1 - barsBack;
return index < 0 ? 0 : tickBuckets[index].Sum(tick => tick.TotalVolume);
});
}
protected override void CalcBar() {
Bar[] bars = null;
if (Bars.CurrentBar > 1)
{
InstrumentDataRequest req = Bars.Request;
req.Resolution.Size = 1;
req.Resolution.Type = EResolution.Tick;
req.From = Bars.Time[1];
req.To = Bars.TimeValue;
_waitHandler.Reset();
IDataLoaderResult result = DataLoader.BeginLoadData(req, r => { if (r.IsCompleted) _waitHandler.Set(); }, null);
_waitHandler.Wait();
tickBuckets.Add(result.Data);
DataLoader.EndLoadData(result);
}
plot1.Set(barVolume.Value);
}
}
}