## TRO_DYNAMIC_SR2CAN - How it works

free & uncensored discussion arena for TheRumpledOne

Moderator: moderators

jvp
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender:
TRO,

No, that really is all there is to it. In fact, on closer inspection I found that this code produces exactly the same results:

[font=Courier New]HH = Highest(H, iPeriods);
if H = HH or Dynamic_R = 0 then Dynamic_R = HH;

LL = Lowest(L, iPeriods);
if L = LL or Dynamic_S = 0 then Dynamic_S = LL;
[/font]

I was curious how this cool indicator works, so I analyzed it rather thoroughly. Here's how I got the code reduced to this:

Code: Select all

`I have copied TRO's slick Dynamic_SR indicator here and pulled out just thecode for calculating Dynamic_R:        PrevDynamic_R = Dynamic_R ;        oExtremeVal = Extremes( H, iPeriods, 1, Dynamic_R , oExtremeBar ) ;        If     Dynamic_R <> H           and Dynamic_R < PrevDynamic_R           then if PrevDynamic_R <> 0              then Dynamic_R = PrevDynamic_R;      First, simplify by replacing the call to Extremes() with a call to Highest()        PrevDynamic_R = Dynamic_R ;        Dynamic_R = Highest( H, iPeriods);  // highest high        If Dynamic_R <> H          and Dynamic_R < PrevDynamic_R           then if PrevDynamic_R <> 0              then Dynamic_R = PrevDynamic_R; Next, take a look at the compound 'If' statement.  Since there are no 'else' statements, the assignment at the end of the second 'If' only gets carriedout if the condition in the first 'If' AND the condition of the second 'If'are true.  So we can simplify to a single 'If' statement like this:         variables: Dynamic_R(0), PrevDynamic_R(0);        PrevDynamic_R = Dynamic_R ;        Dynamic_R = Highest( H, iPeriods);  // highest high        If     Dynamic_R <> H           AND Dynamic_R < PrevDynamic_R           AND PrevDynamic_R <> 0 then Dynamic_R = PrevDynamic_R; Let's think about what's going on here.  First the current value ofDynamic_R is stored in a temporary location called PrevDynamic_R.  Then the highest high is assigned to Dynamic_R.  Then a condition is tested, and if found to be true, Dynamic_R is set back to it's previous value,PrevDynamic_R.  I'm going to substitute variables here and show a simplifiedversion of this calculation.  Substituting PR for PrevDynamic_R, DR for Dynamic_R, HH for Highest(H, iPeriods):         PR = DR;        DR = HH;        if DR <> H AND DR < PR AND PR <> 0 then DR = PR;So DR is going to retain its previous value if the 'if' condition is true.  Thisimplies that DR will be set to HH only when the 'if' condition is false:         (DR <> H AND DR < PR AND PR <> 0) = FALSE  So we could write the if statement like this:        if (DR <> H AND DR < PR AND PR <> 0) = FALSE then DR = HH;But there is a problem.  The condition in the 'if' statement used themodified values of DR and PR from the two assignments right before the 'if' statement.  We can fix this by substituting HH for DR and DR for PR and eliminating those two assignments.  So the whole shebang boils down to:       HH = Highest(H, iPeriods);       if (HH <> H AND HH < DR AND DR <> 0) = FALSE then DR = HH;Rearranging a bit:       HH = Highest(H, iPeriods);       if  ((H <> HH) AND (DR > HH) AND (DR <> 0)) = FALSE then DR = HH;If EasyLanguage had a unary logical inversion operator, also known as a 'not'operator, we could write this code like this:       HH = Highest(H, iPeriods);       if  NOT((H <> HH) AND (DR > HH) AND (DR <> 0)) then DR = HH;Here's where we pull an old trick out of the computer science hat.  We wantto calculate the logical inverse of that condition.  I'm going to apply De Morgan's theorem ( !(A AND B AND C) = !A OR !B OR !C, where ! is logical inverse or 'NOT') to the 'if' condition to get this new version:       HH = Highest(H, iPeriods);       if (H = HH) OR (DR <= HH) OR (DR = 0) then DR = HH;Note that I have replaced the ANDs with ORs and logically inverted each ofthe three terms.  It becomes obvious here that the term 'DR = 0' is only truethe first time the code is run and DR has been initialized to 0.  (My deepestsympathies to you if you have trades that achieve this value otherwise.) Being a simpleminded fellow I pulled that out and did the initialization separately:       if (DR = 0) then DR = Highest(H, iPeriods);       HH = Highest(H, iPeriods);       if (H = HH) OR (DR <= HH) then DR = HH;Now I've got this thing down to the level where I can figure out what it does.I'll rewrite it using the original variables:       if (Dynamic_R = 0) then Dynamic_R = Highest(H, iPeriods);       HH = Highest(H, iPeriods);       if (H = HH) OR (Dynamic_R <= HH) then Dynamic_R = HH;So Dynamic_R is set to the highest high of the last iPeriods if either the current high is equal to the highest high OR if the current value of Dynamic_R is less than or equal to the highest high.Now let's give this some thought.  When does the second part of the 'if'condition actually do anything?  In other words, when can Dynamic_R be less than the highest high of the last iPeriods?  If you think about it, if Dynamic_R is less than HH, you must be at a new local high, which meansthat the 'H = HH' part of the condition is going to be true as well.  Youcould look at it like this: the 'H = HH' term allows Dynamic_R to drop downto a new local high after the series has dropped down and started coming backup.  The 'Dynamic_R <= HH' term causes the output to rise with an increasing input series.  But the 'H = HH' term also applies in that case, so the 'Dynamic_R <= HH' term is redundant and can be removed:       if (Dynamic_R = 0) then Dynamic_R = Highest(H, iPeriods);       HH = Highest(H, iPeriods);       if (H = HH) then Dynamic_R = HH;Thinking about this some more, and being a geek who worries about the tiniestinefficiencies, it would make sense to place the initialization code back intothe 'if' statement.  The 'Dynamic_R = 0' condition has to be evaluated everytime we pass through the code above.  If we write the code like this:       HH = Highest(H, iPeriods);              if H = HH or Dynamic_R = 0 then Dynamic_R = HH;        and if the EasyLanguage compiler has a feature known as 'logical subexpression short-circuit evaluation', it will not perform the '(Dynamic_R = 0)' comparison if the 'H = HH' part of the expression is true.  So that's how I got this.  The argument works the same for Dynamic_S but with the inequalities reversed.`

