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?