Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Reverse 3ngineering the Swing Indicator

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • bltdavid
    replied
    Originally posted by bltdavid View Post
    Whether this per-bar status information is useful to you, that depends upon your needs.
    Btw, If you want to see an example of Swing in action, try studying this indicator,

    Leave a comment:


  • RobVig
    replied
    Thank You for replying David!

    Originally posted by bltdavid View Post
    I think your line numbers are off. Lines 134 & 144 don't show what you're describing.
    Sorry for the confusion. I copied and pasted the Swing code into VS and hit the “return” key a few times to separate the code for readability. I’ll make sure it’s accurate next time.

    Leave a comment:


  • bltdavid
    replied
    Originally posted by RobVig View Post
    Question #002

    On line 89 (or so) " if (lastHighCache.Count == (2 * strength) + 1) " statement begins and ends around line 144. Just prior to closing of that statement there is a final "if / else" block (line 134) that appears to loop through the "left side". My question is: What purpose does the "swingHighSeries" DataSeries serve?
    [Edit: I think your line numbers are off. Lines 134 & 144 don't show what you're describing. I use an editor that expands all regions and always displays absolute line numbers. I mean, I only use NinjaScript editor to compile, I use gvim to edit all my code, so perhaps your line numbers are off due to your particular editor?]

    The swingHighSeries is the "backing store" for the SwingHigh property.

    The description of Swing shows two different syntax descriptions,

    Code:
    Syntax - Bars Ago
    Syntax - Value
    You're basically asking about the second 'Value' syntax. That syntax requires the use of swingHighSeries, because Swing needs an internal DataSeries providing the private storage (aka backing store) for the public SwingHigh property.

    What's the purpose? Well, each element retrieved by SwingHigh via indexer '[n]' is returning the most recent confirmed swing high value (if one existed) recorded for that bar 'n' bars ago.

    What I mean is, SwingHigh returns prior swing status information on a per-bar basis. It returns either 0 (no swing active) or the current swing high/low value active at the time of that bar n bars ago.

    If you wanted to look back 10 bars ago, and ask the question, "Did that bar 10 bars ago have an active swing high already in progress found from a prior bar?" Well, SwingHigh returns an answer for that question. If it returns 0, no swing high was active at the time of that bar, otherwise the answer is yes and you have the swing high value itself.

    Whether this per-bar status information is useful to you, that depends upon your needs.
    Last edited by bltdavid; 06-10-2016, 11:22 AM.

    Leave a comment:


  • RobVig
    replied
    Originally posted by bltdavid View Post
    Line 95: check loop sets isSwingHigh to false due to a higher value left of candidate.
    Line 99: check loop sets isSwingHigh to false due to a higher value right of candidate.
    Ah!
    for (int i = 0; i < strength; i++) // <<<<< The left side [0-4]
    for (int i = strength + 1; i < lastHighCache.Count; i++) // >>>>> The right side [6-10]

    Originally posted by bltdavid View Post
    Hint #5:
    Do you know what CalculateOnBarClose (abbreviated COBC) is yet? ...
    Yes. I am familiar with this concept.

    - - - -

    Question #002

    On line 89 (or so) " if (lastHighCache.Count == (2 * strength) + 1) " statement begins and ends around line 144. Just prior to the closing of that statement there is a final "if / else" block (line 134) that appears to loop through the "left side". My question is: What purpose does the "swingHighSeries" DataSeries serve?

    Thank You,
    Rob
    Last edited by RobVig; 06-10-2016, 11:22 AM.

    Leave a comment:


  • bltdavid
    replied
    Originally posted by RobVig View Post
    David, here's question #001

    On line 101 of Swings.cs

    swingHighSwings.Set(strength, isSwingHigh ? swingHighCandidateValue : 0.0);

    Can you walk through this test? What values / combinations of "strength" and "isSwingHigh" would dictate true or false?
    What you're missing is understanding how isSwingHigh is set to false inside the check loops. There are two check loops, one for the left side of the middle value of the "moving window", and another check loop for the right side. These two check loops are there to confirm the middle candidate value is actually a swing value.

    [Edit: The purpose of the check loops is to decide if the middle value (aka, the swing candidate) is the highest value of all values in the moving window. This is the "ah-hah" moment when Swing knows it has found a confirmed swing high. So, isSwingHigh is just a flag for when a confirmed swing high is found. Note how the check loops set isSwingHigh to false when the candidate is proven not a swing.]

    Line 91: isSwingHigh starts out as true.
    Line 95: check loop sets isSwingHigh to false due to a higher value left of candidate.
    Line 99: check loop sets isSwingHigh to false due to a higher value right of candidate.

    Those check loops don't "break" after setting isSwingHigh to false, but they don't have to. Once isSwingHigh is set to false by either check loop, it will still be false when used by the ternary operator inside the 'Set' method at line 101.

    When isSwingHigh is false, due to swingHighCandidateValue failing the check loops, the code reaches back into the tracking DataSeries and sets slot 'n' to 0.0.

    When isSwingHigh is true, due to swingHighCandidateValue passing the check loops, the code reaches back into the tracking DataSeries and sets slot 'n' to swingHighCandidateValue.

    Strength = 'n', same as before. Thus, the mutability of older values in the DataSeries is essential for Swing.cs to update its internal swing tracking DataSeries.
    Last edited by bltdavid; 06-11-2016, 10:31 AM.

    Leave a comment:


  • RobVig
    replied
    David, here's Question #001

    On line 101 of Swings.cs

    swingHighSwings.Set(strength, isSwingHigh ? swingHighCandidateValue : 0.0);

    Can you walk through this test? What values / combinations of "strength" and "isSwingHigh" would dictate true or false?

    As always, Thank You for sharing your wisdom for the benefit of others!
    Rob
    Last edited by RobVig; 06-10-2016, 09:27 AM.

    Leave a comment:


  • RobVig
    replied
    David,

    I've read your post a few times and Swing is starting to make sense... I'm seeing the light. It's brilliant! Questions forthcoming....

    Rob

    PS: This is key...

    Originally posted by bltdavid View Post
    Make sure you completely understand this "moving window" metaphor. The size of the window is based upon the Strength parameter. That is, the algorithm waits until the moving window contains exactly '(2 * n) + 1' elements. Strength is 'n' and the '+ 1' is the middle value.
    Last edited by RobVig; 06-09-2016, 07:32 PM.

    Leave a comment:


  • RobVig
    replied
    Patrick,

    Swoosh! bltdavid to the rescue again or what?!?!

    Sorry for my delayed response... I've been studying btldavids post and trying to compose a response. Difficult using this medium... I'm going to go over it and over it, before I ask any questions to try and keep this thread as distilled as possible.
    Last edited by RobVig; 06-09-2016, 06:31 PM.

    Leave a comment:


  • NinjaTrader_PatrickH
    replied
    Hello Rob,

    Thank you for your post.

    bltdavid provides some good insight into the Swing indicator. I notice the biggest hang up to be the strength, as bltdavid mentioned.

    Please let us know if you have any specific questions.
    Last edited by NinjaTrader_PatrickH; 06-10-2016, 07:26 AM.

    Leave a comment:


  • bltdavid
    replied
    Originally posted by RobVig View Post
    As a journeyman programmer and long time Market enthusiast, I'm addicted to NT! I've asked for help gaining a deeper understanding of all things Ninja and many of you have responded. For this I Thank You! I'd like to "shout out" to user: bltdavid for his wonderful dissertations for my / our benefit. If you haven't seen my last two posts, check them out. bltdavid gave a few really great lessons.
    Thanks!
    [Edit: He's referring to my "tutorial essays" in threads here and here. ]

    Originally posted by RobVig View Post
    Now...
    I've opened the Swing Indicator and I'm trying to reverse engineer it. It's very interesting. I thought I could grasp it but there's a few "effects" that cause an offset that I can't figure out why... Ultimately, I'm hoping to extend it once I understand the logic / pattern a little better. I was wondering if there's anyone out there that might understand the Swing indicators' logic (code level) in depth and could explain how and why it's written the way it is.
    I understand it very well. Fire away with your questions!

    Hint #1:
    Remember when I said that the mutability of values of indexers n > 0 is a rarely used feature of a DataSeries? Well, I stand by that, but Swing.cs is one of those rare indicators that does reach back and update older slot values.

    Hint #2:
    Make sure you understand that DataSeries 'Set' method has two signatures. One method simply updates the value at slot 0, the other method updates the value stored at the specified slot. Swing.cs uses both signatures of the 'Set' method.

    Hint #3:
    Swing.cs uses ArrayList, and relies upon specific functionality of the RemoveAt method -- make sure you understand the 'queue' nature of what Swing.cs is using the ArrayList data structure to achieve. What I mean is, study how the Add and RemoveAt methods are used together to achieve a "moving window" of values.

    Hint #4:
    Make sure you know exactly what the Strength parameter means. A swing point (if detected) is the middle value in the moving window. If this middle value is the highest of all values on the left, and highest of all values on the right, then a swing high has been detected at this middle value. Same idea for a swing low.

    Make sure you completely understand this "moving window" metaphor. The size of the window is based upon the Strength parameter. That is, the algorithm waits until the moving window contains exactly '(2 * n) + 1' elements. Strength is 'n' and the '+ 1' is the middle value.

    Why? Because you need 'n' values to the left and 'n' values to the right of the candidate swing point to be all higher or all lower to confirm that swing point. Once the ArrayList cache is full, the algorithm confirms the middle value (aka the candidate) is a swing point by checking the 'n' values before and after the middle value.

    This is why a swing point is not known (aka confirmed) until after 'n' bars have passed. This is also why the algorithm needs to reach back into its internal tracking DataSeries and update previous slots after it found a swing point -- it doesn't know it found a confirmed swing point until after 'n' bars have passed.

    Study this swing detection code carefully.

    Hint #5:
    Do you know what CalculateOnBarClose (abbreviated COBC) is yet? The user sets COBC to True or False in the property settings, and the indicator author typically codes their OnBarUpdate to handle either case. The code in OnBarUpdate follows a common model that is designed to accommodate the effects of the COBC setting,

    Code:
    protected override OnBarUpdate()
    {
        if (saveCurrentBar != CurrentBar)
        {
            ... this code runs when bar closes regardless of COBC setting ...
            saveCurrentBar = CurrentBar;
        }
        else
        {
            ... this code runs on every tick but only if COBC is false ...
            ... this code does not run on the first tick, that is handled above ...
        }
    }
    My guess is this 'saveCurrentBar' technique is a legacy code pattern, probably dating back to older versions of NinjaTrader before FirstTickOfBar became the newer recommended way to handle the effects of the COBC setting.

    These hints only scratch the surface. The Swing indicator is indeed very interesting.

    Keep in mind, the Swing indicator is also complicated, and rather clever. But, it is a very good indicator to master if you want to become an expert in NinjaScript.

    Kudos to you, sir, for tackling this beast so soon!
    Last edited by bltdavid; 06-08-2016, 01:51 PM. Reason: added many helpful links

    Leave a comment:


  • RobVig
    started a topic Reverse 3ngineering the Swing Indicator

    Reverse 3ngineering the Swing Indicator

    Ninjas!

    As a journeyman programmer and long time Market enthusiast, I'm addicted to NT! I've asked for help gaining a deeper understanding of all things Ninja and many of you have responded. For this I Thank You! I'd like to "shout out" to user: bltdavid for his wonderful dissertations for my / our benefit. If you haven't seen my last two posts, check them out. bltdavid gave a few really great lessons.

    Now...
    I've opened the Swing Indicator and I'm trying to reverse engineer it. It's very interesting. I thought I could grasp it but there's a few "effects" that cause an offset that I can't figure out why... Ultimately, I'm hoping to extend it once I understand the logic / pattern a little better. I was wondering if there's anyone out there that might understand the Swing indicators' logic (code level) in depth and could explain how and why it's written the way it is.

    @ user sl..... - (with kindness and respect) I know I strike you as a nuisance. Please, hold the sarcasm on this, and my future posts. If you have trouble contributing information that is useful and constructive, then please don't post a reply.

    Thank You!

    Rob

Latest Posts

Collapse

Topics Statistics Last Post
Started by judysamnt7, 03-13-2023, 09:11 AM
4 responses
59 views
0 likes
Last Post DynamicTest  
Started by ScottWalsh, Today, 06:52 PM
4 responses
36 views
0 likes
Last Post ScottWalsh  
Started by olisav57, Today, 07:39 PM
0 responses
7 views
0 likes
Last Post olisav57  
Started by trilliantrader, Today, 03:01 PM
2 responses
21 views
0 likes
Last Post helpwanted  
Started by cre8able, Today, 07:24 PM
0 responses
10 views
0 likes
Last Post cre8able  
Working...
X