I think I know how to get history during OnData while using a universe. However I would like to know which is the 'best' way in terms of efficiency / speed.
So for example:
1) Daily the stocks change (default universe setting)
2) Each day I would like to analyze each stock's daily history going back X days (on the order of months)
Because I'm using a universe I can't simply do a warmup and save the data manually. I am aware of the built-in indicators (like EMA etc) so if it could be made clear how to create my own indicator, that would be a good answer to this as well.
Thanks
Alexandre Catarino
One possible solution for your demand is creating a class to save (and update) the data. Normally, you don't need to save the whole history, only use it to update an indicator.
We can use the class to keep the last time the indicator was updated and call the History method to fetch data for the period that is missing:
private class SelectionData { public static int MinPeriod = 100; public static int MaxPeriod = 300; public DateTime LastUpdateDate; public readonly ExponentialMovingAverage Fast; public readonly ExponentialMovingAverage Slow; public SelectionData() { Fast = new ExponentialMovingAverage(MinPeriod); Slow = new ExponentialMovingAverage(MaxPeriod); } // updates the EMA100 and EMA300 indicators, // returning true when they're both ready public bool Update(DateTime time, decimal value) { LastUpdateDate = time; return Fast.Update(time, value) && Slow.Update(time, value); } }
In OnData, we loop through the symbols that were added and update the indicators, fetching only the history we need.
public void OnData(TradeBars data) { if (_changes == SecurityChanges.None) return; foreach (var security in _changes.AddedSecurities) { var last = _averages[security.Symbol].LastUpdateDate; var spanDays = Math.Min( SelectionData.MaxPeriod, (Time - last).Days ); if (spanDays > 0) { var history = History(security.Symbol, spanDays, Resolution.Daily); foreach(var bar in history) { _averages[security.Symbol] .Update(bar.EndTime, bar.Close); } } _averages[security.Symbol] .Update(Time, data[security.Symbol].Close); } }
Aaron Greenhill
Thanks Alexandre. The essential thing I'm seeing here is that you're calling the History function for each symbol during each OnData (only asking for what's missing). I knew this was an option but wasn't sure if it was a good way to do it... if you think so then I'll try it out. Thanks
Alexandre Catarino
Alternatively you move the logic that uses the History method into the OnSecuritiesChanged event handler:
public override void OnSecuritiesChanged(SecurityChanges changes) { _changes = changes; foreach (var security in _changes.AddedSecurities) { var last = _averages[security.Symbol].LastUpdateDate; var spanDays = Math.Min( SelectionData.MaxPeriod, (Time - last).Days ); if (spanDays > 0) { var history = History(security.Symbol, spanDays, Resolution.Daily); foreach(var bar in history) { _averages[security.Symbol] .Update(bar.EndTime, bar.Close); } } } }
In this case, we cannot update the indicators with the current data that arrives in OnData. For that, we would need to code:
public void OnData(TradeBars data) { if (_changes == SecurityChanges.None) return; foreach (var security in _changes.AddedSecurities) { _averages[security.Symbol] .Update(Time, data[security.Symbol].Close); } }
Aaron Greenhill
That one seems a little more 'elegant'. Thanks.
Aaron Greenhill
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!