TRO_DYNAMIC_SR2CAN - How it works

free & uncensored discussion arena for TheRumpledOne

Moderator: moderators

User avatar
jvp
rank: <50 posts
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender: None specified

Postby jvp » Sat Aug 04, 2007 2:27 am

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 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
Attachments
JVP_DYNAMIC_R_TEST.ELD
(3.59 KiB) Downloaded 205 times

Please add www.kreslik.com to your ad blocker white list.
Thank you for your support.

User avatar
TheRumpledOne
rank: 10000+ posts
rank: 10000+ posts
Posts: 15538
Joined: Sun May 14, 2006 9:31 pm
Reputation: 3035
Location: Oregon
Real name: Avery T. Horton, Jr.
Gender: None specified
Contact:

Postby TheRumpledOne » Sun Aug 05, 2007 4:29 am

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 ).
IT'S NOT WHAT YOU TRADE, IT'S HOW YOU TRADE IT!

Please do NOT PM me with trading or coding questions, post them in a thread.

User avatar
TheRumpledOne
rank: 10000+ posts
rank: 10000+ posts
Posts: 15538
Joined: Sun May 14, 2006 9:31 pm
Reputation: 3035
Location: Oregon
Real name: Avery T. Horton, Jr.
Gender: None specified
Contact:

Postby TheRumpledOne » Sun Aug 05, 2007 4:33 am

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!
IT'S NOT WHAT YOU TRADE, IT'S HOW YOU TRADE IT!



Please do NOT PM me with trading or coding questions, post them in a thread.

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

Postby cvax » Sun Aug 05, 2007 7:22 am

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.

User avatar
jvp
rank: <50 posts
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender: None specified

Postby jvp » Sun Aug 05, 2007 9:12 am

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
(4.48 KiB) Downloaded 229 times

Please add www.kreslik.com to your ad blocker white list.
Thank you for your support.

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

Postby cvax » Sun Aug 05, 2007 4:07 pm

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.

User avatar
jvp
rank: <50 posts
rank: <50 posts
Posts: 4
Joined: Thu May 17, 2007 4:34 pm
Reputation: 0
Gender: None specified

Postby jvp » Sun Aug 05, 2007 5:55 pm

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
rank: 50+ posts
Posts: 83
Joined: Sun May 13, 2007 12:45 am
Reputation: 0
Gender: None specified

Postby cvax » Sun Aug 05, 2007 6:52 pm

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.

Please add www.kreslik.com to your ad blocker white list.
Thank you for your support.


Return to “TheRumpledOne”