Of course, I wouldn't trust that code unless I tested it, so that's what I did. I wrote an indicator that calculates Dynamic_R both ways and then plots the values from your method. If the method I show above is different it plots that out in a different color. The .eld is attached.

I've seen indicators like this in the ads in trading magazines for proprietary trading systems. They're used for setting stop loss orders. Analyzing the code has given me more insight into how they work. Your thoughts?

- Jim
Attachments
JVP_DYNAMIC_R_TEST.ELD

TheRumpledOne
rank: 10000+ posts
Posts: 13178
Joined: Sun May 14, 2006 9:31 pm
Reputation: 1710
Location: Oregon
Real name: Avery T. Horton, Jr.
Gender:
Contact:
That's great if you simplified it... GOOD JOB!!

I just wrote it, it seemed to work and helped to make money ( which is the point of trading ).

TheRumpledOne
rank: 10000+ posts
Posts: 13178
Joined: Sun May 14, 2006 9:31 pm
Reputation: 1710
Location: Oregon
Real name: Avery T. Horton, Jr.
Gender:
Contact:
FYI, the reason I use the EXTREMES function is because that if the fastest code.

HIGHEST/LOWEST makes a call to EXTREMES.

I just cut out the middleman...LOL!

cvax
rank: 50+ posts
Posts: 83
Joined: Sun May 13, 2007 12:45 am
Reputation: 0
Gender:
jvp: Are you sure they are the same? I tried using your method on my indicator conversion to NinjaTrader, but it doesn't seem to work the same.

Notice the DynamicS being very different and the DynamicR with only slight differences (4th bar doesn't set new DynamicR).

I replaced all of TRO's original DynamicR/S modifying code with only this:

Code: Select all

`int HH = Bars.HighestBar(Period);if(High[0]==High[HH] || DynamicR==0)   DynamicR=High[HH];int LL = Bars.LowestBar(Period);if(Low[0]==Low[LL] || DynamicS==0)   DynamicS=Low[LL];`

That code is ran on every single bar and then the DynamicR/S are plotted. Any help is appreciated because I am having difficulty getting it to plot the same even with what I believe is a direct port of TRO's method. The language is C# btw.

jvp
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender:
cvax,

I'm a bit puzzled by the graphics you posted. I can't figure out what is going on in the Tradestation window that you have there. I slapped up a version of the indicator that I posted earlier and added the support side. It's included on this post. When I run that indicator I get the same result that you get in your ninja trader pic. Maybe I'm too bleary eyed at 2:00 am to figure this out. Here's what I'm getting in Tradestation on the same data:

One question on the ninja code: does Bars.HighestBar(Period) return the bar with the highest high, or the highest close?

I'll take another look at this tomorrow.

- Jim
Attachments
JVP_DYNAMIC_SR_TEST.ELD
Dynamic Support and Resistance Test

cvax
rank: 50+ posts
Posts: 83
Joined: Sun May 13, 2007 12:45 am
Reputation: 0
Gender:
Hi jvp.

The first picture I posted was one of TRO's latest screenshots taken from the frontpage. The second one is my version of his indicator in NinjaTrader. If you notice,your TradeStation screenshot and my NinjaTrader screenshot both don't match TRO's TradeStation screenshot. Don't mind all the extra plots on it. Just look at the red and blue dots.

jvp
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender:
cvax,

I just downloaded the .eld that goes with that chart you snagged from the home page. It has iPeriods set to 3. If you set iPeriods to 3 using the indicator I posted you will get the same result as in the picture.

His new indicator has entry and exit points - very interesting.

- Jim

cvax
rank: 50+ posts
Posts: 83
Joined: Sun May 13, 2007 12:45 am
Reputation: 0
Gender:
Oh interesting. For me if I set periods to 3 it doesn't show up the same, but when I set periods to 2 it does. Probably a difference in the way NinjaTrader and TradeStation goes about processing data. That's odd though because if periods is set to 5 we get the same plots.

Edit: Yup I figured it out. There was a difference between TradeStation's Highest() and NinjaTrader's Bars.HighestBar(). TradeStation's Highest() checks x amount of bars as determined by the parameter. It counts the current bar as one of the bars checked. NinjaTrader checks the current bar + however many bars you input into the parameter so essentially one more bar than TradeStation. That is why I had to do the -1 thing to get them to match up.

Anyways thank you for the help jvp.