Your interactive trading laboratory!
 • 
23 users online

Ranking-Rulset by multiples of $10 and Price-Buckets

Months ago, I read about the TASC article "Swing Trading 10-Point Breakouts". First I thought there is no way this can work. This week however, I stumbled across the following article written by Cesar Alvarez: https://alvarezquanttrading.com/blog/monthly-rotation-closeness-to-10/

So I wonder if Quantacula offers the possibility to map the following ranking ruleset?

Rank stocks by closeness to price under a multiple of 10 Rank value = The remainder of Close divided by 10 Price Buckets = Under $50 - Between $50 and $100 - Over $100

Attachment

Cancel

Responses

Hi Merlin,

I read the article, and it was my impression that Cesar determined that the method, in the end, did not have much value. But of course something like this would be possible in Quantacula. I could see this working in this fashion:

  • Create a custom indicator to calculate the rank.
  • Perhaps include a parameter for the desired bucket, if a symbol was outside the bucket set the indicator value to zero for that bar.
  • Use your custom indicator in a monthly Rotation Model.

It struck me that the introduction of buckets was a needless complication meant to overcome the problem of using the fixed modulo value for assets of widely varying price. Why not just create an indicator that returns the percentage distance that closing price is from the next 10 point boundary? Such an indicator would let you get a cleaner run without the complexity of price buckets, and you could rank the whole universe.

Hi Merlin, I read the article, and it was my impression that Cesar determined that the method, in the end, did not have much value. But of course something like this would be possible in Quantacula. I could see this working in this fashion: * Create a custom indicator to calculate the rank. * Perhaps include a parameter for the desired bucket, if a symbol was outside the bucket set the indicator value to zero for that bar. * Use your custom indicator in a monthly Rotation Model. It struck me that the introduction of buckets was a needless complication meant to overcome the problem of using the fixed modulo value for assets of widely varying price. Why not just create an indicator that returns the percentage distance that closing price is from the next 10 point boundary? Such an indicator would let you get a cleaner run without the complexity of price buckets, and you could rank the whole universe.

Unfortunately I don't know how to calculate and sort a list of stocks in a "coded" indicator. The only way I know is the "coded" rotation model. Calculation and sorting for the the percentage distance that closing price is from the next 10 point boundary could be done in the PreExecute Method.

Unfortunately I don't know how to calculate and sort a list of stocks in a "coded" indicator. The only way I know is the "coded" rotation model. Calculation and sorting for the the percentage distance that closing price is from the next 10 point boundary could be done in the PreExecute Method.

Yes, the idea is you'd create a new indicator that you would then use as the weight factor in a standard Rotation Model.

Yes, the idea is you'd create a new indicator that you would then use as the weight factor in a standard Rotation Model.

Hi Glitch, on the BarHistory Object, there's a UserData property which allows to store ad-hoc data. How can I store multiple custom values like an indicator value and a bucket rank?

Hi Glitch, on the BarHistory Object, there's a UserData property which allows to store ad-hoc data. How can I store multiple custom values like an indicator value and a bucket rank?

Hi Merlin, take a look at the Cache property. It is a Dictionary<string, object> that you can use to store ad-hoc objects (keyed by name) in a BarHistory.

Hi Merlin, take a look at the **Cache** property. It is a Dictionary<string, object> that you can use to store ad-hoc objects (keyed by name) in a BarHistory.

Hi Glitch.

Unfortunately, I have not yet managed it to add a second value to the cache property (impossible without debugging or WriteOut). Would it be possible for you to extend the article https://www.quantacula.com/Help/OpenHelp/devblog/665 with such a conditional filter example for multiple values, e.g. the lowest three RSI stocks having an SCTR >= 50?

Thanks...

Hi Glitch. Unfortunately, I have not yet managed it to add a second value to the cache property (impossible without debugging or WriteOut). Would it be possible for you to extend the article https://www.quantacula.com/Help/OpenHelp/devblog/665 with such a conditional filter example for multiple values, e.g. the lowest three RSI stocks having an SCTR >= 50? Thanks...

In the example, you see the line where the RSI is added to the BarHistory Cache:

        //create the weight indicator and stash it into the BarHistory object for reference in PreExecute
        public override void Initialize(BarHistory bars)
        {
		rsi = new RSI(bars.Close, 14);
		bars.Cache["RSI"] = rsi;
        }

to add another indicator, just add it to the Cache using a different string tag. If you want to add an SCTR, try this:

