I am applying the selection algorithm in the snippet below, but I am getting a compilation error on the line that is supposed to take the price-filtered list and apply EMA filtering to it (the line that begins with var EMALong, towards the end).
I've tried understanding what's wrong and suspect it's some kind of a type mismatch issue, though i can't put my finger on it. Can anyone take a look and give a poor C# noob a help?
public class UniverseSelectionADX : QCAlgorithm {
private const int NumberOfSymbols = 10;
private const decimal AllocationProportion= 0.1m;
private readonly ConcurrentDictionary<Symbol, EMASelection> EMASelectionData = new ConcurrentDictionary<Symbol, EMASelection>(); //defines a dictionary: EMASelectionData
private class EMASelection{ //function to handle selection by EMA
public readonly ExponentialMovingAverage Fast;
public readonly ExponentialMovingAverage Slow;
public EMASelection(){
Fast = new ExponentialMovingAverage(9);
Slow = new ExponentialMovingAverage(21);
}
public decimal ScaledDelta{ //calculates the proportion of ema delta
get { return (Fast - Slow)/((Fast + Slow)/2m); }
}
public bool Update(DateTime time, decimal value){ // updates the EMA indicators, returning true when they're both ready
return Fast.Update(time, value) && Slow.Update(time, value);
}
}
SecurityChanges _changes = SecurityChanges.None; // initialize our changes to nothing
public override void Initialize() {
UniverseSettings.Leverage = 2.0m;
UniverseSettings.Resolution = Resolution.Daily;
SetStartDate(2014, 01, 01);
SetEndDate(2015, 01, 01);
SetCash(20000);
AddUniverse(CoarseSelectionFunction); // this add universe method accepts a single parameter that is a function that accepts an IEnumerable<CoarseFundamental> and returns IEnumerable<Symbol>
}
public static IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) { // sort the data by daily dollar volume and take the top 'NumberOfSymbols'
var filteredByPrice = coarse.Where(x => (x.Price > 15m) && (x.Price < 150m)); //filter out stocks by price
var EMALong = EMASelectionData.GetOrAdd(filteredByPrice(x => x.Symbol), selectionF => new EMASelection());
// var EMAFiltered = filteredByPrice;
var sortedByDollarVolume = filteredByPrice.OrderByDescending(x => x.DollarVolume); // sort descending by daily dollar volume
var topEntries = sortedByDollarVolume.Take(NumberOfSymbols); // take the top entries from our sorted collection
return topEntries.Select(x => x.Symbol); // return only the symbol objects
}
Wink Saville
Eyal,
I'm a noob too so take this with a HUGE grain of salt, but remvoing the static from CoarseSelectionFunction and looping over the GetOrAdd makes it compile for me:
public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) { var filteredByPrice = coarse.Where(x => (x.Price > 15m) && (x.Price < 150m)); foreach (var entry in filteredByPrice) { var EMALong = EMASelectionData.GetOrAdd(entry.Symbol, selectionF => new EMASelection()); } var sortedByDollarVolume = filteredByPrice.OrderByDescending(x => x.DollarVolume); var topEntries = sortedByDollarVolume.Take(NumberOfSymbols); return topEntries.Select(x => x.Symbol); }
If you want CoarseSelectionFunction to be static then EMASelectionData needs to be static, i.e. they both need to be static or non-static. As far as I can tell GetOrAdd must take a Symbol directly not an IEnumerable so adding the foreach we manually iterate over the result and invoke GetOrAdd.
Again, this all could be totally wrong :)
-- Wink
Eyal Netanel
Thanks, Wink.
Regarding the second part of your reply, The idea was to have a dictionary named EMALong as a result of that statement. by using it as a local variable inside the forwach statement like you did, it doesn't exist afterwards (and can't for example, be logged) - so in fact i'm not sure what the new statement you wrote does, but I guess it's not what I meant :-)
Please let me know if there's another idea you think I can explore - and thanks again for trying to help!
Wink Saville
Since EMASelectionData is a member of the UniverseSelectionADX class are you trying to accumulate the results or across multiple invcations of CoarseSelectionFuntion? if so then just remove the var EMALong:
foreach (var entry in filteredByPrice) { EMASelectionData.GetOrAdd(entry.Symbol, selectionF => new EMASelection()); }
If you want the results just locally then maybe you'll want to create a local instance of Dictionary<Symbol, EMASelection> and use Add instead of GetOrAdd, maybe something like:
Dictionary<Symbol, EMASelection> dict = new Dictionary<Symbol, EMASelection>(); foreach(var kvp in filteredByPrice) { dict.Add(kvp.Symbol, new EMASelection()); }
So I'm not sure what trying to do, probably none of the above :)
Wink Saville
Eyal Netanel, I'm interested to know if you find a solution?
Eyal Netanel
Thanks for checking - I probably won't have much "quality time" till the weekend to dive into it, but I did fork my thoughts to trying and calculating the indicators OnData instead of defining it as a filter on the universe selection in the initialization - but for some reason when i do things like that (see below) i get all the indicators calculate to be 0 - so i'm not sure if i'm doing it right. (I know I'm jumping to a whole different technique here, but for the time was easier for me to grasp that thought than to dive into further coarse selection attempts:
public void OnData(TradeBars data) { //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. if (_changes == SecurityChanges.None) return; // if we have no changes, do nothing foreach (var security in _changes.AddedSecurities) { // Set allocation to qualifying securities in our universe var adx = new AverageDirectionalIndex("ADX14", 14); var ema9 = EMA(security.Symbol, 9); var ema21 = EMA(security.Symbol, 21); Log("security:"+security.Symbol+" ADX:"+adx+" ema9: "+ema9+" ema21: "+ema21+" p");
The log prints the securities that were previously selected (now only filtered by price and volume) - but they all have 0.0 for adx and ema - - so i guess i'm using it wrong here as well.
The general idea, in case i didn't mention, was to try and use a combination of ema and adx in selecting trending shares at the basis of the algorithm, and then keep improving from there. It's just that i can't seem to make the bbasic part work either in the universe selection or on Data, despite a few code examples i've seen and already some help from you and from Alexandre on another thread... :-( .
/Feeling a bit stupid/
I'll try again when my head is clearer of work and errands, though of course any kind of help is more than welcome.
Thanks!
Wink Saville
It's beyond me for now, I'll be watching what happens :)
Eyal Netanel
This is just to update that I went along with a solution similar to your second soolution - and it seems to have worked so Thanks!
Now on to handling the next brick wall :-)
Wink Saville
Nice, glad it helped. But as you said, there seems to always be another issue just around the bend :)
Eyal Netanel
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!