I have a selection function which rebalances every wednesday:
// Select S&P500 stocks only:
// Market capitalization must be greater than or equal to $6.1 billion USD
// Annual dollar value traded to float-adjusted market capitalization is greater than 1.0
// Minimum monthly trading volume of 250,000 shares in each of the six months leading up to the evaluation date
public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
{
//const decimal MarketCapitalization = 2100000000m;
//^not supported by Quantconnect;
const decimal DollarVolume = 20000000m;
if (!_rebalanceFlag) return Enumerable.Empty<Symbol>();
//https://www.barchart.com/
List<string> sp500StockList = new List<string>() { "A", ...}
// Market capitalization must be greater than or equal to $6.1 billion USD, Traded shares x Price
var filtered = from x in coarse
join SP500 in sp500StockList on x.Symbol.Value equals SP500
let momentums = _momentums.GetOrAdd(x.Symbol, sym => new MomentumSelectionData(MomentumWindow, StockMovingAverageWindow))
// Update returns true when the indicators are ready, so don't accept until they are
where momentums.Update(x.EndTime, x.Price)
&& momentums.AnnualizedSlope > 0
where x.DollarVolume >= DollarVolume &&
//x.Volume > 250000 &&
x.HasFundamentalData //&&
//x.Price > 20
//orderby x.DollarVolume descending
orderby momentums.AnnualizedSlope descending
select x;
var topCoarse = filtered.Take(_universeSelectMaxStocks);
return topCoarse.Select(x => x.Symbol);
}
and a selection function:
// class used to improve readability of the coarse selection function
// href https://www.quantconnect.com/forum/discussion/1233/portfolio-optimization-with-mathnet-numerics
private class MomentumSelectionData
{
public readonly AnnualizedExponentialSlopeIndicator AnnualizedSlope;
public readonly ExponentialMovingAverage MovingAverage;
public readonly AverageTrueRange AverageTrueRange;
public MomentumSelectionData(int AnnualizedSlopeWindow, int movingAverageWindow)
{
AnnualizedSlope = new AnnualizedExponentialSlopeIndicator(AnnualizedSlopeWindow);
MovingAverage = new ExponentialMovingAverage(movingAverageWindow);
AverageTrueRange = new AverageTrueRange(ATRWindowSize, MovingAverageType.Exponential);
}
// updates the indicators, returning true when they're both ready
public bool Update(DateTime time, decimal value)
{
return AnnualizedSlope.Update(time, value) && MovingAverage.Update(time, value);
}
}
I need the ATR in the position sizing. As the coarsefunction returns multiple symbols I was thinking about adding the ATR to the coarsfunction, but it needs a Tradebar. How to do that? In case that ATR is there it will be calculated over and over again while it is only required to calculate the position size. Is there a way to call the ATR on the fly on an ondata event and get also data from the past?
Michael Manus
hm i think thats a too complicated approach
check this maybe it will help you,.....instead of ema add atr
Quant Trader
Hi, I looked into that and implemented that. See code above. However, the ATR does not support Update() as it needs a tradebar instead of slice data.
Update(DateTime time, decimal value)
If I can implement this that would be fine. I am only wondering that I only need this parameter for 30 tradeable stock later in my sample and this will calculate 500 potential tradeble SP500 universe items. For that reason I was looking to speed up the algo by only calculation the ATR for the 30 tradables that have been selected on the highest momentum form the SP500.
I can go either both ways, the one you suggest requires a tradebar I do not know how to provide. Maybe you can give me a heads up.
Quant Trader
This is the error message:
Runtime Error: System.NotSupportedException: AverageTrueRange does not support Update(DateTime, decimal) method overload. Use Update(IBaseDataBar) instead.
Quant Trader
I do not find the solution very tidy, I implemented this and I am verifying if this is oke:
/// <summary> /// Raises the data event. /// </summary> /// <param name="data">Data.</param> public void OnData(TradeBars data) { foreach (var bar in data.Values) { //validate that the security is in the universe if (!_momentums.ContainsKey(bar.Symbol)) { Log(string.Format("Symbol: {0} not found.", bar.Symbol)); continue; } _momentums[bar.Symbol].AverageTrueRange.Update(bar); } }
Quant Trader
For some reason, my indicators are not initialized. The AnnualizedSlope does, but the other two not in the coarse function. I do not see what is wrong. Takes a year to warmup.
Quant Trader
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!