//create the weight indicator and stash it into the BarHistory object for reference in PreExecute
public override void Initialize(BarHistory bars)
{
	rsi = new RSI(bars.Close, 14);
	bars.Cache["RSI"] = rsi;
	sctr = new SCTR(bars.Close, 1, 10, bars);
	bars.Cache["SCTR"] = sctr;
}
In the example, you see the line where the RSI is added to the BarHistory **Cache**: ```csharp //create the weight indicator and stash it into the BarHistory object for reference in PreExecute public override void Initialize(BarHistory bars) { rsi = new RSI(bars.Close, 14); bars.Cache["RSI"] = rsi; } ``` to add another indicator, just add it to the **Cache** using a different string tag. If you want to add an SCTR, try this: ```csharp //create the weight indicator and stash it into the BarHistory object for reference in PreExecute public override void Initialize(BarHistory bars) { rsi = new RSI(bars.Close, 14); bars.Cache["RSI"] = rsi; sctr = new SCTR(bars.Close, 1, 10, bars); bars.Cache["SCTR"] = sctr; } ```

Hi Glitch. The dictionary is not the difficult part, it's more about how to get the second indicator value into the list of participants so that the Sort lambda expression can be extended with a where clause, pointing to the SCTR value?

foreach (BarHistory bh in participants)
{					
  RSI indiRsi = (RSI)bh.Cache["RSI"];
  SCTR indiSctr = (SCTR)bh.Cache["SCTR"];
  
  int idx = GetCurrentIndex(bh);  
  
  double RsiVal = indiRsi[idx];				
  double SctrVal = indiSctr[idx];
  
  bh.UserData = RsiVal;
  **???????? // how can I get the SCTR Value into the bh collection?**		
  
  participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble));		
}
Hi Glitch. The dictionary is not the difficult part, it's more about how to get the second indicator value into the list of participants so that the Sort lambda expression can be extended with a where clause, pointing to the SCTR value? [CODE] foreach (BarHistory bh in participants) { RSI indiRsi = (RSI)bh.Cache["RSI"]; SCTR indiSctr = (SCTR)bh.Cache["SCTR"]; int idx = GetCurrentIndex(bh); double RsiVal = indiRsi[idx]; double SctrVal = indiSctr[idx]; bh.UserData = RsiVal; **???????? // how can I get the SCTR Value into the bh collection?** participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble)); } [/CODE]

Ah I understand now, too much turkey over the past few days, must have dulled my brain :)

You could calculate a compound indicator and store it in the UserData, and then sort by UserData. Since RSI ranges from 0-100 you could assign a value of something like 200 to the stocks that have an SCTR < 50. That would effectively put them at the bottom of the sort.

        //this is called prior to the Execute loop, determine which symbols have the lowest RSI
        public override void PreExecute(DateTime dt, List<BarHistory> participants)
        {
		//store the symbols' RSI value in their BarHistory instances
		foreach (BarHistory bh in participants)
		{
			RSI symbolRsi = (RSI)bh.Cache["RSI"];
			SCTR symbolSctr = (SCTR)bh.Cache["SCTR"];
			int idx = GetCurrentIndex(bh);  //this returns the index of the BarHistory for the bar currently being processed
			double rsiVal = symbolRsi[idx];
			double sctrVal = symbolSctr[idx];
			bh.UserData = rsiVal; //save the current RSI value along with the BarHistory instance
			if (sctrVal < 50)
				bh.UserData = 200.0;
		}

		//sort the participants by RSI value (lowest to highest)
		participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble));
Ah I understand now, too much turkey over the past few days, must have dulled my brain :) You could calculate a compound indicator and store it in the UserData, and then sort by UserData. Since RSI ranges from 0-100 you could assign a value of something like 200 to the stocks that have an SCTR < 50. That would effectively put them at the bottom of the sort. ```csharp //this is called prior to the Execute loop, determine which symbols have the lowest RSI public override void PreExecute(DateTime dt, List<BarHistory> participants) { //store the symbols' RSI value in their BarHistory instances foreach (BarHistory bh in participants) { RSI symbolRsi = (RSI)bh.Cache["RSI"]; SCTR symbolSctr = (SCTR)bh.Cache["SCTR"]; int idx = GetCurrentIndex(bh); //this returns the index of the BarHistory for the bar currently being processed double rsiVal = symbolRsi[idx]; double sctrVal = symbolSctr[idx]; bh.UserData = rsiVal; //save the current RSI value along with the BarHistory instance if (sctrVal < 50) bh.UserData = 200.0; } //sort the participants by RSI value (lowest to highest) participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble)); ```

ah...it's a little trick :-) Thought it's somehow possible to store two different data series in the UserData property.

Thanks anyway for your answers. This should help for the first part of the way...

ah...it's a little trick :-) Thought it's somehow possible to store two different data series in the UserData property. Thanks anyway for your answers. This should help for the first part of the way...
Forum Tips

Please sign in if you want to participate in our forum.

Our forum uses Markdown syntax to format posts.

To embed code snippets, enclose them in [CODE][/CODE] tags.