Accessing data bigger than 2000 bars isn't guaranteed during
Hi all!
I'm getting this error backtesting a strategy that uses HistoricalData as BarData:
Accessing data bigger than 2000 bars isn't guaranteed during backtest
I suppose the offending statement is the following:
BarData historicalData = GetHistoricalData( new HistoricalDataRequest(Instruments.Current, Period.Min)) as BarData;
I understand the error/warning but I haven't figured out a way to limit/slice the amount of data to retrieve.
Let me explain what I am trying to accomplish just in case I am not using the proper method:
I need to get the slice of bars between two dates. Put in code, something like this:
public IEnumerable<Bar> GetBars(int minutes, DateTime fromTime, DateTime toTime)
I have found a method to get the historical index from a date:
int fromIndex = historicalData.FindInterval(fromTime)
But I need the HistoricalData object to be created before anyway so it doesn't seem to help much.
Any idea about how to get/slice a segment of the historical data line?
Thanks!
HI dreyes,
Thanks for using NETScript. I haven't tested this on my end. I believe this may solve the problem you're having.
using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Drawing; using PTLRuntime.NETScript; namespace LoadExamples { public class LoadExamples : NETStrategy { public override void Init() { Instrument inst = Instruments.Current; HistoricalData Hist = GetHistoricalData(new HistoricalDataRequest(inst, Period.Day)); DateTime date_from = new DateTime(2014, 06, 16); DateTime date_to = DateTime.Now; Hist.Load(date_from, date_to); } }
You can also visit the link. I guess you can use multiple Load() methods and have them nested into if-statements. Let the first one be true and remain true until your strategy gets past the range. Then, let the second become true and remain true until its range is complete. You can continue this pattern. The FindInterval() looks promising for using it to see if you should load up another set of data.
If this doesn't work, I hope that it would at least get you closer to accomplishment. And as Alexey said previously, anything that you find inconvenient, bring it to PFSoft attention. I guess you can ask for them to do more than 2000 bars. It would probably be safer to clear the data not used, but I didn't see a method for that. I would personally just keep my code the same and just run smaller ranges. It is hard for me to say how my code recommendation is going to act, if I never tried it. But running in smaller ranges and calculating all the results would be the safest, but it can get tedious quickly.
Thanks again.
Hi! You can deal with bars range in this way.
Instrument instr = Instruments.Current; HistoricalDataRequest req = new HistoricalDataRequest(instr, Period.Hour); HistoricalData hd = GetHistoricalData(req); DateTime fromDate = DateTime.Today.AddDays(-1), toDate = fromDate.AddHours(10); hd.Load(fromDate); int from = hd.Count - hd.FindInterval(fromDate); int to = hd.Count - hd.FindInterval(toDate); Print(String.Format("fromDate: {0} | toDate: {1}", fromDate, toDate)); Print(" |bar | time | high"); for (int i = from; i >= to; i--) { Print(String.Format(" | {0} | {1} | {2}", i, hd.Time(i), hd.GetPrice(PriceType.High, i))); }
Unfortunately, its won't working in backtester. In backtester, we always getting an empty historical data at the start.
BTW Appeal to Protrader developers. Now the FindInterval() method returns an index as opposed to historical data direction, and in order to get proper index we have to do like in code above int from = hd.Count - hd.FindInterval(fromDate); .It would be a more convenient to get a proper index directly.
Thanks guys for your help!
In my actual code I don't even use Load method. It doesn't seem to do anything (at least in backtesting). I already tried this method to limit the data to load. But at least in backtesting it doesn't work. I get all the data since the time the backtesting started.
Calling GetHistoricalData already loads the data. You can check that historicalData object already has data even before the Load was executed.
This:
BarData historicalData = GetHistoricalData(new HistoricalDataRequest(Instruments.Current, Period.Min)) as BarData; Print(historicalData.Count)
and this:
BarData historicalData = GetHistoricalData(new HistoricalDataRequest(Instruments.Current, Period.Min)) as BarData; historicalData.Load(fromTime); Print(historicalData.Count)
do the same: Loads all the data available. Not data starting from fromTIme. So it looks liike Load is "useless".
So... No way to limit the amount of requested data (at least in backtesting). Maybe I can just ignore this message because the data I need is always inside the last 2000 bars. So I assume that at least I can rely on these last 2000 bars are guaranteed to be correct, right?
BTW:
@William The link just redirects me to this post again. Like a endless recursive link ;).
@Konstantin Yep, I had the same WTF with the index returned by FindInterval. I just figured out debugging the code :).
Just in case you are interested, below is the method I am trying to create:
public struct Candle { public double open; public double close; public double high; public double low; } public IEnumerable<Candle> GetCandles(int minutes, DateTime fromTime, DateTime toTime) { BarData historicalData = GetHistoricalData(new HistoricalDataRequest(Instruments.Current, minutes)) as BarData; // historicalData.Load(fromTime); // historicalData.Load(fromTime, toTime); // historicalData.Count - 1 to get the last index (0-based). int lastIndex = historicalData.Count - 1; // Get the index corresponding to the "from" time. // If we don't have such old data get the first available one, that is, // the 0 index that corresponds to the oldest available data. int fromIndex = Math.Max(historicalData.FindInterval(fromTime), 0); // Get the index corresponding to the "to" time. // If we don't have such new data get the last available one, that is, // the last index that corresponds to the newest available data. int to = historicalData.FindInterval(toTime); int toIndex = to != -1 ? to : lastIndex; for (int i = fromIndex; i <= toIndex; i++) { yield return new Candle { open = historicalData.Open(lastIndex - i), close = historicalData.Close(lastIndex - i), high = historicalData.High(lastIndex - i), low = historicalData.Low(lastIndex - i) }; } }