Back

Question about Universe + History

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

Update Backtest








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);
}
}
1

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.


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

0

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);
}
}

 

0

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.


That one seems a little more 'elegant'.  Thanks.

0

Update Backtest





0

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.


Loading...

This discussion is closed