Symbol Rotation Code
Author: trader rog
Creation Date: 7/17/2009 9:45 AM
profile picture

trader rog

#1
Hi Everyone

I am trying to create a symbol rotation strategy that buys ten stocks with the lowest RSI but need some help with the coding. I would like the strategy to always have ten stocks at the beginning of the day. So, for example, if 2 stocks were sold the day before, then 2 stocks would be bought on the following days open. I used the RSI symbol rotation and Dogs of the Dow strategies as a guide but still can't get it to work.

After several hours of unsuccessful troubleshooting, I was hoping someone here could help.

CODE:
Please log in to see this code.
profile picture

Cone

#2
Using your example, if you sold 2 positions today, then you'd go home with 8 positions and in the morning buy 2 to replace them.

But what happens if at the end of the first day on which you sold positions, that 2 of the Positions that you're currently holding move to the bottom of the list? Should you buy them again? If you do, then the logic becomes much more complicated because now you really have 4 positions in 2 of the same stocks, so how do you handle that?

.. it all comes down to requirements, requirements, requirements. The code can only do what you specify, but you have to think through the logic first.
profile picture

trader rog

#3
I agree that the logic must be thought through before coding, however, in this case it's the coding that is giving me difficulty because I'm a programming newbie. When I compile, I get a "namespace name 'RSIHolder' could not be found" error. Any idea what the cause of this error is?

To answer your question, if 2 current positions move to the bottom of the list, I would like the code to skip them and buy the next one on the list. This way there are 10 different stocks populating an equally weighted portfolio.


profile picture

Cone

#4
QUOTE:
Any idea what the cause of this error is?
Sure. You put RSIHolder inside the MyStrategy class, and, you didn't implement IComparer though you derived MyStrategy from it... and that's just for starters!

Throw this away, copy and paste all of the code from the RSI Rotation strategy into a new Strategy window, save, and start modifying from there.
profile picture

trader rog

#5
I have used your advice and was able to compile successfully, however, when I backtest the strategy, I get blank results. Can you please take a glance over my code and point me in the right direction? I have included it below.

Also, since this is a long/short strategy, I need to create a second list from which to choose the shorts from. It would be similar to the current list, however two variables would be different (Close < ma) and (RSI > 90). I understand that the current list can be reversed using the code: list.sort(this); list.reverse(); ,however, I'm not sure that this concept can be applied in this situation since two variables will need to be different. How can I create a second list?

I would greatly appreciate your feedback as these are the final details that need to be worked out before testing. Thanks in advance!

CODE:
Please log in to see this code.
profile picture

trader rog

#6
In regard to my first question above, I believe the problem is multi symbol backtesting. I have read through many posts in the community area, but still find it confusing. My question is, how can I backtest a symbol list using symbol mode backtest?

Also, I would sincerely appreciate anyone's help with the best way to create a second list from which to choose short positions from.
profile picture

Eugene

#7
You're getting zero trades just because of this line:
CODE:
Please log in to see this code.

The RSI rarely goes above 90 or below 10.
profile picture

trader rog

#8
If I change it to RSI < 50, it still doesn't work. If I do a multi symbol backtest on the Dow 30, I get error messages "Error processing symbol xyz" for all of the symbols.
profile picture

Eugene

