NexusFi: Find Your Edge


Home Menu

 





VSA for ThinkorSwim


Discussion in ThinkOrSwim

Updated
      Top Posters
    1. looks_one snowcloud with 93 posts (25 thanks)
    2. looks_two StockJock with 91 posts (27 thanks)
    3. looks_3 cbritton with 37 posts (71 thanks)
    4. looks_4 swimtrader with 22 posts (19 thanks)
      Best Posters
    1. looks_one Hornblower with 2.3 thanks per post
    2. looks_two cbritton with 1.9 thanks per post
    3. looks_3 StockJock with 0.3 thanks per post
    4. looks_4 snowcloud with 0.3 thanks per post
    1. trending_up 304,527 views
    2. thumb_up 223 thanks given
    3. group 86 followers
    1. forum 434 posts
    2. attach_file 131 attachments




 
Search this Thread

VSA for ThinkorSwim

  #31 (permalink)
 
cbritton's Avatar
 cbritton 
Atlanta, Georgia
 
Experience: Intermediate
Platform: NT
Broker: DDT
Trading: ZN, ZB
Posts: 230 since Mar 2010
Thanks Given: 152
Thanks Received: 256


snowcloud View Post
Thanks for your response, C. Will you have time to do a little code-tweaking on this issue? If not, I suppose I could try it myself but I'm not confident that the results will be satisfactory.

I can make the changes when we have agreement on what the changes should be, if that's not too much to ask for. This is the code that is in question:

 
Code
                            
