TOS & Thinkscript Collection
TOS & Thinkscript Collection
Jim Shinger
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Snippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Legend. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Revised: 07/25/14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Organization:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
IMPLEMENTING LABELS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
boolean visible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Any text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
CustomColor Color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
A trap to avoid:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
AGGREGATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
RULES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Specifying plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Specifying parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Combo Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
B&C-NORMALIZATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
LINEAR REGRESSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
LinearRegCh100. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
LinearRegCh50 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
LinearRegChVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
LinearRegCurve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
LinearRegTrendline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
LinearRegrReversal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
LinearRegressionSlope. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
An 'AsDollars' example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
An AsDollars example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
An AsPercent example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
An AsPrice example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
C-EXAMPLE OF 4 NORMALIZATIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
C-IMP-VOLATILITY PERCENTILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
C-YTD PERCENT CHANGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
C-MARKET SENTIMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
C-CANDLESTICK PLOTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
C&S-EARNINGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
C-INSIDE-BAR CODING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Alternate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
C- DMI_OSCILLATOR_SFL_FAV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
C- PolarizedFractalEfficiency_SFL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
C- Three_X_Oscillator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Scans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Contact Me . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Preface
The "TOS and Thinkscript Snippet Collection" by Stanl has been a great help in my thinkscript
development journey. I constantly look to this work for ideas and techniques.
It appears that "TOS and Thinkscript Snippet Collection" hasn’t been update in 3 years as of this
writing, … I am not sure if something happened to StanL or what.
My Motivations: I found the pdf hard to read at times and I want the great work StanL did to live
on. So I converted the PDF to Asciidoctor html format. TOS-and-Thinkscript-Snippet-Collection.
As converting from PDF is a lot of work, … This is a work in process and I will continue to work on
the formatting and clean up.
Please feel free to fork and send me pull requests or corrections and additions.
Introduction
Snippet
A 'snippet' is a small piece(s) of script, oriented towards accomplishing a specific function identified
1
by the snippet’s title:Sort of a building block. This PDF takes the liberty to include TOS-platform-
features that are not only script snippets but may be any TOS features worth knowing. Perhaps this
document can, more appropriately, be call an 'Almanac'.
The emphasis herein is for learning TOS and ThinkScript from the ground up. Numerous examples
are used as a learning tool ranging from simple/basic to complex. The PDF format was selected,
with extra features, like the hyperlinked Table-of-Contents, to make subjects easily found. This
document also proovides a reference for future coding activities.
Hence being familar with what is available herein, will enhance recall when needed. A good PDF
reader with search capability is also recommended.
Legend
Click the underlined Page ? to go to that page When there, you can return to to the TOC by clicking
Return to TOC.
Titles appearing in the Table Of Contents above are the same and colored blue throughout this
document
Revised: 07/25/14
Organization:
The first letter indicates the category of the subject.
B- = Basic platform or coding subjects, fundamental principles, fundamental examples and how-to-
do’s
S- = Scan
T- = A Tip or Trick on how you might use TOS or TS to accomplish a specific useful purpose
?- = In the subject’s heading, ? means that the data is variable 'inputted' data defined by the user
C&S- = On occasion, a item may also have multiple codes defining what is included inside. For
example, this symbol indicates when scan code is included.
Acknowledgements
The people on the ThinkScript Lounge and Yahoo TOS_ThinkScript generously contribute much
time and effort helping those learning and using ThinkOrSwim and ThinkScript. Many items herein
originated on the those chatroom postings.
Much credit and thanks are due those people. We are all grateful to them for their selfless
contributions.
2
Usage
Although a subject may not be of interest to you, the coding techniques involved may be pertinent
to what you desire to code, either today or at some time in the future. It is useful to be aware of the
techniques so that, when the time comes, you will know where to look to get the how-to-do
specifics.
Hope you find this document useful. Any suggestion for improvement or inclusion are welcome.
Use of '…' and "…" Often the single and double quotes are used to identify precise coding, words or
statements whose use is not intended to include the quote marks themselves. At times coloring may
also be used to do the same.
'Pre-defined' and 'built-in' are synonymous when referring to studies that are provided by TOS
within the program. The coding of these may be copied and reused in your own studies but built-ins
cannot be changed.
If you want to find something, enter what you want into the 'find' tool of the PDF reader and it will
navigate you to the possible matches. Try different 'find' entries if you are not successful. Subjects
are often named differently. The most expeditious search is looking over the TOC or using 'find' in
the TOC as opposed to using 'find' throughout the body of the document.
3
Add Info Bubbles To a Study or a Study’s Inputs
As shown above the study list and the inputs have info bubbles. You may add these info bubbles to
your studies.
1. Above the code lines, place #hint: ???????? where ???????? is the description you want
displayed when the bubble is clicked.
2. The tags listed under 'TAGS and their PURPOSE:' may be used to format the ????????.
3. An example is --→ #hint: Plots a <b>trend line</b> between the two input dates.
1. Immediately after the semi-colon on the input’s line (preferred location), place #hint <the input
variable name>: (the desired text you want displayed when the bubble is clicked) .
2. The tags listed under 'TAGS and their PURPOSE:' may be used to format the desired text.
3. An example is --→ input Length = 10 #hint Length: The number of bars used to calculate the
average.
4. Notice that the colon is placed after the input variable name (in this case Length).
Formatting is possible using HTML tags. Some of the common tags you may be interested in are
listed below:
<b> ......... </b> Makes the text between the tags bold.
4
#hint: <b>Bar Count Between Highs</b>\n Counts the number of bars between each high in the
specified length.
• http://demo.thinkorswim.com:7001/manual/metal/thinkscript/reference/Functions/Others/
If.html . The other two are
• http://demo.thinkorswim.com:7001/manual/metal/thinkscript/reference/Reserved%20Words/
if.html . The thinkscript documentation infers that there are more forms of the if-then-else, but
the additional examples are merely the base form shown with nested if-then-else
statements/expressions.
The syntax is: If(double condition, double true value, double false value); This is the simplest
and easiest to use. An example is: Plot Maximum1 = If(close > open, close, open); This reads as “If
the close is greater than the open, then plot the close. Otherwise/else, if the close is not greater than
the open, then plot the open.” This form is very useful as the right-hand side of the equal sign in a
Plot or Def statement. Also this form can be used with else to create more complex conditions. This
form is a function and returns a type of double that is very useful for the if-then-else
statements/expressions when you are processing numbers and nesting.
The word 'double' is often vague in its meaning in ThinkScript but it means a floating-decimal-
point-number of double precision in programming terminology. Any further meaning-clarification
is unnecessary here. The impact of 'double' is that constants such as the names of the 23
ThinkScript colors, like LIGHT_RED, BLUE, UPTICK, etc., are not floating point numbers and hence
cannot be used in this immediate-if. In this case, the if-expression would be used.
The syntax is: if close > open then close else open; An example is: plot Maximum2 = if close >
open then close else open; An IF….THEN….ELSE are all required. A nesting (putting if’s within if’s)
example, in the recommended layout for easy reading, is:
Note that the last 'else open' relates to the 'if close > open' and applies when the intermediate
'else-if close = open' is not true. This nested-if reads as: If close is greater than the open then plot the
close. If the close equals the open then plot the (low + high)/2 . If the close is not greater than the
open and the close does not equal the open, then plot the open.
5
The if-expression will have only one semi-colon that will terminate the entire expression,
regardless of the complexity.
plot Maximum3;
The '[then]' above means that it is optional but it is recommended that it always be used for
clarity. Notice that each statement is enclosed within a block (the parts enclosed in the { } ) and must
end with a semi-colon.
plot Maximum1 = If(close > open, close, open); # This is the immediate-if syntax
plot Maximum2 = if close > open then close else open; # This is an if-expression
Excellent examples of the power of if..then..else can be seen in these documents herein:
A very favorite feature is to change the color of a plot based on a condition that you
define. The 'HullMovingAvg' illustrates this very well. Here is its code:
6
input price = close;
input length = 20;
input displace = 0;
HMA.DefineColor("Up", GetColor(1));
HMA.DefineColor("Down", GetColor(0));
HMA.AssignValueColor(if HMA > HMA[1] then HMA.color("Up") else HMA.color("Down"));
In the above HMA>HMA[1] is the condition that says IF the current HMA is greater than the
previous value of the HMA, i.e. HMA > HMA[1] , THEN paint the plot with the “Up” color which is
defined as color(1) OTHERWISE/ELSE paint the plot with the “Down” color which is defined as color
(2). (1) and (2) are color index numbers. Color-assigned-index-numbers are explained in the
separate topic.
The condition is always in a 'if…. then…. else' format. If-statements may be nested without limits.
The format thenbecomes 'if…..then….. else if…..then…..else if…..then……else'. The closing 'else' is
always present and relates to the initialif…. then when none of the nested if …then’s produce a
result.
Example:
if SlowK > SlowD then color.green else if SlowK < SlowD then color.red else color.gray
The multiple conditions may be used to define a conditional statements. They are joined by 'and' or
its equivalent '&&'.
Example:
def RangeCondition = ADX > 0 && ADX < 13;# ADX is between 0 and 13
Diamonds.AssignValueColor(
If BullishCondition then color.green else
If RangeCondition then color.white else
If BearishCondition then color.red else
color.black);
Note in the above, since color.green, color.white, color.red and color.black are constants and not
double variables, the if-expression must be used and that requires the presence of all IF…..THEN…
..ELSE parts.
7
AddLabel(1, Concat("IV Percentile ", AsPercent(perct)), if perct > 0.80
then Color.Green
else if perct < 0.80 and perct > 0.50
then Color.Yellow
else color.Red);
In studies or strategies, ThinkScript runs your script once for each and every bar on your chart,
regardless of the aggregation period.
You will often hear knowledgeable programmers say with disappointment that 'ThinkScript' does
not have arrays. Arrays are a common powerful programming feature for storing/recalling various
data and data types. This is a limitation of ThinkScript that we must live with as best we can.
The colors are used via the function 'GetColor(index number);' Example: GetColor(1) as used in the
HullMovingAvg previous topic. Reference: [See Index Colors]https://tlc.thinkorswim.com/center/
charting/thinkscript/reference/Functions/Look---Feel/GetColor.html
8
9
Table 1. Table Colors
This free tool will help you to get the RGB values for any color you desire to compose.
http://www.colorschemer.com/online.html
Note that colors 'UPTICK' and 'DOWNTICK' are defined respectively as a red and green tone because
they are frequently used in chart coloring. In the above chart the capitalized words are the names
used to specify that color i.e. color.CYAN or color.LIGHT_RED.
Not all colors are defined: for example, PURPLE. You may find any color at
http://en.wikipedia.org/wiki/List_of_colors:_A%E2%80%93F or http://en.wikipedia.org/wiki/
X11_color_names .
You can create that color for use in TOS by using the function 'CreateColor(double red, double
10
green, double blue); ' similar to the RGB Code in the chart above. Each RGB component ranges in
value from 0 (meaning none or 0%) to 255 (meaning the max 100% value).
You may also assign a text-name, for later use, to any color you create via
DefineGlobalColor("Purple" , CreateColor(160,32,240) );
Other constants:
11
The name "normal" above is unique to the RSI plot. Another plot cannot use the name 'normal'
without redefining it.
NinetyPercent.SetDefaultColor(GlobalColor("normal"));
Note that UPTICK and DOWNTICK are TOS predefined color constants
Or
DefineGlobalColor("Purple" , CreateColor(160,32,240) );
After the above global definition, GlobalColor("Purple") can be use wherever a color is needed. For
example:
Price.SetDefaultColor(GlobalColor("Purple"));
12
plot Data = close;
Data.SetDefaultColor(color.RED);
or
IMPLEMENTING LABELS
Labels are boxes of info placed at the top-left of a study. They are very useful and well worth the
time to master them.
The label function is AddLabel(boolean visible, Any text, CustomColor color); and has three
components.
1. ' boolean visible' is a true or false statement that defines when the label shows or doesn’t
show. If you use a '1' or 'yes' here it will always show the label, Otherwise you define a condition
or an input selection-value that evaluates to 'true' or 'false' and reference that condition
statement here.
2. 'Any text' is what appears inside the label box. There are two way to compose this text using
'concat' or '+' syntax(known as the string concatenation symbol). Concat is a term that means to
connect two text phrases together. This includes converting ThinkScript variable-values into
text.
3. ' CustomColor color' defines the background color of the label box. The text font color is always
black.
boolean visible
This can be a 'yes' or 'no', or any condition statement or a reference to: (1) a previously defined
condition statement; or (2) an input true/false value. When this evaluates to 'true' then the label will
show or, when false, will not show. This is very handy when referring to an input whose value
choices are 'yes' or 'no'. Programmers use the yes/no input in condition statements to display or
not-display certain features such as the labels or plots.
Any text
The label’s text can be defined using using 'concat' or '+' which is known as the string
concatenation symbol. Using the '+' symbol is much easier to master and is recommended.
Examples will help explain:
input weeks = 4;
AddLabel(yes, concat(weeks, " Weeks till expiration"), color.YELLOW);
13
Using the '' symbol …. `AddLabel(yes, weeks + " Weeks till expiration", color.YELLOW);` produces
the same label as above. You will find that complex texts with numerous segments are much easier
to compose using the '' symbol. There is, however, one pitfall to be avoided using the '+' symbol as
discussed below:
The key is when using the + syntax, one must put all calculations-within-a-label inside of
parentheses. Also multiple conditions such as HiTrue && LoTrue should be within parenthesis like
(HiTrue && LoTrue).To illustrate this, a right and wrong is shown below:
This works:
See also LITERAL TEXT IN LABEL FOR THE 11 CHOICES OF INPUT PRICE and C-% CHANGE OF THE
FIRST BAR VALUE and C-ADD AN INDEX OR FUTURE LOWER CHART for examples of putting drop-
down literals into label text.
CustomColor Color
• Defines the color of the label box. Conditional coloring can also be had with the addition of if…
.then…..else statements. There are no limits to the number of conditional statements but they
follow the format if…..then….else if…..then…..else if…..then…..else. Note the closing else that
relates to the very first 'if…..then'.
You may have a label take on the same color as a plot. The syntax is: ChartPlotName.TakeValueColor()
There are times when a label interferes with the top of a plotted chart’s data. To avoid that, you can
plot a line at the top of the chart at a value above the plots data. The labels will then have their
centerline equal to the value of the line.
To make the line invisible, paint it the same color as your background.
AddLabel is an excellent tool to observe a value for debugging purposes. In addition to that, a neat
trick is, while in the code editor, drag the editor window down so that you can see the chart’s label
and header values. That way, when you change the code and press apply, you can see the value
change while staying in the code editor.
If you are inclined towards the use of concat, here is a guide on its use as well as an example of
conditional coloring.
14
The equivalent using the '+' syntax is:
The built-in ZigZagPercent study demonstrates the excellent use of conditional showing of the label
itself, the use of the + syntax and conditional coloring. The code is duplicated below:
AddLabel(showLabel and barNumber != 1, (if isConf then "Confirmed " else "Unconfirmed
") + "ZigZag: " + round(chg) +
"%", if !isConf then globalColor("Unconfirmed") else if isUp then globalColor("Up")
else globalColor("Down"));
SLOPE OF AN AVERAGE herein shows how to reteieve the literal of 'AverageType' choices in a label.
A trap to avoid:
If your definition of the label text involves long and multiple 'if…then…else' statements, to insure
that they all print, enclose each 'if…then else' statement in parentheses e.g. '(if…then…else)'.
Otherwise, you may not get an error but an 'if…then…else' statement may not print. C- THE
'AdvanceDecline' STUDY herein is an excellent example of this.
AGGREGATION
15
Each bar on a plot represents a period of time known as the primary aggregation: one minute, five
minutes, day, etc.
A chart may also have one or more secondary aggregations. Variables are assumed to be of primary
aggregation and those of a secondary aggregation must have their aggregation specified every time
they are used.
def Agg = AggregationPeriod.FIFTEEN_MIN;# Use the desired constant to specify the time plot Data
= close(period = agg) / close(period = agg)[3];# The phrase 'period =' is always used when referring
to the variable aggregation. In this case 'agg'.
You may need to learn other ways of specifying aggregation to read other people’s code such as in
the built-in DailySMA.
RULES
1. The secondary aggregation period cannot be less than the primary aggregation period defined
by chart settings. This is a hard-fast rule that often comes into play.
2. Two different secondary aggregation periods cannot be used within a single variable. You can
define each separately and then use the two definitions in a single statement.
It has been observed that using more than one secondary aggregation may affect the proper
plotting. Using 'Expansion Area: ? Bars to the right' in chart settings may have an improvement.
A single "=" is the assignment operator. The statement "input Show_ChartPeriod = yes;" reads:
assign (or set) the memory location labeled 'Show_ChartPeriod' to yes (boolean TRUE);
The double "==" is the logical equality operator. The statement "if AggPeriod ==
AggregationPeriod.DAY then … else…;" reads: if the variable AggPeriod equals (is the same as)
AggregationPeriod.DAY then do something else (otherwise) if it’s not, then do some other thing.
When evaluating equality in an 'if' statement, two equal signs must be used ('==').
Not related to the above = and == is the "bang" (exclamation mark). As an example, use isnan()
which returns true if the specified parameter is not a number, returns false otherwise. The ! (
exclamation mark called "bang" ) is a logical NOT perator. So if 'isnan(close)' is true i.e.
since/when close is not a number then 'isnan(close)' reads as true. Using the "bang" and close
remains not being a number, then '!isnan(close)' reads as " NOT close is not a number" or NOT
true = false when close is not a number (⇐0).
16
REFERENCING OTHER STUDIES
This subject is about including existing studies in your code 'by reference' in lieu of duplicating its
actual code. The syntax for this procedure is: reference <StudyName>(parameter1=value1,..,
parameterN=valueN).<PlotName>
Occasionally a study and a function may have the same name e.g. vwap and moneyflow. In that
case: - Call the vwap function like ….plot MyVWAP1 = vwap; - Reference the vwap study like ….plot
MyVWAP1 = reference VWAP; - The use of the word 'reference' is optional but, if 'reference' is omitted,
the () must always follow the study’s name. Example: plot MyVWAP1 = VWAP();
In studies, you may reference built-in studies but not user-defined studies in (currently). However,
user-defined studies may be referenced in scans.
In the following, the 'StochasticSlow' study will be used as an example for explanation.
Specifying plots
Studies may have a single plot or multiple plots: ' StochasticSlow' has four plots named SlowK,
SlowD, OverBought and OverSold. Referencing the SlowD plot would be via StochasticSlow().SlowD
Just using StochasticSlow() would plot the SlowK because SlowK is the first plot in the actual code
and is the default. Since no parameters are specified, the default parameters specified in the actual
code are automatically used. Using parameters is explained below.
Specifying parameters
If you look at the actual code of StochasticSlow study you’ll see that it has a series of "input"
variables. Those are the default parameters and cannot be changed because they are in a pre-
defined study which is not editable. There are three ways to specify parameters: (1) Full form; (2)
Compact form; and (3) A combo of (1) and (2). Specifying no parameters will use all the default
values. The parameter list is in a fixed order of inputs from left to right i.e. each parameter/input
has a fixed location in the list.
Full form
The full form specifies the input variable name with its intended value. An example is:
def SlowK = StochasticSlow( KPeriod = 10, DPeriod = 10, priceH = High, smoothingType = "SMA" );
Any parameter not listed herein takes on its default value. Note that the names like 'KPeriod',
'DPeriod', 'priceH', 'smoothingType' and others are as defined in the actual code’s input list.
Compact Form
The compact form is simplest in that you simply put your values in the place/position of the default
parameter you wish to change. You start with the first input value as the left most value in the
reference. An example is:
17
def SlowK = StochasticSlow( 80, 20, 10, 10, high, low, close, "SMA" ).SlowK;
Note that you cannot omit any intermediate values or modify their positions. Only the right-most
parameters may be dropped off and those will then take on their default values.
Combo Form
This allows you to choose only the variables you want to change. An example is:
def SlowK = StochasticSlow( 80, 20, 10, 10, smoothingType = "SMA" ).SlowK;
Here you have omitted the price parameters. Once again, you must preserve the parameter’s
position rule.
There are two ways of referencing constant inputs : smoothingType = "SMA" and smoothingType ==
smoothingType.SMA are equivalent.The first is the short syntax ("SMA"), while the second is the full
syntax .
A different but related subject is referencing pre-defined studies using 'Script'. See
http://tda.thinkorswim.com/manual/metal/thinkscript/tutorials/advanced/referencing/
other%20study.html
B&C-NORMALIZATION
If you want to compare two (or more) indicators that have values much different that are non-
receptive to comparison, you can normalize each of the two (or more) indicators and compare
them on a basis you define i.e. 0 to 100%, -1 to +1, -100 to +100, or whatever you want. Below is the
code to do normalization and an example. Note that not all studies can be normalized e.g. 'AccDist'
has no parameters and cannot be normalized.
script normalizePlot {
input data = close;
input newRngMin = -1;
input newRngMax = 1;
Examples
18
input price = close;
input CCI_length = 7;
input Momentum_length = 12;
input RSI_length = 4;
input WR_length = 10;
input newRngMax = 100;#Maximum normalized value
input newRngMin = 0;#Minimum normalized value
input OverBought = 80;#Fixed value upper line for reference
input OverSold = 20;#Fixed lower value line for reference
By the way, you can identify a recursive variable definition when the variable itself, in this case
'count', also appears on right side of the equal sign/equation like, in this case, 'count[1]'.
If you have a reason to re-start the counting from 0 or 1 based on a defined condition, you place the
condition after the 'else' like 'else if <condition to restart counting> then 0 ' and close with 'else
19
count[1]'.
LINEAR REGRESSION
There are several built-in Linear Regression studies in ThinkScript. This section is intended to
clarify their differences and usage.
http://tda.thinkorswim.com/manual/metal/thinkscript/reference/Functions/Statistical/Inertia.html
1. LinearRegCh100
2. LinearRegCh50
3. LinearRegChVar
4. LinearRegCurve
5. LinearRegTrendline
6. LinearRegrReversal
7. LinearRegressionSlope
LinearRegCh100
Uses the data of the entire plot. The upper and lower channel lines, parallel to the centerline (the
true linear regression)., indicate the furthest that the data has been from the middle line The '100'
in the title means that it shows the upper and lower lines at 100% of the data difference from the
centerline .
LinearRegCh50
Is the same as the LinearRegCh100 except that the upper and lower lines ar at 50% of the of the
data difference from the centerline in lieu of 100%.
LinearRegChVar
This version allows the user to define the 'percentage-distance-from-the-centerline' of the upper
and lower lines. Also, this version allows the user to select the number of bars for the linear
regression plot in lieu of the previous two studies that use the entire chart (all bars).
20
LinearRegCurve
Plots a single curve in which you have defined the type of price and the number of bars as the basis
for the curve.
LinearRegTrendline
Uses the data of the entire chart. Plots a straight linear regression line for whichever of the eleven
choices you have selected. The choices include other than price items such as volume and 'imp
volatility'.
LinearRegrReversal
This study indicates "+1" when the current value of Linear Regression Curve is equal to or greater
than that of the previous bar and "-1" otherwise. If you compare this to the LinearRegCurve be sure
to use the same number of bars input for each study.
LinearRegressionSlope
Plots the changing slope of the LinearRegCurve based on the price and length that you select.
Note that LinearRegCurve, LinearRegTrendline, and LinearRegressionSlope all have the same
eleven price input choices.
Studies #1, #2 and #3 are very popular in searching for stocks that are at buy-low prices. You may
find these especially beneficial to learn and comfortably use them.
As an example let 10 be the original value (B4) and 15 the final value (NOW). NOW/B4 is the
"RATIO"
First way:
In words, final value divided by the original value; minus one; times 100. or 15/10 = 1.5; 1.5 - 1 = 0.5;
0.5 X 100 = 50 % increase
Example:
21
Second way:
In words, the change difference (NOW minus the B4) divided by the original (B4) value times 100.
or 15 -10 = 5 = change difference; 5/10 = 0.5; 0.5 X 100 = 50% increase.
If the difference (B4 - NOW) is negative the percent is also negative i.e. 'decrease'. Also if the
"RATIO" (NOW/B4) is less than zero then the percent change will be negative.
Example:
Additional Comments:
The two ways above example, "value1 is what percent larger/smaller than value2." For value1 = 85
and value2 = 38 then: 85 /38 = 2.24; 2.24 X 100 = 224%. In words value1 is 224% of value2. Or, in a
different way, it can be said that 2.24 -1 = 1.24 X 100 = 124% which reads that value1 is 124% larger
than (or above) value2.
An aside: A calculated value of -0.0331 will be formatted with 'AsPercent' to show the below label in
cyan.
input length = 9;
AddLabel(yes, AsPercent((close - close[length]) / close[length]),color.cyan);
An 'AsDollars' example
22
An 'AsText' plus 'decimal-places' example
An AsDollars example
AddLabel(yes, "Current True Range is " + AsDollars(TrueRange(high, close, low)),color.cyan);
An AsPercent example
An AsPrice example
AddLabel(yes, "10 period SMA of Close price using 1/32nds price notation (XXX’YYZ) = "+
AsPrice(Average(close, 10)),color.cyan);
23
#Puts any of the 11 price choices into a literal text in a label like ohlc4 = 75
input price = close;#Price automatically avails 11 choices and the label below tells
which was selected.
#Puts any of the 11 price-choices into a literal text in a label like ohlc4 = 75
Comments: The 11 choices of Price are close, high, hl2, hlc3, imp_volatility, low, ohlc4, open,
open_interest, volume, vwap.
Def swinghigh = if high > high[1] and high > high[2] and high > high[-1] and high > high[-2]
then 1 else 0;
Or if you are interested in the rise of the last 5 bars, you may use something like this:
plot pivotHigh = if high == (highest(high, 5) and sum(high > high[-1], 5) == 5) then high else
Double.NAN;
The code for a swing low is similar. Note that the confirmation of a swing point does not come until
2 bars after the swing high in this case. If you wanted to extend the swing check to 3 bars before
and after, you would add the checks for a high > high[3] and high > high [-3]. The resulting swing
24
will be more significant, but the signal comes 3 bars after the fact.
This would paint a dot on all the swing highs, and nothing everywhere else. The code for swing
lows is similar.
This is the simplified basics of swingHi/SwingLo. Many coders add all kinds of conditions to
supplement the simplified code herein. Also the look-back and the look-forward lengths do not
need to be the same.
• If none of the ready-made comparisons have what you want, then click 'Custom Symbol….'
If you have forgotten or are unsure of the symbol, you can find it easily as follows:
25
The comparison will be overlaid on the upper panel using the left-hand price scale. You can edit the
study to change the symbol or the type of plot, i.e. Line, Bar, Candle, or the color. Choose any
aggregation but 'day' is most meaningful.
def <result> = fold <index> = <start> to <end> [ with <variable> [ = <init> ] ] [ while
<condition> ] do <expression>;
Each component of the fold function will be explained separately. The function is not easy to use
but understanding the purpose of the components will help you to feel comfortable with it.
General Comment:
• The fold function is used to define the value for a named variable i.e. def <result>. You cannot
operate on other variables or do anything within the fold. Studies may be used within a fold.
• Rather than define a variable, the fold may be plotted directly i.e. def <result> = becomes Plot
<result> =.
• Remember that the fold calculation is executed at every bar as ThinkScript processes from bar 1
to the last bar.
• As discussed in GetValue below, studies may be used in the Fold function especially in the do
<expression>.
• The names assigned <index> and <variable> are persistent variables. Hence, if you have two
folds in a study and you assign 'idx' to <index> in the first fold you cannot assign 'idx' to <index>
in the second fold. This will create an error.
• Fold will normally work in a scan and custom columns. Complexity may become an issue
especially if the servers are loaded up.
• fold
26
• A fixed word that identifies the following as a 'Fold' function.
• This defines how many times the fold calculation loops on each bar. You need to figure out how
many times "fold" needs to repeat itself, OR at what value it is going to stop churning away. Let’s
say you want a calculation to repeat 5 times. If the <start> is at 0 and the <end> is at 5, then the
calculation will repeat 5 times. <start> is inclusive but <end> is exclusive. When the counter gets
to 5, fold stops and there is no results related to loop 5. <index> can be any name you want but
'i' or 'index' is commonly used e.g. i = 0 to 50. The value of the index can be used in the do
<expression>. When <index> is used in the do statement, the last value of <index> is used and
not the current value. The current value would be <index> + 1.
• First of all, anything within brackets is optional. So when/why would you include this.?The
answer lies in that this is an internal variable that fold uses. So when is it needed? If the 'do'
section of the fold performs a activity like 'add to', 'multiply by' or similar, it must have a
previous number to 'add to' for example. This 'with <variable>' is the value that will be added to
when you see code like 'do nice + idx3'. This means that 'nice' is the with <variable> that fold has
been keeping tract of internally and '+ idx3' is the current loop’s calculated value that is to be
added to nice. 'nice + idx3' then becomes the new value of the internal variable nice and nice is
available for the next loop’s calculation. <variable> can be any name you want to assign. In this
example, 'nice' was used.
• [ = <init> ] is the initial value of the 'with <variable>' and is optional. If it is omitted, then the
default value of 0 is used. <init> is a number. Since it is in brackets, it is optional if there is a
with <variable>.
• [ while <condition> ]
• This defines a condition, upon violation of which, the loop (not the fold itself) is terminated
when calculating the fold function and TOS procedes to the next bar. The fold will do some
action but that action may be subject to certain conditions. This [ while <condition> ] defines
conditions/ limitations that are imposed on the actions that follow. The conditions may qualify
the do-actions results or they may define conditions that terminate any further loops at the
current bar. Conditions here do not preclude the 'do' statements from having an 'if' statement
that may also set conditions but those conditions are used in getting the desired result from the
'do' statement. A example would look like
• do <expression>
• Defines an action to be performed, for each loop, when calculating the fold function. The do
<expression> may be of numerous types. For example, if it is a true/false type then the fold
results will be a true/false. Or it may be a arithmetic type like 'do nice * index' which multiplies
fold’s internal variable, nice, by the index value. Another example is 'do nice + getValue(close, n,
length - 1)) / length'(a simple moving average) which gets a close value; divides it by a length
variable; and adds it to the internal variable, nice. Or it may be a more complicated fold such as:
fold i = 0 to 100 with price = Double.NaN while !IsNaN(price) do if getValue(high, -i) > 40 then
getValue(high, -i) else Double.NaN; This finds the next high price value greater than 40 among
the following 100 bars and terminates looping if price is no longer a number.
27
• GetValue function
• The syntax for GetValue is: GetValue(IDataHolder data, IDataHolder dynamic offset, int max
offset);
• A discussion of fold would not be complete without discussing the GetValue function. This
function goes and gets data used in the do <expression>.
• The third parameter, int max offset,is a fail stop value to prevent an endless loop in the
scripting engine. Ideally it should be set to the maximum number that the dynamic index is
expected to be. Set it too small and the script engine stops the loop before all index values are
processed. Set it too high and you may unnecessarily be wasting server capacity. It would be OK
to set it a little higher than you know is needed. If the script engine hits the stop value you’ll get
a run-time error message.
Note that int max offset is a fixed integer value, while IDataHolder dynamic offset is an expression
that defines the offset value. The expression used for the IDataHolder dynamic offset often has a
length parameter in it and that length parameter is also the value used for int max offset. Two very
popular expressiona for IDataHolder dynamic offset are LookUpHighest(price,'look up
price',length) and LookUpLowest(price,'look up price',length). The length inthese two studies is
often the value that int max offset is set to.
• do <expression>
Examples of
• The heart of the fold function is the 'do expression' which is crucial for success but is not
naturally intuitive. A number
• Example 1 :
• input n = 10;
• Calculates the factorial of a number. 10 loops are executed and each loop is multiplied by the
value of the previous loop.
Example 2 :
Calculates the simple moving average using fold. 9 loops are run i.e. 0 thru 8 with the internal
variable named Var_ma.
Note the importance of the index starting with 0. The first value is getValue(price,n) or price[0] . If
the index was to be 1 thru 10, the current value of price would not be included in the average
28
because the first value would be price[1].
Example 3:
This simple fold sums the 'index' values. The AddLabel enables you to change any variable and
predict what the label will show. If not determine where your thinking went astray.
Example 4:
This is interesting because it illustrates the concept of the fold and def being applied to every bar.
The def causes each bar to hold the value of bigCount and the fold’s 'do a + bigCount[1]' essentially
causes each bar to be increased by a factor of 9 due to its looping. It is easy to see that the result will
eventually reach infinity for a normal sized chart. It’s not likely that you will ever use a def value in
a do statement of a fold like this. This is known as a runaway calculation.
Example 5:
input length = 10
def smlCount = compoundValue( 1, fold idx2 = 1 to length with b = 0 do if smlCount[1]
>= 1000 and b >= 1000 then 1000 else b + smlCount[1], 1 );
This allows 'smlCount' to rise to 1000 and then it limits smlCount toa value of 1000.
Example6:
What is the value of test? If your answer was not 7, rethink it.
If we change it to:
Example7:
29
input period = 20; #hint period:Number of bars to look in
def Hi = fold i = 0 to period with n = high do Max(n, GetValue(high, i, period - 1));
def Lo = fold k = 0 to period with m = low do Min(m, GetValue(low, k, period - 1));
AddLabel(1, "High in last " + period + " bars = " + Round(Hi,2), Color.GREEN);
AddLabel(1, "Low in last " + period + " bars = " + Round(Lo,2), Color.GREEN);
Labels allow you to look at the chart and verify the values.
Example8:
This fold counts the number of times, in the last 20 bars, the SDr (std dev of the change ratio) has
fallen below the SD.
Example9:
declare lower;
input volTarget = 200000;
input length = 20;
plot atLeastVolumeTgt = fold idx = 0 to length + 1 with s = yes while s == yes do if
GetValue( volume, idx, length + 2 ) >volTarget then yes else no;
The above works as a study, omit the "declare lower;" if you want to use it directly in a scan or
column.
This code that will check for "daily" average volume greater than 200,000 in the last 20 days,
meaning that the stock should have traded at least 200,000 shares every single day for at least the
last 20 days. If it complies, 1 is plotted if not 0 is plotted. In a study, it is more meaningful to put the
1 or 0 result in an clarifying label.
In the above 'Scan/StockHacker' tab, all fundamental filters have been deleted using 'red-circled-X'.
• To re-establish, click 'Add Fundamental Filter'. Only a 'Study Filter' is showing now.
30
THE STOCHASTIC OSCILLATOR EXPLAINED
Comment 1: The stochastics indicator can be confusing because it is referred to as: 1. Fast
Stochastics; 2. Slow Stochastics; or 3. Full Stochastics. This video gives a clear explanation of the
differences between the three in Part 1 and usage in Part 2. See video (2 parts)
Comment 2: While at this site check out the other indicator tutorials that may interest you. View
indicator tutorial list
Whenever you see 'squared' or 'square root' in a technical calculation, SD is likely involved because
'squared' and 'square root' are used to calculate the SD in that mildly complex formula . Also,
whenever someone talks of a 'Gaussian distribution' they are talking of a 'normal distribution'
curve. Likewise for 'Bell curve'.
SD values
31
#hint:Draws upper & lower bands at defined percent
input length = 10;#hint length:Length of base ExpAverage
input percentShift = 5.0;#hint PercentShift: Percent of upper & lower bands from
ExpAverage
input price = close;#hint price: Basis for base ExpAverage
input SD1Up = 1;
input SD1Dn = -1;
input SD2Up = 2;
input SD2Dn = -2;
input SD3Up = 3;
input SD3Dn = -3;
def avg = Average(price, length);
def StdDev = StDev(price, length);
plot StDev1Up = avg + (SD1up * StdDev);
plot StDev1Dn = avg + (SD1dn * StdDev);
plot StDev2Up = avg + (SD2up * StdDev);
plot StDev2Dn = avg + (SD2dn * StdDev);
plot StDev3Up = avg + (SD3up * StdDev);
plot StDev3Dn = avg + (SD3dn * StdDev);
32
all kinds of conditions and resulting actions.
C-EXAMPLE OF 4 NORMALIZATIONS
Usage: 'input data = close' is substituted by any indicator and its parameters.
declare lower;
script normalizePlot {
input data = close;
input newRngMin = -1;
input newRngMax = 1;
def HHData = HighestAll( data );
def LLData = LowestAll( data );
plot nr = ((( newRngMax - newRngMin ) * ( data - LLData )) / ( HHData - LLData )) +
newRngMin;
}
Examples
33
input price = close;
input CCI_length = 7;
input Momentum_length = 12;
input RSI_length = 4;
input WR_length = 10;
input newRngMax = 100;#Maximum normalized value
input newRngMin = 0;#Minimum normalized value
input OverBought = 80;#Fixed value upper line for reference
input OverSold = 20;#Fixed lower value line for reference
The switch statement is used to control the flow of program execution via a multi-branch using the
enum Def, and enum input: Its features are:
• It processes an enumeration: In this case 'input exchange'. Each enum value has a case ????:
where ???? is the enum value.
• If each item in the enum’s list i.e. {default NYSE, NASDAQ, AMEX}, does not have a case, then
there must be a case default: In this example, each of the enums has a case so there is no case
default:.
34
• If a case default: is present, its code is applicable to ALL the enum values that do not have a
case.
• The variables being processed, i.e. 'def advances;' and 'def declines;', must be addressed in each
case ????: Otherwise an error is produced.
• Any enum item having a space should have that item enclosed within quotes whenever used.
• Use of a switch inside a switch is possible but is very complex. Hence it is not addressed herein.
Other examples of switch usage can be found at S-PRICE DIRECTION SCAN , S-PRICE DIRECTION
SCAN, C-ATR TRAILING STOP and C- THE 'AdvanceDecline' STUDY
Alertnate 1:
35
#hint <b> Highest High and Lowest Low lines & bubble for 3, 6 or 12 momths</b>
declare upper;
input timeFrame = { default threeMonths, sixMonths, twelveMonths };#hint timeFrame:
select the TimeFrame desired
def numBars;
switch( timeFrame ) {
case threeMonths:
numBars = 63;
case sixMonths:
numBars = 126;
case twelveMonths:
numBars = 252;
}
36
Alertnate 2:
#hint:<b>Plots a line for the highest in the last ? bars</b>\nHas option for a % lower
plot
declare upper;
input numBars = 50;#hint numBars: The number of bars monitored
input price = high;#hint price:Select the price to monitor
input hidePctLowerPlot = yes;#hint hidePctLowerPlot: Yes hides the hidePctLowerPlot
input PctLower = 5;#hint PctLower: define the % lower plot criteria
AddChartBubble( barNum == startBar, HighestHigh, "Highest High in the Past " + totBars
+ " bars: " + HighestHigh, color.CYAN );
AddChartBubble( barNum == startBar and !hidePctLowerPlot, PercentDown,
PctLower + " % Below Highest High in the Past " + totBars + " bars: " + PercentDown,
color.RED );
37
input showOnlyToday = YES;
input Market_Open_Time = 0930;
input Market_Close_Time = 1600;
38
#hint:Places vertical lines at start and end times of all days or selected days.\n
Realize that, when certain times are inputted, the lines may overlap.
declare upper;
input linePos1 = 10;#hint linePos1:Must be greater than zero
input linePos2 = 20;#hint linePos2:Enter the agg-bars larger than previous input.
Enter zero to omit the plot.
input linePos3 = 50;#hint linePos3:Enter the agg-bars larger than previous input.
Enter zero to omit the plot.
input linePos4 = 100;#hint linePos4:Enter the agg-bars larger than previous input.
Enter zero to omit the plot.
input linePos5 = 150;#hint linePos5:Enter the agg-bars larger than previous input.
Enter zero to omit the plot.
39
input linePos6 = 200;#hint linePos6:Enter the agg-bars larger than previous input.
Enter zero to omit the plot.
Comment: This is a good example illustrating the use of the Assert function.
40
# Title = Bar_Number_Plot_Interval
#hint: Numbers the bars at inputted intervals. A line plot is also selectable. This
may be shown on the upper or lower plot by using 'EDIT STUDIES'.
Input Interval = 5;#hint Interval: Enter the desired interval between shown bar
mumbers.\n 0 and 1 plots at every bar.
Input BarNumbLine = Yes;#hint BarNumbLine: YES shows a line plot of bar number at the
'high' price.
bn.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);
plot bn_1 = if interval == 0 or interval == 1 then barNumber else double.nan;
bn_1.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);
#####################
def TotalBars = HighestAll(barNumber());
AddLabel( yes, "TotalBars = " + TotalBars , Color.white);
AddLabel( yes, "Numbering Interval = " + Interval, Color.pink);
41
#hint: <b>Bar Count Between Highs</b>\n Counts the number of bars between each high in
the specified length, default 20.
input gap_length = 200;#hint gap_length: If there is a large gap between new highs,
this gap_length is used to find the previous highest high and it subtracts the current
high bar number from the previous high barnumber. <b>\n(Default is 200)</b>
count.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);
plot Bar_number = if show_Bar_number == yes then barnumber() else double.nan;
Bar_Number.setPaintingStrategy(paintingStrategy.VALUES_BELOW);
```
42
=== C-SHOWING WHERE A CANDLE PATTERN EXISTS
-You can show/plot where any particular candle pattern exists. Below is code that
shows where the popular Doji pattern exists:
plot d = Doji();# If a Doji is present Doji() is true.The below lines format what to show at that
location.
d.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP); d.setLineWeight(2);
d.setDefaultColor(Color.White);
Doji() as used above is the simplest of all candles to show because it has only a
single plot. But other patterns are more complicated. For example, some candles may be
bullish (up) or bearish (down) patterns. As an example on how to substitute them for
the Doji() used above, we'll use Harami. When we inspect its code , we see that it has
three input variables and two plots named 'bullish' and 'bearish'. In this example,
we'll retain all the parameters (assuming that
ThinkScript knows the best parameters to use) and show the 'bullish' plot only. The
def condition above now becomes:
The remainder of the code statements can be changed to reflect reading correctness but
what plots will be unaffected if they are not changed.
-If you want to also change the candle's parameters then the code becomes as follows
with you providing values for the ????. The code becomes `def condition = if
(Harami(length = ????, trendSetup = ????, bodyFactor = ????).Bullish , 1, 0);`
Note that the parameter names (length, trendSetup and bodyFactor) are exactly the
same as in the Harami code.
#hint:Uses the VolumeAvg study and adds a label showing volume as the percent of the average
daily volume. The average daily volume length is based on the variable inputted length.
43
#Title = VolumeAvg_WithLabel
AddLabel(yes, "Today’s Vol = " + round(Pct_Avg,1) + " % of the " + length + "-day-average"
,color.PINK);
Alternate 1:
#Hint: <b>Shows a label of current Volume as a % of the input Period Average Volume</b>\n Colors
Label based on current Volume being > or < Average Volume
#Usage: All 'edit studies' check boxes are blank when used as a pure label only. If you want to see
the percentage for any bar under your cursor, then: (1) Check the 'show study' box in edit studies;
OR (2) Change 'declare upper' to 'declare lower' and check all boxes in 'edit studies'.
declare upper;
input VolAvgLength = 50;#hint VolAvgLength:Insert the base agg-bars volume length def data =
(Volume / VolumeAvg(VolAvgLength).VolAvg)-1;#Vol as fraction of VolAvgLength
Alternate 2:
#hint: Plots: 1. The volume histogram; 2. The inputted agg-bar average; and 3. A arrow when the
volume exceeds the inputted average with an info label.
declare lower; input length = 10;#hint length:The length of the average volume plot input pct =
25.0;#hint pct:Plots an arrow when volume exceeds the average by this percent def _volAvg =
Average( volume, length ); def volTest = volume >= _volAvg * ( 1+ ( pct / 100 ) ); plot Vol = volume;
Vol.SetPaintingStrategy( PaintingStrategy.HISTOGRAM ); Vol.SetLineWeight(3);
Vol.DefineColor("Up", Color.UPTICK); Vol.DefineColor("Down", Color.DOWNTICK);
Vol.AssignValueColor(if close > close[1] then Vol.color("Up") else if close < close[1] then
44
Vol.color("Down") else GetColor(1));
#Plot or scan for current low that has gaped-up by an input percent
input price1 = low;#hint Price1:The post-gap-up basis input GapPct = 0.5;#Hint GapPct: The gap-up
percent input price2 = high;#hint Price2: The prior gap-up-bar-basis input WithinBars = 15;#hint
WithinBars:The number of bars-back to evaluate
def x = 1+GapPct/100; # factor for above 100 % def term = x*price2[1]; # = factor * previous high plot
scan = price1 >= term;
To scan for above happening within the last 15 days the above would read #plot scan = price1 >=
term within WithinBars bars; #=== below items not needed for a scan ##
scan.SetpaintingStrategy(paintingStrategy.BOOLEAN_ARROW_up); scan.SetLineWeight(5);
scan.SetDefaultColor(Color.White);
declare hide_on_daily; def barnumber = BarNumber(); input time = 1000;#hint time:Time to place
the arrow at
45
barnumber else plotPrice[1], barnumber); def data = plotPrice; def a = barnumber - data;
=== C-SHOWS ARROWS WHEN THE PRICE CROSSES THE MOVING AVERAGE
#hint: <b>MovingAverage Crossover - Once Per Chart</b>\nThis study shows arrows when the price
crosses the moving average. The study by default only shows the latest crossing to free up screen
space for more awesome studies.\n Enjoy - Jesse (author on the Mr. Script show)
input price = close;#hint price:Select the price of choice input length = 10;#hint Length:Length of the
average input averageType = AverageType.EXPONENTIAL;#hint averageType:Select the type of
average desired input MostRecentOnly = Yes;#hint MostRecentOnly: Shows the most recent crossing
only. \n <b>(Default is Yes)</b>
def avg = MovingAverage(averageType, price, length); def crossingdown = price crosses below avg;
def crossingup = price crosses above avg; def crossingover = close("Greatest Show Ever!"); def
barnumber = barnumber(); def count = if crossingdown or crossingup then barnumber else 0;
plot onceperchartup = if MostRecentOnly and crossingUP and count == highestall(count) then low
else double.nan;
onceperchartdown.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_down);
onceperchartup.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_UP);
onceperchartup.setDefaultColor(color.light_green);
onceperchartdown.setDefaultColor(color.light_red); onceperchartdown.setLineWeight(3);
onceperchartup.setLineWeight(3); onceperchartdown.hidetitle(); onceperchartup.hidetitle();
#plot a flat line from open of first bar of day. For use on multi-day charts.
46
AssignPriceColor(if firstBar then color.ORANGE else color.CURRENT); def dayOpen = if firstBar then
high else dayOpen[1];
declare upper; def barNum = if IsNaN( close ) then Double.NaN else BarNumber(); def highestBar =
HighestAll( barNum ); def previousClose = if barNum == highestBar - 1 then close else Double.NaN;
plot CloseLine = HighestAll( previousClose ); CloseLine.SetDefaultColor( Color.gray);
#Puts any of the 11 price choices into a literal text in a label like ohlc4 = 75
AddLabel(yes, if price == close then "The price-variable selected is close = " + Round(close,2) else if
price == open then "The price-variable selected is open = " + Round(open,2) else if price == high then
"The price-variable selected is high = " + Round(high,2) else if price == low then "The price-variable
selected is low = " + Round(low,2) else if price == hl2 then "The price-variable selected is hl2 = " +
Round(hl2,2) else if price == hlc3 then "The price-variable selected is hlc3 = " + Round(hlc3,2) else if
price == imp_volatility then "The price-variable selected is current imp_volatility = " +
AsPercent(imp_volatility) else if price == ohlc4 then "The price-variable selected is ohlc4 = " +
Round(ohlc4,2) else if price == open_interest then "The price-variable selected is Open_interest = " +
Round(open_interest,0) else if price == volume then "The price-variable selected is Volume = " +
Round(volume,0) else if price == VWAP then "The price-variable selected is VWAP = " +
Round(VWAP,0) else "N/A",color.white);
#hint:Plots and shows a label for the change compared to the past inputted-number-of-days. declare
lower;
input length = 30;#hint length:the number of trading days-ago for the change def price =
close(period = AggregationPeriod.day); def Change = (price / price[length] - 1);
Plot PctChange = 100 * change; AddLabel(yes,"% Change compared to " + length + " days ago = " +
Round(PctChange, 1) + "%",color.PINK);
```
47
C-LOW IS ?% ABOVE YESTERDAY’S HIGH
C-IMP-VOLATILITY PERCENTILE
# hint: you can also copy/paste this code to create a custom IV percentile column for
a watch list
AddLabel(1, "IV Percentile + " + AsPercent(perct)+ " of the yearly range", if perct >
0.80
then Color.Green
else if perct < 0.80 and perct > 0.50
then Color.Yellow
else color.Light_Red);
48
#Hint:watchlist or label YTD-percent-change
#=== Comment out the next hide code if this is used as a column watchlist #####
"YTD Percent Change".hide();#Plot has nothing of value to see
##=== Comment-out the below label if this is used as a column watchList ####
AddLabel(1,"YTD % Change of the " + if price == close then "close = "+ "YTD Percent
Change" + " else
"'ERROR...WRONG PRICE-VARIABLE SELECTED'" ,if price == close then color.cyan else
color.red);
49
C-PLOT A HORIZONTAL LINE THRU A DEFINED DATE
declare hide_on_intraday;
input Date = 20130801;#hint Date: Set the date you want see.<b>\n(Enter in
YYYYMMDD)</b>
input price = CLOSE;
input show_line = Yes;#hint show_line: Show a horizontal line at this price<b>(Default
is Yes)</b>
AddChartBubble(timetest, price,
concat(concat(concat("Date: ",Concat(month, "/")), monthday), concat((if price ==
close
then " Close: $" else if price == open then " Open: $" else if price == low then "
Low: $" else if price == high then "High: $" else " Value: "), price)),
(if price == close then color.cyan else if price == open then color.pink else if price
== low then color.yellow else if price == high then color.green else color.red)
, yes);
Usage example: You may have a stock plotted on the upper panel:Say an oil company, CVX. You may
want to see how its price varies with the oil futures. The code below allows you to show the oil
futures (/CL) below for comparison.
50
declare lower;
input Security = {default "SPX", "COMP", "DJX", "HUI", "MNX", "SOX", "NDX", "OEX",
"QQQQ","QQQ","RUT", "VIX", "VXO", "XAU", "QQV", "TNX","/ES","/CL"};
51
declare lower;
input RSI_Wilder_length = 14;
input RSI_Wilder_over_bought = 70;
input RSI_Wilder_over_sold = 30;
input RSI_Wilder_price_type = close;
def RSIplot = RSIWilder(RSI_Wilder_length, RSI_Wilder_over_bought,
RSI_Wilder_over_sold,
RSI_Wilder_price_type);
plot RSI_line = 0;
RSI_line.SetPaintingStrategy(PaintingStrategy.POINTS);
RSI_line.AssignValueColor(if RSIplot >= RSI_Wilder_over_bought then Color.RED else if
RSIplot <=
RSI_Wilder_over_sold then Color.GREEN else Color.YELLOW);
#######################
=== MACD HISTOGRAM PLOT#####
#######################
input MACD_Histogram_fastLength = 12;
input MACD_Histogram_slowLength = 26;
input MACD_Histogram_MACDLength = 9;
input MACD_Histogram_AverageType = {SMA, default EMA};
MACD_Histogram_AverageType).Diff;
Diff.SetDefaultColor(GetColor(5));
Diff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Diff.SetLineWeight(3);
Diff.DefineColor("Positive and Up", Color.GREEN);
Diff.DefineColor("Positive and Down", Color.DARK_GREEN);
Diff.DefineColor("Negative and Down", Color.RED);
Diff.DefineColor("Negative and Up", Color.DARK_RED);
Diff.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then Diff.color("Positive
and Up") se Diff.color("Positive and
Down") else if Diff < Diff[1] then Diff.color("Negative and Down") else
Diff.color("Negative d Up"));
AddLabel(yes, if RSIplot >= RSI_Wilder_over_bought then "RSI on the line is
Overbought" else if Iplot <=
RSI_Wilder_over_sold then "RSI on the line is Oversold" else "RSI on the line is
Neutral",if Iplot >=
RSI_Wilder_over_bought then Color.RED else if RSIplot <= RSI_Wilder_over_sold then
Color.GREEN se
Color.YELLOW);
C-MARKET SENTIMENT
52
#hint: <b>Market Sentiment</b>\nThe Market Sentiment study is a popular study in
Prophet Charts.
declare lower;
input perioda = 51;
input periodb = 47;
input RoundingValue = 4;
def llow = Lowest(low, perioda);
def c_ln = close - llow;
def hhigh = Highest(high, perioda);
def hn_ln = hhigh - llow;
def numerator = Sum(c_ln, periodb);
def denominator = Sum(hn_ln, perioda);
plot MarketSentiment = round(100* (numerator/denominator), RoundingValue);
marketsentiment.setDefaultColor(color.yellow);
declare lower;
plot x = MarketForecast();#Momentum is the default plot: The first listed in the study
code.
plot y = MarketForecast().NearTerm;
plot z = MarketForecast().Intermediate;
plot HighValue = 80;
plot LowValue = 20;
x.setdefaultColor(color.green);
addlabel(1,"Market Forecast Momentum",color.green);
addlabel(1,"Market Forecast NearTerm",color.pink);
addlabel(1,"Market Forecast Intermediate",color.white);
53
#by Mr. Script. Formatting added by SFL.
#Triple EMA & Std Dev monitoring
#start code
declare lower;
input bperiod = 18;
input TEMAavg = 8;
input std_dev_up = 1.5;
input std_dev_down = -1.5;
input stdev_length = 63;
def haopen = CompoundValue(1, ((open[1] + high[1] + low[1] + close[1]) / 4 +
haopen[1]) / 2, hl2);
def haclose = ((open + high + low + close) / 4 + haopen + Max(high, haopen) + Min(low,
haopen)) / 4;
#.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
percB.SetLineWeight(1);
percB.SetDefaultColor(Color.cyan);
54
#by Pacodeveux in Mr. Script show
#Fast, med, slow true range osc
declare lower;
input fastLength = 7;
input medLength = 14;
input slowLength = 28;
input FactorFast = 4;
input FactorMed = 2;
input FactorSlow = 1;
55
#by Mr. Script:
#Change studies based on symbol viewed
input symbol_1 = "SPY";
input symbol_2 = "DIA";
input symbol_3 = "IWM";
input symbol_4 = "AMTD";
plot x;
plot y;
plot z;
if (GetUnderlyingSymbol() == symbol_1)
{
x = LinearRegChVar("width of channel" = 25.0, "full range" = No, length =
50).UpperLR;
y = LinearRegChVar("width of channel" = 25.0, "full range" = No, length = 50);
z = LinearRegChVar("width of channel" = 25.0, "full range" = No, length =
50).LowerLR;
}
else if (GetUnderlyingSymbol() == symbol_2)
{
x = BollingerBandsSMA().UpperBand;
y = BollingerBandsSMA();
z = BollingerBandsSMA().LowerBand;
}
else if (GetUnderlyingSymbol() == symbol_3)
{
x = close + 5;
y = hlc3;
z = close - 5;
}
else if (GetUnderlyingSymbol() == symbol_4)
{
x = SimpleMovingAvg(length = 50);
y = SimpleMovingAvg(length = 200);
Z = PPS().BuySignal;
}
else
{
x = double.nan;
y = double.nan;
z = double.nan;
}
56
#Hint: Plots consecutive (defined by number) higher-highs AND lower-lows
def hi = high;
def lo = low;
def higher = if hi > hi[1] then hi else higher[1];
def lower = if lo < lo[1] then lo else lower[1];
plot h = higher;
h.SetLineWeight(1);
h.SetDefaultColor(Color.cyan);
plot l =lower;
l.SetLineWeight(1);
l.SetDefaultColor(Color.pink);
C-CANDLESTICK PLOTS
If you are interested in seeing examples of various candlesticks, there are two studies available.
They are: (1) Bearish candle plots.txt; and (2) Bullish candle plots.txt. They are too big to include
here but may be downloaded from http://mytrade.com/StanL There are many examples of coding
procedures within those files. They are also excellent for correlating the looks of a candle with its
title.
57
input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};
switch (state[1]) {
case init:
if (!IsNaN(loss)) {
switch (firstTrade) {
case long:
state = state.long;
trail = close - loss;
case short:
state = state.short;
trail = close + loss;
}
} else {
state = state.init;
trail = Double.NaN;
}
case long:
if (close > trail[1]) {
state = state.long;
trail = Max(trail[1], close - loss);
} else {
state = state.short;
trail = close + loss;
}
case short:
58
if (close < trail[1]) {
state = state.short;
trail = Min(trail[1], close + loss);
} else {
state = state.long;
trail = close - loss;
}
}
C&S-EARNINGS
On Earnings by Jesse on Mr Script show
59
#The move after earnings
declare lower;
actual_earnings.setpaintingstrategy(paintingstrategy.points);
###########################
#The below is how to scan for earnings
Input length = 10;#hint length: The days to scan for
def a = hasearnings();
def b = getday();
def c = if a then b else 0;
def d = average(c, length);
def e = d[-length];
plot f = e > 0;
60
#hint:Plots the tangent angle of the inputted average
declare lower;
input length = 9;#hint length:The number agg-bars of the average
input price = close;#hint Price:The price choice being evaluated
input averageType = AverageType.EXPONENTIAL;#hint averageType:Select the average type
desired
addlabel(1,"Plot is the tangent angle of the " + length + "-bar " + If averageType ==
AverageType.EXPONENTIAL then "Exponential average"
else if averageType == AverageType.Hull then "Hull average"
else if averageType == AverageType.simple then "Simple average"
else if averageType == AverageType.wilders then "Wilders average"
else if averageType == AverageType.weighted then "Weighted average"
else "" ,color.white);
Comment: In the label, note the retrieval of the literal AverageType selection. The code shown is
very reusable.
#by Mobius©:
#hint: Plots a horizontal line at a value of today's market opening price
61
C-PLACING OF PLOTTED ARROWS
When you want to move a plotted arrow you can place it with the 'values_above' or 'values_below'
painting strategy constants. See:
http://tda.thinkorswim.com/manual/metal/thinkscript/reference/Constants/PaintingStrategy/
PaintingStrategy.VALUES_ABOVE.html
Another method has been used that plots a value and assigns an arrow to it with
'SetPaintingStrategy'. An example follows:
put spacer= 3;
ot arrowdn= if BarNumber() == SundayBar and SundayOpen < FridayClose then
high+ticksize()pacer else double.nan;
ArrowDn.SetPaintingStrategy(PaintingStrategy.Arrow_Down);
ArrowDn.SetLineWeight(3);
ArrowDn.SetDefaultColor(Color.Red);
62
#hint:Order based on value difference of three averages
input averageType1 = {default Simple, Exponential, Weighted, Wilders, Hull};
input averageType2 = {default Simple, Exponential, Weighted, Wilders, Hull};
input averageType3 = {default Simple, Exponential, Weighted, Wilders, Hull};
input length1 = 10;
input length2 = 46;
input length3 = 230;
input val_diff = .05;
addOrder(OrderType.BUY_AUTO, condition);
addOrder(type = OrderType.SELL_TO_CLOSE,!condition);
addOrder(OrderType.BUY_AUTO, condition3);
addOrder(OrderType.SELL_TO_CLOSE,condition4);
```
Comment: This is the built-in 'AdvanceDecline' study. It is duplicated here because it demonstrates
so well the selection of various choices and because it is so popular for viewing the market
conditions. There is a lot to learn by studying this script. Even the label coding is neat. The bottom
label was added to the built-in for clarity. declare lower; input type = {default "Advance/Decline
Line", "Advance/Decline Line (Breadth)", "Advance/Decline Line (Daily)", "Advance/Decline Ratio",
"Advance/Decline Spread (Issues)", "Absolute Breadth Index"};
63
def advances; def declines;
AddLabel(yes, "Showing is the " + (if type == type."Advance/Decline Line" then "Advance/Decline
Line" else if type == type."Advance/Decline Line (Breadth)" then "Advance/Decline Line (Breadth)"
else if type == type."Advance/Decline Line (Daily)" then "Advance/Decline Line (Daily)" else if type ==
type."Advance/Decline Ratio" then "Advance/Decline Ratio" else if type == type."Advance/Decline
Spread (Issues)" then "Advance/Decline Spread (Issues)" else if type == type."Absolute Breadth
Index" then "Absolute Breadth Index" else "") + " for the "
(if exchange == exchange.NYSE then "NYSE" else if exchange == exchange.NASDAQ then "NASDAQ"
else if exchange == exchange.AMEX then "AMEX" else ""), color.white);
#Hint: Plot for ? calendar (not trading) days from an inputted date\n This works only on a lower
plot and <b>not for HA and EquiVolume charts.</b>
Input DaysToPlot = 20;#hint DaysToPlot: the number of calendar days to plot. Input Price = Close;
input BeginDate =20130810;#hint BeginDate: The start date in YYYYMMDD format
AddLabel(1, "If you do not see a plot, check if the chart timeframe cover the input date",
Color.WHITE);
64
=== C- PLOT THE CURRENT PRICE ACROSS AN ENTIRE CHART
declare lower;
input ShowBubble = No;#hint ShowBubble:Yes shows the over-reference-% bubble input Ref_val =
25;#hint Ref_val:The reference percent
#Hint:For intraday values, plots the days highest cloud and overlays the current price cloud
declare lower;
input IntraDay = Yes;#Hint IntraDay:Yes for intraday only input price = high;#hint Price:Pick the
price option desired.\nHigh is the default.\nOpen_Interest and Imp_Volatility are not valid choices.
input Mkt_Start = 0930;#hint Mkt_Start:Show market start time e.g. 930 input Mkt_End = 1600;#hint
Mkt_End:Show market end time e.g. 1600
65
If((SecondsTillTime(Mkt_End) > 0), 0, 1); def MktIsOpen = If(Past_Mkt_Start and !Past_Mkt_End, 1, 0);
def day = GetDay(); def lastDay = GetLastDay(); def Today = If(day == lastDay, 1, 0); def Show =
If(IntraDay and Today, 1, If(!IntraDay, 1, 0; def Bar1 = If (day[1] != day, day - 1, 0); def HighestHigh =
If(price > HighestHigh[1] and MktIsOpen, price, If(MktIsOpen and !Bar1, HighestHigh[1], price)); def
LowestLow = If(price < LowestLow[1] and MktIsOpen, price, If(MktIsOpen and LowestLow[1] > 0
and !Bar1, LowestLow[1], price));
##
declare upper; input price = close;#hint price:Select the price choice input MA1_length = 50;#hint
MA1_length:Input a MA1 length input MA2_length = 200;#hint MA2_length:Input a MA2 length
Input ShowBubbles = yes;
addLabel(1,"Mov Avg input price choice = " + (if price == close then "close" else if price == open then
"open" else if price == high then "high" else if price == low then "low" else if price == hl2 then "hl2"
else if price == hlc3 then "hlc3" else if price == imp_volatility then "imp_volatility" else if price ==
ohlc4 then "ohlc4" else if price == open_interest then "Open_interest" else if price == volume then
"Volume" else if price == VWAP then "VWAP" else "ERROR"),color.white); ` #
66
Comment: A more complex study that allows all five moving average types for all nine price choices
is available but is too ong (245 lines) for inclusion here. This is the abridged version using a simple
moving average for the nine price choices.
declare upper;
input price = close;
input displace = 0;
input EMALength1 = 9;
input EMALength2 = 39;
AddCloud(upper,lower);
#hint: <b>Find Moving Average Xover</b>\nFinds when a fast moving average crosses over
or under a slow.\n The fast average going above the slow average (bullish crossover)
is a signal to buy, while the opposite situation (bearish crossover) is a signal to
sell.
input price = close;#hint price: The price used to calculate the crossover.
<b>(Default is CLOSE)</b>
input fastLength = 3;#hint fastLength: The number of bars used to calculate the fast
moving average. <b>(Default is 3)</b>
input slowLength = 8;#hint slowLength: The number of bars used to calculate the slow
moving average. <b>(Default is 8)</b>
input slowAvgType = {default Simple, Exponential, Weighted, Wilders, Hull};#hint
slowAvgType: Type of the fast moving average to be used for calculation. <b>(Default
is Expontential)</b>
input fastAvgType = {default Simple, Exponential, Weighted, Wilders, Hull};#hint
fastAvgType: Type of the fast moving average to be used for calculation. <b>(Default
67
is Exponential)</b>
Input DoArrows = no;#hint DoArrows:Yes shows arrows to define crosses
Input DoPlots = yes;#hint DoPlots: Yes shows MA plots to define crosses. Default is
'YES'
Input DoAlerts = No;#hint DoAlerts:No turns off alerts
def fastAvg;
switch (slowAvgType) {
case Simple:
fastAvg = Average(price, fastLength);
case Exponential:
fastAvg = ExpAverage(price, fastLength);
case Weighted:
fastAvg = wma(price, fastLength);
case Wilders:
fastAvg = WildersAverage(price, fastLength);
case Hull:
fastAvg = HullMovingAvg(price, fastLength);
}
def slowAvg;
switch (fastAvgType) {
case Simple:
slowAvg = Average(price, slowLength);
case Exponential:
slowAvg = ExpAverage(price, slowLength);
case Weighted:
slowAvg = wma(price, slowLength);
case Wilders:
slowAvg = WildersAverage(price, slowLength);
case Hull:
slowAvg = HullMovingAvg(price, slowLength);
}
signalXup.SetDefaultColor(Color.pink);
signalXup.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
signalXup.SetLineWeight(3);
plot signalXdn = If DoArrows Then crosses(fastAvg, slowAvg, CrossingDirection.below)
else Double.nan;
signalXdn.SetDefaultColor(Color.Green);
signalXdn.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
signalXdn.SetLineWeight(3);
Alert(signalXup && DoAlerts, "UP...Fast MA Cross Above Slow MA", Alert.BAR, Sound.Ring
68
);
Alert(signalXdn && DoAlerts, "Down...Fast Ma Cross Below Slow MA", Alert.BAR,
Sound.Bell );
It seems like whenever the fast EMA crosses the slow EMA AND a certain amount of time passes the
combination of those 3 events signals a longer term trend. When I say "long" I mean like half a day
for day trading"
Solution: Here’s a study for you. The indicator stays 'red' after the Moving Averages cross. When it
turns green you are in the safe zone. This is great for true mechanical systems to make sure you
don’t enter and exit on false signals.
69
C-USING THE SETHIDING FUNCTION
#hint:This illustrates the use of the SetHiding function. which controls visibility of
a plot depending on a condition. If this condition is true, the plot is hidden;
otherwise the plot is visible.
input offset = 1 ;# Used to position the plot this amount above the high
plot EachBar = if close < close[1] && close[1] < close[2] then high + offset else
double.NaN;
EachBar.SetPaintingStrategy(paintingStrategy.POINTS);
EachBar.SetDefaultColor(color.LIGHT_GREEN);
EachBar.SetLineWeight(5);
EachBar.setHiding(if(close > reference SimpleMovingAvg(length = 21),1,0));
Plot MA = SimpleMovingAvg(length=21);
Comment: The above plots a light_green point (dot) whenever there are two consecutive lower
closes. However,EachBar.setHiding… hides that point when it’s condition is true i.e. the close >
SimpleMovingAvg(21).
declare upper;
70
Average(close, L18);
plot A19 = Average(close, L19);plot A20 = Average(close, L20);plot A21 =
Average(close, L21);
plot A22 = Average(close, L22);plot A23 = Average(close, L23);plot A24 =
Average(close, L24);
plot A25 = Average(close, L25);plot A26 = Average(close, L26);plot A27 =
Average(close, L27);
A1.SetDefaultColor(Color.RED);A2.SetDefaultColor(Color.RED);A3.SetDefaultColor(Color.R
ED);
A4.SetDefaultColor(Color.ORANGE);A5.SetDefaultColor(Color.ORANGE);A6.SetDefaultColor(C
olor.ORANGE);
A7.SetDefaultColor(Color.YELLOW);A8.SetDefaultColor(Color.YELLOW);A9.SetDefaultColor(C
olor.YELLOW);
\
A10.SetDefaultColor(Color.GREEN);A11.SetDefaultColor(Color.GREEN);A12.SetDefaultColor(
Color.GREEN);
A13.SetDefaultColor(Color.CYAN);A14.SetDefaultColor(Color.CYAN);A15.SetDefaultColor(Co
lor.CYAN);
A16.SetDefaultColor(Color.PLUM);A17.SetDefaultColor(Color.PLUM);A18.SetDefaultColor(Co
lor.PLUM);
A19.SetDefaultColor(Color.Violet);A20.SetDefaultColor(Color.Violet);A21.SetDefaultColo
r(Color.Violet);
A22.SetDefaultColor(Color.MAGENTA);A23.SetDefaultColor(Color.MAGENTA);A24.SetDefaultCo
lor(Color.MAGENTA);
A25.SetDefaultColor(Color.PINK);A26.SetDefaultColor(Color.PINK);A27.SetDefaultColor(Co
lor.PINK);
C-INSIDE-BAR CODING
Comment: An inside bar is a frequent item of interest. Code related to such a bar is below:
71
#####Current bar is an inside Bar: Green if true #######
plot Data = if high <= high [1] and low >= low[1] then 1 else 0;
AssignBackgroundColor( if Data > 0 then Color.GREEN else Color.BLACK );
Data.assignValueColor(color.BLACK);
###Prior Bar was an inside bar and current bar's high broke above prior bar high:Green
if true ###
plot Data = if (high[1] <= high [2] and low[1] >= low[2]) and (high > high[1]) then 1
else 0;
AssignBackgroundColor( if Data > 0 then Color.GREEN else Color.BLACK );
Data.assignValueColor(color.BLACK);
####Prior Bar was an inside bar and current bar's low broke below prior bar's low:Red
if true #####
plot Data = if (high[1] <= high [2] and low[1] >= low[2]) and (low < low[1]) then -1
else 0;
AssignBackgroundColor( if Data < 0 then Color.RED else Color.BLACK );
Data.assignValueColor(color.BLACK);
###Prior Bar was an inside bar and current bar broke above or below: Green above/Red
below ###
plot Data = if (high[1] <= high [2] and low[1] >= low[2]) and (high > high[1]) then 1
else if (high[1] <= high [2] and low[1] >= low[2]) and (low < low[1]) then -1 else 0;
AssignBackgroundColor( if Data > 0 then Color.GREEN else if Data < 0 then Color.RED
else Color.BLACK );
Data.assignValueColor(color.BLACK);
72
C-IDENTIFYING AGGREGATION IN A LABEL
declare upper;
Input Offset = -10;
def LastBar = !IsNaN(open) and IsNaN(open [-1] ) ;
Def BubbleLocation = LastBar[Offset];
def barNum = barNumber();
def FirstBar = if barNum == 1 then 1 else 0;
Comment: HideBubble() Makes the last value bubble of a plot invisible. This is the bubble in e right
margin and not on the chart itself.
73
#Hint:Define Previous day's close
declare upper;
input price = FundamentalType.Close;
def barNum = if IsNaN( close ) then Double.NaN else barNumber();
def prevBarNum = HighestAll( barNum ) - 1;
def prevPrice = if barNum == prevBarNum then fundamental( price ) else Double.NaN;
plot PreviousPriceLine = HighestAll( prevPrice );
PreviousPriceLine.SetDefaultColor( CreateColor( 102, 102, 102 );
74
#hint:Plots of counts of consecutive rises or drops of the close.
def count_CloseDrops =
if Close < close[1] then count_CloseDrops[1] +1 else 0;
plot close_going_down = count_CloseDrops ;
close_going_down.SetPaintingStrategy(PaintingStrategy.line);
close_going_down.SetLineWeight(1);
close_going_down.SetDefaultColor(Color.red);
AddLabel(yes, "Count of consecutive drops of the CLOSE = " + Close_going_down
,color.red);
75
#Define Bar at a time and date
plot Data1 = volume;
declare hide_on_daily;
def barnumber = BarNumber();
input time = 1100;
Input TodayDate = 20130104;
def GetYMD = GetYYYYMMDD() == TodayDate;
def timeTest = SecondsFromTime(time) == 0;
def BarID = CompoundValue(1, if timeTest && GetYMD then barnumber else Double.nan,
barnumber());
#def BarIDNo = if(!isnan(BarID), Double.nan,barID);
AddLabel(yes, "BarNumber at arrow = " + BarID, color.white);#?????why this doesn't
show BarID
Plot Data2 = BarID;#The barnumber value
Data2.setPaintingStrategy(PaintingStrategy.VALUES_below); # Arrow_Down, Arrow_Points,
Data2.SetDefaultColor(Color.Green); # for data plot
Data2.SetLineWeight(5);
Plot Data3 = BarID;#An arrow at the selected barnumber
Data3.setPaintingStrategy(PaintingStrategy.Arrow_down); # Arrow_Down, Arrow_Points,
Data3.SetDefaultColor(Color.Green); # for data plot
Data3.SetLineWeight(5);
AddChartBubble( timeTest && GetYMD, Volume , BarID + " is the base \nbar for
comparison", lor.white, no);#Bubble
at the selected barnumber stating the barnumber
76
input Begin = 0930;
input End = 1600;
def IsClosed = if SecondsFromTime(End) == 0 and
SecondsTillTime(End) == 0
then close
else IsClosed [1];#If market IsClosed then IsClosed's value = close
def data = if IsClosed > 0 then IsClosed else Double.NaN;
plot cond = close(priceType = "Mark") * 1.01 > IsClosed ;#Must use Mark in
Pre/PostMarket
#Above uses 1.01 to scan for close > 1%. Change for your % desired.
################
Mobius©: this is the corresponding chart study
input Begin = 0930;
input End = 1600;
data.SetPaintingStrategy(PaintingStrategy.Dashes);
# In the plot below change 1.01 (1%) to your desired %
plot cond = if close(priceType = "Mark") crosses above Data * 1.01 then low else
Double.NaN; #Must use Mark in pre/postmarket
cond.SetPaintingStrategy(PaintingStrategy.Arrow_Up);
Comment1: Pre-market scan and chart may be had by changing 'End' to 'Begin' in the above code
Comment2: To display pre and post- market chart displays, click the wrench to open 'Chart Settings'
and then go to 'equities' and check 'Show Extended Session'
77
#hint:Order based on value difference of three averages
input averageType1 = {default Simple, Exponential, Weighted, Wilders, Hull};
input averageType2 = {default Simple, Exponential, Weighted, Wilders, Hull};
input averageType3 = {default Simple, Exponential, Weighted, Wilders, Hull};
input length1 = 10;
input length2 = 46;
input length3 = 230;
input val_diff = .05;
condition.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_UP);
addOrder(OrderType.BUY_AUTO, condition);
addOrder(type = OrderType.SELL_TO_CLOSE,!condition);
78
#hint:Defines the aggregation in a label
def AggPeriod = getAggregationPeriod();
AddLabel(yes,concat("Aggregation Period = ",
if AggPeriod == AggregationPeriod.min
then "1 MIN"
else if AggPeriod == AggregationPeriod.Two_Min
then "2 MINS"
else if AggPeriod == AggregationPeriod.Three_min
then "3 MINS"
else if AggPeriod == AggregationPeriod.Four_Min
then "4 MINS"
else if AggPeriod == AggregationPeriod.Five_min
then "5 MINS"
else if AggPeriod == AggregationPeriod.ten_min
then "10 MINS"
else if AggPeriod == AggregationPeriod.fifteen_min
then "15 MINS"
else if AggPeriod == AggregationPeriod.Twenty_min
then "20 MINS"
else if AggPeriod == AggregationPeriod.Thirty_min
then "30 MINS"
else if AggPeriod == AggregationPeriod.hour
then "1 HOUR"
else if AggPeriod == AggregationPeriod.TWO_Hours
then "2 HOURS"
else if AggPeriod == AggregationPeriod.Four_hours
then "4 HOURS"
else if AggPeriod == AggregationPeriod.DAY
then "DAY"
else if AggPeriod == AggregationPeriod.two_DAYs
then "2 DAYS"
else if AggPeriod == AggregationPeriod.three_DAYs
then "3 DAYS"
else if AggPeriod == AggregationPeriod.four_DAYs
then "4 DAYS"
else if AggPeriod == AggregationPeriod.week
then "WEEK"
else if AggPeriod == AggregationPeriod.MONTH
then "MONTH"
else "Use time charts only"),
Color.cyan);
AddLabel(yes,"Not for TICK or RANGE bar usage",color.red);
79
declare upper;
Input Offset = -10;
def LastBar = !IsNaN(open) and IsNaN(open [-1] ) ;
Def BubbleLocation = LastBar[Offset];
def barNum = barNumber();
def FirstBar = if barNum == 1 then 1 else 0;
AddLabel( yes, "Total bars = " + barNum, ), Color.pink );
addchartbubble(BubbleLocation , close, "Last Bar", color.white);
addchartbubble(FirstBar, close, "FirstBar", color.white);
Comment HideBubble() Makes the last value bubble of a plot invisible. This is the bubble in the
right margin and not onthe chart itself.
Comment: A good example of a nested fold. Note that the variable designations (n, s, i and t) cannot
be duplicated in the folds.
80
#hint:<b> Counts the number of bars where close > open. </b>\n Yes/No options to show
a summary label, count numbers and bar numbers.
input ShowBarNumb = No;#hint ShowBarNumb: Yes show the bar numbers below the low.
input ShowCountNos = yes;#hint ShowCountNos:Yes show the count of when close > open.
It shows above the high.
input ShowLabel = yes;#hint ShowLabel:yes shows a summary label of the percent of bars
that are up.
Def counter_AnyDay = CompoundValue (1,if close > open then counter_AnyDay[1] + 1 else
counter_AnyDay[1],1);
plot count = if close > open && ShowCountNos then counter_AnyDay else double.nan;
Count.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);
Comment: This counter can be easily converted to counting whatever you want. For example, if you
want to count the number of days that have risen 1%, you would substitute the term 'close > open'
with '(close/close[1] > 1.01) '. Naturally the aggregation is set to what you want to count like days,
hours, 15 min bars, etc. The below code illustrates how this existing code can be taken and easily
modified into another study. Compare the two.
81
#hint:<b> Counts the number of bars where close has risen an inputted percent. </b>\n
Yes/No options for label, count numbers and bar numbers.
input ShowBarNumb = No;#hint ShowBarNumb: Yes show the bar numbers below the low.
input ShowCountNos = yes;#hint ShowCountNos:Yes show the count of occurences. It shows
above the high.
input ShowLabel = yes;#hint ShowLabel:Yes shows a summary label of the percent of bars
that are up by the inputted percentage.
input PctUp = 0.5; #hint PctUp:<b>Show the percent rise desired</b>\nA stock
infrequently rises more than 2% in a day.
Def counter_AnyDay =if close !=first(close) && (close/close[1] > PctFactor) then
counter_AnyDay[1] + 1 else counter_AnyDay[1];
Count.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);
Comment: The label is complex and a good example of the use of '+' in lieu of the concat function.
#hint:<b>Plots the high, low and close of inputted days ago</b>\n The plots persist
across the entire chart.\n Bubbles identify the plots.\nWorks for all aggregations
thru 'Day'.
declare upper;
input LastBubble = No;#hint LastBubble: No omits the last bubble. May affect reading
82
of data.
Input DaysAgo = 1;#hint DaysAgo: Excludes today
def AdjDaysAgo = DaysAgo + 1;#Adjusted to match a true LastDate which includes today
83
addchartbubble(BubbleLocation && LastBubble, PreviousClose, ("Close of " + DaysAgo +
" day(s) ago"), color.white);
The date and time functions take a lot of time to learn and much usage to feel comfortable with
them. Hence, this section will be as thorough as possible with many examples to illustrate their
usage. Additional examples will be added as they may surface online and in the chatroom.
• GetDay, GetWeek, GetMonth and GetYear all relate to the CURRENT BAR and return values that
relate to the ENTIRE YEAR: i.e. 1 to 366, 1 to 53, 1 to 12, and the year respectively.
• GetLastDay, GetLastWeek, GetLastMonth and GetLastYear all relate to the LAST BAR and return
values that relate to the ENTIRE YEAR: i.e. 1 to 366, 1 to 53, 1 to 12, and the year respectively.
• GetYYYYMMDD() is the most frequently used. Returns the date of the current bar in the
YYYYMMDD format. This date corresponds to the day whose trading session contains the
current bar. Note that on intraday charts, this date and the actual date might not be the same
for Forex and Futures symbols.
• The 'fromDate', 'toDate’and 'tillDate' used in CountTradingDays, DaysFromDate and DaysTillDate are
all in the YYYYMMDD format.
In summary, all date/time functions beginning with 'Get……..', except for GetDayOfWeek and
GetDayOfMonth, have no parameters. All date/time functions having parameters, except for
SecondsFromTime and SecondsTillTime, use a parameter format of YYYYMMDD. SecondsFromTime and
SecondsTillTime use a HHMM format.
REMEMBER THAT DATE/TIME FUNCTIONS RELATE TO A BAR ON A CHART. NO BAR THEN THE
DATE/TIME RETURNED VALUES ARE NOT RELIABLE.
Comment 2: CountTradingDays includes the CurrentDate and the LastDate in the count
84
#hint: Between the two input dates
#hint startDateYyyyMmDd: Select starting date of line.
#hint endDateYyyyMmDd: Select ending date of line.
Usage: The above two line are conditions that you use to restrict your data
Example: plot trendLine = if start then startPrice else if end then endPrice else double.nan;
Comment 1: 'SecondsFromTime' and 'Seconds TillTime' work smoothly during market hours but
beware after-hours. A time is always associated with a bar. If there is no bar, TOS will have a
problem
Comment 2: Thinly trader stocks may not have a bar at the time defined. Beware for the same
reason as above.
Example 1:
#Hint: his defines a time range during which the close will be plotted.
input OpenTime = 1130;
input DurationHours = 5;
def durationSec = DurationHours * 60 * 60;
def secondsPassed = SecondsFromTime(OpenTime);
plot Price = if secondsPassed >= 0 and secondsPassed <= durationSec then close else
double.NaN;
Comment 3: "if secondsPassed >= 0 and secondsPassed ⇐ durationSec then….." may be applied to
any activity you want to do.
Example 2:
85
======== SecondsFromTime & SecondsTillTime ========
# Defines the hours from last bar till end-of-day (midnight) on an intra-day chart
input time = 0001;# Is midnight which is the start of counting seconds in the
functions below.
def TimeFrom = SecondsFromTime(time);# Returns the seconds from 'time'. If not an
intra-day chart, returns 0.
def TimeLeft = SecondsTillTime(time);# Returns the seconds till input 'time'. If not
an intra-day chart, returns 0.
AddLabel(1, "Time from last bar till end-of-day (midnight) = " +(Round( (24 +
(TimeLeft / 3600)),1)) + " Hours",color.white);
Returns the date of the current bar. If there is no bar on a chart, like in pre and after-market hours
or weekends and holidays, then results, including label values, from the date/time functions are not
reliable.
A typical GetYYYYMMDD() result date is 20,131,107. This result doesn’t look like a date especially with
the commas but it is.
When GetYYYYMMDD() is compared to an inputted date the commas are omitted in the input date. An
example is input endDate = 20100101;
• RegularTradingEnd(int yyyyMmDd); #Returns the end of the regular trading hours for the current
symbol on the trading day specified in the YYYYMMDD. This value is the number of milliseconds
since the epoch (January 1, 1970, 00:00:00 GMT).
• RegularTradingStart(int yyyyMmDd); Returns the start of the regular trading hours for the
current symbol on the trading day specified in the YYYYDDMM format. This value is the number
of milliseconds since the epoch (January 1, 1970, 00:00:00 GMT).
Usage example 1:
`def yyyymmdd = GetYYYYMMDD(); `#Returns the date of the chart’s current bar. During trading
hours this is also today’s date. If run on a weekend, this is not today’s date since there is no current
bar for today.
Assuming that 20,131,107 was returned it can be formatted into a normal view as follows:
86
Usage example 2:
DaysFromDate(First(yyyymmdd));# This defines the number of days from the first bar of
the chart to the last bar (current bar).
Usage example 3:
Returns the number of days from the specified date in YYYYMMDD format.
Usage example 1:
Usage example 2:
Usage example 3:
87
#Hint: In the script below, "count" counts calendar days, while "count2" counts
trading days, between the startDate and today.
declare lower;
input startDate = 20130201;
plot count = if startDate <= GetYYYYMMDD() then DaysFromDate( startDate ) else
Double.NaN;
plot count2 = if startDate <= GetYYYYMMDD() then CountTradingDays( startDate, if(
GetYYYYMMDD() < startDate,
startDate, GetYYYYMMDD() ) ) else Double.NaN;
Usage example 4:
#Stock scan for all stocks down 25% (from example) from the Highest over the last ??
months
#Enter numMonths and PctDown
Alternate
Returns the number of seconds from/till the specified time (24-hour clock notation) in the EST
timezone. For intra-day only.
Usage example 1:
Scan for PreMarket that shows stocks > 1% from Bid above Close last nite? After-hours must be
activated in settings.
88
input Begin = 0930;
input End = 1600;
plot cond = close(priceType = "Mark") * 1.01 > IsClosed ;#Must use Mark in
Pre/PostMarket
Usage example 2:
Usage example 3:
Usage example 4:
89
#hint: Used to define if OR (Opening Range) is active.
Usage example 5:
Usage example 6:
Usage example 7:
90
#Hint: Identifies a bar at a time and date
plot Data1 = volume;
declare hide_on_daily;
def barnumber = BarNumber();
input time = 1100;
Input TodayDate = 20130104;
def GetYMD = GetYYYYMMDD() == TodayDate;
def timeTest = SecondsFromTime(time) == 0;
def BarID = CompoundValue(1, if timeTest && GetYMD then barnumber else Double.nan,
barnumber());
#def BarIDNo = if(!isnan(BarID), Double.nan,barID);
AddLabel(yes, "BarNumber at arrow = " + BarID, color.white);#?????why this doesn't
show BarID
Plot Data2 = BarID;#The barnumber value
Data2.setPaintingStrategy(PaintingStrategy.VALUES_below); # Arrow_Down, Arrow_Points,
Data2.SetDefaultColor(Color.Green); # for data plot
Data2.SetLineWeight(5);
Plot Data3 = BarID;#An arrow at the selected barnumber
Data3.setPaintingStrategy(PaintingStrategy.Arrow_down); # Arrow_Down, Arrow_Points,
Data3.SetDefaultColor(Color.Green); # for data plot
Data3.SetLineWeight(5);
AddChartBubble( timeTest && GetYMD, Volume , BarID + " is the base \nbar for
comparison", Color.white, no);#Bubble at the selected barnumber stating the barnumber
#Counts the number of trading days from first of the year to current day.
def YearStart = GetYear() * 10000 + 101;#This defines January 1 of the current year.
Good to keep handy.
Usage example 1:
declare lower;
input DaysToInclude = 90;
def Last90Days = daysTillDate(getYyyyMmDd()[-DaysToInclude]) < 0;
plot Data = Last90Days;
Comment: Above plots a horizontal line at a value of 1 (true)for 90 days. The following code will
plot the close for 90 days.
91
Usage example 2:
#Hint: Plots a horizontal line at yesterday's low across the entire chart.This works
if you have at least two days data on the chart.
declare upper;
def lastDaysDate = HighestAll( if getLastDay() == getDay() and getLastYear() ==
getYear() then getYyyyMmDd() else Double.NaN );
Usage example 1:
#hint: Plots the close for bars in the 50 days interval starting from BeginDate
Usage example 2:
#hint: Displays the Point of Control plot for weekly TPO profiles.
92
#hint:Draws a vertical line at 10 bars from the last bar
input x = 10;
declare hide_on_intraday;
input Date = 20130604;#hint Date: Set the date you want see.<b>\n(Enter in
YYYYMMDD)</b>
input price = CLOSE;
input show_line = Yes;#hint show_line: Show a horizontal line at this price<b>(Default
is Yes)</b>
Comment: The AddChartBubble has coding worth studying. Using the '+' formatting syntax is
recommended and has replaced the original 'Concat' syntax used by the author.
93
C-SCALPER’S HELPER W/ SQUEEZE
• === START STUDY
declare lower;
input paintBars = No; # hint paintBars: Yes to color price bars.
input diFilter = Yes; #hint diFilter: No to turn off DI filter.
input avgFilter = Yes; #hint avgFilter: No to turn off mov. avg. filter.
input prFilter = Yes; #hint prFilter: No to turn off price filter.
input price = close; #hint price: price fundamental.
input prMom = 1; #hint prMom: offset for price (mom)entum.
input diLength = 13; #hint diLength: For DI+, DI- calc, and mom sum.
input signal = 13; #hint signal: Horiz. position of the Sig line.
#############################################
# Keltner Channel and Bollinger Band Squeeze:
input avgType = AverageType.SIMPLE; # Mov. avg type.
input avgLength = 20; # length for band and channel mov. avg.
input numDev = 2.0; # number of std devs of band.
input factor = 1.5; # factor for offsetting channel.
def MA = MovingAverage(avgType, price, avgLength);
#
#############################################
def hiDiff = high - high[1];
def loDiff = low[1] - low;
def ATR = WildersAverage(TrueRange(high, close, low), diLength);
#diDif is ("DI+" - "DI-")
def diDif = (100 * WildersAverage(if hiDiff > loDiff and hiDiff > 0 then hiDiff else
0, diLength) / ATR) - (100 * WildersAverage(if loDiff > hiDiff and loDiff > 0 then
loDiff else 0, diLength) / ATR);
94
def diUp = !diFilter or (diFilter and diDif > 0 and diDif > diDif[1]);
def diDn = !diFilter or (diFilter and diDif < 0 and diDif < diDif[1]);
def avgUp = !avgFilter or (avgFilter and price > MA);
def avgDn = !avgFilter or (avgFilter and price < MA);
#dir is 1 if last PPS signal was up, and up filters are valid or turned off; dir is
-1 if last PPS signal was down, and down filters are valid or turned off.
def dir = CompoundValue(1, if ppsDir > 0 and avgUp and diUp then 1 else if ppsDir < 0
and avgDn and diDn then -1 else dir[1], 0);
#If dir is up (> 0) then add to dirCnt the sum of price bars moving up, else add to
dir the sum of price bars moving down.
AssignPriceColor(if !paintBars then Color.CURRENT else if dir > 0 then if Count > Sig
then Color.GREEN else Color.DARK_GREEN else if dir < 0 then if Count > Sig then
Color.RED else Color.DARK_RED else Color.GRAY);
95
C-COLOR A PORTION OF A CHART
By Krill at http://groups.yahoo.com/neo/groups/TOS_thinkscript/info
#Colors a portion of a chart from top to bottom between the times entered
input start = 0930; # time in ET
input end = 1200;
def toPaint = SecondsFromTime(start) >= 0 and SecondsTillTime(end) > 0;
def up = if toPaint then Double.POSITIVE_INFINITY else Double.NaN;
# Unfortunetly Double.NEGATIVE_INFINITY does not work in AddCluod()
def down = if toPaint then LowestAll(low) else Double.NaN;
AddCloud(up, down, Color.RED);
96
#created Richard Houser - tos_thinkscript@yahoogroups.com
#Labels added by SFL
#TOS Title = CloudBetweenMovingAverages
#hint:Cloud usage between two moving averages
declare upper;
input price = close;
input fastLength = 8;
input fastAvgType = AverageType.SIMPLE;
input slowLength = 20;
input slowAvgType = AverageType.SIMPLE;
97
#hint:<b>Daily_Hi_Lo</b>\nWhite lines show the current day's H/L range. Cyan shows the
previous day's. The red line shows the previous day's close
DailyHigh.SetDefaultColor(GetColor(9));
DailyHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
DailyLow.SetDefaultColor(GetColor(9));
DailyLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#************************************************************
def PreDailyHigh = Highest(high(period = aggregationPeriod)[1], length);
def PreDailyLow = Lowest(low(period = aggregationPeriod)[1], length);
plot YesterHi = PreDailyHigh;
plot YesterLo = PreDailyLow;
YesterHi.SetDefaultColor(color.cyan);
YesterHi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
YesterLo.SetDefaultColor(color.cyan);
YesterLo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#input timeFrame = {default DAY, WEEK, MONTH};
def YstrdaysClose = close(period = aggregationPeriod)[1];
plot YesterClose = YstrdaysClose;
YesterClose.SetDefaultColor(GetColor(5));
YesterClose.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
98
C -SELF-ADJUSTING RSI BANDS
declare lower;
input Length = 14;
input StdDevConst = 1.8;
input SMA_const = 2.0;
input Method = { default SD, SMA };
input price = close;
MidLine.SetPaintingStrategy(PaintingStrategy.LINE);
MidLine.SetLineWeight(2);
MidLine.SetDefaultColor(Color.YELLOW);
MidLine.SetStyle(Curve.SHORT_DASH);
99
#by R. Houser
#hint:<b>Three MVSs ascending/descending color change</b> \nWhen the MovingAverage is
increasing in value it will change color, and when it is decreasing in value change
color again. User is able to select color of MovingAverage line when it is increasing
or decreasing
declare upper;
input fastLength = 3;
input mediumLength = 8;
input slowLength = 21;
input price = close;
input avgType = AverageType.EXPONENTIAL;
plot fastMVA = MovingAverage( avgType, price, fastLength );
plot mediumMVA = MovingAverage( avgType, price, mediumLength );
plot slowMVA = MovingAverage( avgType, price, slowLength );
fastMVA.DefineColor( "up", GetColor( 0 ) );
fastMVA.DefineColor( "dn", GetColor( 1 ) );
fastMVA.DefineColor( "def", GetColor( 2 ) );
fastMVA.AssignValueColor( if fastMVA > fastMVA[1] then fastMVA.Color( "up" ) else if
fastMVA < fastMVA[1] then
slowMVA.Hide();
100
#Hint:<b>T3 - Adaptive Smoothing Indicator</b>
# by Richard Houser tos_thinkscript@yahoo.groups
# --------------------------------------------------------------------------------
# The Formula . . . . . .more on Formulas
# T3(n) = GD(GD(GD(n)))
# GD(n,v) = EMA(n)*(1+v) - EMA(EMA(n))*v
# GD stands for Generalized DEMA (double-smoothed exponential MA)
# where
# n = Period
# v = Volume Factor
# http://www.linnsoft.com/tour/techind/t3.htm
declare upper;
script GD {
input period = 10;
input volumeFactor = 0.7;
input price = close;
101
#hint: Plots the RSI oscillating about the ZeroLine in lieu of a OB/OS format
#TOS Title = RSI_Zero_Osc
#Comment: See the two methods of coloring a histogram in "#=== COLORING =" below.
declare lower;
#################################
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.YELLOW);
ZeroLine.SetLineWeight(1);
#The line below plots at the bar values and adds a lot of class to the looks of a
histogram
plot RSI_Line = (50 * (ChgRatio + 1) - 50);
RSI_Line.SetDefaultColor(GetColor(1));
C-INSYNC INDEX
102
different technical indicators, and used to determine extreme overbought/oversold
values in the market.
#InSync Index
# Coded by Eric Rasmussen
#
# The InSync Index is used detect extreme levels.
# Values higher or equal to 50 are considered to be high extreme levels. (sell)
# Values lower or equal than -50 are considered to be low extreme levels. (buy)
declare lower;
#Study Definitions
def bbUpper = BollingerBandsEMA().UpperBand;
def bbLower = BollingerBandsEMA().LowerBand;
def bbCalc = (close - bbLower)/(bbUpper - bbLower);
def macd1 = MACD(8, 17);
def macd2 = macd1 - (MACD(8, 10) - MACD(17, 20));
def rsi = rsIWilder();
def change = RateOfChange(10);
def dpo = detrendedPriceOsc();
def eom = easeOfMovement();
def mf = moneyFlowIndex();
def stoch = StochasticFull("k period" = 14);
def bomp = balanceOfMarketPower();
def cc = cci();
#Indicator Scoring
def bb = if bbCalc > .95 then 5 else if bbCalc < .05 then -5 else 0;
def cci = if cc > 100 then 5 else if cc < -100 then -5 else 0;
def macd = if macd1 > 0 and macd2 > 0 then 5 else if macd1 < 0 and macd2 < 0 then
-5 else 0;
def roc = if change > 1 and change > expAverage(change, 10) then 5 else if change
< 1 and change < expAverage(change, 10) then -5 else 0;
def sto = if stoch > 80 then 10 else if stoch < 20 then -10 else 0;
def rsiW = if rsi > 70 then 5 else if rsi < 30 then -5 else 0;
def bop = if bomp > 0 and bomp > expAverage(bomp, 10) then 5 else if bomp < 0 and
bomp < expAverage(bomp, 10) then -5 else 0;
#Point Sum
def sum = bb + cci + macd + roc + sto + rsiW + bop + dp + emv + mfi;
#Plots
plot inSync = expAverage(sum, smooth);
103
plot zero = if isNaN(close) then double.NaN else 0;
plot pos55 = if isNaN(close) then double.NaN else 50;
plot neg55 = if isNaN(close) then double.NaN else -50;
inSync.assignValueColor(if sum > 0 then color.GREEN else color.RED);
inSync.setLineWeight(2);
zero.assignValueColor(color.LIGHT_GRAY);
pos55.assignValueColor(color.RED);
neg55.assignValueColor(color.GREEN);
zero.hideTitle();
pos55.hideTitle();
neg55.hideTitle();
#COMMENT: You can alter the criteria and/or the indicators to suit your trading style
104
#hint:<b>An improved TimeSeriesForecast study.</b> \nThe improvement is done here
using a non-TOS correct regression slope calculation comparable with the RH's code on
this topic. This is a substitute for the builtin 'TimeSeriesForecast'.
Buy.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
Buy.SetLineWeight(5);
Buy.SetDefaultColor(Color.GREEN);
C-VOLATILITY LABEL
105
#hint:Places a volatility label on the upper panel
#begin
declare upper;
def IV = Round(ImpVolatility() * 100);
def HV = Round(HistoricalVolatility() * 100);
AddLabel(yes, "ImpVolatility = " + IV + " % and HistoricalVolatility = " + HV + " %",
color.green);
Comment:HV and IV do not plot on intraday. The default HV is annual and that is what will show in
the label. On an intraday chart the IV will show N/A and the HV will be annual HV. to get the daily
value of Implied Volatility:
#hint:Battle of the Bands Indicates the range of price using Implied Volatility,
Bollinger Bands or Keltner Channel. No direction (up or down) is implied since price
is assumed random by the calculations. Mobius©: # Battle of the Bands
#V02.10.17.2013
declare hide_on_daily;
input n = 21;
input IvDailyBands = no;
input IvHourBands = no;
input IV15minBands = yes;
input AtrBands = no;
input BollingerBands = yes;
input DisplayLabels = yes;
def o = open;
def h = high;
def l = low;
def c = close;
def period = AggregationPeriod.DAY;
def hd = high(period = period);
def ld = low(period = period);
def cd = close(period = period);
def DaysMean = hl2(period = period);
def HoursMean = hl2(period = AggregationPeriod.HOUR);
def IVd = imp_Volatility(period = period);
106
def IV = if isNaN(IVd) then IV[1] else IVd;
def hIV = Highest(IV, 252);
def lIV = Lowest(IV, 252);
def IVpercentile = (IV - lIV) / (hIV - lIV);
AddLabel(DisplayLabels, "IV " + AsPercent(IV) + " IV Percentile: " +
AsPercent(IVpercentile)
, if IsAscending(IV)
then Color.GREEN
else if IsDescending(IV)
then Color.RED
else Color.WHITE);
107
DaysIVhigh.SetHiding(!IvDailyBands);
DaysIVhigh.SetPaintingStrategy(PaintingStrategy.DASHES);
108
else if ATR < ATR[1]
then Color.RED
else Color.WHITE);
declare upper;
#Study Inputs
input gaussian = { "ONE", "TWO", "THREE", default "FOUR" };
input data = OHLC4;
input length = 10;
input gaussianOrder = 3;
input cloud = yes;
#Definitions
def w; def beta; def alpha;
def rbi1; def rbi2; def rbi3; def rbi4;
def rbi5; def rbi6;def rbi7; def rbi8;
#Alpha Calculation
w = ( 2 * double.Pi / length );
beta = ( 1 - cos( w ) ) / ( power( 1.414, 2.0 / gaussianOrder ) - 1 );
alpha = ( -beta + sqRt( beta * beta + 2 * beta) );
#Average Calculations
switch( gaussian ) {
case "ONE":
rbi1 = alpha * data + ( 1 - alpha ) * rbi1[1];
rbi2 = alpha * rbi1 + ( 1 - alpha ) * rbi2[1];
rbi3 = alpha * rbi2 + ( 1 - alpha ) * rbi3[1];
rbi4 = alpha * rbi3 + ( 1 - alpha ) * rbi4[1];
rbi5 = alpha * rbi4 + ( 1 - alpha ) * rbi5[1];
rbi6 = alpha * rbi5 + ( 1 - alpha ) * rbi6[1];
rbi7 = alpha * rbi6 + ( 1 - alpha ) * rbi7[1];
rbi8 = alpha * rbi7 + ( 1 - alpha ) * rbi8[1];
case "TWO":
rbi1 = power( alpha, 2 ) * data +
2 * ( 1 - alpha ) * rbi1[1] -
power( 1 - alpha, 2 ) * rbi1[2];
109
rbi2 = power( alpha, 2 ) * rbi1 +
2 * ( 1 - alpha ) * rbi2[1] -
power( 1 - alpha, 2 ) * rbi2[2];
rbi3 = power( alpha, 2 ) * rbi2 +
2 * ( 1 - alpha ) * rbi3[1] -
power( 1 - alpha, 2 ) * rbi3[2];
rbi4 = power( alpha, 2 ) * rbi3 +
2 * ( 1 - alpha ) * rbi4[1] -
power( 1 - alpha, 2 ) * rbi4[2];
rbi5 = power( alpha, 2 ) * rbi4 +
2 * ( 1 - alpha ) * rbi5[1] -
power( 1 - alpha, 2 ) * rbi5[2];
rbi6 = power( alpha, 2 ) * rbi5 +
2 * ( 1 - alpha ) * rbi6[1] -
power( 1 - alpha, 2 ) * rbi6[2];
rbi7 = power( alpha, 2 ) * rbi6 +
2 * ( 1 - alpha ) * rbi7[1] -
power( 1 - alpha, 2 ) * rbi7[2];
rbi8 = power( alpha, 2 ) * rbi7 +
2 * ( 1 - alpha ) * rbi8[1] -
power( 1 - alpha, 2 ) * rbi8[2];
case "THREE":
rbi1 = power( alpha, 3 ) * data +
3 * ( 1 – alpha ) * rbi1[1] -
3 * power( 1 - alpha, 2 ) * rbi1[2] +
power( 1 - alpha, 3 ) * rbi1[3];
rbi2 = power( alpha, 3 ) * rbi1 +
3 * ( 1 – alpha ) * rbi2[1] -
3 * power( 1 - alpha, 2 ) * rbi2[2] +
power( 1 - alpha, 3 ) * rbi2[3];
rbi3 = power( alpha, 3 ) * rbi2 +
3 * ( 1 – alpha ) * rbi3[1] -
3 * power( 1 - alpha, 2 ) * rbi3[2] +
power( 1 - alpha, 3 ) * rbi3[3];
rbi4 = power( alpha, 3 ) * rbi3 +
3 * ( 1 – alpha ) * rbi4[1] -
3 * power( 1 - alpha, 2 ) * rbi4[2] +
power( 1 - alpha, 3 ) * rbi4[3];
rbi5 = power( alpha, 3 ) * rbi4 +
3 * ( 1 – alpha ) * rbi5[1] -
3 * power( 1 - alpha, 2 ) * rbi5[2] +
power( 1 - alpha, 3 ) * rbi5[3];
rbi6 = power( alpha, 3 ) * rbi5 +
3 * ( 1 – alpha ) * rbi6[1] -
3 * power( 1 - alpha, 2 ) * rbi6[2] +
power( 1 - alpha, 3 ) * rbi6[3];
rbi7 = power( alpha, 3 ) * rbi6 +
3 * ( 1 – alpha ) * rbi7[1] -
3 * power( 1 - alpha, 2 ) * rbi7[2] +
power( 1 - alpha, 3 ) * rbi7[3];
rbi8 = power( alpha, 3 ) * rbi7 +
110
3 * ( 1 – alpha ) * rbi8[1] -
3 * power( 1 - alpha, 2 ) * rbi8[2] +
power( 1 - alpha, 3 ) * rbi8[3];
case "FOUR":
rbi1 = power( alpha, 4 ) * data +
4 * ( 1 – alpha ) * rbi1[1] –
6 * power( 1 - alpha, 2 ) * rbi1[2] +
4 * power( 1 - alpha, 3 ) * rbi1[3] -
power( 1 - alpha, 4 ) * rbi1[4];
rbi2 = power( alpha, 4 ) * rbi1 +
4 * ( 1 – alpha ) * rbi2[1] –
6 * power( 1 - alpha, 2 ) * rbi2[2] +
4 * power( 1 - alpha, 3 ) * rbi2[3] -
power( 1 - alpha, 4 ) * rbi2[4];
rbi3 = power( alpha, 4 ) * rbi2 +
4 * ( 1 – alpha ) * rbi3[1] –
6 * power( 1 - alpha, 2 ) * rbi3[2] +
4 * power( 1 - alpha, 3 ) * rbi3[3] -
power( 1 - alpha, 4 ) * rbi3[4];
rbi4 = power( alpha, 4 ) * rbi3 +
4 * ( 1 – alpha ) * rbi4[1] –
6 * power( 1 - alpha, 2 ) * rbi4[2] +
4 * power( 1 - alpha, 3 ) * rbi4[3] -
power( 1 - alpha, 4 ) * rbi4[4];
rbi5 = power( alpha, 4 ) * rbi4 +
4 * ( 1 – alpha ) * rbi5[1] –
6 * power( 1 - alpha, 2 ) * rbi5[2] +
4 * power( 1 - alpha, 3 ) * rbi5[3] -
power( 1 - alpha, 4 ) * rbi5[4];
rbi6 = power( alpha, 4 ) * rbi5 +
4 * ( 1 – alpha ) * rbi6[1] –
6 * power( 1 - alpha, 2 ) * rbi6[2] +
4 * power( 1 - alpha, 3 ) * rbi6[3] -
power( 1 - alpha, 4 ) * rbi6[4];
rbi7 = power( alpha, 4 ) * rbi6 +
4 * ( 1 – alpha ) * rbi7[1] –
6 * power( 1 - alpha, 2 ) * rbi7[2] +
4 * power( 1 - alpha, 3 ) * rbi7[3] -
power( 1 - alpha, 4 ) * rbi7[4];
rbi8 = power( alpha, 4 ) * rbi7 +
4 * ( 1 – alpha ) * rbi8[1] –
6 * power( 1 - alpha, 2 ) * rbi8[2] +
4 * power( 1 - alpha, 3 ) * rbi8[3] -
power( 1 - alpha, 4 ) * rbi8[4];
}
#plots
plot ga1 = rbi1; plot ga2 = rbi2; plot ga3 = rbi3; plot ga4 = rbi4;
plot ga5 = rbi5; plot ga6 = rbi6; plot ga7 = rbi7; plot ga8 = rbi8;
111
ga1.assignValueColor( color.MAGENTA );
ga2.assignValueColor( color.PLUM );
ga3.assignValueColor( color.BLUE );
ga4.assignValueColor( color.CYAN );
ga5.assignValueColor( color.GREEN );
ga6.assignValueColor( color.YELLOW );
ga7.assignValueColor( color.DARK_ORANGE );
ga8.assignValueColor( color.RED );
ga1.hideTitle(); ga2.hideTitle(); ga3.hideTitle(); ga4.hideTitle();
ga5.hideTitle(); ga6.hideTitle(); ga7.hideTitle(); ga8.hideTitle();
#Cloud Plots
addCloud( if cloud == yes then ga1 else double.NaN, ga8, color.RED, color.BLACK );
addCloud( if cloud == yes then ga1 else double.NaN, ga7, color.DARK_ORANGE,
color.BLACK );
addCloud( if cloud == yes then ga1 else double.NaN, ga6, color.YELLOW, color.YELLOW );
addCloud( if cloud == yes then ga1 else double.NaN, ga5, color.GREEN, color.GREEN );
addCloud( if cloud == yes then ga1 else double.NaN, ga4, color.BLUE, color.BLUE );
addCloud( if cloud == yes then ga1 else double.NaN, ga3, color.PLUM, color.PLUM );
addCloud( if cloud == yes then ga1 else double.NaN, ga2, color.MAGENTA, color.MAGENTA
);
def s = ShowTodayOnly;
def na = Double.NaN;
def ORActive = if SecondsTillTime(OREnd) > 0 and SecondsFromTime(ORBegin) >= 0 then 1
else 0;
def today = if s == 0 or GetDay() == GetLastDay() and SecondsFromTime(ORBegin) >= 0
then 1 else 0;
112
rec ORLow = if ORLow[1] == 0 or ORActive[1] == 0 and ORActive == 1 then low else if
ORActive and low < ORLow[1] then low else ORLow[1];
113
d6.SetPaintingStrategy(PaintingStrategy.POINTS);
d7.SetPaintingStrategy(PaintingStrategy.POINTS);
d8.SetPaintingStrategy(PaintingStrategy.POINTS);
d9.SetPaintingStrategy(PaintingStrategy.POINTS);
d10.SetPaintingStrategy(PaintingStrategy.POINTS);
def Span = (O - ORL2) / (ORH2 - ORL2);
plot bd1 = If (TimeLineb , ORHA, na); plot bd2 = If (TimeLineb , ORHA - ( posbd * 2),
na);
plot bd3 = If (TimeLineb , ORHA - ( posbd * 3), na); plot bd4 = If (TimeLineb , ORHA -
( posbd * 4), na);
plot bd5 = If (TimeLineb , ORHA - ( posbd * 5), na); plot bd6 = If (TimeLineb , ORHA -
( posbd * 6), na);
plot bd7 = If (TimeLineb , ORHA - ( posbd * 7), na); plot bd8 = If (TimeLineb , ORHA -
( posbd * 8), na);
plot bd9 = If (TimeLineb , ORHA - ( posbd * 9), na); plot bd10 = If (TimeLineb ,
(ORL2), na);
bd1.SetPaintingStrategy(PaintingStrategy.POINTS);
bd2.SetPaintingStrategy(PaintingStrategy.POINTS);
114
bd3.SetPaintingStrategy(PaintingStrategy.POINTS);
bd4.SetPaintingStrategy(PaintingStrategy.POINTS);
bd5.SetPaintingStrategy(PaintingStrategy.POINTS);
bd6.SetPaintingStrategy(PaintingStrategy.POINTS);
bd7.SetPaintingStrategy(PaintingStrategy.POINTS);
bd8.SetPaintingStrategy(PaintingStrategy.POINTS);
bd9.SetPaintingStrategy(PaintingStrategy.POINTS);
bd10.SetPaintingStrategy(PaintingStrategy.POINTS);
bd1.SetDefaultColor(Color.YELLOW); bd2.SetDefaultColor(Color.YELLOW);
bd3.SetDefaultColor(Color.YELLOW);
bd4.SetDefaultColor(Color.YELLOW); bd5.SetDefaultColor(Color.YELLOW);
bd6.SetDefaultColor(Color.YELLOW);
bd7.SetDefaultColor(Color.YELLOW); bd8.SetDefaultColor(Color.YELLOW);
bd9.SetDefaultColor(Color.YELLOW);
bd10.SetDefaultColor(Color.YELLOW);
AddCloud(Shade1, shade2,color.light_red,color.light_red);
#======= end of Shade option selection ========
AddLabel(yes,"OR High = "+ ORH2 + " & OR Low = " + ORL2, color.pink);
115
#hint:Plots a <b>replica of the builtin 'MarketForecast'</b> with labels added &
colors altered\nThis replica provides parameters that can be used in a subsequent
plot/scan to identify the powerful cluster concept.
declare lower;
def na = Double.NaN;
Plot OB =80;
OB.SetPaintingStrategy(PaintingStrategy.LINE);
OB.SetLineWeight(1);
OB.SetDefaultColor(Color.YELLOW);
Plot OS = 20;
OS.SetPaintingStrategy(PaintingStrategy.LINE);
OS.SetLineWeight(1);
OS.SetDefaultColor(Color.YELLOW);
116
Comment:The following code plots when a cluster exists in the above code. A cluster is when all
three plots are either above OB (80) or below OS (20). Clusters are powerful points for buy/sell
decisions.
#Hint: <b>Plots when the market forecast high or low clusters are true.</b>\n When
used as a scan, <b>EITHER</b> 'Plot Cluster_Hi' or 'Plot Cluster_Lo' need to be
commented-out with #. When used as a plot the day agg is most meaningful
#Title = Cluster_TMF
declare lower;
#===== When used as a study plot, all four lines below are active ========#
#===== When used as a scan, two of the four lines below are commented out depending on
the scan desired =======#
Plot Cluster_Hi = if clusterhigh then 1 else 0;
Cluster_Hi.SetDefaultColor(Color.CYAN);
117
#Hint: Draws a line between to points defined by dates, times and price type
Developed by RCG3 and StanL on the ThinkScript Lounge 1/2/14
input time1 = 1000;#hint time1:Time of first point using the 24-hour clock
input date1 = 20140102;#hint date1:Date of the first point in YYYYMMDD format
input time2 = 1300;#hint time2: Time of second point using the 24-hour clock
input date2 = 20140102;#hint date2: Date of the first point in YYYYMMDD format
input price = high;#hint price: Select the price type desired
#====== To see dots on the inputted dates/times change the def below for
#===== 'asdf' and 'asdf2' to plot and uncomment the setpaintingstrategy =====
118
#hint:Shows a label stating the current day's volume as a percent of an inputted X-
days-AvgVolume
declare upper;
#AddLabel(1,aspercent(Percent),if Percent <= .70 AND ( dayOpen < curClose or dayOpen >
curClose ) then Color.LIGHT_GRAY else if (.80 >= Percent > .70) AND ( dayOpen <
curClose or dayOpen > curClose ) then Color.YELLOW else if Percent > .80 AND dayOpen <
curClose then Color.Green else if Percent > .80 AND dayOpen > curClose then
Color.red else Color.WHITE );# This label may be used in a custom column
Comment1: This has all the ingredients for a custom column except the label text is
too verbose for a column. The lower label is suitable for a custom column
Def Example1 = sum(low > Average(close, 21), 5) == 5;# Is true when the 21-bar-average-of-the-close
exists (is true) for the last 5 consecutive bars.
119
To change the above to a condition use:
Def Example4 = sum(close > close[1],5) >= 5;#Is true when the close has been rising (trending up) for
the last 5 bars
Example 5: Uses sum to look for a divergence. Can be useful in a custom watchlist column. Here the
MACD average is going up while the MACD itself is going down for the number of 'Bars'.
Input Bars = 3;
def macdAvg = MACD().Avg;
def macdValue = MACD();
def div = sum( macdAvg > macdAvg[1],Bars) == Bars ;#True if rising for the last 'Bars'
bars
def div2 = sum( macdValue < macdValue[1],Bars) == Bars;#True if falling for the last
'Bars' bars
plot scan = div and div2;
Def Example6 = sum(close < close[1],5) == 5;# The has declined for the last 5 bars
Example 7 = A more flexible code having selectable price, length and direction (Choice).
plot scan;
switch (Choice){
case "increased":
scan = sum(price > price[1], length) == length;
case "decreased":
scan = sum(price < price[1], length) == length;
}
Comment: If the above code was in a saved study named 'MyPriceTrend', you would run it by
entering the following code in the custom scan location. This procedure is applicable for all saved
custom studies.
Note that 'hlc3' may be any parameter such as open, hugh, low, hl2, volume, etc. Be sure to set the
time aggregation you desired i.e. 5 min, hour, day, etc.
Def Example 8: The following code is used to scan for stocks having future earnings.
120
Input length = 10;#Hint length:The number of future/ahead agg-bars to look in
def earnings = hasearnings();#When true this evaluates to one which then appears in
the following 'sum'
plot scan = sum(earnings,length)[-length +1] > 0;# Will return all stocks having
earnings within the next 10 days.
Def Example 9
declare lower;
121
def length = 5;# The numbers of agg-bars DMI is climbing
def x =DMI_Oscillator();
def up = x > x[1];
Plot Scan = x > 10 && sum(up,length) >= length;# This returns stocks whose
DMI_Oscillator value is greater than +10 and has been up for the last 5 bars. The DMI
is the driving force behind the ADX, so this is equivalent to the bullish ADX trending
up for the last 5 bars.
122
def pro = projectionBands();
def prol = ProjectionBands().MinBound;
def cond = pro - prol < pro[1] - prol[1];
plot scan = sum(cond,5) >= 5;# Returns stocks whose projrction bands have been
narrowing for the last 5 bars
def hi = high;
def lo = low;
def higher = if hi > hi[1] then hi else higher[1];
def lower = if lo < lo[1] then lo else lower[1];
plot h = higher;
h.SetLineWeight(1);
h.SetDefaultColor(Color.cyan);
plot l =lower;
l.SetLineWeight(1);
l.SetDefaultColor(Color.pink);
def hig = higher > higher[1];
def lowe = lower < lower[1];
plot x = sum(hig,number) >= number;# Plots an arrow down when a higher high exists for
3 (number) bars.
x.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_DOWN);
x.SetLineWeight(1);
x.SetDefaultColor(Color.White);
plot y = sum(lowe,number) >= number;# Plots an arrow up when a lower low exists for 3
(number) bars.
y.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_UP);
y.SetLineWeight(1);
y.SetDefaultColor(Color.yellow);
Example 15 #Scan for stocks with the consecutive number of higher-highs(plot scan1) or lower-lows
(plot scan2)
123
input price = close;
input number = 7;#hint number: The number of consecutive bars
def hi = high;
def lo = low;
def higher = if hi > hi[1] then hi else higher[1];
def lower = if lo < lo[1] then lo else lower[1];
def hig = higher > higher[1];
def lowe = lower < lower[1];
plot scan1 = sum(hig,number) >= number;#returns stocks that have a higher high for the
last 7 (number) bars
#plot scan2 = sum(lowe,number) >= number;#returns stocks that have a lower low for the
last 7 (number) bars
Another point to remember is that some candles are both bearish and bullish. If you do nt
distinguish which you want like Harami() the default bearish Harami will be returned. To be
thorough and clear, you ought to code Harami().Bearish or Harami().Bullish instead depending on
what you desire. A Doji() is neither bearish nor bullish so Doji() is used alone.
"Here is the code for my favorite indicator. It is an overbought oversold indicator that I use on just
about everything. I think the settings I use are the best ones, I have tried different values over the
124
last several years, but these seem to work the best across all time frames. The best major signal
come when the two oscillators line up. Plot it on a stock daily chart and a 5 min futures chart and I
think you will get the picture. On my 3 minute or 5 minutes futures charts, I use the same settings
except for one, the second to the last choice for slowing period1 I use 9 instead of 24. It provides a
more responsive Stochastic for day trading.
Comment: Although there are many stochastis studies out there, this one looked very useful. It is
similar to the Market Forecast. A powerful signal is present when both speeds are simultaneously
below OS or above OB.
declare lower;
WhiteLabel.SetDefaultColor(Color.White);
plot FullK;
plot FullD;
if smoothingType == 1
then {
FullK = Average(FastK, slowing_period);
FullD = Average(FullK, DPeriod);
125
} else {
FullK = ExpAverage(FastK, slowing_period);
FullD = ExpAverage(FullK, DPeriod);
}
FullK.SetPaintingStrategy(PaintingStrategy.LINE);
FullK.SetLineWeight(2);
FullK.SetDefaultColor(Color.RED);
FullD.SetPaintingStrategy(PaintingStrategy.LINE);
FullD.SetLineWeight(1);
FullD.SetDefaultColor(Color.YELLOW);
#========================================
plot OverBought = over_bought;
OverBought.SetDefaultColor(Color.CYAN);
#
# thinkorswim, inc. (c) 2008
# Stochastics
126
def c11 = priceC - Lowest(priceL, KPeriod1);def c21 = Highest(priceH, KPeriod1) -
Lowest(priceL, KPeriod1);
def FastK1 = c11 / c21 * 100;
plot FullK1;
plot FullD1;
if smoothingType1 == 1
then {
FullK1 = Average(FastK1, slowing_period1);
FullD1 = Average(FullK1, DPeriod1);
} else {
FullK1 = ExpAverage(FastK1, slowing_period1);
FullD1 = ExpAverage(FullK1, DPeriod1);
}
FullK1.SetPaintingStrategy(PaintingStrategy.LINE);
FullK1.SetLineWeight(2);
FullK1.SetDefaultColor(Color.GREEN);
FullD1.SetPaintingStrategy(PaintingStrategy.LINE);
FullD1.SetLineWeight(1);
FullD1.SetDefaultColor(Color.YELLOW);
############################################
#=== plot min arrows for FullK1 (Slow)====
def cond2 = if crosses(FullK1,Over_Sold,CrossingDirection.any) then 1 else 0;
Plot Min_Slow = if cond2 then FullK1 else double.nan;
Min_Fast.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
Min_Fast.SetLineWeight(4);
Min_Fast.SetDefaultColor(Color.GREEN);
#========================================
Alert(Crosses(FullK, 5, CrossingDirection.ABOVE), "DT OSC Buy", Alert.ONCE,
Sound.Ding);
Alert(Crosses(FullK, 95, CrossingDirection.BELOW), "DT OSC Sell", Alert.ONCE,
Sound.Ding);
Plot Mid_line = 50;
Mid_line.SetPaintingStrategy(PaintingStrategy.DASHES);
Mid_line.SetLineWeight(1);
Mid_line.SetDefaultColor(Color.YELLOW);
127
plot StochSell = If(Crosses(FullK1 or FullD1, 90, CrossingDirection.BELOW) , high,
Double.NaN);
StochSell.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
Label_Line.setDefaultColor(color.CURRENT);
#hint:Today's Dow Jones Industrial status. Any symbol may be substituted for the DJI.
If you enter a futures symbol for the label while showing a stock chart, the label
functions normally during stock trading hours but should be used along with a futures
chart during stock-trading-off-hours. Use multiple instances to monitor additional
stocks.
input symbol = "$DJI";#Hint symbol:Enter in cap letters to improve looks of the label
128
#hint:Show support/resistance lines based on an inputted-number-of-bars
(markPeriod).\n You can adjust the agg to suit your style but 'day' is very
meaningful. \nThe support and resistance lines are generated based on a swing-
high/swing-low concept.
# Keep in mind too few days and you'll get a bunch of false s/r lines. Too many days
and
# you'll miss some number of s/r days. Five days is a good floor to start. Also note
that the right hand bubble value only show for the full S/R and not the intermedite
S/R lines.
#A new support line starts at the lowest-low of the input period when both:
#1. the current bar is the lowest of the last markPeriod and
# 2. the lowest-low of the markPeriod is less than that at the markPeriod-in-the-
future
# are true: In essence forms a V shape. The resistance lines are formed the same but
inverted.
declare upper;
def _highInPeriod = Highest( high, markPeriod );#The highest high in the markperiod
i.e. the PERIOD
def _lowInPeriod = Lowest( low, markPeriod );#The lowest value in the markperiod
i.e. the PERIOD
#=== below saves the marked low for plotting the support line ======
rec _lastMarkedLow = compoundValue( 1, if IsNaN( _markedLow ) then _lastMarkedLow[1]
else if _markedLow then low else _lastMarkedLow[1], low )
#============================[ Marked High ]===================================
def marketHigh = if _highInPeriod > _highInPeriod[-markPeriod] then _highInPeriod
else _highInPeriod[-markPeriod];
def _markedHigh = high == marketHigh;
#=== below saves the marked high for plotting the resistance line ======
rec _lastMarkedHigh = compoundValue( 1, if IsNaN( _markedHigh ) then
_lastMarkedHigh[1] else if _markedHigh then high else _lastMarkedHigh[1], high );
129
def spread = Resistance - Support;
plot IntermediateResistance = Support + ( spread * upperPercent / 100 );
plot IntermediateSupport = Support + ( spread * lowerPercent / 100 );
declare lower;
declare hide_on_intraday;
#IVPercentile
def vol = imp_volatility();
130
def data = if !isNaN(vol) then vol else vol[-1];
def hi = highest(data, TimePeriod);
def lo = lowest(data, TimePeriod);
def ShortHi = highest(data, ShortTimePeriod);
def ShortLo = lowest(data, ShortTimePeriod);
#Labels
addlabel(DisplayIVPercentile , concat("Long IV Rank: ",aspercent(round(Percentile
/100, 2))), if lowend then GlobalColor("lowcolor") else if highend then
GlobalColor("highcolor") else color.yellow);
131
plot LowVol = LowVolLimit;
plot HighVol = HighVolLimit;
LowVol.SetDefaultColor(GetColor(6));
HighVol.SetDefaultColor(GetColor(5));
#hint:The popular builtin <b>DMI_Oscillator with arrows and lines</b> in positive and
negative levels based on inputs. Use the lines and arrows to define your
criteria/decision points.
declare lower;
input length = 10;#hint length:The number of bars with which the DI+ and DI-
components are calculated.
#input paintBars = yes;#hint paintBars:Defines whether or not to color price plot
according to respective oscillator values (red for negative, green for positive).
input CrossAboveValue = 10;#hint CrossAboveValue:Defines the above-zero-value at which
an arrow is plotted.
input CrossBelowValue = 5;#hint CrossBelowValue:Defines the below-zero-value at which
an arrow is plotted.
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.YELLOW);
#plot line_5above = 5;
#line_5above.SetDefaultColor(Color.YELLOW);
plot line_10above = CrossAboveValue;
line_10above.SetDefaultColor(Color.YELLOW);
132
DefineGlobalColor("Positive", Color.UPTICK);
DefineGlobalColor("Negative", Color.DOWNTICK);
Comment 2: As a coding note, since the desired result was in minutes in lieu of bars, a 'bars-X-factor
= minutes' had to be established for each aggregation. The numerous 'getAggregationPeriod() =='
lines are to define such a factor.
#hint:<b>A WLC that shows the minutes-ago since the last turn of the moving average
either up or down.</b>\nFor comparison, you may create duplicate copies of this WLC
with their own names and desired aggregations. The exclusion of extended hours is
recommended.\nSet the Aggregation to the desired value with proper name to ID it.
\nLabels show the number of bars that correlate with the column's minutes-ago.
declare lower;
133
input price = close;#hint price: The price component being mearured
input fastLength = 2;#Hint fastLength: A very short length used as a reference
for the turn-up of the slower MA
input fastMvaType = AverageType.SIMPLE;#hint fastMvaType: The type of MovAvg of
the fast reference average.
input slowLength = 30;#hint slowLength:The length of the main slow MovingAverage
input slowMvaType = AverageType.SIMPLE;#hint slowMvaType: The type of MovAvg of
the main slow Moving Average
def fastMva = MovingAverage( fastMvaType, price, fastLength );
def slowMva = MovingAverage( slowMvaType, price, slowLength );
def Histogram = fastMva - slowMva;
#========
Def MinsSinceTurn = if count_downs == 0 then count_Ups * factor else if count_Ups == 0
then count_Downs * factor else 0 ;
Plot Data_MST = MinsSinceTurn;
Data_MST.setdefaultcolor(color.YELLOW);
134
count_Downs,color.RED);
declare lower;
script normalizePlot {
input data = close;
input newRngMin = -1;
input newRngMax = 1;
#==============================================
# VWAP Calculations
def v = volume;
def p = close;
135
def n = 5;
def vwap = Sum((p * v), n) / Sum(v, n);
def l = low;
def h = high;
def Data = 100 * ((value - Lowest(l, nK)) / (Highest(h, nK) - Lowest(l, nK)));
def K = Inertia(Data, nK);
136
ml.SetLineWeight(1);
ml.SetDefaultColor(Color.WHITE);
#BB KC Squeeze
def Avg = Average(close, 20);
def stDeviation = stDev(close, 20);
def ATR = Average(TrueRange(high, low, close), 20);
def upperBB = Avg + (2 * stDeviation);
def upperKC = Avg + (1.5 * ATR);
def Squeeze = If upperBB < upperKC then yes else Double.NaN;
#Chart Management
#Plots
MACD.SetPaintingStrategy(PaintingStrategy.Histogram);
MACD.AssignValueColor(if MACD >= 50 and MACD > MACD[1] then Color.GREEN
else if MACD >= 50 and MACD < MACD[1]
then Color.RED
else if MACD <= 50 and MACD < MACD[1]
then Color.RED
else Color.DARK_GREEN);
MACD.SetLineWeight(3);
#=======================================
Stoch.SetPaintingStrategy(PaintingStrategy.Line);
Stoch.AssignValueColor(if Stoch >= 50 and Stoch > Stoch[1] then Color.CYAN else if
Stoch >= 50 and Stoch < Stoch[1] then Color.BLUE
else if Stoch <= 50 and Stoch < Stoch[1]
then Color.LIGHT_RED else Color.YELLOW);
Stoch.SetLineWeight(2);
MACD Code
def cond1 = if close > open and close > close[1] and MACD > MACD[1] and Stoch >
Stoch[1] then yes else Double.NaN;
137
plot zeroLine = if IsNaN(close)
then Double.NaN
else if isNaN(Squeeze) and isNaN(Cond1)
then 0
else Double.NaN;
zeroLine.SetPaintingStrategy(PaintingStrategy.Points);
zeroLine.SetLineWeight(2);
zeroLine.SetDefaultColor(Color.Yellow);
AddLabel(1,"MACD is Histogram",Color.PINK);
AddLabel(1, "Stochastic is the line plot", color.PINK);
AddLabel(1,if squeeze then "A Squeeze is ON now" else "A squeeze is OFF
now",color.PINK);
138
#hint:<b> Counts the number of bars where close > open. </b>\n Yes/No options are for
label, count numbers, bar numbers and a count-plot.
input ShowBarNumb = No;#hint ShowBarNumb: Yes shows the bar numbers below the low.
input ShowCountNos = yes;#hint ShowCountNos:Yes shows the count of when close > open.
It shows above the high.
input ShowLabel = yes;#hint ShowLabel:Yes shows a summary label of the percent of bars
that are up.
input Show_Plot = No;#hint Show_Plot:Yes plots the count of up-bars. Chart-
settings/general/'fit studies' must be checked to see this plot.
Def counter_AnyDay = CompoundValue (1,if close > open then counter_AnyDay[1] + 1 else
counter_AnyDay[1],if close > open then 1 else 0);#Note that the value of the first bar
is determined by the last CompoundValue If-condition
plot count = if close > open && ShowCountNos then counter_AnyDay else double.nan;
Count.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);
Comment: Some TOS studies deal with the same subject. The below code illustrates,
using the DMI and DMI_Oscillator studies as examples, how you may accomplish the same
result in different ways.
#========== The below 3 code lines produce the same result ===========
def DMItest = DMIplus > DMIminus and DMIplus[1] <= DMIminus[1]; # DMItest == 1 when
true; 0 when false
def crossing = Crossing(DMIplus, DMIminus, CrossingDirection.above); # crossing == 1
when true; 0 when false
139
def crossing = Crossing(DMI_Oscillator("length" = 25 ).Hist,
DMI_Oscillator().ZeroLine,crossingDirection.above); #crossing == 1 when true; 0 when
false. DMI_Oscillator is by reference-with-parameters
#========== The below 2 code lines produce the same result ===========
def DMItest = DMIplus > DMIminus;# DMItest == 1 when true; 0 when false
def DMItest = DMI_Oscillator("length" = 25 ).Hist > 0; # DMItest == 1 when true; 0
when false. DMI_Oscillator is by reference-with-parameters.
#========== The below 3 code lines produce the same result ===========
def DMItest = DMIplus < DMIminus and DMIplus[1] >= DMIminus[1]; # DMItest == 1 when
true; 0 when false
def crossing = Crossing(DMIplus, DMIminus, CrossingDirection.below); # crossing == 1
when true; 0 when false
def crossing = Crossing(DMI_Oscillator("length" = 25
).Hist,DMI_Oscillator().ZeroLine,crossingDirection.below); #crossing == 1 when true; 0
when false. DMI_Oscillator is by reference-with-parameters.
#========== The below 2 code lines produce the same result ===========
plot DMItest = DMIplus < DMIminus; # DMItest == 1 when true; 0 when false
def DMItest = DMI_Oscillator("length" = 25).Hist > 0; # DMItest == 1 when true; 0
when false. DMI_Oscillator is by reference-with-parameters.
140
input price = FundamentalType.CLOSE;
input aggregationPeriod = AggregationPeriod.DAY;
input length = 200;
input averageType = AverageType.SIMPLE;
#=================================================
#============= Scan code ===================
Plot scan_above = MovingAverage(averageType, Fundamental(price), length) * 1.1;
Plot scan_below = MovingAverage(averageType, Fundamental(price), length) * 0.9;
#============= below for combined scan ====================
Plot Scan_combined = MovingAverage(averageType, Fundamental(price), length) * 1.1 OR
MovingAverage(averageType, Fundamental(price), length) * 0.9;
141
C-AN ALTERED 'PERCENTCHG' TO MAKE IT MORE
USEFUL
Comment: The builtin 'PercentChg' has been altered to allow inputs for loAlert and hiAlert to be less
than one. This then enables this study to be referenced/used in intra-day studies/strategies where
less-than-one-percent changes are normal. Info hints were also added to be more informative,
#PercentChg_SFL
#hint:Plots the percent change from length-bars ago. Input loAlert and hiAlert values
may be changed to convert the plot to an oscillator which may be used as a reference
in a strategy. The plot coloring automatically changes to be RED above hiAlert and
CYAN below loAlert.
declare lower;
input hiAlert = 0.25;#hint hiAlert:The value, above which the plot is colored RED.\n
The neutral area (between hiAlert and loAlert) is colored "Normal" = LIGHT_GRAY = 3
input length = 14;#hint length: The look-back bars being compared to.
input loAlert = 0.25;#hint loAlert:The value, below which the plot is colored GREEN.
\nThe neutral area (between hiAlert and loAlert) is colored "Normal" = LIGHT_GRAY = 3
input price = close;#hint price:Select the data type to be evaluated
142
#LinRegr_of_ProjectionBands
#hint:<b>LinRegr_of_ProjectionBands</b>\nThis study plots the linear regression of the
ProjectionBands study. Arrows are plotted at the min and max values to indicate
possible long and short opportunities\nTick (133) charts present better views.\n The
bands are based on LR so this study is a LR of a LR.
def Max_LR_UPB = if data1 > data1[1] && data1 > data1 [-1] then 1 else 0;plot D_Max_LR
= if Max_LR_UPB == 1 then
LR_UPB else double.nan;
D_Max_LR.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
D_Max_LR.SetLineWeight(3);
D_Max_LR.SetDefaultColor(Color.DOWNTICK);
1. "COMPARISON OF ALL SECTORS OF THE S&P 500 (SPX)" plots all sectors of the S&P 500 (SPX) as
absolute percent change all starting at 0 percent.
2. "S&P 500 SECTORS RELATIVE TO SPX = 0" plots all sectors of the S&P 500 (SPX) as relative
percent referenced to the SPX being the 'Zero Line'. So the percentages shown are a sector’s
percent above or below the SPX value.
Each of the three above have the format of starting the comparison at 'Zero Percent'. A useful
external-to-TOS tool for comparison of symbols may be had at Symbol Comparison Tool Also a S&P
500 sector comparison tool may be had at S&P 500 Sector Comparison
143
C-COMPARISON OF ALL SECTORS OF THE S&P 500
(SPX)
#Revised 3/17/14
declare lower;
144
#====== calc percents and plot related to the first bar for each sector ==========
def d_close1 = close(symbol1);
145
Plot Zero = 0;
Zero.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
Zero.SetLineWeight(1);
Zero.SetDefaultColor(Color.YELLOW);
146
#AddLabel(1, symbol1 + " first close = close1 = " + close1, Color.PINK);
#AddLabel(1, "Plot Data_ Pct = " + Data_Pct1, Color.PINK);
#Revised 3/17/14
declare lower;
147
input symbol1 = "SPX";#hint symbol1:Normally this is the SPX.
input symbol2 = "XLY";#hint symbol2:Normally this is the SPX's XLY
input symbol3 = "XLK";#hint symbol3:Normally this is the SPX's XLK
input symbol4 = "XLI";#hint symbol4:Normally this is the SPX's XLI
input symbol5 = "XLB";#hint symbol5:Normally this is the SPX's XLB
input symbol6 = "XLE";#hint symbol6:Normally this is the SPX's XLE
input symbol7 = "XLP";#hint symbol7:Normally this is the SPX's XLP
input symbol8 = "XLV";#hint symbol8:Normally this is the SPX's XLV
input symbol9 = "XLU";#hint symbol9:Normally this is the SPX's XLU
input symbol10 = "XLF";#hint symbol10:Normally this is the SPX's XLF
input CloudSymbol = {default SPX, XLY, XLK, XLI, XLB, XLE, XLP, XLV, XLU, XLF};#hint
CloudSymbol:Select the sector to show the Sector cloud referenced to SPX = Zero. If no
cloud is desired, select SPX.
#====== calc percents and plot related to the first bar for each sector ==========
def d_close1 = close(symbol1);
plot D1_SPX = (d_close1 - close1) / close1 * 100;
D1_SPX.SetLineWeight(3);
148
D5_XLB.SetLineWeight(Line_wt5);
plot D1_SPX_Zero = 0;
D1_SPX_Zero .SetPaintingStrategy(PaintingStrategy.LINE);
D1_SPX_Zero .SetLineWeight(3);
D1_SPX_Zero .SetDefaultColor(Color.YELLOW);
D1_SPX_Zero.SetStyle(Curve.LONG_DASH);
149
== CloudSymbol.XLY) then
D2_XLY.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLK) then D3_XLK.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLI) then D4_XLI.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLB) then D5_XLB.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLE) then D6_XLE.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLP) then D7_XLP.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLV) then D8_XLV.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLU) then D9_XLU.TakeValueColor() else if
(CloudSymbol == CloudSymbol.XLF) then D10_XLF.TakeValueColor() else
Color.PINK);
150
AddChartBubble(BubbleLocation && ShowBubbles, D8_XLV, symbol8 + " health care",
D8_XLV.TakeValueColor());
AddChartBubble(BubbleLocation && ShowBubbles, D9_XLU, symbol9 + " utilities",
D9_XLU.TakeValueColor());
AddChartBubble(BubbleLocation && ShowBubbles, D10_XLF, symbol10 + " financials",
D10_XLF.TakeValueColor());
declare lower;
#hint showKey: OFF hides the symbol key, NUM numbers the symbol text, TXT shows just
the symbol text.
input showKey = {OFF, NUM, default TXT};
#hint price: Changes the fundamental price type.
input price = FundamentalType.CLOSE;
#The following symbols may be changed to your preference but none should be blank. You
may turn off any of these via the 'input use? = ' function. Each symbol is implied-
numbered from 1 to 10, top-to-bottom sequentially.
input symbol1 = "SPY";
input symbol2 = "QQQ";
input symbol3 = "IWM";
input symbol4 = "DIA";
input symbol5 = "AAPL";
input symbol6 = "FCX";
input symbol7 = "GOOG";
input symbol8 = "IBM";
input symbol9 = "JPM";
input symbol10 = "XOM";
151
input use9 = Yes;
input use10 = Yes;
#changing the Min and Max values will determine the minimum and maximum plotted values
for all symbols.
script normalize {
input data = close;
input Min = -10000;
input Max = 10000;
152
if st[1] == st."0" {
if (!use1 or !isNaN(r1)) and (!use2 or !isNaN(r2))
and (!use3 or !isNaN(r3)) and (!use4 or !isNaN(r4))
and (!use5 or !isNaN(r5)) and (!use6 or !isNaN(r6))
and (!use7 or !isNaN(r7)) and (!use8 or !isNaN(r8))
and (!use9 or !isNaN(r9)) and (!use10 or !isNaN(r10))
{
ofst1 = r1;
ofst2 = r2;
ofst3 = r3;
ofst4 = r4;
ofst5 = r5;
ofst6 = r6;
ofst7 = r7;
ofst8 = r8;
ofst9 = r9;
ofst10 = r10;
st = st."1";
} else {
# Not initialized.
ofst1 = Double.NaN;
ofst2 = Double.NaN;
ofst3 = Double.NaN;
ofst4 = Double.NaN;
ofst5 = Double.NaN;
ofst6 = Double.NaN;
ofst7 = Double.NaN;
ofst8 = Double.NaN;
ofst9 = Double.NaN;
ofst10 = Double.NaN;
st = st[1];
}
} else {
ofst1 = ofst1[1];
ofst2 = ofst2[1];
ofst3 = ofst3[1];
ofst4 = ofst4[1];
ofst5 = ofst5[1];
ofst6 = ofst6[1];
ofst7 = ofst7[1];
ofst8 = ofst8[1];
ofst9 = ofst9[1];
ofst10 = ofst10[1];
st = st[1];
}
153
plot p4 = if ok then r4 - ofst4 else Double.NaN;
plot p5 = if ok then r5 - ofst5 else Double.NaN;
plot p6 = if ok then r6 - ofst6 else Double.NaN;
plot p7 = if ok then r7 - ofst7 else Double.NaN;
plot p8 = if ok then r8 - ofst8 else Double.NaN;
plot p9 = if ok then r9 - ofst9 else Double.NaN;
plot p10 = if ok then r10 - ofst10 else Double.NaN;
plot Zero = 0;
Zero.SetDefaultColor(Color.GRAY);
AddLabel(showKey and use1, (if n then "1. " else "") + symbol1, p1.TakeValueColor());
AddLabel(showKey and use2, (if n then "2. " else "") + symbol2, p2.TakeValueColor());
AddLabel(showKey and use3, (if n then "3. " else "") + symbol3, p3.TakeValueColor());
AddLabel(showKey and use4, (if n then "4. " else "") + symbol4, p4.TakeValueColor());
AddLabel(showKey and use5, (if n then "5. " else "") + symbol5, p5.TakeValueColor());
AddLabel(showKey and use6, (if n then "6. " else "") + symbol6, p6.TakeValueColor());
AddLabel(showKey and use7, (if n then "7. " else "") + symbol7, p7.TakeValueColor());
AddLabel(showKey and use8, (if n then "8. " else "") + symbol8, p8.TakeValueColor());
AddLabel(showKey and use9, (if n then "9. " else "") + symbol9, p9.TakeValueColor());
AddLabel(showKey and use10, (if n then "10. " else "") + symbol10,
p10.TakeValueColor());
154
#Percentage Price Oscillator (PPO): with comparitor
# Mobius
# Chat Room request 03.28.2014
declare lower;
declare lower;
input Sym = "";#hint Sym:The input symbol for this DMI Oscillator and/or ADX
input length = 10;#hint length:The same length used for the ADX calculation and the
155
DMI Osc calculation
input PlotADX = yes;#hint PlotADX:YES plots the ADX line
Osc.SetDefaultColor(Color.WHITE);
Osc.SetLineWeight(2);
Hist.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Hist.SetLineWeight(3);
Hist.AssignValueColor(if ("DI+" > "DI-") then color.uptick else color.downtick);
Hist.HideTitle();
ZeroLine.SetDefaultColor(Color.GRAY);
DefineGlobalColor("Positive", Color.UPTICK);
DefineGlobalColor("Negative", Color.DOWNTICK);
156
#OneGlance by StanL Version 1.0, 5/1/14
#Hint:The 'OneGlance' study evaluates 13 criteria in a bullish(green)/bearish(red)
dashboard presentation. All study parameters and the bullish-bearish-triggers may be
set via inputs.
# OVERVIEW: 'OneGlance' is by StanL 5/01/14. Emphasis has been put on clarity and
flexibility: clarity via bubbles and labels; flexibility via input-setable parameters
and triggers to match your trading style. The info bubbles in rdite studies often
state the default values buil into TOS' studies.
# USAGE: 'OneGlance' uses up a lot of a chart's real estate and is much more readable
when not squeezed; perhaps as an only lower study. One viewing option, when comparing
a 'OneGlance' item to a corresponding full TOS chart, is to turn off the price data in
'chart Settings'. Depending on your vision quality and space availability, you may
find a magnifier usage useful (google Magnifixer freeware).
# POINT-OF-VIEW: 'OneGlance' is oriented (parameters and triggers) towards defining
the bullish aspects of the studies used. Realize that if a study is not bullish, then
it is not necessarily bearish. If you are bearish oriented, i.e. looking for short-
opportunities, the modifying of parameters and triggers can enhance you bearish
orientation.
# FUTURE: Although 'OneGlance' already uses a lot of real estate, there is no limit to
additional studies being added except for space. Also, depending on your coding
skills, certain user-preferred studies may be extracted to form a more- specific
abridged 'OneGlance' utilizing less chart real estate and just the studies that you
are most interested in.
#INPUTS: Because of the multitude of studies, the input list in 'Edit Studies' is long
but components have been titled to make them self explanatory and with info-bubbles to
further identify TOS default values.
declare lower;
def c = close;
def h = high;
def l = low;
def o = open;
157
PFE_Line.SetLineWeight(5);
PFE_Line.AssignValueColor(if PFE > PFE_trig then Color.UPTICK else Color.DOWNTICK);
#== end ==
#MomentumPercent
#=================
input MOM_Pct_trig = 0.00;#Hint MOM_Pct_trig:The percent value that toggles the chart
between green and red. Normal is 0.00 %.
input MomPctLength = 5;#Hint MomPctLength:The offset length (bars back) that the
current bar is compared to calculate this Momentum Percent. TOS default is 10.
#Ichimoku Study
#==============
#NOTES: One major bullish indication in this study is when the Tenkan excaads the
Kijun. Their default lengths of 26 and 9 may be shortened to increase response
sensitivity. There are other bullish Ichimoku indicators.
input tenkan_period = 9;#hint tenkan_period:The agg-bars used to calculate the tenkan
value. TOS' default is 9.
input kijun_period = 26;#hint kijun_period:The agg-bars used to calculate the kijun
value. TOs' default is 26.
158
def RSI_trig = if (Between(rsi_here, RSILowTrig, 100) && Sum(rsi_here < rsi_here[1],
rsi_UpBars) == rsi_UpBars) then 1 else 0;
#def HullMA = HullMovingAvg(Price = Hull_price, length = Hull_length, displace =
Hull_displace).HMA;
def nK = 1.5;
def nBB = 2.0;
def lengthsqueeze = 20;
def BBHalfWidth = StDev(c, lengthsqueeze);
def KCHalfWidth = nK * AvgTrueRange(h, c, l, lengthsqueeze);
def isSqueezed = nBB * BBHalfWidth / KCHalfWidth < 1;
159
BBS_Ind.AssignValueColor(if isSqueezed then Color.RED else Color.WHITE);
BBS_Ind.SetPaintingStrategy(PaintingStrategy.POINTS);
BBS_Ind.SetLineWeight(3);
BBS_Ind.HideBubble();
#=== end ===
#TrueStrengthIndex
#===================
input TSI_trig = 0 ;#hint TSI_trig:The value that toggles bull/bear. TSI has a
'TSI(value)' and a 'signal' line with a zero line. This deals with the 'TSI(value)'
160
being above the zero line. An earlier trigger could be had by analysis as was done
with the MACD herein.
161
#def MACD_Value = MACD(MACDLength = MACDLength, AverageType = "EMA").Diff;
162
#Input Offset = BarNumber() / 2;
def barNum = BarNumber();
def offset = 50;
def LastBar = !IsNaN(open) and IsNaN(open [-1] ) ;
def BubbleLocation = LastBar[offset];
def FirstBar = if barNum == 1 then 1 else 0;
def FirstBarValue = if barNum == 1 then 1 else 0;
def LastBarValue = if LastBar then barNum else 0;
def MidBar = if LastBar then barNum == (BarNumber() / 2) else 0;
#example
#addchartbubble(LastBar,45, "This is a last bar bubble", color.White);
#==========================================
#======== Bubbles ==============
AddChartBubble(FirstBar, 42, " HullMovingAvg(" + Hull_length + "). " + "Trigger =
bullish when HullMovingAvg > previous HullMovingAvg.", Color.WHITE);
AddChartBubble(FirstBar, 35, " MACD(" + fastLength_1 + "," + slowLength_1 + "," +
MACDLength_1 + "," + AverageType_1 + "). Bullish when MACD.Value is above MACD.Avg
(signal line). Trigger = MACD().value > MACD().avg", Color.PINK);
AddChartBubble(FirstBar, 38.5, " MACD.Value(" + fastLength_2 + "," + slowLength_2 +
"," + MACDLength_2 + "," + AverageType_2 + ")" + "Bullish when MACD.Value is above the
zero line. Trigger = " + macdVal_trig + "(Normally the zero line)", Color.PINK);
AddChartBubble(FirstBar, 17.5 , " Polarized Fractal Efficiency (" + PFE_length + "). "
+ "Trend UP = 0 to 100. Trigger = " + PFE_trig, Color.WHITE);
AddChartBubble(FirstBar, 21, " MomentumPercent(" + MomPctLength + "). Bullish when > 0
% & for long periods. Trigger = " + MOM_Pct_trig + " percent", Color.CYAN);
AddChartBubble(FirstBar, 24.5, " Ichimoku(" + tenkan_period + ", " + kijun_period +
"). Bullish trigger = when tenkan > kijun. The more the diff, the stronger the
trend.", Color.WHITE);
AddChartBubble(FirstBar, 28, " RSI(" + RSI_length + ")." + " Trigger = RSI is between
" + RSILowTrig + " and 100 and is rising for last " + rsi_UpBars + " bars",
Color.CYAN);
AddChartBubble(FirstBar, 31.5, " Bollinger Bands(+/- " + Num_Dev_up + " SD)" + "
MOmentum Break Out (MOBO(" + MOBO_length + "))." + " Trigger when close goes above
upper band and stays bullish until the close goes below the lower band.",
Color.WHITE);
AddChartBubble(FirstBar, 14, " DMI_Oscillator(" + DMIO_Length + "). Bullish DMI =
green = >0: Bearish DMI = red. Trigger = " + DMIO_trig, Color.PINK);
AddChartBubble(FirstBar, 10.5, " ADX(" + ADX_Length + "). Bullish ADX = green: Bearish
ADX = red. Strong bullish ADX trend is > 25. Trigger = " + ADX_trig, Color.PINK);
AddChartBubble(FirstBar, 7, " TrueStrengthIndex(25,13,8,'WMA')." + " Bullish TSI =
green & 0 to +50. Bearish TSI = red & 0 to -50. Trigger = " + TSI_trig, Color.CYAN);
AddChartBubble(FirstBar, 50, " RED dot denotes presence of a SQUEEZE", Color.WHITE);
AddChartBubble(FirstBar, 3.5, " DynamicMomentumIndex-DYMI(" + DYMI_length + ").
Overbought = 70: Oversold = 30. Trigger = " + DYMI_trig, Color.CYAN);
#== end ==
#== Labels ==
#Count of Periods in consecutive squeeze
163
rec count = if isSqueezed then count[1] + 1 else 0;
AddLabel(showlabels, if isSqueezed then "Squeeze is on for " + count + " bars" else
"No Squeeze is on", if isSqueezed then Color.RED else Color.WHITE);
AddLabel(showlabels, "HullMovingAvg(" + Hull_length + ") = " + Round(HullMA, 2), if
HullMA > HullMA[1] then Color.GREEN else Color.RED);
AddLabel(showlabels, "MACD.Value(" + round(macd_Val_1,1) + ") cross above MACD.Avg(" +
Round(macd_Avg1,1) + ") (signal) = " + if round(macd_Val_1,1) > Round(macd_Avg1,1)
then "true" else "not true", if round(macd_Val_1,1) > Round(macd_Avg1,1) then
Color.GREEN else color.LIGHT_RED);
AddLabel(showlabels, "MACD.Value(" + round(MACDValue_2,1) + ") cross above 0 line = "
+ if round(MACDValue_2,1) >= 0 then "true" else "not true", if round(MACDValue_2,1) >=
0 then color.GREEN else color.LIGHT_RED);
#MomentumPercent
#=================
input MOM_Pct_trig = 0.00;#Hint MOM_Pct_trig:The percent value that toggles the chart
between green and red. Normal is 0.00 %.
input MomPctLength = 5;#Hint MomPctLength:The offset length (bars back) that the
current bar is compared to calculate this Momentum Percent. TOS default is 10.
164
def mom_pct = MomentumPercent(length = MomPctLength)."Momentum, %" - 100;
#Ichimoku Study
#==============
#NOTES: One major bullish indication in this study is when the Tenkan excaads the
Kijun. Their default lengths of 26 and 9 may be shortened to increase response
sensitivity. There are other bullish Ichimoku indicators. input tenkan_period =
9;#hint tenkan_period:The agg-bars used to calculate the tenkan value. TOS' default is
9.
165
#== end ==
#Explanation of how this works. +/- 0.8 std deviation Bollinger Bands are the
criteris for bullish/bearish plots. When the close rises above the upper band the
signal is bullish and stays bullish until the close moves below the lower band when
the plot turns to bearish and remains bearish until the close rises above the upper
band.
def nK = 1.5;
def nBB = 2.0;
def lengthsqueeze = 20;
def BBHalfWidth = StDev(c, lengthsqueeze);
def KCHalfWidth = nK * AvgTrueRange(h, c, l, lengthsqueeze);
def isSqueezed = nBB * BBHalfWidth / KCHalfWidth < 1;
166
invisible
#== end ==
#TrueStrengthIndex
#===================
input TSI_trig = 0 ;#hint TSI_trig:The value that toggles bull/bear. TSI has a
'TSI(value)' and a 'signal' line with a zero line. This deals with the 'TSI(value)'
being above the zero line. An earlier trigger could be had by analysis as was done
with the MACD herein.
plot TSI_Line = 7;
TSI_Line.SetPaintingStrategy(PaintingStrategy.LINE_VS_SQUARES);
TSI_Line.SetLineWeight(5);
TSI_Line.AssignValueColor(if TSI_here > TSI_trig then Color.UPTICK else
167
Color.DOWNTICK);
#=== end ===
168
#==== MACD value is above zero ====
#NOTE that the fast and slow length may been shortened for faster response. These
inputs have a '_2' after the standard MACD parameters to distinguish them from the
MACD.
input fastLength_2 = 12;#hint fastLength_2:For the MACD plot that evaluates the
MACD.Value being above the zero line. The value may be altered for faster response.
input slowLength_2 = 26;#hint slowLength_2:For the MACD plot that evaluates the
MACD.Value being above the zero line. The value may be altered for faster response.
input MACDLength_2 = 9;#hint MACDLength_2:For the MACD plot that evaluates the
MACD.Value being above the zero line. The value may be altered for faster response.
input AverageType_2 = {SMA, default EMA};#hint AverageType_2:For the MACD plot that
evaluates the MACD.Value being above the zero line. The value may be altered for
faster/slower response. This selects tha average type to be used.
input macdVal_trig = 0;#hint macdVal_trig:For the MACD plot that evaluates the MACD
value being above the zero line. The normal default value is 0, i.e. the zero line,
but may be altered here.
169
def LastBarValue = if LastBar then barNum else 0;
def MidBar = if LastBar then barNum == (BarNumber() / 2) else 0;
#example
#addchartbubble(LastBar,45, "This is a last bar bubble", color.White);
#==========================================
#======== Bubbles ==============
AddChartBubble(FirstBar, 42, " HullMovingAvg(" + Hull_length + "). " + "Trigger =
bullish when HullMovingAvg > previous HullMovingAvg.", Color.WHITE);
AddChartBubble(FirstBar, 35, " MACD(" + fastLength_1 + "," + slowLength_1 + "," +
MACDLength_1 + "," + AverageType_1 + "). Bullish when MACD.Value is above MACD.Avg
(signal line). Trigger = MACD().value > MACD().avg", Color.PINK);
AddChartBubble(FirstBar, 38.5, " MACD.Value(" + fastLength_2 + "," + slowLength_2 +
"," + MACDLength_2 + "," + AverageType_2 + ")" + "Bullish when MACD.Value is above the
zero line. Trigger = " + macdVal_trig + "(Normally the zero line)", Color.PINK);
AddChartBubble(FirstBar, 17.5 , " Polarized Fractal Efficiency (" + PFE_length + "). "
+ "Trend UP = 0 to 100. Trigger = " + PFE_trig, Color.WHITE);
AddChartBubble(FirstBar, 21, " MomentumPercent(" + MomPctLength + "). Bullish when > 0
% & for long periods. Trigger = " + MOM_Pct_trig + " percent", Color.CYAN);
AddChartBubble(FirstBar, 24.5, " Ichimoku(" + tenkan_period + ", " + kijun_period +
"). Bullish trigger = when tenkan > kijun. The more the diff, the stronger the
trend.", Color.WHITE);
AddChartBubble(FirstBar, 28, " RSI(" + RSI_length + ")." + " Trigger = RSI is between
" + RSILowTrig + " and 100 and is rising for last " + rsi_UpBars + " bars",
Color.CYAN);
AddChartBubble(FirstBar, 31.5, " Bollinger Bands(+/- " + Num_Dev_up + " SD)" + "
MOmentum Break Out (MOBO(" + lengthmobo + "))." + " Trigger when close goes above
upper band and stays bullish until the close goes below the lower band.",
Color.WHITE);
AddChartBubble(FirstBar, 14, " DMI_Oscillator(" + DMIO_Length + "). Bullish DMI =
green = >0: Bearish DMI = red. Trigger = " + DMIO_trig, Color.PINK);
AddChartBubble(FirstBar, 10.5, " ADX(" + ADX_Length + "). Bullish ADX = green: Bearish
ADX = red. Strong bullish ADX trend is > 25. Trigger = " + ADX_trig, Color.PINK);
AddChartBubble(FirstBar, 7, " TrueStrengthIndex(25,13,8,'WMA')." + " Bullish TSI =
green & 0 to +50. Bearish TSI = red & 0 to -50. Trigger = " + TSI_trig, Color.CYAN);
AddChartBubble(FirstBar, 50, " RED dot denotes presence of a SQUEEZE", Color.WHITE);
AddChartBubble(FirstBar, 3.5, " DynamicMomentumIndex-DYMI(" + DYMI_length + ").
Overbought = 70: Oversold = 30.
Trigger = " + DYMI_trig, Color.CYAN);
#== end ==
#== Labels ==
#Count of Periods in consecutive squeeze
rec count = if isSqueezed then count[1] + 1 else 0;
AddLabel(showlabels, if isSqueezed then "Squeeze is on for " + count + " bars" else
"No Squeeze is on", if isSqueezed then Color.RED else Color.WHITE);
AddLabel(showlabels, "HullMovingAvg(" + Hull_length + ") = " + Round(HullMA, 2), if
HullMA > HullMA[1] then Color.GREEN else Color.RED);
AddLabel(showlabels, "MACD.Value(" + round(macd_Val_1,1) + ") cross above MACD.Avg(" +
Round(macd_Avg1,1) + ") (signal) = " + if round(macd_Val_1,1) > Round(macd_Avg1,1)
170
then "true" else "not true", if round(macd_Val_1,1) > Round(macd_Avg1,1) then
Color.GREEN else color.LIGHT_RED);
AddLabel(showlabels, "MACD.Value(" + round(MACDValue_2,1) + ") cross above 0 line = "
+ if round(MACDValue_2,1) >= 0 then "true" else "not true", if round(MACDValue_2,1) >=
0 then color.GREEN else color.LIGHT_RED);
AddLabel(showlabels, if upmobo and c < Uppermobo then "MOBO close is between(" +
Num_Dev_up + " SD) bands"
else if upmo then "MOBO is above upper(" + Num_Dev_up + " SD) band"
else if dnmo then "MOBO is below lower(" + Num_Dev_up + " SD) band"
else "", Color.GREEN);
AddLabel(showlabels, "RSI(" + RSI_length + ") = " + Round(rsi_here, 1), if RSI_trig
then Color.GREEN else Color.RED);
AddLabel(showlabels, "Ichimoku(" + tenkan_period + ", " + kijun_period + "):" +
"Tenkan / Kijan = " + Ichimoku().Tenkan + " / " + Ichimoku().kijun, if
Ichimoku()."Tenkan" > Ichimoku()."Kijun" then Color.GREEN else Color.RED);
AddLabel(showlabels, "MomentumPercent(" + MomPctLength + ") = " + Round(mom_pct, 2) +
" %", if mom_pct >= MOM_Pct_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "Polarized Fractal Eff(" + PFE_length + ") = " + Round(PFE, 0),
if PFE >= PFE_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "DMI Osc(" + DMIO_Length + ") = " + Round(DMI_OSC_here, 1), if
DMI_OSC_here >= DMIO_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "ADX(" + ADX_Length + ") = " + ADX_here, if ADX_here >= ADX_trig
&& DMI_Pos then Color.GREEN else Color.RED);
AddLabel(showlabels, "TSI = " + Round(TSI_here,1), if TSI_here >= TSI_Trig then
color.GREEN else color.RED);
AddLabel(showlabels, "DYMI(" + DYMI_length + ") = " + Round(DYMI_here, 1), if
DYMI_here >= DYMI_trig then Color.GREEN else Color.RED);
#== end ==
of Code
#hint:This is a Ichimoku Tenkan/Kijun an early exit warning study that plots the
difference between the tenkan and kijun in histogram format. A YELLOW down warning
arrow plots when a Heikin Ashi downtrend starts.
#Background:The difference of the Tenkan and the Kijun indicate the strength of this
bullish signal as shown by the histogram above zero values. When this strength
difference weakens a downward trend may(often?) start. Heikin Ashi candles are adept
at showing trend development. The plotted YELLOW arrows are points to consider exiting
even though the entity may be in buillsh territory(i.e. above the cloud). In summary,
this is an early warning signal that is productive and calls your attention to it to
consider exiting.
#USAGE:When YELLOW down arrows are present, watch the Heikin Ashi style candles to see
the extent of the downtrend.(Configure your Heikin Ashi for 'Red Fill' when down. The
DMI_Oscillator, MACD and ADX are good complementary studies
#SUMMARY: The histograqm shows the change in strength of the bullish T/K signal while
the YELLOW arrows call your attention to a possible start of a downtrend.
171
#TOS Title = Ichi_TK_Exit_Warning
# Version date = 3/17/14 by StanL, version 2
# Revision 2.1, added dots at the zero line 5/18/14
declare lower;
ZeroLine.SetDefaultColor(GetColor(0));
#################################################
#def HAopen = (open[1] + close[1]) / 2;
#def HAhigh = Max(high, close[1]);
#def HAlow = Min(low, close[1]);
#def HAclose = (open + high + low + close) / 4;
AddLabel(1, "Plot of Tenkan - Kijun early warning of T/K strength weakening",
Color.WHITE);
AddLabel(1, "A YELLOW down arrow plots at the start of a HA downtrend.Watch the HA
style chart candles to see the length of the downtrend", Color.YELLOW);
#######################################
#=== Extracted Mobius Heikin Ashi code #
#######################################
172
else barSeq[1] + 1;
173
# Trade Management Conditions
def Bcond = CompoundValue(1, if HAclose_EV crosses above HAopen_EV
then Bcond[1] + 1
else if HAclose_EV crosses below HAopen_EV
then 0
else Bcond[1], 0);
#UP arrow is the start of an HA-up series. Need to view HA Chart style to see the
extent & end
#plot ArrowUp = if Bcond crosses above 0 && Show_HA_Up && Diff < 0 then HistoLiner[0]
else Double.NaN;# this line used when up HA arrows are implemented
plot ArrowUp = if Bcond crosses above 0 && Diff < 0 then HistoLiner[0] else
Double.NaN;
ArrowUp.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
ArrowUp.SetLineWeight(5);
ArrowUp.SetDefaultColor(Color.YELLOW);
#DOWN arrow is the start of an HA-down series. Need to view HA Chart style to see the
extent & end
plot ArrowDn = if Scond crosses above 0 && Show_HA_Down && Diff > 0
then HistoLiner[0]
else Double.NaN;
ArrowDn.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
ArrowDn.SetLineWeight(5);
ArrowDn.SetDefaultColor(Color.YELLOW);
line.EnableApproximation();
line.SetLineWeight(2);
line.SetStyle(Curve.SHORT_DASH);
line.AssignValueColor(if lineCond == 1
then Color.GREEN
else if lineCond == -1
then Color.RED
else Color.WHITE);
174
######=== define dot on zero line when above the cloud ######
def IsAboveCloud = if close > Ichimoku()."Span A" && close > Ichimoku()."Span B" then
1 else 0; # close is above the cloud
def IsBelowCloud = if close < Ichimoku()."Span A" && close < Ichimoku()."Span B" then
1 else 0; # close is below the cloud
#==========================================
AddChartBubble(FirstBar, 0, "GREEN dot = close IS ABOVE CLOUD\nRED dot = close IS
BELOW CLOUD",
Color.PINK,no);
#---- End Of Code ---
declare lower;
175
input tenkan_period = 9;#Hint tenkan_period: The number of bars used to calculate the
Tenkan (cyan) plot. Default is 9 and should be retained.
input kijun_period = 26;#Hint kijun_period: The number of bars used to calculate the
Kijun (pink) plot. Default is 26 and should be retained.
input ShowLabels = YES;#hint ShowLabels:Toggles labels on/off.
#========================================
def barNum = BarNumber();
def offset = 50;
def LastBar = !IsNaN(open) and IsNaN(open [-1] ) ;
def BubbleLocation = LastBar[offset];
def FirstBar = if barNum == 1 then 1 else 0;
def FirstBarValue = if barNum == 1 then 1 else 0;
def LastBarValue = if LastBar then barNum else 0;
#example
#addchartbubble(LastBar,45, "This is a last bar bubble", color.White);
#==========================================
176
#=== scan code for 'Close above the cloud' (primary Bullish scan)===
#(close is greater than Ichimoku()."Span A" within 2 bars and close is greater than
Ichimoku()."Span B" within 2 bars)
#== end of scan code ==
#==== Scan code for Triple Bullish ====(to use remove '#')
#(close is greater than Ichimoku()."Span A" within 2 bars or close is greater than
Ichimoku()."Span B" within 2 bars) and
# Ichimoku()."Tenkan" is greater than Ichimoku().Kijun within 2 bars and
# Ichimoku()."Chikou" from 26 bars ago is greater than Ichimoku()."Span A" within 2
177
bars
#== end of scan code ==
AddLabel(Showlabels && !InCloud ,if ST_Bull then "Bullish 'Tenkan > Kijun' is true"
else "Bullish 'Tenkan is > Kijun' is false", if ST_Bull then color.UPTICK else
color.DOWNTICK);
AddLabel(Showlabels && !InCloud ,if close > SpanA[26] && close > SpanB[26] then
"Bullish 'Chikou is above the cloud' is true" else "Bullish 'Chikou is above the
178
cloud' is false", if close > SpanA[26] && close > SpanB[26] then color.UPTICK else
color.DOWNTICK);
AddLabel(Showlabels && !InCloud , if ST_Bull && TT_Bull[26] && PT_Bull then "A
powerful 3XBullish signal exists" else "A powerful 3XBullish signal does not
exists",if ST_Bull && TT_Bull[26] && PT_Bull then color.UPTICK else color.DOWNTICK);
AddLabel(Showlabels && InCloud, "The close is inside the cloud. No trading recommended
here. All other labels are suspended. Look for a signal on exiting the
cloud.",Color.MAGENTA);
#=== end of IchiOneGlance ===
##Hint:This Ichmoku study has many signals. Some are more important/controlling than
others. This study allows you to select the type of signal you are interested in, the
strength level of those signals and the bullish or bearish sentiment.The appropriate
arrows will be plotted with optional bubbles to identify the signal strength and
bull/bear.
# TOS title = 'Ichi_Signals' by StanL version 1.0
#USAGE NOTES: !.All Bullish signals are UP arrows of cyan coloring. All Bearish
signals are DOWN arrows of magenta coloring.
#2.Bubbles may be toggled OFF to avoid chart clutter. All bubbles are colored white
for readability.
#3.Selectable inputs for arrow plotting are:1. Each of the 5 Ichimoku
parameters(lines); 2.Signal strengths of strong, neutral, weak or All;3.Bullish,
Bearish or All.
# The main Ichimoku signals to monitor, in order of importance, are:
# 1. Price vs Cloud (the 'big picture')
# 2. Price vs Tenkan/Kijun
# 3. Momentum
# 4. Future Cloud
#These signals are not 'stand alone' for decision making and must be evaluated using
other related ichimoku data as well as other external studies and indicators.
#A free detailed reference, 'Ichmoku E-Book', is available at
https://www.ichimokutrade.com/c/videos/categories/ichimoku-videos/ as well as a
tutorial at
http://www.kumotrader.com/ichimoku_wiki/index.php?title=Ichimoku_components
#The E-Book has details for developing buy/sell strategies using the Ichimoku signals.
179
input Type_Signal = {default "T/K Cross", "Kijun Cross", "Cloud BreakOut", "SpanA/B
Cross", "Chikou Cross"};#Hint Type_Signal:Select the type of signal to show. All is
not a choice because there would be too many signals to show. Each choice could have
up to 6 signals i.e. Bullish/Bearish, Strong, Neutral & Weak signals.
input Signal_strength = {default Strong, Neutral, Weak, All};#hint
Signal_strength:Show only signals having the strength selected
input Bullish_Bearish = {default Bullish, Bearish, Both};#hint Bullish_Bearish:Select
the orientation desired
180
def want_Neutral = if Signal_strength == Signal_strength."Neutral" or Signal_strength
== Signal_strength."All" then 1 else 0;
def want_Weak = if Signal_strength == Signal_strength."Weak" or Signal_strength ==
Signal_strength."All" then 1 else 0;
def want_Bull = if Bullish_Bearish == Bullish_Bearish."Bullish" or Bullish_Bearish ==
Bullish_Bearish."Both" then 1 else 0;
def want_Bear = if Bullish_Bearish == Bullish_Bearish."Bearish" or Bullish_Bearish ==
Bullish_Bearish."Both" then 1 else 0
;
###############################################
#==== TENKAN/KIJUN (T/K) CROSS SIGNALS ==== #
#The tenkan/kijun cross is one of the most traditional trading strategies within the
Ichimoku system.
###############################################
def Is_TKC = if Type_Signal == Type_Signal."T/K Cross" then 1 else 0;
=== === BULLISH SIGNALS == T crosses above the K ====
#===================================================
#=== === STRONG T/K Bullish cross happens while ABOVE the cloud ===
def cond_STK = Crosses(Tenkan, Kijun, CrossingDirection.ABOVE) && IsAboveCloud;
plot STK_Cross = If (cond_STK && Is_TKC && want_Strong && want_Bull , Tenkan,
Double.NaN);
STK_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
STK_Cross.SetLineWeight(5);
STK_Cross.SetDefaultColor(GlobalColor("BullStrong"));
plot NTK_Cross = If(cond_NTKC && Is_TKC && want_Neutral && want_Bull , Tenkan,
Double.NaN);
NTK_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
NTK_Cross.SetLineWeight(5);
NTK_Cross.SetDefaultColor(GlobalColor("BullNeutral"));
###=== WEAK cross T/K(WTKC) happens while BELOW the cloud ===
def cond_WTKC = Crosses(Tenkan, Kijun, CrossingDirection.ABOVE) && IsBelowCloud;
plot WTK_Cross = If(cond_NTKC && Is_TKC && want_Bull && want_Weak, Tenkan,
Double.NaN);
WTK_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
WTK_Cross.SetLineWeight(5);
WTK_Cross.SetDefaultColor(GlobalColor("BullWeak"));
181
AddChartBubble(ShowBubbles && cond_NTKC && Is_TKC && want_Bull && want_Weak, Tenkan,
"weak\nbullish", Color.WHITE, yes);
plot SKT_Cross = If(cond_SKT_Cross && Is_TKC && want_Strong && want_Bear, Tenkan,
Double.NaN);
SKT_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
SKT_Cross.SetLineWeight(5);
SKT_Cross.SetDefaultColor(CreateColor(255, 0, 255));
plot NKT_Cross = If(cond_NKT_Cross && Is_TKC && want_Neutral && want_Bear, Tenkan,
Double.NaN);
NKT_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
NKT_Cross.SetLineWeight(5);
NKT_Cross.SetDefaultColor(CreateColor(221, 160, 221));
#=== === WEAK cross K/T happens while ABOVE the cloud ===
def Cond_WKT_Cross = Crosses(Tenkan, Kijun, CrossingDirection.BELOW) && IsAboveCloud;
plot WKT_Cross = If (Cond_WKT_Cross && Is_TKC && want_Weak && want_Bear, Tenkan,
Double.NaN);
WKT_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
WKT_Cross.SetLineWeight(5);
WKT_Cross.SetDefaultColor(CreateColor(186, 85, 211));
#####################################
#==== KIJUN CROSS SIGNALS ==== ##
#The kijun cross is one of the most powerful and reliable trading strategies within
the Ichimoku system. It can be used on nearly all time frames with excellent results,
though it will be somewhat less reliable on the lower, daytrading time frames due to
the increased volatility on those time frames.
#####################################
def is_KC = if Type_Signal == Type_Signal."Kijun Cross" then 1 else 0;
=== === BULLISH SIGNALS when close crosses above the Kijun
#######################################
182
#=== === BULL & STRONG ===
def is_KC_bull_strong = Crosses(close, Kijun, CrossingDirection.ABOVE) &&
IsAboveCloud;
plot KC_weak_Bull = If (is_KC_bull_weak && is_KC && want_Weak && want_Bull, Kijun,
Double.NaN);
KC_weak_Bull.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
KC_weak_Bull.SetLineWeight(5);
KC_weak_Bull.SetDefaultColor(GlobalColor("BullWeak"));
=== === BEARISH SIGNALS when close crosses below the Kijun
####################################
#=== === BEAR & STRONG ===
def is_KC_bear_strong = Crosses(close, Kijun, CrossingDirection.BELOW) &&
IsBelowCloud;
183
#=== === BEAR & NEUTRAL ===
def is_KC_bear_neutral = Crosses(close, Kijun, CrossingDirection.BELOW) && IsInCloud;
plot KC_weak_Bear = If (is_KC_bear_weak && is_KC && want_Weak && want_Bear, Kijun,
Double.NaN);
KC_weak_Bear.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
KC_weak_Bear.SetLineWeight(5);
KC_weak_Bear.SetDefaultColor(GlobalColor("Bearweak"));
#################################
#==== CLOUD BREAKOUT SIGNALS ==== ##
#CLOUD BREAKOUT trading is a trading strategy that can be used on multiple time
frames, though it is most widely used on the higher time frames (e.g.: Daily, Weekly,
Monthly). CLOUD breakout trading is the purest form of trend trading offered by the
Ichimoku charting system, as it looks solely to the CLOUD and price's(close)
relationship to it for its signals. It is "big picture" trading that focuses only on
whether price is trading above or below the prevailing CLOUD. . In a nutshell, the
signal to go long in CLOUD BREAKOUT trading is when price closes above the prevailing
CLOUD and, likewise, the signal to go short is when price closes below the prevailing
CLOUD.
#############################
def is_CBO = if Type_Signal == Type_Signal."Cloud BreakOut" then 1 else 0;
=== === BULLISH SIGNALS ===
###########################
#A bullish signal is present when the close moves above the cloud. Caution is needed
if close is rising above a flat-top- cloud (a persistent resistance). The position of
the close related to the cloud is the most controlling aspect of signal
evaluation.....it is the 'Big Picture'.
def SpanA_OnTop = if ("Span A" > "Span B",1,0);
def isCBO_bull_aboveA = if "Span A" > "Span B" && crosses(close,"Span
A",CrossingDirection.ABOVE) then 1 else 0;
def isCBO_bull_aboveB = if "Span B" > "Span A" && crosses(close,"Span
B",CrossingDirection.ABOVE) then 1 else 0;
184
plot CBO_Bull_Strong = if (isCBO_bull_aboveA or isCBO_bull_aboveB) && is_CBO &&
want_Strong && want_Bull then close else Double.Nan;
CBO_Bull_Strong.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
CBO_Bull_Strong.SetLineWeight(5);
CBO_Bull_Strong.SetDefaultColor(GlobalColor("BullStrong"));
#def is_FlatTop = If (isCBO_bull_cross && SpanA_OnTop && Sum("Span A" > .90 * "Span
A"[1], 8) >= 5, 1, 0) or
if(isCBO_bull_cross && !SpanA_OnTop && sum("Span B" > .95 * "Span B"[1],8) >= 5 ,1,0);
#def SpanA_FlatTop = If (isCBO_bull_cross && SpanA_OnTop && Sum("Span A" == "Span
A"[1], 8) >= 5, 1, 0);
#def SpanB_FlatTop = If (isCBO_bull_cross && !SpanA_OnTop && Sum("Span B" == "Span
B"[1], 8) >= 5, 1, 0);
AddChartBubble(ShowBubbles && (isCBO_bull_aboveA or isCBO_bull_aboveB) && is_CBO &&
want_Strong && want_Bull,close,"strong\nbullish", Color.WHITE, yes);
##################################################
def is_SpanAB = if Type_Signal == Type_Signal."SpanA/B Cross" then 1 else 0;
185
Plot SpanAB_StrongBull = if is_SpanAB_Cross && isSpanAB_AboveCloud_26 && is_SpanAB &&
want_Strong && want_Bull then "Span A" else Double.Nan;
SpanAB_StrongBull.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
SpanAB_StrongBull.SetLineWeight(5);
SpanAB_StrongBull.SetDefaultColor(GlobalColor("BullStrong"));
186
#A bearish signal is when Span A crosses below Span B (or Span B crosses above Span A)
def SpanAS_Bearish_Cross = if crosses("Span A","Span B", CrossingDirection.BELOW) then
1 else 0;
###########################################
187
#==== CHIKOU CROSS(CC) SIGNALS ==== ##
#chikou cross is essentially the "chikou confirmation" that savvy Ichimoku traders
utilize to confirm chart sentiment before entering any trade. This confirmation comes
in the form of the chikou crossing through the price curve in the direction of the
proposed trade. If it crosses through the price curve from the bottom up, then it is a
bullish signal. If it crosses from the top down, then it is considered a bearish
signal.
############################################
def is_ChikouCross = if Type_Signal == Type_Signal."Chikou Cross" then 1 else 0;
=== ===CHIKOU CROSS BULLISH SIGNALS ===
###########################
#Bullish = Chikou crsses above close.Strong when close is above the cloud.
def ChikouCross_Bull = if Crosses(Chikou,close, CrossingDirection.ABOVE) then 1 else
0;
188
#=== === CHIKOU CROSS BEAR & STRONG ===
def ChikouCross_Bear = if Crosses(Chikou,close, CrossingDirection.BELOW) then 1 else
0;
plot CC_Strong_Bear = If (is_ChikouCross && ChikouCross_Bear && IsBelowCloud &&
want_Strong && want_BEAR, Chikou, Double.NaN);
CC_Strong_Bear.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
CC_Strong_Bear.SetLineWeight(5);
CC_Strong_Bear.SetDefaultColor(GlobalColor("BearStrong"));
189
Signal_strength."Strong" then "'Strong'"
else if Signal_strength == Signal_strength."Neutral" then "'Neutral'"
else if Signal_strength == Signal_strength."Weak" then "'Weak'"
else if Signal_strength == Signal_strength."All" then "'All'"
else ""), Color.WHITE);
AddLabel(yes, "The bullish/bearish sentiment selected is " + (if Bullish_Bearish ==
Bullish_Bearish."Bullish" then "'Bullish'"
else if Bullish_Bearish == Bullish_Bearish."Bearish" then "'Bearish'"
else if Bullish_Bearish == Bullish_Bearish."Both" then "'Both'"
else ""), Color.WHITE);
=== of code ###
declare lower;
plot Value;
plot Avg;
switch (AverageType) {
190
case SMA:
Value = Average(close, fastLength) - Average(close, slowLength);
Avg = Average(Value, MACDLength);
case EMA:
Value = ExpAverage(close, fastLength) - ExpAverage(close, slowLength);
Avg = ExpAverage(Value, MACDLength);
case HULL:
Value = MovingAverage(AverageType.HULL, close, fastLength) -
MovingAverage(AverageType.HULL, close, slowLength);
Avg = Average(Value, MACDLength);
}
191
DwnArrow.AssignValueColor(Color.cyan);
DwnArrow.SetPaintingStrategy(PaintingStrategy.ARROW_Down);
DwnArrow.SetLineWeight(1);
DwnArrow.HideBubble();
C- DMI_OSCILLATOR_SFL_FAV
#hint:The popular builtin <b>DMI_Oscillator with arrows and lines</b> in positive and
negative levels based on inputs. Use the lines and arrows to define your
criteria/decision points.
declare lower;
input length = 10;#hint length:The number of bars with which the DI+ and DI-
components are calculated.
#input paintBars = yes;#hint paintBars:Defines whether or not to color price plot
according to respective oscillator values (red for negative, green for positive).
input PlotADX = yes;#hint PlotADX:Toggles plot the ADX line
input ShowArrowsLines = YES;#hint ShowArrowsLines:Toggles all arrows and above/below
zero lines
input CrossAboveValue = 10;#hint CrossAboveValue:Defines the above-zero-value at which
an arrow is plotted.
input CrossBelowValue = 5;#hint CrossBelowValue:Defines the below-zero-value at which
an arrow is plotted.
def na = Double.NaN;
def diPlus = DMI(length)."DI+";
def diMinus = DMI(length)."DI-";
def DX = if (diPlus + diMinus > 0) then 100 * AbsValue(diPlus - diMinus) / (diPlus +
diMinus) else 0;
192
plot ADX = if PlotADX then WildersAverage(DX, length) else Double.NaN;
ADX.AssignValueColor(if (diPlus > diMinus) then Color.UPTICK else Color.DOWNTICK);
ADX.SetPaintingStrategy(PaintingStrategy.LINE);
ADX.SetLineWeight(2);
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.YELLOW);
#plot line_5above = 5;
#line_5above.SetDefaultColor(Color.YELLOW);
plot line_10above = if ShowArrowsLines then CrossAboveValue else double.nan;
line_10above.SetDefaultColor(Color.YELLOW);
#plot line_5below = -5;
#line_5below.SetDefaultColor(Color.YELLOW);
plot line_10below = if ShowArrowsLines then - CrossBelowValue else Double.nan;
line_10below.SetDefaultColor(Color.YELLOW);
ZeroLine.SetDefaultColor(Color.GRAY);
DefineGlobalColor("Positive", Color.UPTICK);
DefineGlobalColor("Negative", Color.DOWNTICK);
#AssignPriceColor(if yes
# then Color.CURRENT
# else if Osc > 0
# then GlobalColor("Positive")
# else GlobalColor("Negative"));
#======== Above-zero arrow plots when crossing input values ==========
def Upper_Up_Cross = if ShowArrowsLines && Osc crosses above CrossAboveValue then 1
else 0;
193
else 0;
plot D_Upper_Dwn_Cross = if Upper_Dwn_Cross then Osc else Double.NaN;
D_Upper_Dwn_Cross.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
D_Upper_Dwn_Cross.SetLineWeight(1);
D_Upper_Dwn_Cross.SetDefaultColor(Color.DARK_GREEN);
#AddLabel(ShowArrowsLines,"Above-zero arrow value = " + CrossAboveValue,
color.DARK_GREEN);
def Lower_MinOSC = if Osc < (-CrossBelowValue) && Osc < Osc[1] && Osc < Osc[-1] then 1
else 0;
C- PolarizedFractalEfficiency_SFL
194
#TOS Title = PolarizedFractalEfficiency_SFL
declare lower;
plot PFE = ExpAverage(if diff > 0 then val else -val, smoothingLength);
PFE.SetDefaultColor(GetColor(8));
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(GetColor(5));
ZeroLine.SetPaintingStrategy(PaintingStrategy.LINE);
ZeroLine.SetStyle(Curve.LONG_DASH);
ZeroLine.SetLineWeight(2);
ZeroLine.SetDefaultColor(Color.YELLOW);
195
C- Three_X_Oscillator
declare lower;
input Use_OB_OS = yes;#hint Use_OB_OS:<b>Show OverBought/OverSold lines.</b>\n Is
alternate to using HH/LL lines.
input Use_HH_LL = no;#hint Use_HH_LL:<b>Show Highest/Lowest actual value lines.</b>\n
Is alternate to using OB/OS lines.
input show40_60 = no;#hint show40_60:Yes shows the 40 & 60 lines
input K_period = 21;
input D_period = 9;
input SlowTrendLength = 3;
input smoothing_type = { default EMA, SMA };
input stochastic_type = { FAST, default SLOW };
input over_bought = 80;#hint over_bought:This can be replaced by the line of the
highest actual value
input over_sold = 20;#hint over_sold:This can replaced by the line of the lowest
actual value
196
def adjAggPer = if aggPer == AggregationPeriod.MIN then
AggregationPeriod.THREE_MIN
else if aggPer == AggregationPeriod.TWO_MIN then
AggregationPeriod.FIVE_MIN
else if aggPer == AggregationPeriod.THREE_MIN then
AggregationPeriod.TEN_MIN
else if aggPer == AggregationPeriod.FOUR_MIN then
AggregationPeriod.TEN_MIN
else if aggPer == AggregationPeriod.FIVE_MIN then
AggregationPeriod.FIFTEEN_MIN
else if aggPer == AggregationPeriod.TEN_MIN then
AggregationPeriod.THIRTY_MIN
else if aggPer == AggregationPeriod.FIFTEEN_MIN then
AggregationPeriod.HOUR
else if aggPer == AggregationPeriod.TWENTY_MIN then
AggregationPeriod.HOUR
else if aggPer == AggregationPeriod.THIRTY_MIN then
AggregationPeriod.TWO_HOURS
else if aggPer == AggregationPeriod.HOUR then
AggregationPeriod.FOUR_HOURS
else if aggPer == AggregationPeriod.TWO_HOURS then
AggregationPeriod.DAY
else if aggPer == AggregationPeriod.FOUR_HOURS then
AggregationPeriod.DAY
else if aggPer == AggregationPeriod.DAY then
AggregationPeriod.THREE_DAYS
else if aggPer == AggregationPeriod.TWO_DAYS then
AggregationPeriod.WEEK
else if aggPer == AggregationPeriod.THREE_DAYS then
AggregationPeriod.WEEK
else if aggPer == AggregationPeriod.FOUR_DAYS then
AggregationPeriod.MONTH
else if aggPer == AggregationPeriod.WEEK then
AggregationPeriod.MONTH
else if aggPer == AggregationPeriod.MONTH then
AggregationPeriod.MONTH
else
Double.NaN;
def _kPeriod;
def _dPeriod;
def _slowTrendLength;
if aggPer == AggregationPeriod.MONTH
then {
_kPeriod = K_period * 3;
_dPeriod = D_period * 3;
_slowTrendLength = SlowTrendLength * 3;
} else {
_kPeriod = K_period;
_dPeriod = D_period;
197
_slowTrendLength = SlowTrendLength;
}
#---Stochastic
plot stochD = if stochastic_type == stochastic_type.FAST then fastD else slowD;
stochD.SetPaintingStrategy( PaintingStrategy.POINTS );
stochD.HideBubble();
stochD.AssignValueColor( if stochD >= stochD[1] then Color.GREEN else if stochD <
stochD[1] then Color.RED else Color.GRAY );
##################################################
# Script below will plot a horizontal line at the lowest 3x Osc levelfor all of the
data loaded to the chart
plot stochlowest = If Use_HH_LL then LowestAll(stochD) else double.nan;
stochlowest.SetPaintingStrategy(PaintingStrategy.LINE);
stochlowest.SetStyle(Curve.SHORT_DASH);
stochlowest.SetDefaultColor(Color.red);
stochlowest.SetLineWeight(2);
stochlowest.HideBubble();
stochlowest.HideTitle();
#####
#Script below will plot a horizontal line at the highest 3x Osc level for all of the
data loaded to the chart
plot stochhighest = If Use_HH_LL then HighestAll(stochD) else double.nan;
stochhighest.SetPaintingStrategy(PaintingStrategy.LINE);
stochhighest.SetStyle(Curve.SHORT_DASH);
stochhighest.SetLineWeight(2);
stochhighest.SetDefaultColor(Color.green);
stochhighest.HideBubble();
stochhighest.HideTitle();
198
C-ONEGLANCE STUDY
declare lower;
def c = close;
def h = high;
def l = low;
def o = open;
199
#Define variables used to place a bubble
#========================================
#Input Offset = BarNumber() / 2;
def barNum = BarNumber();
def offset = 0;
def LastBar = !IsNaN(open) and IsNaN(open [-1] ) ;
def BubbleLocation = LastBar[offset];#Use this to locate the ending bar location
def FirstBar = if barNum == 1 then 1 else 0;
def FirstBarValue = if barNum == 1 then 1 else 0;
def LastBarValue = if LastBar && barNum == barnumber() then barNum else 0;
def MidBar = if LastBar then barNum == (BarNumber() / 2) else 0;
Def TotalBars = HighestAll(barNumber());
#AddLabel( yes, concat( TotalBars, " = Total bars" + " and bar count = " +
barnumber()), Color.white);
#example
#addchartbubble(LastBar,45, "This is a last bar bubble", color.White);
#==========================================
#Polarized Fractal Efficiency
#===========================
input PFE_length = 10;#hint PFE_length:The length used in calculating the Polarized
Fractal Efficiency. TOS default is 10.
input PFE_smoothingLength = 5;#hint PFE_smoothingLength:TOS default is 5.
input PFE_trig = 50;#hint PFE_trig:The value that triggers the PFE from Bullish to
bearish.
#MomentumPercent
#=================
input MOM_Pct_trig = 0.00;#Hint MOM_Pct_trig:The percent value that toggles the chart
between green and red. Normal is 0.00 %.
input MomPctLength = 5;#Hint MomPctLength:The offset length (bars back) that the
current bar is compared to calculate this Momentum Percent. TOS default is 10.
200
Color.DOWNTICK);
MomPct_Line.HideBubble();
#=== end ====
#Ichimoku Study
#==============
#NOTES: One major bullish indication in this study is when the Tenkan excaads the
Kijun. Their default lengths of 26 and 9 may be shortened to increase response
sensitivity. There are other bullish Ichimoku indicators.
201
#Bollinger Bands MOBO(MOmentum BreakOut)
#============================================
#Explanation of how this works. +/- 0.8 std deviation Bollinger Bands are the
criteris for bullish/bearish plots. When the close rises above the upper band the
signal is bullish and stays bullish until the close moves below the lower band when
the plot turns to bearish and remains bearish until the close rises above the upper
band.
input MOBO_length = 10;#hint MOBO_length:The agg-bars used in the standard
deviation(SD) calculation to define the upper and lower bands.
input Num_Dev_Dn = -0.8;#hint Num_Dev_Dn:The SD of the lower band. Similar to the 2,0
SD used in the Bollinger Bands
input Num_Dev_up = 0.8;#hint Num_Dev_up:The SD of the upper band. Similar to the 2,0
SD used in the Bollinger Bands
plot line55 = if IsNaN(close) then Double.NaN else 55;#Used to manage space to set
labels above this value.
line55.SetDefaultColor(Color.BLUE);#Insert color to match your background to make line
202
invisible
line55.HideBubble();
#== end ==
#TrueStrengthIndex
#===================
input TSI_trig = 0 ;#hint TSI_trig:The value that toggles bull/bear. TSI has a
'TSI(value)' and a 'signal' line with a zero line. This deals with the 'TSI(value)'
being above the zero line. An earlier trigger could be had by analysis as was done
with the MACD herein.
def TSI_here = reference TrueStrengthIndex(25, 13, 8, "WMA").TSI;
203
TSI_Line.SetLineWeight(5);
TSI_Line.AssignValueColor(if TSI_here > TSI_trig then Color.UPTICK else
Color.DOWNTICK);
TSI_Line.HideBubble();
204
Macd_Line1.AssignValueColor(if macd_Val_1 > macd_Avg1 then Color.UPTICK else
Color.DOWNTICK);
Macd_Line1.HideBubble();
#== end ====
205
AddChartBubble(FirstBar && LH_Bubbles, 42, "HullMovingAvg(" + Hull_length + "). " +
"Trigger = bullish when HullMovingAvg > previous HullMovingAvg.", Color.WHITE);
AddChartBubble(BubbleLocation, 42, "HullMovingAvg" ,Color.WHITE);
#=====
AddChartBubble(FirstBar && LH_Bubbles, 35, "MACD(" + fastLength_1 + "," +
slowLength_1 + "," + MACDLength_1 + "," +
AverageType_1 + "). Bullish when MACD.Value is above MACD.Avg (signal line). Trigger =
MACD().value > MACD().avg",
Color.PINK);
AddChartBubble(BubbleLocation, 35, " MACD > signal line" , Color.PINK);
#======
AddChartBubble(FirstBar && LH_Bubbles, 38.5, "MACD.Value(" + fastLength_2 + "," +
slowLength_2 + "," + MACDLength_2 + "," + AverageType_2 + ")" + "Bullish when
MACD.Value is above the zero line. Trigger = " + macdVal_trig + "(Normally the zero
line)", Color.PINK);
AddChartBubble(BubbleLocation, 38.5, "MACD > 0" , Color.PINK);
#=======
AddChartBubble(FirstBar && LH_Bubbles, 17.5 , "Polarized Fractal Efficiency (" +
PFE_length + "). " + "Trend UP = 0 to 100. Trigger = " + PFE_trig, Color.WHITE);
AddChartBubble(BubbleLocation, 17.5 , "Polarized Fractal Efficiency" , Color.WHITE);
#==========
AddChartBubble(FirstBar && LH_Bubbles, 21, "MomentumPercent(" + MomPctLength + ").
Bullish when > 0 % & for long periods. Trigger = " + MOM_Pct_trig + " percent",
Color.CYAN);
AddChartBubble(BubbleLocation, 21, "Momentum Pct", Color.CYAN);
#========
AddChartBubble(FirstBar && LH_Bubbles, 24.5, "Ichimoku(" + tenkan_period + ", " +
kijun_period + "). Bullish trigger = when tenkan > kijun. The more the diff, the
stronger the trend.", Color.WHITE);
AddChartBubble(BubbleLocation, 24.5, "Ichimoku" , Color.WHITE);
#======
AddChartBubble(FirstBar && LH_Bubbles, 28, "RSI" + RSI_length + ")." + " Trigger = RSI
is between " + RSILowTrig + " and 100 and is rising for last " + rsi_UpBars + "
bars", Color.CYAN);
AddChartBubble(BubbleLocation, 28, "RSI" , Color.CYAN);
#====
AddChartBubble(FirstBar && LH_Bubbles, 31.5, "Bollinger Bands(+/- " + Num_Dev_up + "
SD)" + " MOmentum Break Out (MOBO(" + MOBO_length + "))." + " Trigger when close goes
above upper band and stays bullish until the close goes below the lower band.",
Color.WHITE);
AddChartBubble(BubbleLocation, 31.5, "BB MOBO", Color.WHITE);
#========
AddChartBubble(FirstBar && LH_Bubbles, 14, "DMI_Oscillator(" + DMIO_Length + ").
206
Bullish DMI = green = >0: Bearish DMI = red. Trigger = " + DMIO_trig, Color.PINK);
AddChartBubble(BubbleLocation, 14, "DMI_Oscillator" , Color.PINK);
#=======
AddChartBubble(FirstBar && LH_Bubbles, 10.5, "ADX(" + ADX_Length + "). Bullish ADX =
green: Bearish ADX = red. Strong bullish ADX trend is > 25. Trigger = " + ADX_trig,
Color.PINK);
AddChartBubble(BubbleLocation, 10.5, "ADX" , Color.PINK);
#======
AddChartBubble(FirstBar && LH_Bubbles, 7, "TrueStrengthIndex(25,13,8,'WMA')." + "
Bullish TSI = green & 0 to +50. Bearish TSI = red & 0 to -50. Trigger = " + TSI_trig,
Color.CYAN);
AddChartBubble(BubbleLocation, 7, "TrueStrengthIndex", Color.CYAN);
#=======
AddChartBubble(FirstBar && LH_Bubbles, 50, "RED dot denotes presence of a SQUEEZE",
Color.WHITE);
AddChartBubble(BubbleLocation, 50, "Red when Squeeze is 'on'", Color.WHITE);
#=====
AddChartBubble(FirstBar && LH_Bubbles, 3.5, "DynamicMomentumIndex-DYMI(" + DYMI_length
+ "). Overbought = 70: Oversold = 30. Trigger = " + DYMI_trig, Color.CYAN);
AddChartBubble(BubbleLocation, 3.5, " DynMomIndex-DYMI", Color.CYAN);
#=========
#== Labels ==
#Count of Periods in consecutive squeeze
rec count = if isSqueezed then count[1] + 1 else 0;
AddLabel(showlabels, if isSqueezed then "Squeeze is on for " + count + " bars" else
"No Squeeze is on", if isSqueezed then Color.RED else Color.WHITE);
AddLabel(showlabels, "HullMovingAvg(" + Hull_length + ") = " + Round(HullMA, 2), if
HullMA > HullMA[1] then Color.GREEN else Color.RED);
AddLabel(showlabels, "MACD.Value(" + MACDValue_2 + ") is above 0 line = " + if
MACDValue_2 >= 0 then "true" else "not true", if round(MACDValue_2,1) >= 0 then
color.GREEN else color.LIGHT_RED);
AddLabel(showlabels, "MACD.Value(" + macd_Val_1 + ") is above above MACD.Avg(" +
macd_Avg1 + ")(signal) = " + if macd_Val_1 > macd_Avg1 then "true" else "not true", if
macd_Val_1 > macd_Avg1 then Color.UPTICK else Color.DOWNTICK);
AddLabel(showlabels, if upmobo and c < Uppermobo then "MOBO close is between(" +
Num_Dev_up + " SD) bands"
else if upmo then "MOBO is above upper(" + Num_Dev_up + " SD) band"
else if dnmo then "MOBO is below lower(" + Num_Dev_up + " SD) band"
else "", Color.GREEN);
207
AddLabel(showlabels, "MomentumPercent(" + MomPctLength + ") = " + Round(mom_pct, 2) +
" %", if mom_pct >= MOM_Pct_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "Polarized Fractal Eff(" + PFE_length + ") = " + Round(PFE, 0),
if PFE >= PFE_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "DMI Osc(" + DMIO_Length + ") = " + Round(DMI_OSC_here, 1), if
DMI_OSC_here >= DMIO_trig then Color.GREEN else Color.RED);
AddLabel(showlabels, "ADX(" + ADX_Length + ") = " + ADX_here, if ADX_here >= ADX_trig
&& DMI_Pos then Color.GREEN else Color.RED);
AddLabel(showlabels, "TSI = " + Round(TSI_here,1), if TSI_here >= TSI_Trig then
color.GREEN else color.RED);
AddLabel(showlabels, "DYMI(" + DYMI_length + ") = " + Round(DYMI_here, 1), if
DYMI_here >= DYMI_trig then Color.GREEN else Color.RED);
AddLabel(1,"Use 'Drawings/Pan' to move chart to the left for bubble
clarity",color.WHITE);
#== end ==
of All Code
C-ICHIONEGLANCE STUDY
declare lower;
input tenkan_period = 9;#Hint tenkan_period: The number of bars used to calculate the
Tenkan (cyan) plot. Default is 9 and should be retained.
input kijun_period = 26;#Hint kijun_period: The number of bars used to calculate the
Kijun (pink) plot. Default is 26 and should be retained.
input ShowLabels = YES;#hint ShowLabels:Toggles labels on/off.
input LH_Bubbles = yes;#hint LH_Bubbles:Toggles left-hand bubbles ON/OFF
208
def Kijun_here = Ichimoku(tenkan_period, kijun_period).Kijun;
#example
#addchartbubble(LastBar,45, "This is a last bar bubble", color.White);
#==========================================
#===== Secondary Trend(ST) --- When T > K =======
def Tenkan = Ichimoku(tenkan_period, kijun_period).Tenkan;
def ST_Bull = if Ichimoku(tenkan_period, kijun_period).Tenkan >
Ichimoku(tenkan_period, kijun_period).Kijun then 1 else 0;
#=== scan code for 'Close above the cloud' (primary Bullish scan)===
209
#(close is greater than Ichimoku()."Span A" within 2 bars and close is greater than
Ichimoku()."Span B" within 2 bars)
#== end of scan code ==
#== end of primary trend ==
210
Ichimoku()."Span B" within 2 bars) and
# Ichimoku()."Tenkan" is greater than Ichimoku().Kijun within 2 bars and
# Ichimoku()."Chikou" from 26 bars ago is greater than Ichimoku()."Span A" within 2
bars
#== end of scan code ==
No_Trend.SetPaintingStrategy(PaintingStrategy.LINE_VS_SQUARES);
No_Trend.SetLineWeight(5);
No_Trend.SetDefaultColor(Color.White);
No_Trend.HideBubble();
211
line25.SetDefaultColor(Color.BLUE);#Insert color to match your background to make line
invisible
line25.HideBubble();
#== end ==
Watchlist Columns
WLC-PRICE-TO-EARNINGS (P/E) RATIO FOR A
WATCHLIST COLUMN
AddLabel(yes, round(PE,1));
#end
212
WLC-WHEN A DIVERGENCE EXISTS BETWEEN PRICE
AND THE MACD
#hint:Looks for and indicates positive (price rising) and negative (price declining)
divergences of price and the MACD
Input Bars = 3;#Hint Bars:The number of bars in the pattern to evaluate
AddLabel(1, if pos_div then "pos" else if neg_div then "neg" else "none", if pos_div
== 1 then color.green else if neg_div == 1 then color.red else color.pink );
#=====to prove out the code or to use this as a study, plot the below
# and evaluate that the conditions and results are correct ========
plot Positive = pos_div;# A CYAN value of 'one' plots where true exists
Plot Negative = neg_div;# A PINK value of 'one' plots where true exists
#==================================================================
#end
WLC OF BARS-INTO-A-SQUEEZE
213
#hint;A WatchList Column (WLC) that shows whether an equity is in a squeeze and if so
how many bars it has been in a squeeze. Be sure to set the agg to the chart agg you
want to view this on. This is very efficient code.
#addlabel(1, "Bars into a squeeze = " + count, If squeeze then Color.LIGHT_RED else
color.Current);
#if column width is a concern the label below shortens the word length and shows the
count value
Scans
S-LINEAR REGRESSION-VAR SCAN
This is a scan that works well in a dynamic watch list with your favorite companies to trade. It
works well as a signal when a company is moving up through resistance in a trough or lower area
for a long trade. Vary the "width of channel" and “length” to suit your own preferences.
Plot scan = low crosses LinearRegChVar ("width of channel" = 69, "full range" = no, "length" =
252)."LowerLR"
Another example
214
input length = 20;#hint length:Number of agg-bars to test for ascending conditions
input bars = 5;#hint bars:Number of agg-bars being evaluated in <b>sum</b>
def trendup = IsAscending(close,length);
def trendup2 = sum(close > close[1],bars) >= bars;
def mcd = MACD();
def mcdtrend = sum(mcd > mcd[1],bars) == bars;
plot scan = trendup && trendup2 && mcdtrend;
#end
This scan does a good job finding stocks that are tanking!
Comment: When entering the scan, the set aggregation defines the length of a bar. It likely is 'day'
but doesn’t have to be. Also, this is a simple clear example of how the 'switch; function operates.
215
Scan for a price increase
Low correlation
216
S-DMI_OSCILLATOR SCAN FOR TRENDING-UP STOCKS
Comment: A good scan for stocks trending up. The aggregation for this is “day”. Change length or
the value of 'X > 10' for a more powerful trend. This reads as 'scan for stocks with a DMI_Oscillator
value greater than 10 and rising for the last 5 agg-bars.'
#Time Bracket
input Begin = 0930;
input End = 1030;
#Hint: scan for stocks in the top 10 percentile of their 52-week high-low range
# Set aggregation to 'day'
input range = 252;#hint range:Number of trading days in a year
input price = close;
def hi = highest(high,range);
def lo = lowest(low,range);
def x = (price - lo) / (hi - lo) * 100;
plot scan = x > 90;
217
Alternate 2 = Stocks between 47% and 53% (or the middle of) their 52-week-high-low range
#Hint: scan for stocks between 47% and 53% (or the middle of) their 52-week-high-low
range
input low_pct = 47;
input hi_pct = 53;
input range = 252;
input price = close;
def hi = highest(high,range);
def lo = lowest(low,range);
def x = (price - lo) / (hi - lo) * 100;
plot scan = x <= hi_pct and x >= low_pct;
Plot scan = (RSIWilder(length = 2) < 20 && RSIWilder(length = 2)[1] < 20 && RSIWilder(length =
[2] < 20 && Close > SimpleMovingAvg(length = 200))
Alternate 2: stocks that have a 3-day RSI under 20 a closing price above the 200 SMA
#end
218
input DaysBack = 3;
def MA = average(close,10); #10 bar MA
def EMA = expaverage(close,20); # 20-Bar EMA
def cross = MA[DaysBack] < EMA[DaysBack] && MA>EMA;
Alternate 3: Plot a dot below the bar that crosses and only that bar.
If you want to see a dot anytime the condition is true, then remove the '&& !cross[1]'
#end
219
Alternate 2: Price crosses the 200-day MA
Alternate 3: For a better study for the scan, use this. You’ll get more hits. This one doesn’t care if the
close is above the 200-day MA as long as EITHER the close is above the 200-day MA OR the 200-day
MA is bracketed. Same for the reverse case.
OR
#end
#end
220
def DMIplus = DMI(length = 25)."DI+";
def DMIminus = DMI(length = 25)."DI-";
plot Scan = DMIplus > DMIminus;
#end
OR
ADXCrossover: Scan for the ADX (bullish or bearish) crossing a specified level (threshold). The
default parameters are length = 14, threshold = 20. When the DMIplus is greater than the DMIminus
the ADX is 'Bullish' or vice versa is 'Bearish'.
OR
221
Plot ADX_Bear = ADXCrossover(crossingType = "above") .signal && DMI."DI-" > DMI."DI+";
#MomentumCrossover: Scans for the Momentum crosses the zero line. The default length = 12;
OR
MoneyFlowIndexCrossover: Scans for the Money Flow Index crossing the specified level. The
default parameters are
• OR
MovingAvgCrossover: Scans for crossovers of moving averages of different types and lengths. The
defaults parameters are price = close, length1 = 15, length2 = 30. This example will specify all
parameters to avoid confusion.
The above reads as a’based on the close, simple average1 of length = 15 crosses above exponential
average2 of length = 30.'
OR
The above reads as a’based on the close, simple average1 of length = 15 crosses below exponential
average2 of length = 30.'
ParabolicSARCrossover: Scans for the Parabolic SAR crossing the price plot close. The defaults are
accelerationFactor = 0.02, accelerationLimit = 0.2
222
input crossingType = {default Bearish, Bullish};
Plot SAR_Bear = ParabolicSARCrossover(crossingType = "Bearish").signal;
OR
PriceAverageCrossover: The Price Average Crossover scans for crossovers of price with its moving
average. The default parameters are price = close, length = 15
The above reads 'scan for when the 15 bar exponential moving average crosses above the close'.
OR
The above reads 'scan for when the 15 bar exponential moving average crosses below the close'.
The above reads 'scan for when the RSI Wilder crosses above 30'.
OR
The above reads 'scan for when the RSI Wilder crosses below 30'.
RateOfChangeCrossover: The Rate Of Change Crossover for where Rate Of Change crosses zero
level. The default is length = 14.
The above reads as 'scan for when the rate of change crosses below zero (or goes negative).'
223
OR
The above reads as 'scan for when the rate of change crosses above zero (or goes positive).'
StochasticCrossover: The Stochastic Crossover for when the Stochastic Slow or Stochastic Fast
crosses overbought (80%) or oversold (20%) level. The default parameters are KPeriod = 14. Note
the overbought and oversold levels are predefine as 80/20 respectively and can’t be changed when
using this crossover study.
The above reads as 'scan for when the 14 period fast stochastic crosses above 80'.
OR
The above reads as 'scan for when the 14 period slow stochastic crosses below 20'.
Comment1: Re all crossover scans, refer to "Referencing other studies" for a complete explanation
of the applicable rules for specifying parameters
Comment2: The examples shown above do not represent all possible combinations of the
parameters available. Using the examples guides you re what parameters are applicable and how
you may change them to suit your desires.
Comment3: Each of the 11 crossover scans are selectable in the Scan/StockHacker tab. This is a very
easy way toimplement these scans since all the parameters are presented for easy assgnment.
#end
S-MACD SCAN
Bullish Scan: The MACD value crosses above the MACD average while both are below zero
224
def MACD_Val = MACD(12,26,9).Value;
def MACD_Avg = MACD(12,26,9).Avg;
def xOver = MACD_Val [1] < MACD_Avg [1] and MACD_Val >= MACD_Avg ;
plot bullishScan = xOver and MACD_Val < 0 and MACD_Avg < 0;
Bearish scan: The MACD value crosses above the MACD average while both are Above zero
def MACD_Val = MACD(12,26,9).Value;
def MACD_Avg = MACD(12,26,9).Avg;
def xOver = MACD_Val [1] < MACD_Avg [1] and MACD_Val >= MACD_Avg ;
plot bearishScan = xOver and MACD_Val > 0 and MACD_Avg > 0;
Scanning for stocks that have just crossed over produces less hits that a scan that looks for a xOver
within one (1) day.
Suggest: To get a meaningful scan use: 1) fundamental filter: close >=10, and 2) study filter:
VolumeAvg(50) >= 500000
#end
#end
Alternate:
225
#hint:High correlation scan. By Mr Script
input length = 10;#hint length: the agg-bar length being compared
input correlationWithSecurity = "SPX";#hint correlationWithSecurity; The security
that the stock is correlated with
input inarow = 10;#hint inarow:The number of agg-bars in a row with >0.9 correlation
def x = Correlation(close, close(correlationWithSecurity), length) > .9;#greater then
0.9 indicates a high correlation
#end
226
#Increasing Earnings Scan
#v2.28.14.1
#Scan for earnings > previous quarter earnings
#times_up input determines the number of times earnings increased
#Example: times_up = 4, scan checks for earnings increasing at least 4 quarters in a
row
#default = 2 since 2 was the requested number
#extensive notes are provided for the curious
input times_up = 2;
#define a variable for GetActualEarnings() for efficiency
def gae = GetActualEarnings();
#Description of recs are written in plain English, followed by the corresponding
script use
# We need to get the earnings value and carry it forward so we can compare the next
earnings to it
#if earnings are reported: if(!isNaN(gae),
#then get the earnings number: gae,
#else keep the last earnings number: earn[1]);
#If you wanted to scan for earnings increasing only x number of times and not more,
change >= to == . e.g. with times_up == 2, using >= means earnings increasing 4 times
in a row meet the criteria.
#end
227
S-SCAN FOR TOS' STRENGTH METER
Comment: TOS has a column heading titled 'Strength Meter' which reads "stocks that have risen
10% in the last three weeks will have their strength meter activated. The green sloped bar in the
watchlist column wil then be activated. The code is presented here so you may change it to your
liking. For example, you may want this to show based on 2 weeks in lieu of 3 weeks. The reverse is
also true when a down-sloped RED bar shows.This is the picture of the subject:
declare lower;
def Agg = AggregationPeriod.Week;
plot Data = close(period = agg) / close(period = agg)[3];
Data.SetPaintingStrategy(PaintingStrategy.Histogram);
Data.AssignValueColor(if Data > 1.1
then Color.Green
else if Data < .9
then Color.Red
else Color.Yellow);
Data.SetLineWeight(3);
#end
Realize that the data-feed for Stock Charts may not be the same as that for TOS but that should not
likely cause any conflicts because the source of all data is the exchanges. Visit the site
If aggregation is 'week' then 'agg-bars ago' is 2 weeks ago. If aggregation is set to 'Day' then 'agg-bars
ago' is 2 days go
228
S-NEW BULLISH CLOSE ABOVE THE ICHIMONU CLOUD
new bullish close above the cloud
Tutorials (How-To-Do’s)
Alert Sounds
Usage Tips
T-USING CUSTOM COLUMN AGGREGATION
Here’s an interesting concept/tip that you may find very useful and it’s not obvious. The '%HL
Custom Column' (available at http://mytrade.com/StanL ) tells where, in today’s prices, a stock is
now i.e. 35% means it is now at 35% of today’s range (low to high). 100% means it is at its high of
today’s range. These numbers are based on the columns "day" aggregation. That agg can be changed
to say '4 days'. The column will then tell where in the range of the last 4 days, the stock currently is.
Use a month agg and it will tell where in the last month’s range the stock currently is. The same
concept applies to all aggs. Isn’t that neat? And it is so easy to change the agg. Also custom columns
have some aggs that are different from the normal chart aggs. For example 4-days is a column agg
choice but is not a choice of the chart settings (the agg dropdown).
The example used here, %HL, is a custom column study available at http://mytrade.com/StanL Of
course, you will need to keep track of what agg you are currently using. Perhaps you can do that
with the title of the custom column. After installing the %HL you access editing it by right-clicking
the watchlist column headings to customize and follow the snapshots below:
There are some studies that have numerous plots. Deciphering what plot corresponds to particular
229
code can be a challenge. Here is a tricky way to do it.
In this example, if you want to identify what plot is the ORH, you uncheck 'Show Plot' and the click
'Apply'. While doing this you can observe which plot is ORH because it disappears. This can be
reversed and redone if you missed the observation.This works on any highlighted plot. You can also
use color changes to identify various plots.
• #end
Setups frequently have rules re what needs to exist to implement its buy/sell strategy. Such rules
may be simple or complex but, regardless, are not easy to remember. This tip is to use TOS
'ThinkLog' to store those rules for easy reference. ThinkLog is accessed via the 'Tools/ThinkLog' tab
and is a ready reference place where you could refresh you memory on the implementation details
of the 9/30 strategy’s particulars.
230
T-WIZARD ACCESS FOR EDITING EXISTING STUDIES
When editing existing studies and you want to use the wizard, you have two choices: 1. Open a new
study. Copy the wizard result via CTRL-C and then 'CANCEL' the new study; or 2. Use the wizard in
the 'scan/stock hacker' and copy the wizard result via CTRL-C for pasting into the existing study
editing.
Note that the columns can be customized and adding a 'Send to [4] Green', for example, gives a
quick chart of the stock.
The end-time markers may seem redundant and they are if you do not 'Show Extended Session' or
'Expansion Area' for stocks. Futures and Forex are a different story.
AddVerticalLine(StartTime,"Market Open",Color.RED,Curve.SHORT_DASH);
AddVerticalLine(EndTime," Market Closed",Color.RED,Curve.SHORT_DASH);
231
In the left panel In the Market Watch/Quotes In the Market Watch/Quotes
The procedure for charting the stock is different in the two locations:
2. In 'Market Watch/ Quotes', clicking on the 'Send To' button (in this case the green square) will
chart the stock.
#end
Occasionally this color is hard to read if it is close to your screens background color. The following
code, placed as the top lines in your study, will reset the header text color and affect nothing else
except a shown below in 'edit studies'.
Note that the LinearRegCh100 color cannot be changed because it is a built-in study and its code is
non-editable.
However, there are unintended consequences as shown below in this 'edit studies' screen.
#end
Comment: The Sequence Counter is used as an example and is not a recommended indicator:
reviews are not in unison.
#end
232
plot Histogram_Liner = Same data as for the histogram plot
Histogram_Liner.SetPaintingStrategy(PaintingStrategy.LINE);
Histogram_Liner.SetLineWeight(1);
Histogram_Liner.SetDefaultColor(Color.CYAN);
Ctrl+X
Cut the selected item. Item cut becomes available for pasting.
• Ctrl+Z
• Ctrl+Y
• Shift+Delete
Delete the selected item without moving it to the Recycle Bin first
• Ctrl+Right Arrow
233
Move the cursor to the beginning of the next word
• Ctrl+Left Arrow
• Ctrl+Down Arrow
• Ctrl+Up Arrow
Select more than one item in a window or on the desktop, or select text within adocument
• key+Spacebar
• Ctrl+A
• Ctrl+Shift+Esc
• Right Arrow
• Left Arrow
• Others
• The free 'Notepad++' is an excellent editor made specifically for coding: http://notepad-plus-
plus.org/
• #end
234
T-THE DREADED 'TOO COMPLEX ERROR'
Custom columns run in "TOS real-time". Additionally they have CPU performance limits (which is
on their servers where all scripts run), so if your script has too much "stuff" in it and is pre-
analyzed to take more execution time than is allowed you get the dreaded "too complex error."
The solution is to pare the script down to its essence and apply some good ole brain power to the
data. Say you have two plots (which always generates an error in custom columns, scans, and
conditional orders) and seven to eight conditions shown as nine colors packed into a single column.
How did you expect to display two numerical results in each single cell?
Not to mention the rainbow of colors. Not every script that works on a chart/study is worthy of
putting in a custom column.
Long series of 'if conditions' also can create the 'too complex error'. You may be able to eliminate
the error if you break up a long series of if-conditions into simple sub-conditions and then combine
the sub-conditions into an overall 'If' statement. Another example that you may try as a work-
around is as follows:
Realize also that overly complex if-conditions are only one aspect that generates the 'too complex'
error. As initially said, it could be superfluous lines in your code retained when converting a study
into a custom column. For example, 'PlotName.SetPaintingStrategy(PaintingStrategy.LINE);' and
'PlotName.SetLineWeight(1);' are superfluous in a custom column but contribute to TOS' evaluation
of the 'too complex error'. Remember that we are not privy to what TOS uses to evaluates the 'too
complex error' but you can be sure that the presence of superfluous code lines contribute to the
error. In summary, make your code compact and smart with only necessary essential lines.
The concept is to define each of your conditions in the format of '1 when true' and '0 when false'.
Then plot each condition. Below you see 5 conditions and plots showing when each condition is
true or false ( 1 or 0). Placing the cursor over an arrow, you can see what conditions are firing (are
1, true) to produce that arrow. Conversely, if arrows are not desired at a particular location, you
then will see what condition to change. The reverse is also true when desired arrows do not exist
because a condition is not being triggered.
235
How to do this? You take your basic code study…the one that plotted the arrows, and change the
'plot' statements to 'def' statements. You change the condition-def statements to plot statements. You
create a new study for each condition so it will be plotted or you may combine condition plots in a
study if you are able to identify one condition from another by colors or type of plot. Also labels are
valuable for clarifications.
Don’t forget to delete the studies, 5 in this example, that plotted the cnditions to preclude
accumulation of studies that have no further use.
Builtin-name + _ + your-initials. So the MACD will look like 'MACD_ME'. The benefit of doing this is
that the builtin and your modified copy stay adjacent in the list and it helps you to keep track of
what you may have done two months ago.
1. By going to 'chart settings/price axis' tab and checking the boxes per the picture below
3. Clicking 'style' then 'Chart Scale' to bring up the same menu as above.
While 'percentage view' is activated, place the cursor-line over the desired bar and right click.
In the menu presented, select 'Set bar as 0%'. A horizontal 0% line will appear accross the chart at
the value of the selected bar’s close.
To reset the chart to the original first bar’s close, right click on the zero percent level line and
choose 'Reset to default 0% level'.
The calculation for the percentage shown is: (current price – close price of 0%-selected-bar) / close
236
price of 0%-selected-bar * 100.
#end
1. Using the 'pan' tool Go to 'Drawings' and select the 'Pan' tool . This icon will now show on the
chart in lieu of the cursor. Simply hold- down the left mouse key and drag the chart to the left
for as much right-space as you want. Return to 'drawings' and select 'pointer' to re-establish it.
The space you panned for will be recorded in 'Chart settings/time axis/expansion area'.
2. Using the chart’s lower-right symbol Click the symbol and this menu will appear: Clicking as
shown will take you to 'Chart settings/time axis' where you set the’expansion bars to the right'.
3. Using the chart settings directly Clicking as shown will take you to 'Chart settings/time axis'
where you set the’expansion bars to the right'.
If you use a study on say 15 different charts. Renaming a study will automatically change the study
to the new name on each of the 15 charts. However, there are a number of places in TOS like Study
Filters, Study Alerts, Custom Quotes, and Conditional orders that are allowed to use referenced
studies. If the renamed study is referenced therein with the old name, then that reference(old
name) will be broken i.e. will no longer work and will not be changed to the new study name.
Dynamic scans are particularly vulnerable and will become ineffective if a custom referenced study
is renamed.
References
Contact Me
Jim Shingler
shinglerjim@gmail.com
Social Media
237