#9
If you execute your rotation strategy in single symbol mode (as it should be; please see our Wiki: A Rotation strategy isn't working like it should), does it work?
profile picture

trader rog

#10
No, I still get no trades in the performance results. I open the Dow 30 under DataSets and click on AA (the first symbol) to run the backtest. Is that the right way to do it?
profile picture

Eugene

#11
Did you compile it before running?
profile picture

trader rog

#12
Yes. Could it have to do with an error in my code?
profile picture

trader rog

#13
I did further testing, and found that it works on the S&P 100 DataSet but not the Dow 30 or Wealth-Lab 100 DataSets. This also holds true for the RSI Rotation strategy built by Wealth-Lab. Strangely enough, when I test my strategy on the NAZ 100, it only works on symbols AAPL through ISRG.
profile picture

Eugene

#14
QUOTE:
it only works on symbols AAPL through ISRG.

Since your rules are pretty tight, that doesn't necessarily indicate an error somewhere. It just could mean the conditions were met on those stocks in that period.
profile picture

trader rog

#15
But what can I do about it working on one DataSet(S&P 100) and not another(Wealth-Lab 100)? The DataSet I created has about 900 symbols and no trades. What can I do to fix this?
profile picture

Eugene

#16
I would normally say "work through your conditions until you find which one is the culprit" but your code works for me (with RSI < 10 commented, of course) on both the S&P 100 and Wealth-Lab 100 Data Sets.

Are there any warning messages in the debug log? Are your data up to date?
profile picture

trader rog

#17
I have a check next to Update Data on Demand. When I comment out RSI<10, it still doesn't work for the Wealth-Lab 100 DataSet. The only error message is: Runtime error: Could not load data for symbol: GM. Do you think maybe there is a corrupt file somewhere and that I should re-install Wealth-Lab?
profile picture

Eugene

#18
QUOTE:
Do you think maybe there is a corrupt file somewhere and that I should re-install Wealth-Lab?

Of course no. Please see this: I have a problem. Tried to reinstall Wealth-Lab, but it didn't help!
QUOTE:
I have a check next to Update Data on Demand.

Better uncheck it as that unnecessarily slows down backtesting. Just make sure the dataset has been normally updated.
QUOTE:
Could not load data for symbol: GM.

GM is now GMGMQ or GMGMQ.PK (Yahoo).
profile picture

trader rog

#19
Okay, I updated all DataSets using the Data Manager but I still can't get the backtest to work with the DataSet I created.
profile picture

Eugene

#20
Can you be specific about what does "can't get it to work" mean?
profile picture

trader rog

#21
Sure, when I backtest using the DataSet I created and click on the Performance tab, the All Trades column has all zeros.
profile picture

Cone

#22
And that would be correct if the Trades view has no trades.
profile picture

trader rog

#23
Only if no trades met the strategy criteria, however that is not the case. If I comment out the RSI<10 to generate more signals, I get 7,809 trades on the S&P 100 over a 5 year range. Keeping everything the same and using the Wealth-Lab 100 DataSet generates zero trades. I am trying to figure out why it works on one DataSet but not the other.
profile picture

Eugene

#24
Probably there are symbols that have experienced data errors and were moved to Symbol Quarantine. Check out the error log of the Strategy in the Editor window.
profile picture

trader rog

#25
There are only 4 symbols in the Quarantine, and still I get no trades under the performance tab. I created a new DataSet with over 900 symbols, then updated data in the Data Manager, but still no luck.
profile picture

Eugene

#26
How many bars of data loaded? What kind of symbols? Any messages in the editor window?
profile picture

trader rog

#27
About 4,000 bars loaded for each stock. I am testing the last 2 years using daily bars, so that should be fine. The symbols are exchange traded (no OTC), ave. volume > 1,000,000, price > 5. Here is the message in the editor window:
Runtime error: Could not load data for symbol: FCE.A
at WealthLab.Strategies.RSIRotation.Execute()
at WealthLab.WealthScript.SetContext(String symbol, Boolean synchronize)
profile picture

Eugene

#28
Well, it means that you need to consider paying attention to those error messages in the editor.

FCE.A is not a valid symbol and/or Fidelity does not provide its data.

Eliminate all bad symbols like that from the DataSet, then the strategy should start working.
profile picture

trader rog

#29
Wow! Thank you for your patience. Everything works great now. I didn't think that one bad symbol could trip everything up like that. Painful lesson!

I had one last question from my post above that should hopefully be much simpler. Since this is a long/short strategy, I need to create a second list from which to choose the shorts from. It would be similar to the current list (in the code above), however two variables would be different (Close < ma) and (RSI > 90). What is the best way to create this second list?

Thanks again for your help!
profile picture

Eugene

#30
Have you already tried to throw in a second list? Was there a problem?
profile picture

trader rog

#31
I tried creating a second list using this line of code:

CODE:
Please log in to see this code.


From there, I duplicated the blocks of code for the longs, and used listshorts instead of list to create the exit rules, etc. for the shorts.

I get one error (error CS1518: Expected class, delegate, enum, interface, or struct) on this line when compiling:

CODE:
Please log in to see this code.


Is this the right approach?







profile picture

trader rog

#32
In addition to the question above, I double-checked the performance results and they are not correct. I used the script above but relaxed the RSI contstraint to RSI < 40 and backtested 1 year on the S&P 100. Under the trades tab, I am showing positions that were entered below the 50 day SMA (the code states that the stock must be above the SMA before entering on the following day's open) as well as positions that were exited before the rules in the code were triggered.
For example, the simulation went long XOM on 7/10/09, even though the stock was below the 50 day SMA, and exited the position prematurely on 7/13/09, before the exit criteria were met. I would appreciate it if someone could help with explaining what could be going wrong here. Thanks!

profile picture

ss161

#33
Just looking at the script above, I think there is a fairly significant logic error in it.

Here's the top part of the script:
CODE:
Please log in to see this code.


the first three lines of code after the execute procedure only get called once, and only for whichever symbol you clicked on to start running the strategy.

these are the lines of code to which i'm referring:
CODE:
Please log in to see this code.


instead, i think you'd need something like this:

CODE:
Please log in to see this code.


assuming, I'm right -- and I've only looked at the code, not tested it, so I very well could be wrong -- what I'm suggesting above would be very inefficient as it is recreating the dataseries for each bar, instead of once before processing begins. you'd have to re-work your code a bit to store each dataseries once for each symbol before processing the main loop. if you're interested, i posted something a while ago that does that, here: /Forum/Posts/Help-with-Symbol-Rotation-modifications-29357


profile picture

Eugene

#34
Steve, you're right regarding the series placement -- it was dependent on the clicked symbol and therefore incorrect.

I doubt that the series will be recreated on each bar in your code, though, as the Bars.Cache mechanism is here to take care of it.
profile picture

trader rog

#35
Thank you very much for your great insight Steve. That was very helpful. Moving the lines of code as you suggested solved the moving average problem. I still haven't found the right spot for the third line of code because I get the error: name 'ma_1' does not exist in the current context. So, I tried this:

CODE:
Please log in to see this code.


Unfortunately, there were still trades that were closed out before the exit criteria were met. Any ideas on where the right spot for this line would be?

CODE:
Please log in to see this code.


Also, the backtest performed just as quickly before, so I believe Eugene's assessment is right and that perhaps the code will not need to be re-worked.

profile picture

ss161

#36
that's just a problem of the "scope" of the variable. you can declare each variable where you initially had it in your code -- up top -- and then below just refer to them where you need to (without "redefining" them). so for example, at the top of your code define each of the three variables -- i tend to define the variables and initialize them to null, and then later in the code, refer to them --

CODE:
Please log in to see this code.


now when you refer to ma_1 or any of the other variables, you won't get the name does not exist in this context error.

note, if you define all the variables at the top (where you initially had them) then you'll need to modify the code in the for loop as follows:

from:
CODE:
Please log in to see this code.


to:
CODE:
Please log in to see this code.


since you've already defined them.
profile picture

trader rog

#37
Thanks Steve. I declared the variables, but for some reason the exit rules still don't work right. All trades are exited within 5 days, which is correct, but some are exited before the stock closes above the 5 day SMA for what looks like no apparent reason. I put this code:

CODE:
Please log in to see this code.


in place of the previous line of code under Exit rules but it didn't fix this issue. Also, something I just noticed that is strange is that when analyzing the trades, there are a few days that have more than 10 positions. For example, July 13th has 17 positions being exited. My intention is to have 10 positions max at any time, so I also need to limit ActivePositions to <= 10 somehow. Thanks to anyone that can help.
profile picture

ss161

#38
try this. your exit logic was not correct because you were referring to ma_1 without setting context back to the symbol that contained the series for ma_1 that you cared about. fwiw, i agree that the data caching allows these variables to be declared all over the place without performance issues, i think it also tends to confuse one's understanding of the logic that's actually going on in the program -- just my opinion.

i modified the code from your 7/19/08 post below.
CODE:
Please log in to see this code.

profile picture

Eugene

#39
QUOTE:
fwiw, i agree that the data caching allows these variables to be declared all over the place without performance issues, i think it also tends to confuse one's understanding of the logic that's actually going on in the program -- just my opinion.

Hi Steve,

It's documented in the QuickRef entry of Bars.Cache.
profile picture

trader rog

#40
Thanks again Steve! I appreciate your help. After reviewing the trades, everything seems to be working perfectly.

For the final part of the strategy, I need to create a second list from which to choose the shorts from. It would be similar to the current list (in the code above), however two criteria would be different (Close < ma) and (RSI > 30). I have attempted this in the script below but get this error:
Expected class, delegate, enum, interface, or struct

on this line:
CODE:
Please log in to see this code.


Is this the right approach for creating a second list? Thank you for your patience in helping a newbie programmer get up to speed.

CODE:
Please log in to see this code.
profile picture

ss161

#41
your curly braces were in the wrong spot in several places. i could tell almost right away because i pasted your code into SharpDevelop -- which is a free .net development environment. visual studio is another one. for code like this, it is a significant time saver / productivity enhancer to use it. there's a minor learning curve, but you will save a lot of time very quickly by adopting either. Eugene wrote an article about how to use them to step through your code while running wealth-lab.

you also had an error with these lines:
CODE:
Please log in to see this code.


as you wanted to write: listshorts.RemoveAt(i);

i also noticed you flipped around the RSI signals to be more inclusive (buying if RSI < 70 and shorting if > 30) -- when i started debugging several versions ago, i wasnt getting any signals with RSI < 30 and price > ma.

here's your code:
CODE:
Please log in to see this code.


profile picture

trader rog

#42
This forum has been very helpful and a great learning experience. The script is now performing exactly as needed. Thank you for your advice to use SharpDevelop or visual studio to debug the script. I'm sure it will save countless hours of frustration in the future.

One last minor issue before putting this thread to rest. How can I limit the number of open positions to 10 for each the longs and shorts? I set position size to 5% of equity to allow for 20 total positions, and created the block of code below. I was able to limit longs by the total active positions but am not sure how to separately limit the longs to 10 and the shorts to 10.

CODE:
Please log in to see this code.
profile picture

DartboardTrader

#43
Get rid of your 'ActivePositions.Count > 10' condition.
In your ActivePositions loop, you can keep track of the 'active' positions.

CODE:
Please log in to see this code.


Then, in your buy/short logic, prevent buying based on the maximum long or short positions you wish to have 'active', since you will have the current count as of that 'bar'.

Regards,
--Mike
profile picture

trader rog

#44
Hi Mike,

I tried this below for the buys but the trade results showed multiple purchases of the same symbol on the same day. Any idea where I'm going wrong here?

CODE:
Please log in to see this code.


profile picture

trader rog

#45
Anyone have an idea what is wrong with the code in the post above? Thanks to anyone that can help.
profile picture

Cone

#46
I don't see anything wrong with the snippet. So the problem could be in the context in which this is used, or somewhere else in the code.
This website uses cookies to improve your experience. We'll assume you're ok with that, but you can opt-out if you wish (Read more).