def x1 = if (close == lowthen avgSpread else (spread / (close low));

def isUpCloseBar = (x1 2);
def isDownCloseBar = (x1 2);
def isMidCloseBar = (x1 2.2 && x1 1.8);
def isVeryHighCloseBar = (x1 1.35); 
My thinking is to change the first line to this:

 
Code
                            
def x1 = if (high == lowthen avgSpread else if (close == lowthen 2.3 else (spread / (close low)); 

This handles the case where high = low, which really means undermined because there is not much that can be interpreted with a spread like this. I let the value x1 be the average spread. Any other ideas?

The second part (close == low) will set x1 to be 2.3 which will make isDownCloseBar true, isUpCloseBar false, isMidCloseBar false and isVeryHighCloseBar false. This part is ok, but may seem a bit odd in cases where the spread is narrow and isMidCloseBar *could* be true, depending on the spread.

The last part sets x1 to be the spread/(close-low) which is the same as before.

Any questions about my suggestions?

Regards,
-C

“Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat.” - Sun Tzu
Started this thread Reply With Quote

Can you help answer these questions
from other members on NexusFi?
My NT8 Volume Profile Split by Asian/Euro/Open
NinjaTrader
Better Renko Gaps
The Elite Circle
ZombieSqueeze
Platforms and Indicators
New Micros: Ultra 10-Year & Ultra T-Bond -- Live Now
Treasury Notes and Bonds
Exit Strategy
NinjaTrader
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Get funded firms 2023/2024 - Any recommendations or word …
59 thanks
Funded Trader platforms
38 thanks
NexusFi site changelog and issues/problem reporting
25 thanks
GFIs1 1 DAX trade per day journal
19 thanks
The Program
18 thanks
  #32 (permalink)
snowcloud
LA, CA
 
Posts: 93 since Jul 2010
Thanks Given: 2
Thanks Received: 25

I'm in over my head here programming-wise and might be reading the code incorrectly but here goes...

1. So if high = low which should be the case in the first iteration of this code on a bar what will X1 be? I took a look at the avgSpread calculations but don't understand how the WildersAverage works:

def avgSpread = WildersAverage (spread, volumeEMAlength) [0];

In this case will it be avgSpread = WildersAverage (0, 30) [0]; ? If so, what will x1 be? (I got the 0 from spread = high - low and the 30 from input volumeEMAlength = 30. It seems to me that on the first iteration of this code on a bar the result should be isMidCloseBar = true.

2. (close = low) will generate a 2.3 which seems right to me.

Your thoughts?

Reply With Quote
  #33 (permalink)
 
cbritton's Avatar
 cbritton 
Atlanta, Georgia
 
Experience: Intermediate
Platform: NT
Broker: DDT
Trading: ZN, ZB
Posts: 230 since Mar 2010
Thanks Given: 152
Thanks Received: 256



snowcloud View Post
I'm in over my head here programming-wise and might be reading the code incorrectly but here goes...

1. So if high = low which should be the case in the first iteration of this code on a bar what will X1 be? I took a look at the avgSpread calculations but don't understand how the WildersAverage works:

def avgSpread = WildersAverage (spread, volumeEMAlength) [0];

In this case will it be avgSpread = WildersAverage (0, 30) [0]; ? If so, what will x1 be? (I got the 0 from spread = high - low and the 30 from input volumeEMAlength = 30. It seems to me that on the first iteration of this code on a bar the result should be isMidCloseBar = true.

isMidClose bar = true works for me.



snowcloud View Post

2. (close = low) will generate a 2.3 which seems right to me.

Your thoughts?

Yes, 2.3 will make the interpretation a "low close" bar which is correct.

So based on your suggestion above, the new definition of x1 is this:

 
Code
                            

def x1 
= if (high == lowthen 2.0 else if (close == lowthen 2.3 else (spread / (close low)); 
x1 = 2.0 will set isMidCloseBar to be true and the others to be false when high = low based on the definitions here:

 
Code
                            

def isUpCloseBar 
= (x1 2);
def isDownCloseBar = (x1 2);
def isMidCloseBar = (x1 2.2 && x1 1.8);
def isVeryHighCloseBar = (x1 1.35); 
I'll wait a day or two for any new comments before posting an update to the ToS study.

Regards,
-C

“Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat.” - Sun Tzu
Started this thread Reply With Quote
  #34 (permalink)
snowcloud
LA, CA
 
Posts: 93 since Jul 2010
Thanks Given: 2
Thanks Received: 25

Yes, I can see that high = low will now generate x1 = 2 and isMidCloseBar = true which seems right to me.

Going further into the assignments I am puzzled by the fact that if, for example, x1 = 1.9 both isUpCloseBar = true and isMidCloseBar = true which seems that it could lead to some problems unless there's code that compensates for this further into the study. If you have a quick answer for this please let me know. If not, I'll put my old programmer's hat on and dig around in the code to see if I can find an answer.

Another related example: if x1 = 2.1 then both isDownCloseBar = true and isMidCloseBar = true.

I'm also noticing some places where the study should report un upThrust and is not doing it. I'm gathering some data on examples as I see them and will report my findings later. For now, let's see what the new isMidCloseBar code does.

Thanks for your work on this!

Reply With Quote
  #35 (permalink)
 
cbritton's Avatar
 cbritton 
Atlanta, Georgia
 
Experience: Intermediate
Platform: NT
Broker: DDT
Trading: ZN, ZB
Posts: 230 since Mar 2010
Thanks Given: 152
Thanks Received: 256


snowcloud View Post
Yes, I can see that high = low will now generate x1 = 2 and isMidCloseBar = true which seems right to me.

Going further into the assignments I am puzzled by the fact that if, for example, x1 = 1.9 both isUpCloseBar = true and isMidCloseBar = true which seems that it could lead to some problems unless there's code that compensates for this further into the study. If you have a quick answer for this please let me know. If not, I'll put my old programmer's hat on and dig around in the code to see if I can find an answer.

Another related example: if x1 = 2.1 then both isDownCloseBar = true and isMidCloseBar = true.

I'm also noticing some places where the study should report un upThrust and is not doing it. I'm gathering some data on examples as I see them and will report my findings later. For now, let's see what the new isMidCloseBar code does.

Thanks for your work on this!

These are happening because of the overlap in the assignment for each type which makes it possible to have multiple states true at the same time:

 
Code
                            
def isUpCloseBar = (x1 2);
def isDownCloseBar = (x1 2);
def isMidCloseBar = (x1 2.2 && x1 1.8);
def isVeryHighCloseBar = (x1 1.35); 
This comes right from the NT code, so whoever coded it either knows something we don't or made a mistake.

Regards,
-C

“Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat.” - Sun Tzu
Started this thread Reply With Quote
  #36 (permalink)
snowcloud
LA, CA
 
Posts: 93 since Jul 2010
Thanks Given: 2
Thanks Received: 25


cbritton View Post
These are happening because of the overlap in the assignment for each type which makes it possible to have multiple states true at the same time:

 
Code
                            
def isUpCloseBar = (x1 2);
def isDownCloseBar = (x1 2);
def isMidCloseBar = (x1 2.2 && x1 1.8);
def isVeryHighCloseBar = (x1 1.35); 
This comes right from the NT code, so whoever coded it either knows something we don't or made a mistake.

Regards,
-C

This could explain why there are occasionally two symbols for one bar. Just yesterday I saw a few instances - two examples of a green circle (stopping volume) / green square (strength) combo, one example of a Red Square (Upthrust) / yellow circle on the median (effort to fall), and another of a Red Triangle (Upthrust confirmation) / Green Circle (stopping volume).

As I mentioned in my last post I'm gathering data on some anomalies that I encounter. Here are a couple. I'm using the term "mid-stream" to indicate symbols that are drawn before the bar closes. I've also used some CAPS for emphasis. I trade the EUR/USD so the price numbers below should all be pre-pended with "1.".

1. a bar that was initially described as an upThrust bar but when the price FELL mid-stream it lost its status as an upThrust Bar and its Red Square even though it was now a BETTER example of an upThrust bar. Ending OHLC 3062, 3067, 3062, 3062. When the bar was in mid-stream it was 3062, 3067, 3062, and 3064 or so. The closing volume (200) was considerably higher than the previous bar (59) and the bar before that (66). I didn't record the trends but the short term trend should have been up because it was at the end of a 9-bar run starting at 3055 and ending with the high of the bar in question high at 3067. The code that generates a Red Square upthrust is:

rec isUpThrustBar = isWideSpreadBar && isDownCloseBar && ShortTermTrendSlope > 0;

Now that I look at it I'm thinking that what might have happened is that the ShortTermTrendSlope might have flipped to <= 0 mid-stream. I'll watch very carefully the next time I see this happen.

2. 2 bars at 5:28 AM PT on GDP news. Red Triangle BEFORE Red Square - Red Tri 3030, 3069, 3029, 3041, vol = 3,052 [huge]; Red Square 3041,3043, 3024, 3027, vol = 2,359 [Big]. I don't understand why the Triangle confirmation appeared in the bar BEFORE the initial upThrust Red Square.

As you can see I've started to dig through the code and I have a few questions that I hope you can answer.

1. What does the [0] in this line do?

def avgSpread = WildersAverage(spread, volumeEMAlength) [0];

I thought that def creates single variables whereas rec creates arrays. The [0] in this line seems to indicate that avgSpread is an array.

2. What is Double.NaN and what does it do? I get that NaN is Not a Number but have no idea of how it functions.

3. How do the TrendSlopes work? Is it that values > 0 for each indicate an uptrend with 0 indicating no trend and values < 0 indicating a downtrend?

4. How many decimal places are in each floating point number?

Thanks again! Yesterday when I studied my charts after market close I saw that in a number of instances the study gave a clear indication of market direction. With each day I become more and more confident that learning to apply it to my trading will lead to a very profitable future.

Reply With Quote
  #37 (permalink)
 
cbritton's Avatar
 cbritton 
Atlanta, Georgia
 
Experience: Intermediate
Platform: NT
Broker: DDT
Trading: ZN, ZB
Posts: 230 since Mar 2010
Thanks Given: 152
Thanks Received: 256


snowcloud View Post
1. What does the [0] in this line do?

def avgSpread = WildersAverage(spread, volumeEMAlength) [0];

I thought that def creates single variables whereas rec creates arrays. The [0] in this line seems to indicate that avgSpread is an array.

WildersAverage returns an array. The [0] at the end of the line indicates that the assignment to avgSpread should be the value at the 0 index of the array. It's innocuous however since "WildersAverage(spread, volumeEMAlength)" will return the same value.


snowcloud View Post
2. What is Double.NaN and what does it do? I get that NaN is Not a Number but have no idea of how it functions.

Double.NaN is used in the thinkscript plot to indicate that somthing should not be plotted. Thinkscript does not allow arbitrary items to be put on a chart, so you plot a line and turn "on" or "off" values at each bar. Take the red square at the top of the bar for example, the plot is made for every bar but only "turned on" when the criteria is met. Otherwise it is "turned off" by setting the value to Double.NaN.


snowcloud View Post

3. How do the TrendSlopes work? Is it that values > 0 for each indicate an uptrend with 0 indicating no trend and values < 0 indicating a downtrend?

If you are referring to the chart labels for long, mid and short term trend, then the evaluation is done on the linear regression for long, mid and short terms. "Up" is when the slope is positive (>0), down otherwise. There is no flat according to the original NT code. This is the ToS code:

 
Code
                            
# Trend Definitions
rec fiveDaysSma compoundValue(5Average(close5)[0], Double.NaN);
def LongTermTrendSlope LinearRegressionSlope(price fiveDaysSmalength 40)[0];
def MiddleTermTrendSlope LinearRegressionSlope(price fiveDaysSmalength 15)[0];
def ShortTermTrendSlope LinearRegressionSlope(price fiveDaysSmalength 5)[0];
...

AddChartLabel(trendTextconcat("Trend: "concat("Short Term ", if (ShortTermTrendSlope 0then "Up"
    
else "Down")), Color.white);

AddChartLabel(trendTextconcat("Mid Term ", if (MiddleTermTrendSlope 0then "Up" else "Down"), Color.white);

AddChartLabel(trendTextconcat("Long Term ", if (LongTermTrendSlope 0then "Up" else "Down"), Color.white); 

snowcloud View Post

4. How many decimal places are in each floating point number?

This I don't know.


Regards,
-C

“Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat.” - Sun Tzu
Started this thread Reply With Quote
  #38 (permalink)
snowcloud
LA, CA
 
Posts: 93 since Jul 2010
Thanks Given: 2
Thanks Received: 25

Thank you!

Reply With Quote
  #39 (permalink)
snowcloud
LA, CA
 
Posts: 93 since Jul 2010
Thanks Given: 2
Thanks Received: 25

Quote:
If you are referring to the chart labels for long, mid and short term trend, then the evaluation is done on the linear regression for long, mid and short terms. "Up" is when the slope is positive (>0), down otherwise. There is no flat according to the original NT code. This is the ToS code:

[php]
# Trend Definitions
rec fiveDaysSma = compoundValue(5, Average(close, 5)[0], Double.NaN);
def LongTermTrendSlope = LinearRegressionSlope(price = fiveDaysSma, length = 40)[0];
def MiddleTermTrendSlope = LinearRegressionSlope(price = fiveDaysSma, length = 15)[0];
def ShortTermTrendSlope = LinearRegressionSlope(price = fiveDaysSma, length = 5)[0];

End Quote
...

OK, let's see how close I can come to describing in English what's going on here. Please correct my errors.

First, the 5-bar simple moving average based upon each bar's close is placed into a 5-cell array named fiveDaysSma.

Next, 3 trends are defined for LT, MT, and ST by creating arrays of 40, 15, and 5 cells respectively. Only the current [0] value is used to define each slope. (It is not clear to me how the LinearRegressionSlope function creates, for example, a 40 cell array with only 5 cells of data in fiveDaysSma).

Is this description close to correct?

Currently I'm using the VSA study in my 2-minute, 5-minute, and 15-minute charts. Does this mean that the LongTermTrendSlope using 40 cells covers the last 80 minutes on the 2-minute chart , the last 200 minutes on the 5-minute chart, and the last 600 minutes on the 15-minute chart?

****

On another topic I found a possible bug in the code for noSupplyBar. The code for noDemandBar fits pretty well with the description of No Demand and of a No Demand Up-Bar in the glossary of Williams' first book Master the Markets. The study defines it as an Up bar with narrow spread closing down on volume that has been decreasing over a 2 bar period. Williams' book doesn't define it quite as explicitly but the study's code seems to be a good fit.

def noDemandBar = (isUpBar[0] && isNarrowSpreadBar[0] && isTwoDaysLowVol && isDownCloseBar);

However, in the code for noSupplyBar I think that the last term should be isUpCloseBar not isDownCloseBar. No Supply implies lack of selling pressure which would be more evident if the bar closes up not down.

def noSupplyBar = (isDownBar[0] && isNarrowSpreadBar[0] && isTwoDaysLowVol && isDownCloseBar);

****
I am going through the study's code line-by-line and comparing it with Williams' definitions and descriptions. I'll report issues as I find them.

Reply With Quote
  #40 (permalink)
 
cbritton's Avatar
 cbritton 
Atlanta, Georgia
 
Experience: Intermediate
Platform: NT
Broker: DDT
Trading: ZN, ZB
Posts: 230 since Mar 2010
Thanks Given: 152
Thanks Received: 256



snowcloud View Post
Next, 3 trends are defined for LT, MT, and ST by creating arrays of 40, 15, and 5 cells respectively. Only the current [0] value is used to define each slope. (It is not clear to me how the LinearRegressionSlope function creates, for example, a 40 cell array with only 5 cells of data in fiveDaysSma).

Is this description close to correct?

Amost.

The LRS is not computing 40 bars worth of approximation using 5 bars from the SMA. Rather, each value in the 40 position array is the avareage computed by the 5 bar SMA at that time.

The latest value added to the LRS is the 5 bar sma, which is this: (c[4]+c[3]+c[2]+c[1]+c[0])/5

The previous value for the LRS is the same thing, but you can compute it again using the most recent bar: (c[5]+c[4]+c[3]+c[2]+c[1])/5

And so on up until you reach 40 for the LT, 15 for the MT, etc. Notice how the index advances every time a new bar comes into existance.

Think of the 5 bar sma as a line on the graph, the LRS computes the slope of the line between 2 points on that graph: 40, 15 and 5 bars away (roughly speaking).



snowcloud View Post
On another topic I found a possible bug in the code for noSupplyBar. The code for noDemandBar fits pretty well with the description of No Demand and of a No Demand Up-Bar in the glossary of Williams' first book Master the Markets. The study defines it as an Up bar with narrow spread closing down on volume that has been decreasing over a 2 bar period. Williams' book doesn't define it quite as explicitly but the study's code seems to be a good fit.

def noDemandBar = (isUpBar[0] && isNarrowSpreadBar[0] && isTwoDaysLowVol && isDownCloseBar);

However, in the code for noSupplyBar I think that the last term should be isUpCloseBar not isDownCloseBar. No Supply implies lack of selling pressure which would be more evident if the bar closes up not down.

def noSupplyBar = (isDownBar[0] && isNarrowSpreadBar[0] && isTwoDaysLowVol && isDownCloseBar);

Makes sense to me. I don't have the NT code with me to compare with. I could have made a mistake in conversion, but the entire reason why I've documented the process on this thread is so mistakes can be identified and corrected


snowcloud View Post
I am going through the study's code line-by-line and comparing it with Williams' definitions and descriptions. I'll report issues as I find them.

This is something I've been wanting to do but I don't have the time. I appreciate your efforts!!

Regards,
-C

“Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat.” - Sun Tzu
Started this thread Reply With Quote




Last Updated on May 21, 2023


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts