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 the

code 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 carried

out 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 of

Dynamic_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 simplified

version 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. This

implies 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 the

modified 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 want

to 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 of

the three terms. It becomes obvious here that the term 'DR = 0' is only true

the first time the code is run and DR has been initialized to 0. (My deepest

sympathies 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 means

that the 'H = HH' part of the condition is going to be true as well. You

could look at it like this: the 'H = HH' term allows Dynamic_R to drop down

to a new local high after the series has dropped down and started coming back

up. 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 tiniest

inefficiencies, it would make sense to place the initialization code back into

the 'if' statement. The 'Dynamic_R = 0' condition has to be evaluated every

time 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