├── .gitignore
├── LICENSE
├── README.md
├── thinkscripts
├── PM_PercentChg_STUDY.ts
├── PM_Rank_STUDY.ts
├── PM_Sandbox_STUDY.ts
└── PM_ShowOHLC_STUDY.ts
└── thinkscripts_cq
├── PM_IV_Rank_CQ_STUDY.ts
├── PM_PercentChg_CQ_STUDY.ts
├── PM_Price_Rank_CQ_STUDY.ts
├── PM_Rank_CQ_STUDY.ts
└── PM_Rank_Coloring_CQ_STUDY.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .DS_Store
3 | *backup*
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PM ThinkScripts
2 | ===============
3 | This is a collection of handy thinkscripts for use on the thinkorswim (TOS)
4 | trading platform. There are two types of [ThinkScript][]:
5 |
6 | 1. __*ThinkScripts*__
7 | These scripts are full powered and intended for use on charts,
8 | scan queries, and conditional orders. The instructions for
9 | importing/exporting ThinkScripts applies to these scripts.
10 |
11 | 2. __*Custom Quote Scripts*__
12 | These scripts are intended for use on watchlists, anywhere
13 | a [custom quote][] can be inserted as a column, and scan queries.
14 | To use these, the user must copy and paste the code into a
15 | custom quote thinkscript code area. TOS offers 20 custom quote
16 | slots.
17 |
18 | The workflow for ThinkScripts and Custom Quote Scripts can be made much
19 | more fluid once TOS enables features open to builtin scripts to user
20 | created scripts. These are features such as the `#Wizard` keyword, [direct
21 | referencing][script referencing] of user created scripts (not just builtin
22 | scripts), not creating a copy of referenced thinkscript code when referencing
23 | them as a condition in a custom script (this causes changes in the original
24 | to not propagate to the custom script), etc.
25 |
26 | What ThinkScripts Are Available?
27 | --------------------------------
28 |
29 | __*PM Rank*__
30 | Calculates the percentile rank for the current value of the selected
31 | [Fundamental Data][] (IV, Price, etc.) as it compares to its range over a
32 | user or chart specified number of [periods][agg_per] (FIVE_MIN, DAY, etc).
33 | It is essentially `(value-lowest)/(highest-lowest)`. This script can be
34 | used as a plot and as a label.
35 |
36 | __*PM Percent Change*__
37 | Calculates the percent change in value from now and N periods ago where:
38 |
39 | * *value* is any data type enumerated by [Fundamental Data][] such as
40 | CLOSE, IV, etc.,
41 | * *N* is any user specified lookback length, and
42 | * *period* is any user or chart selected [aggregation period][agg_per]
43 | such as FIVE_MIN, DAY, etc.
44 |
45 | This script can be used as a plot and as a label.
46 |
47 | __*PM Show OHLC*__
48 | Plots the previous day's OHLC and today's OHL.
49 |
50 | __*PM Sandbox*__
51 | A playground to wrangle with [thinkscript][] syntax, functions, and assumptions.
52 |
53 | #### Custom Quote Scripts
54 |
55 | __*PM IV Rank CQ*__
56 | A bare bones distilled version of PM_Rank that only computes the IV Rank
57 | over 252 trading days rounded to one significant digit (one decimal place).
58 | Note, this script colors the value based on where it lays within the rank.
59 | Edit the code to change the lookback period and rank coloring thresholds
60 | to fit your needs.
61 |
62 | __*PM Price Rank CQ*__
63 | A bare bones distilled version of PM_Rank that only computes the Price Rank
64 | over 252 trading days rounded to one significant digit (one decimal place).
65 | Note, this script colors the value based on where it lays within the rank.
66 | Edit the code to change the lookback period and rank coloring thresholds
67 | to fit your needs.
68 |
69 | __*PM Rank CQ*__
70 | A bare bones distilled version of PM_Rank with less user input controls. It
71 | calculates the percentile rank over 252 trading days for desired fundamental
72 | data (IV, O, H, L, C, Volume, etc.). Note, this script colors the value based
73 | on where it lays within the rank. Edit the input data source or the lookback
74 | period and rank coloring thresholds to fit your needs.
75 |
76 | This one is intended to be imported as a study and referenced for custom
77 | quote scripts and scan queries. Once TOS fixes workflow issues, this will
78 | be the preferred method so there will be one source file for Rank related
79 | computations. Until then, it's easier/faster to use the rank specific cq
80 | scripts above.
81 |
82 | __*PM Rank Coloring CQ*__
83 | This is an example script to show how one can enable the coloring of data
84 | if the core script is referenced. As of 2013-11-09, the TOS limitations
85 | will essentially copy the core script code into a custom script using the
86 | `script { } ` notation and add the coloring details below it.
87 |
88 | __*PM Percent Chg CQ*__
89 | A bare bones distilled version of PM_PercentChg that only computes the %chg
90 | over 10 trading days rounded to one significant digit (one decimal place).
91 | Note, this script colors the value based on hi and lo alert thresholds.
92 | Edit the code to change the data type, lookback period, and alert coloring
93 | thresholds to fit your needs. Also, this script minimizes column space by
94 | not outputting the "%" character.
95 |
96 |
97 | How Do I Install/Update ThinkScripts?
98 | -------------------------------------
99 |
100 | #### Downloading the script(s)
101 |
102 | Enumerated below are a few ways to obtain these scripts:
103 |
104 | 1. Clone this project in the following ways:
105 | 1. Click on the `Clone in Desktop` link located on the right sidebar on GitHub
106 | 2. Run `git clone https://github.com/dranem05/thinkscripts-pub.git` locally
107 | 2. Download an untracked version of these files:
108 | 1. Click on the `Download ZIP` link located on the right sidebar on GitHub
109 | 2. Unzip the dowloaded archive to a local directory
110 | 3. Download a specific script:
111 | 1. Navigate to the file on GitHub
112 | 2. Click on the source file
113 | 3. Click on `Raw` to download the file
114 |
115 | #### Installing
116 |
117 | 1. Download this project into a local directory
118 | 2. Fire up TOS
119 | 3. Open up a chart
120 | 4. Click on the `analysis tools` icon (looks like something dripping)
121 | 5. Click on `edit studies`
122 | 6. Click on `import` on the bottom of the left panel
123 | 7. Navigate to the thinkscripts directory where you dowloaded this project
124 | _It should be somewhere like: `path/to/download/thinkscripts-pub.git/thinkscipts/`_
125 | 8. Select the desired study and click open (or just double click the desired study)
126 |
127 | The script should now be available in your TOS database.
128 |
129 | #### Updating
130 |
131 | 1. Get the latest version of the script
132 | _run `git pull origin` if you created a local clone of this project_
133 | 2. Fire up TOS
134 | 3. Open up a chart
135 | 4. Click on the `analysis tools` icon (looks like something dripping)
136 | 5. Click on `edit studies`
137 | 6. Click on `import` on the bottom of the left panel
138 | 7. Navigate to the thinkscripts directory where you dowloaded this project
139 | _It should be somewhere like: `path/to/download/thinkscripts-pub.git/thinkscipts/`_
140 | 8. Select the desired study and click open (or just double click the desired study)
141 | 9. You will be asked if you really want to replace the study in TOS
142 | 10. Click on `Yes`
143 |
144 | Note, that the "latest version of the script" could be local edits you
145 | made in your local copy of the file outside of TOS. The same steps above
146 | allow you to update the TOS version of the script.
147 |
148 | #### Exporting Changes Made via TOS's ThinkScript Editor
149 |
150 | If you edit the thinkscripts via TOS, you can export these edits to your local
151 | copy of this project.
152 |
153 | 1. Navigate to the script via the `edit studies` window
154 | 2. Click on `export`
155 | 3. You will be asked where you would like the study to be exported
156 | 4. Export to your local directory of thinkscripts
157 | 5. Confirm your desire to overwrite the local copy with this new copy
158 |
159 | If your local thinkscripts directory is a git clone location, you can
160 | use it to maintain your own version controlled copy of the scripts.
161 |
162 | #### Using/Referencing in Custom Quotes and Scan Queries
163 |
164 | 1. Navigate to the `Condition Wizard` tab
165 | 1. *For [Custom Quotes][custom quote]*
166 | 1. Follow the instructions in the "How Do I Install/Update
167 | Custom Quote Scripts" section up to the step just prior
168 | to clicking on the `thinksScript Editor` tab.
169 | 2. Click on the `Condition Wizard` tab.
170 | 2. *For [Scan Query Criteria][scan_q]*
171 | 1. Click on the `Scan` tab
172 | 2. Click on `Add Study Filter`
173 | 3. Click on the study selector widget
174 | 4. Click on the `Custom...` option
175 | 2. Click on `Edit` or `Add Condition`
176 | 3. Click on the study selector widget
177 | 4. Click on the `Study` option
178 | 5. Search for the desired study
179 | 6. Update input parameters if applicable
180 | 7. Select which plot to use as the scripts _value_
181 | 8. Select your comparison operator, etc.
182 |
183 | **IMPORTANT:**
184 |
185 | Once referenced, TOS essentially creates an exact copy of the referenced
186 | script and uses this copy. Thus any changes made to the original *DOES NOT
187 | PROPAGATE* to the custom script. You have to re-reference the script
188 | to propagate any changes that were made to the original.
189 |
190 | How Do I Install/Update Custom Quote Scripts?
191 | ---------------------------------------------
192 |
193 | Downloading and getting the latest updates from this GitHub repository
194 | are the same as with the regular ThinkScripts. Installing/Updating into
195 | TOS is a bit different.
196 |
197 | #### Installing
198 |
199 | 1. Right click on a column name in a watchlist type of widget
200 | _(or nearly anything that looks like a table with columns)_
201 | 2. Click on `Customize`
202 | 3. Under the `Available Items` left side panel, search for `custom`
203 | 4. Click on the scroll icon that appears to the left of any `custom` item
204 | 5. Click on the `thinkScript Editor` tab in the window that appears
205 | 6. Copy and paste the custom quote script into this window
206 | 7. Rename the script from `Custom` to whatever you like
207 | 8. Click on `OK`
208 |
209 | #### Updating
210 |
211 | 1. Get the latest version of the script
212 | 2. Right click on a column name in a watchlist type of widget
213 | _(or nearly anything that looks like a table with columns)_
214 | 3. Click on `Customize`
215 | 4. Under the `Available Items` left side panel, search for the desired script
216 | 5. Click on the scroll icon that appears to the left of that script
217 | 6. Click on the `thinkScript Editor` tab in the window that appears
218 | 7. Copy and paste the updated code into the thinkScript Editor
219 | 8. Click on `OK`
220 |
221 | References
222 | ----------
223 | * [TOS Charting](http://tlc.thinkorswim.com/center/charting/index.html)
224 | * [thinkScript][]
225 | * [Custom Quote][]
226 |
227 | License
228 | -------
229 | Code is under the [MIT license][license].
230 |
231 | [license]:https://github.com/dranem05/thinkscripts-pub/blob/master/LICENSE
232 | [fundamental data]:http://tlc.thinkorswim.com/center/charting/thinkscript/reference/Constants/FundamentalType/index
233 | [agg_per]:http://tlc.thinkorswim.com/center/charting/thinkscript/reference/Constants/AggregationPeriod/index
234 | [custom quote]:http://tlc.thinkorswim.com/center/charting/thinkscript/thinkscript-integration/customquotes
235 | [scan_q]:http://tlc.thinkorswim.com/center/charting/thinkscript/thinkscript-integration/studyfilters
236 | [thinkscript]:http://tlc.thinkorswim.com/center/charting/thinkscript/index
237 | [script referencing]:http://tlc.thinkorswim.com/center/charting/thinkscript/tutorials/Chapter-14---Referencing-Other-Data
238 | [reference keyword]:http://tlc.thinkorswim.com/center/charting/thinkscript/reference/Reserved-Words/reference
239 |
--------------------------------------------------------------------------------
/thinkscripts/PM_PercentChg_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Percent Change\nCalculates the percent change in value from now and N periods ago where
value: any data type enumerated by FundamentalData such as CLOSE, IV, etc.N: user specified look back lengthperiod: user or chart selected aggregation period such as FIVE_MIN, DAY, WEEK, etc.
3 | #
4 | # PM Percent Change
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # This script calculates the percent change in value from now and N periods ago
9 | # where:
10 | #
11 | # value: data type enumerated by FundamentalData := CLOSE, IV, VOLUME, etc.
12 | # N: user specified look back length
13 | # period: user or chart selected aggregation period := MIN, DAY, WEEK, etc.
14 | #
15 | # This script can be used as a plot and as a label. If displayed on a lower
16 | # subgraph, the % chg and its hi and lo alert triggered instances will be
17 | # shown as it occurred over time. If 'show_label' is enabled, the most recent
18 | # % chg will be displayed on the chart. To use this script purely as a label
19 | # on the main price chart, set 'label_only' to YES in the script settings window
20 | #
21 | # This script utilized ThinkOrSwim's built-in PercentChg script and the
22 | # customizability provided in the PM_Rank script as inspiration.
23 | #
24 | # LICENSE ---------------------------------------------------------------------
25 | #
26 | # This PM_PercentChg script is free software distributed under the terms of the
27 | # MIT license reproduced here:
28 | #
29 | # The MIT License (MIT)
30 | #
31 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
32 | #
33 | # Permission is hereby granted, free of charge, to any person obtaining a copy
34 | # of this software and associated documentation files (the "Software"), to deal
35 | # in the Software without restriction, including without limitation the rights
36 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37 | # copies of the Software, and to permit persons to whom the Software is
38 | # furnished to do so, subject to the following conditions:
39 | #
40 | # The above copyright notice and this permission notice shall be included in
41 | # all copies or substantial portions of the Software.
42 | #
43 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49 | # THE SOFTWARE.
50 | #
51 | # =============================================================================
52 |
53 |
54 | input label_only = YES; #Hint label_only: use this script only as a label (supercedes 'show_label')
55 | input show_label = YES; #Hint show_label: Toggle display of a label to display the % chg value (superceded by 'label_only')
56 | input data_type = FundamentalType.CLOSE; #Hint data_type: Data on which to compute a % chg
57 | input length = 10; #Hint length: 252 ~= 12 mth
189 ~= 9 mth
126 ~= 6 mth
63 ~= 3 mth
58 | input period = AggregationPeriod.DAY; #Hint period: Must be DAY or greater for IV computations
59 | input use_chart_ap = NO; #Hint use_chart_ap: Set to YES to utilize the chart's aggregation period
60 | input high_alert = 5.0; #Hint high_alert: Percent equal to or above which to change % chg display color
61 | input low_alert = -5.0; #Hint low_alert: Percent equal to or below which to change % chg display color
62 | input multiplier = 100; #Hint multiplier: 100 turns the % chg into a percentage, 1 leaves it as a decimal
63 | input rounding = 2; #Hint rounding: Number of decimal digits to which % chg value shall round
64 | input no_nans = YES; #Hint no_nans: If YES, return the previous % chg if current data is NaN
65 |
66 | # -------------------------------------------------------------------------
67 | # Ensure Aggregation Period is supported per the Fundamental Type specified
68 | # -------------------------------------------------------------------------
69 | #
70 | # IMP_VOLATILITY does not support Aggregration periods less than 1 day.
71 | # So, display at least the daily IV value
72 |
73 | def ap_choice = if use_chart_ap then GetAggregationPeriod() else period;
74 | def ap = If( ap_choice < AggregationPeriod.DAY && FundamentalType.IMP_VOLATILITY == data_type, AggregationPeriod.DAY, ap_choice );
75 |
76 | # -------------------------------------------------------------------------
77 | # Adjust high and low alert thresholds to account for % chg multiplier
78 | # -------------------------------------------------------------------------
79 |
80 | plot pct_chg; # declare here so it appears first in strategy settings box on TOS
81 | plot hi_alert = high_alert * multiplier / 100.0;
82 | plot lo_alert = low_alert * multiplier / 100.0;
83 |
84 | # -------------------------------------------------------------------------
85 | # Compute the percent change
86 | # -------------------------------------------------------------------------
87 |
88 | # If 'no_nans' is enabled, the previously computed % chg is returned when
89 | # the fundamental data is NaN. If there is no previously computed % chg,
90 | # the value returned will be what TOS uses to initialize variables:
91 | #
92 | # 0 as of 11/4/2013.
93 | #
94 | # Otherwise, NaN will be returned when a gap is encountered.
95 | #
96 | # TODO: may need to distinguish between gap meaning no data period vs. a temporary hole in the data (like a halt)
97 |
98 | #def data = Fundamental(data_type, period=ap); #TODO: creates an array or maps 'data' to this fundamental array?
99 | #def data = close(period=ap); #TODO: creates an array or maps 'data' to this fundamental array?
100 | #def pct_chg_v = if no_nans && (IsNaN(data) or IsNaN(data[length]))
101 | # then pct_chg_v[1]
102 | # else Round(multiplier * (data / data[length] - 1), rounding);
103 |
104 | # Using 'data', whether def or plot, to reference Fundamental() does not
105 | # work as one would assume. During market hours (OnDemand or Live), the
106 | # result returned for data[N] is the same as data[0]. Whereas explicitly
107 | # doing Fundamental(dt,pd)[N] returns the actual value for N periods ago.
108 | # The same is true if we reference directly 'close', 'open', etc.
109 | #
110 | # So, we have to be explicit in code until this ThinkScript error is fixed.
111 |
112 | def pct_chg_v = if no_nans && (IsNaN(Fundamental(data_type, period=ap)) or IsNaN(Fundamental(data_type, period=ap)[length]))
113 | then pct_chg_v[1]
114 | else Round(multiplier * (Fundamental(data_type, period=ap) / Fundamental(data_type, period=ap)[length] - 1), rounding);
115 | pct_chg = pct_chg_v;
116 |
117 | # DEBUGGING TOOLS
118 | #AddLabel(1, Concat("d[0]: ", data[0]), Color.CYAN);
119 | #AddLabel(1, Concat("d[" + length + "]: ", data[length]), Color.CYAN);
120 | #AddLabel(1, Concat("c[0]: ", close(period=ap)[0]), Color.CYAN);
121 | #AddLabel(1, Concat("c[" + length + "]: ", close(period=ap)[length]), Color.CYAN);
122 | #AddLabel(1, Concat("f[0]: ", Fundamental(data_type, period=ap)[0]), Color.CYAN);
123 | #AddLabel(1, Concat("f[" + length + "]: ", Fundamental(data_type, period=ap)[length]), Color.CYAN);
124 |
125 | # -------------------------------------------------------------------------
126 | # Create visual effects, display label if requested
127 | # -------------------------------------------------------------------------
128 |
129 | # set colors based on hi and lo alert thresholds --------------------------
130 |
131 | pct_chg.DefineColor("HiAlert", Color.UPTICK);
132 | pct_chg.DefineColor("Normal" , Color.GRAY);
133 | pct_chg.DefineColor("LoAlert", Color.DOWNTICK);
134 | pct_chg.AssignValueColor( if pct_chg >= hi_alert then pct_chg.Color("HiAlert") else if pct_chg <= lo_alert then pct_chg.Color("LoAlert") else pct_chg.Color("Normal") );
135 | hi_alert.SetDefaultColor( Color.YELLOW );
136 | lo_alert.SetDefaultColor( Color.YELLOW );
137 |
138 | # select the label's prefix based on the fundamental type -----------------
139 |
140 | # cannot use switch/case as ThinkScript's fundamental types are not enums
141 |
142 | AddLabel(show_label or label_only,
143 | Concat( if data_type == FundamentalType.IMP_VOLATILITY then "IV "
144 | else if data_type == FundamentalType.OPEN then "$O "
145 | else if data_type == FundamentalType.HIGH then "$H "
146 | else if data_type == FundamentalType.LOW then "$L "
147 | else if data_type == FundamentalType.CLOSE then "PRICE "
148 | else if data_type == FundamentalType.HL2 then "$HL2 "
149 | else if data_type == FundamentalType.HLC3 then "$HLC3 "
150 | else if data_type == FundamentalType.OHLC4 then "$OHLC4 "
151 | else if data_type == FundamentalType.VWAP then "VWAP "
152 | else if data_type == FundamentalType.VOLUME then "VOLUME "
153 | else if data_type == FundamentalType.OPEN_INTEREST then "OI "
154 | else "",
155 | "%CHG("+length+") " + pct_chg),
156 | pct_chg.TakeValueColor() );
157 |
158 | # hide plots if user wants labels only ------------------------------------
159 |
160 | hi_alert.SetHiding( label_only );
161 | lo_alert.SetHiding( label_only );
162 | pct_chg.SetHiding( label_only );
--------------------------------------------------------------------------------
/thinkscripts/PM_Rank_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Rank\nCalculates the percentile rank for the current value of the selected data type (IV, Price, etc.) as it compares to its range over a user specified number of days. It is essentially (value-lowest)/(highest-lowest).\n\nThis script can be used as a plot and as a label.
3 | #
4 | # PM Rank
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # This script calculates the percentile rank for the current value of the
9 | # selected data type (IV, Price, etc.) as it compares to its range over a user
10 | # specified number of days. It is essentially (value-lowest)/(highest-lowest).
11 | #
12 | # Notes:
13 | #
14 | # > As of 2013-10-20, the TOS imp_volatility() function does not support
15 | # aggregation period's less than DAY. Thus this script defaults to DAY
16 | # if the user specifies IMP_VOLATILITY as the 'rank_type' and an
17 | # aggregation period less than DAY.
18 | #
19 | # > During market hours, whether OnDemand or Live, TOS will return real
20 | # time "tick" data for the most recent value of the Fundamental Data
21 | # Type specified, regardless of aggregation period. As a result, the
22 | # rank value will also change in real time, except for IV as described
23 | # in the previous note. In OnDemand, imp_volatility() returns NaN
24 | # whereas in Live mode, imp_volatility() returns a non-NaN value that
25 | # does change to some degree.
26 | #
27 | # > Sometimes fundamental data will be returned as NaN. As a result,
28 | # current rank will return NaN. If instead the previous valid non-NaN
29 | # rank is desired, set 'no_nan_rank' to yes (YES is the default setting)
30 | #
31 | # > The "previous valid non-NaN data" is based on the value computed for
32 | # the previous rank. Very simply, if fundamental data is NaN, then
33 | # rank[1] will be returned, otherwise (value-lowest)/(highest-lowest).
34 | # Due to initial conditions, it is possible for the first value (and
35 | # following values until non-NaN data emerges) to be zero.
36 | #
37 | # What using rank[1] means for real time streaming data (market hours
38 | # data in OnDemand mode or Live mode) depends on how the underlying
39 | # TOS ThinkScript implementation populates/grows the rank array
40 | # during this period regardless of AP.
41 | #
42 | # This script can be used as a plot and as a label. If displayed on a lower
43 | # subgraph, the rank and its hi and lo alert triggered instances will be
44 | # shown as it occurred over time. If 'show_rank_label' is enabled, the most
45 | # recent percentile rank will be displayed on the chart. To use this script
46 | # purely as a label on the main price chart, set 'label_only' to YES in the
47 | # script settings window.
48 | #
49 | # LICENSE ---------------------------------------------------------------------
50 | #
51 | # This PM_Rank script is free software distributed under the terms of the MIT
52 | # license reproduced here:
53 | #
54 | # The MIT License (MIT)
55 | #
56 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
57 | #
58 | # Permission is hereby granted, free of charge, to any person obtaining a copy
59 | # of this software and associated documentation files (the "Software"), to deal
60 | # in the Software without restriction, including without limitation the rights
61 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62 | # copies of the Software, and to permit persons to whom the Software is
63 | # furnished to do so, subject to the following conditions:
64 | #
65 | # The above copyright notice and this permission notice shall be included in
66 | # all copies or substantial portions of the Software.
67 | #
68 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74 | # THE SOFTWARE.
75 | #
76 | # =============================================================================
77 |
78 |
79 | input label_only = YES; #Hint label_only: use this script only as a label (supercedes 'show_rank_label')
80 | input show_rank_label = YES; #Hint show_rank_label: Toggle display of a label to display the rank value (superceded by 'label_only')
81 | input rank_type = FundamentalType.IMP_VOLATILITY; #Hint rank_type: Data on which to compute a percentile rank
82 | input rank_multiplier = 100; #Hint rank_multiplier: 100 turns the percentile into a percentage, 1 leaves it as a decimal
83 | input rounding = 2; #Hint rounding: Number of decimal digits to which rank value shall round
84 | input days_range = 252; #Hint days_range: 252 ~= 12 mth
189 ~= 9 mth
126 ~= 6 mth
63 ~= 3 mth
85 | input agg_per = AggregationPeriod.DAY; #Hint agg_per: Must be DAY or greater for IV computations
86 | input use_chart_ap = NO; #Hint use_chart_ap: Set to YES to utilize the chart's aggregation period and supercede 'agg_per'
87 | input no_nan_rank = YES; #Hint no_nan_rank: If YES, return the previous rank if current data is NaN
88 | input high_alert = 50; #Hint high_alert: Percent equal to or above which to change rank display color
89 | input low_alert = 50; #Hint low_alert: Percent strictly below which to change rank display color
90 |
91 | # -------------------------------------------------------------------------
92 | # Ensure Aggregation Period is supported per the Fundamental Type specified
93 | # -------------------------------------------------------------------------
94 | #
95 | # IMP_VOLATILITY does not support Aggregration periods less than 1 day.
96 | # So, display at least the daily IV value.
97 | #
98 | # TODO: Eliminate Agg Period checking code for IV once imp_vol() supports all agg periods
99 |
100 | def ap_choice = if use_chart_ap then GetAggregationPeriod() else agg_per;
101 | def ap = If( ap_choice < AggregationPeriod.DAY && FundamentalType.IMP_VOLATILITY == rank_type, AggregationPeriod.DAY, ap_choice );
102 |
103 | # -------------------------------------------------------------------------
104 | # Adjust high and low alert thresholds to account for rank multiplier
105 | # -------------------------------------------------------------------------
106 |
107 | #TODO: may need to declare rank last in order for this value to be returned as the study's value
108 |
109 | plot rank; # declare here so it appears first in strategy settings box on TOS
110 | plot hi_alert = high_alert * rank_multiplier / 100.0;
111 | plot lo_alert = low_alert * rank_multiplier / 100.0;
112 |
113 | # -------------------------------------------------------------------------
114 | # Fill gaps in the data with usable values
115 | # -------------------------------------------------------------------------
116 | #
117 | # If any NaNs are present in the data, highest/lowest functions will return NaN.
118 | # These NaNs (aka, gaps in the data) must be filled in a way that does not cause
119 | # the highest/lowest functions to return incorrect values.
120 | #
121 | # Method 1 is to fill gaps with the previous value received.
122 | #
123 | # Note:
124 | #
125 | # There are two ways this could break:
126 | #
127 | # 1 - every value is NaN
128 | #
129 | # > case is moot, can't remedy this
130 | #
131 | # 2 - first value ever is NaN and is within 'days_range' of current value
132 | #
133 | # > this becomes case 1 if every subsequent value of F(FType) is NaN
134 | # as every data[0] value will be set to data[1] which is NaN
135 | #
136 | # > the instant any non-NaN value emerges from F(FType) no other NaNs
137 | # will ever pollute the 'data' array. however any queries where
138 | # that first value is still within 'days_range' will fail with NaN
139 | # being returned as the rank value
140 |
141 | #def data = if !IsNaN(Fundamental(rank_type, period=ap)) then Fundamental(rank_type, period=ap) else data[1];
142 |
143 | # Unfortunately, the above method 1 doesn't work if 'ap'=DAY and the chart's
144 | # actual ap is less than DAY (e.g., 5 mins). This method, taken from a native
145 | # TOS ThinkScript, is technically incorrect since TOS initializes values to 0.
146 | # Normally, we aren't affected because the erroneous value falls off the edge
147 | # of our lookback period. However, this incorrectness rears its head with real
148 | # time streaming data on a 5 min chart and user ap set to DAY:
149 | #
150 | # data[1] returns 0 and lowest is permanently 0
151 | #
152 | # This difference in behavior may point to some underlying ThinkScript issue...
153 |
154 | # Method 2 is to fill gaps with saturated values.
155 | #
156 | # Since we need both high and low data, this method require storage x2.
157 | #
158 | # TODO: Figure out how to eliminate this waste of memory
159 |
160 | def gapsPeggedHi;
161 | def gapsPeggedLo;
162 |
163 | if IsNaN(Fundamental(rank_type, period = ap))
164 | {
165 | gapsPeggedHi = Double.POSITIVE_INFINITY;
166 | gapsPeggedLo = Double.NEGATIVE_INFINITY;
167 | }
168 | else
169 | {
170 | gapsPeggedHi = Fundamental(rank_type, period = ap);
171 | gapsPeggedLo = Fundamental(rank_type, period = ap);
172 | }
173 |
174 | # -------------------------------------------------------------------------
175 | # Query the high and low range of the data and compute the present rank
176 | # -------------------------------------------------------------------------
177 | #
178 | # If 'no_nan_rank' is enabled by the user, the previously computed rank
179 | # will be returned if gaps are encountered in the fundamental data. If
180 | # there is no previously computed rank, the value returned will be what
181 | # TOS uses to initialize variables: 0 as of 11/4/2013.
182 | #
183 | # Otherwise, NaN will be returned when a gap is encountered.
184 | #
185 | # TODO: may need to distinguish between gap meaning no data period vs. a temporary hole in the data (like a halt)
186 |
187 | #def lo = Lowest(data, days_range); # re-enable if 'data' becomes valid again for all scenarios
188 | #def hi = Highest(data, days_range); # re-enable if 'data' becomes valid again for all scenarios
189 | def lo = Lowest(gapsPeggedHi, days_range); # use gaps pegged hi to ensure correct selection of the min value for known data
190 | def hi = Highest(gapsPeggedLo, days_range); # use gaps pegged lo to ensure correct selection of the max value for known data
191 |
192 | # Cannot use recursion if variable is a plot. So compute using a 'def' and
193 | # copy result to a 'plot'. This is another waste of memory that only
194 | # functions to provide non-nan values if current fundamental data is NaN.
195 | #
196 | # TODO: figure out a way to eliminate this waste of space
197 |
198 | def rank_val = if IsNaN(Fundamental(rank_type, period=ap)) && no_nan_rank then rank_val[1] else Round(rank_multiplier * (Fundamental(rank_type, period=ap) - lo) / (hi - lo), rounding);
199 | rank = rank_val;
200 |
201 | # DEBUGGING TOOLS
202 | #AddLabel(1, Concat("lo: ", lo), Color.CYAN);
203 | #AddLabel(1, Concat("hi: ", hi), Color.CYAN);
204 | #AddLabel(1, Concat("d[0]: ", data[0]), Color.CYAN);
205 | #AddLabel(1, Concat("d[1]: ", data[1]), Color.CYAN);
206 | #AddLabel(1, Concat("f[0]: ", Fundamental(rank_type, period=ap)), Color.CYAN);
207 |
208 | # -------------------------------------------------------------------------
209 | # Create visual effects, display label if requested
210 | # -------------------------------------------------------------------------
211 |
212 | # set colors based on hi and lo alert thresholds --------------------------
213 |
214 | rank.DefineColor("HiAlert", Color.UPTICK); #GetColor(5)); # RED
215 | rank.DefineColor("Normal" , Color.GRAY); #GetColor(7)); # GRAY
216 | rank.DefineColor("LoAlert", Color.DOWNTICK); #GetColor(1)); # CYAN
217 | rank.AssignValueColor( if rank >= hi_alert then rank.Color("HiAlert") else if rank < lo_alert then rank.Color("LoAlert") else rank.Color("Normal") );
218 | hi_alert.SetDefaultColor( Color.YELLOW );
219 | lo_alert.SetDefaultColor( Color.YELLOW );
220 |
221 | # select the label's prefix based on the fundamental type -----------------
222 |
223 | # cannot use switch/case as ThinkScript's fundamental types are not enums
224 |
225 | AddLabel(show_rank_label OR label_only,
226 | Concat( if rank_type == FundamentalType.IMP_VOLATILITY then "IV "
227 | else if rank_type == FundamentalType.OPEN then "$O "
228 | else if rank_type == FundamentalType.HIGH then "$H "
229 | else if rank_type == FundamentalType.LOW then "$L "
230 | else if rank_type == FundamentalType.CLOSE then "PRICE "
231 | else if rank_type == FundamentalType.HL2 then "$HL2 "
232 | else if rank_type == FundamentalType.HLC3 then "$HLC3 "
233 | else if rank_type == FundamentalType.OHLC4 then "$OHLC4 "
234 | else if rank_type == FundamentalType.VWAP then "VWAP "
235 | else if rank_type == FundamentalType.VOLUME then "VOLUME "
236 | else if rank_type == FundamentalType.OPEN_INTEREST then "OI "
237 | else "",
238 | "RANK("+days_range+") " + rank),
239 | rank.TakeValueColor() );
240 |
241 | # hide plots if user wants labels only ------------------------------------
242 |
243 | hi_alert.SetHiding( label_only );
244 | lo_alert.SetHiding( label_only );
245 | rank.SetHiding( label_only );
246 |
247 |
--------------------------------------------------------------------------------
/thinkscripts/PM_Sandbox_STUDY.ts:
--------------------------------------------------------------------------------
1 | #Hint: PM Sanbox
This is a sandbox to play around with ThinkScript Code testing hint markupand again
2 |
3 | declare lower;
4 |
5 | input bogus = 0; #Hint bogus: Nothing really
6 | input dayStyle = Curve.FIRM;
7 |
8 | # ------------------------------------------------------------------
9 | # Test Referencing
10 | # ------------------------------------------------------------------
11 |
12 | #plot blah = reference My_IV_Percentile; # cannot reference user created scripts
13 | #plot blah = reference SimpleMovingAvg; # can reference builtin scripts
14 |
15 | # ------------------------------------------------------------------
16 | # Test assumptions on GetDay() and GetLastDay()
17 | # ------------------------------------------------------------------
18 |
19 | plot day = GetDay(); # gets day based on where we are in the chart
20 | plot lastDay = GetLastDay(); # returns the most recent day available in simulation time context or real time context
21 | plot diff = lastDay - day;
22 | def val;
23 |
24 | if (bogus == 0)
25 | {
26 | val = diff;
27 | }
28 | else
29 | {
30 | val = 23;
31 | }
32 |
33 | day.SetStyle( dayStyle );
34 | diff.Hide();
35 |
36 | # [PASS] GetDay() is whatever the day is based on where we are in the chart
37 | # [PASS] GetLastDay() is the most recent day based on frame of reference (simulation or real life)
38 |
39 | # ------------------------------------------------------------------
40 | # Test IV Rank Stuff
41 | # ------------------------------------------------------------------
42 |
43 | # The problem here is that the Lowest/Highest functions will return
44 | # NaN if any NaNs are present in the data, and neither has an option
45 | # to "ignore" NaNs
46 |
47 | input period = 252; # default to 60 trading days ~3 months; 252 ~= 12 months
48 | input ap = AggregationPeriod.DAY; #getAggregationPeriod();
49 | #input ap = AggregationPeriod.FIVE_MIN; #getAggregationPeriod();
50 | #def iv = imp_volatility(period=ap); # if any NANs are present in the data, highest/lowest functions will return NaN
51 | def iv = if !IsNaN(imp_volatility(period = ap)) then imp_volatility(period = ap) else 0;
52 | def iv2 = if !IsNaN(imp_volatility(period = ap)) then imp_volatility(period = ap) else iv2[1];
53 | def ivGapsPeggedHi = if IsNaN(imp_volatility(period = ap)) then Double.POSITIVE_INFINITY else imp_volatility(period = ap);
54 | def ivGapsPeggedLo = if IsNaN(imp_volatility(period = ap)) then Double.NEGATIVE_INFINITY else imp_volatility(period = ap);
55 | def lo;
56 | def hi;
57 | def use_gap = yes;
58 | #def use_gap = NO;
59 | if use_gap
60 | {
61 | lo = Lowest(ivGapsPeggedHi, period);
62 | hi = Highest(ivGapsPeggedLo, period);
63 | }
64 | else
65 | {
66 | lo = Lowest(iv2, period);
67 | hi = Highest(iv2, period);
68 | }
69 | def cv = imp_volatility(period = ap);
70 | def cvcap = imp_volatility(period = getAggregationPeriod());
71 | #plot ivp = ((cv - lo)/(hi-lo)*100);
72 | plot ivp = ((imp_volatility(period = ap) - lo) / (hi - lo) * 100); # if most recent imp_vol data is NaN, this result will be NaN
73 |
74 | AddLabel(1, Concat("iv:", iv), Color.CYAN);
75 | AddLabel(1, Concat("iv2:", iv2), Color.CYAN);
76 | AddLabel(1, Concat("cv:", cv), Color.CYAN);
77 | AddLabel(1, Concat("cvcap:", cvcap), Color.CYAN);
78 | AddLabel(1, Concat("lo:", lo), Color.CYAN);
79 | AddLabel(1, Concat("lo[3]:", lo[3]), Color.CYAN);
80 | AddLabel(1, Concat("hi:", hi), Color.CYAN);
81 | AddLabel(1, Concat("IV%:", ivp), Color.CYAN);
82 | #AddLabel(1,concat("IV%:",ivp),if ivp > 50 then Color.UPTICK else Color.DOWNTICK);
83 |
84 | # [FAIL] iv set to 0 if isNaN clobbers the data
85 | # [PASS] gapsPegged code ensures we collect the right hi and lo IV values for the specified range
86 | # [PASS] using recursive iv2[1] does not cause compilation error and also returns same needed values as gapsPegged does but with less waste of memory and coding
87 | # [FAIL] cannot obtain realtime iv changes during the trading day in OnDemand (imp_vol() function returns NaN everytime)
88 | # [PASS] can obtain realtime iv changes during the trading day in Live mode (imp_vol() function returns a non-NaN value)
89 | # [FAIL] if chart AP is less than designated AP, the iv2[1] recursive trick does not work and lowest keeps returning zero (e.g., AP = DAY and chart AP = 5 mins)
90 | # [PASS] imp_vol for aggregation period < DAY is not supported by TOS
91 |
92 |
93 | # ------------------------------------------------------------------
94 | # Test input types
95 | # ------------------------------------------------------------------
96 |
97 | input data_type = FundamentalType.IMP_VOLATILITY; # allows user to change fundamental type
98 | input data_type2 = close; # shows all fundamental types, but skips need to call Fundamental(FTYPE..) in code
99 |
100 | # [PASS] both methods show all fundamental types
101 | # [FAIL] currently no way to discern FundamentalType in code if using method 2
102 |
103 | # ------------------------------------------------------------------
104 | # Test creation of color select widget if using CreateColor
105 | # ------------------------------------------------------------------
106 |
107 | plot labelColor = 0; # only to pull in color select widget
108 | labelColor.SetHiding(1) ; #never want to show this
109 | labelColor.HideBubble();
110 | labelColor.HideTitle();
111 | labelColor.DefineColor("Up", CreateColor(255, 0, 255)); # Strong Magenta
112 | labelColor.DefineColor("Down", CreateColor(255, 100, 255)); # Weak Magenta
113 | AddLabel(1, Concat("IV% 2: ", ivp), if IsNaN(ivp) then Color.CYAN else if ivp >= 50.0 then labelColor.Color("Up") else labelColor.Color("Down"));
114 |
115 | # [PASS] Yup, this works, a color widget is made available to the user in the settings dialogue.
116 |
117 | # ------------------------------------------------------------------
118 | # Test concat
119 | # ------------------------------------------------------------------
120 |
121 | AddLabel(1, Concat(FundamentalType.HIGH, " RANK")); # This concatenates a the number to which HIGH is equal to
122 |
123 | # [FAIL] this doesn't translate HIGH into a string "HIGH", just gives the id code of HIGH
124 |
125 | # ------------------------------------------------------------------
126 | # Test Real Time Price Changes
127 | # ------------------------------------------------------------------
128 |
129 | # note:
130 | # - secondary aggregation period cannot be less than the primary aggregation period defined by chart settings
131 |
132 | def cap = getAggregationPeriod(); # get the primary aggregation period (the chart's ap)
133 | def cp = close; # implicitly call out the most recent closing price based on implicit chart ap
134 | def cpex = close(period=cap); # implicitly call out the most recent closing price based on explicit chart ap
135 | def cval = close(period=cap)[0]; # explicitly call out the most recent closing price based on explicit chart ap
136 | def pval = close(period=ap)[10]; # explicitly call out the closing price 10 periods ago based on secondary ap
137 | # Due to mixed aggregation periods, pct_chg will be computed based
138 | # on something funky. I still have yet to decipher what values it
139 | # is using, but the closest result is from AP[1]/AP[10] in OnDemand,
140 | # and CAP[0]/CAP[10] in Live mode, the latter of which is
141 | # as expected from using mixed type per thinkscript website:
142 | # http://tlc.thinkorswim.com/center/charting/thinkscript/tutorials/Chapter-12---Referencing-Secondary-Aggregation
143 | plot pct_chg = round(100 * (close(period=cap) / close(period=ap)[10] - 1),2); # computes unexpected value unless cap == ap
144 | plot pct_chg2 = round(100 * (cval / pval - 1),2); # computes desired result
145 | plot pct_chg3 = round(100 * (cp / pval - 1),2); # also computes desired result, but shouldn't according to thinkscript website
146 | plot pct_chg4 = round(100 * (cpex / pval - 1),2); # also computes desired result, but shouldn't according to thinkscript website
147 | AddLabel(1, Concat("%CHG ",pct_chg));
148 | AddLabel(1, Concat("%CHG2 ",pct_chg2));
149 | AddLabel(1, Concat("%CHG3 ",pct_chg3));
150 | AddLabel(1, Concat("%CHG3 ",pct_chg4));
151 | AddLabel(1, Concat("pri(cap) ", close(period=cap))); # at aggregation period of the chart
152 | AddLabel(1, Concat("pri(ap) ", close(period=ap))); # at aggregation period of DAY
153 | AddLabel(1, Concat("pri(ap)[1] ", close(period=ap)[1])); # at aggregation period of DAY
154 | AddLabel(1, Concat("pri(ap)[10] ", close(period=ap)[10])); # at aggregation period of DAY
155 | AddLabel(1, Concat("pri(ap)[11] ", close(period=ap)[11])); # at aggregation period of DAY
156 | AddLabel(1, Concat("pri(cap)[1] ", close(period=cap)[1])); # at aggregation period of chart
157 | AddLabel(1, Concat("pri(cap)[10] ", close(period=cap)[10])); # at aggregation period of chart
158 | AddLabel(1, Concat("pri(cap)[11] ", close(period=cap)[11])); # at aggregation period of chart
159 |
160 | # [FAIL] do not get correct pct_chg if use fundamental function directly in one line but w/ two aggregation types
161 | # [PASS] we do get correct pct_chg if use fundamental function directly and both aggregation types are equal
162 | # [PASS] we do get correct pct_chg if we use the data indirectily via explicit variables
163 | # [FAIL] expected incorrect pct_chg if did not call out explicit values we wanted in the variables
164 | # [PASS] get real time price changes in the data if Aggregation Period < DAY (i.e., 4 hrs to 1 min)
165 | # [PASS] get real time price changes in the data if aggregation period >= DAY (at least in ondemand)
166 |
--------------------------------------------------------------------------------
/thinkscripts/PM_ShowOHLC_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Show OHLC
Plots previous OHLC and today's OHL
3 | #
4 | # PM Show OHLC
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # While the market is open, this script plots Day aggregation
9 | # OHLC data for the previous day, and OHL for today. A user
10 | # can toggle which fundamental data she would like displayed.
11 | #
12 | # Today's open plot is RED when price falls below the open
13 | # and GREEN when price is at or above the open.
14 | #
15 | # Conventions:
16 | #
17 | # RT = Real Time : up-to-date context regardless of
18 | # chart time. in live market data,
19 | # this means today is actually today.
20 | # in on demand, aka simulation mode,
21 | # today is the most recent sim time.
22 | #
23 | # CT = Chart Time: historical context that bleeds into
24 | # real time once script traverses all
25 | # historical bars
26 | #
27 | # This script was adapted from the Previous Day Script written
28 | # by Justin Williams (justin@theinfinitygroup.us, @infinitycap)
29 | # which can be found here:
30 | #
31 | # http://www.shadowtrader.net/forum/viewtopic.php?f=9&t=268&sid=648ed5a68a84c1d587b3720efb2bd20f#p891
32 | #
33 | # LICENSE ---------------------------------------------------------------------
34 | #
35 | # This PM_ShowOHLC script is free software distributed under the terms of the
36 | # MIT license reproduced here:
37 | #
38 | # The MIT License (MIT)
39 | #
40 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
41 | #
42 | # Permission is hereby granted, free of charge, to any person obtaining a copy
43 | # of this software and associated documentation files (the "Software"), to deal
44 | # in the Software without restriction, including without limitation the rights
45 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46 | # copies of the Software, and to permit persons to whom the Software is
47 | # furnished to do so, subject to the following conditions:
48 | #
49 | # The above copyright notice and this permission notice shall be included in
50 | # all copies or substantial portions of the Software.
51 | #
52 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58 | # THE SOFTWARE.
59 | #
60 | # ======================================================
61 |
62 | # TODO: show plot line bubbles at an earlier time so they don't block regular trading hours data
63 | # TODO: figure out to do overnight high and low
64 | # TODO: /ES close("DAY")[1] returns close(16:45) EST, but that is extended hours. reg hrs close is 16:15, adjust so we get 16:15 EST value. note this will affect all HLC fundamental data since price can exceed any of those in the 16:15-16:45 period
65 | # TODO: assess merits of the plotLiveHoursOnly option; implement if useful
66 | input prevDayPlotStartTime = 0530; #Hint prevDayPlotStartTime: time (EST) when previous OHLC data should begin plotting
67 | input marketOpenTime = 0930; #Hint marketOpenTime: time (EST) for start of regular trading hours
68 | input marketCloseTime = 1600; #Hint marketCloseTime: time (EST) for end of regular trading hours
69 |
70 | #input plotLiveHoursOnly = YES; #Hint plotLiveHoursOnly: Toggle plotting for current day only (YES) or all days (NO)
71 |
72 | input showPrevBubbles = NO; #Hint showPrevBubbles: Enable/Disable bubble on previous day plots
73 | # TODO: assess merits of showing day bubbles; impement if useful
74 | #input showDayBubbles = NO; #Hint showDayBubbles: Enable/Disable bubble on today's plots
75 | input showOvernightBubbles = NO; #Hint showOvernightBubbles: Enable/Disable bubble on overnight plots
76 |
77 | input showPreviousDay = YES; #Hint showPreviousDay: Enable/Disable display of previous OHLC data
78 | input showPreviousOpen = NO; #Hint showPreviousOpen: Toggle display of previous Open if showPreviousDay is True
79 | input showPreviousHigh = YES; #Hint showPreviousHigh: Toggle display of previous High if showPreviousDay is True
80 | input showPreviousLow = YES; #Hint showPreviousLow: Toggle display of previous Low if showPreviousDay is True
81 | input showPreviousClose = NO; #Hint showPreviousClose: Toggle display of previous Close if showPreviousDay is True
82 | input previousStyle = Curve.FIRM;
83 |
84 | input showOvernight = YES; #Hint showOvernight: Enable/Disable display of extended hours OHLC
85 | input showONHigh = YES; #Hint showONHigh: Toggle display of overnight High if showOvernight is True
86 | input showONLow = YES; #Hint showONLow: Toggle display of overnight Low if showOvernight is True
87 |
88 | input showDay = YES; #Hint showDay: Enable/Disable display of day OHL data
89 | input showDayOpen = YES; #Hint showDayOpen: Toggle display of the day's Open if showDay is True
90 | input showDayHigh = YES; #Hint showDayHigh: Toggle display of the day's High if showDay is True
91 | input showDayLow = YES; #Hint showDayLow: Toggle display of the day's Low if showDay is True
92 | input dayStyle = Curve.LONG_DASH;
93 |
94 |
95 | def mostRecentDay_RT = GetLastDay(); #TODO: make configurable to other Aggregation Periods
96 | def currentDay_CT = GetDay(); #TODO: make configurable to other Aggregation Periods
97 | def CTDayIsCurrent = currentDay_CT == mostRecentDay_RT;
98 | def marketIsOpen = 0 <= SecondsFromTime( marketOpenTime ) && SecondsTillTime( marketCloseTime ) > 0;
99 | def ap = AggregationPeriod.DAY; #TODO: make an input
100 |
101 | plot ohlc_colors; # phantom plot to trick TOS platform, details in look and feel section below
102 | plot prevOpen;
103 | plot prevHigh;
104 | plot prevLow;
105 | plot prevClose;
106 | #plot onHigh; # overnight high
107 | #plot onLow; # overnight low
108 | plot dayOpen;
109 | plot dayHigh;
110 | plot dayLow;
111 |
112 | #plot dbg;
113 |
114 | # ------------------------------------------------------
115 | # Collect OHLC data
116 | # ------------------------------------------------------
117 |
118 | if CTDayIsCurrent && marketIsOpen
119 | {
120 | prevOpen = open( period = ap )[1];
121 | prevHigh = high( period = ap )[1];
122 | prevLow = low( period = ap )[1];
123 | prevClose = close( period = ap )[1];
124 | dayOpen = open( period = ap );
125 | dayHigh = high( period = ap );
126 | dayLow = low( period = ap );
127 | }
128 | else
129 | {
130 | #if ( CTDayIsCurrent || not plotLiveHoursOnly ) &&
131 | # ( 0 <= SecondsFromTime( prevDayPlotStartTime ) && SecondsTillTime( marketCloseTime ) > 0 )
132 | if ( CTDayIsCurrent && 0 <= SecondsFromTime( prevDayPlotStartTime ) && SecondsTillTime( marketCloseTime ) > 0 )
133 | {
134 | # Previous data plots only when we are in the current day in RT context (live or simulated)
135 | prevOpen = open( period = ap )[1];
136 | prevHigh = high( period = ap )[1];
137 | prevLow = low( period = ap )[1];
138 | prevClose = close( period = ap )[1];
139 | }
140 | else
141 | {
142 | prevOpen = Double.NaN;
143 | prevHigh = Double.NaN;
144 | prevLow = Double.NaN;
145 | prevClose = Double.NaN;
146 | }
147 | dayOpen = Double.NaN;
148 | dayHigh = Double.NaN;
149 | dayLow = Double.NaN;
150 | }
151 |
152 | #if CTDayIsCurrent
153 | #{
154 | # if SecondsTillTime( marketOpenTime ) > 0
155 | # {
156 | # dbg = high( period = ap );
157 | # }
158 | # else
159 | # {
160 | # dbg = CompoundValue( 1, dbg, Double.NaN);
161 | # }
162 | #}
163 | #else
164 | #{
165 | # dbg = dbg;
166 | #}
167 |
168 | #dbg.AssignValueColor( Color.RED );
169 |
170 | # ------------------------------------------------------
171 | # Hiding
172 | # ------------------------------------------------------
173 |
174 | prevOpen.SetHiding( !(showPreviousDay && showPreviousOpen ) );
175 | prevHigh.SetHiding( !(showPreviousDay && showPreviousHigh ) );
176 | prevLow.SetHiding( !(showPreviousDay && showPreviousLow ) );
177 | prevClose.SetHiding( !(showPreviousDay && showPreviousClose) );
178 |
179 | dayOpen.SetHiding( !(showDay && showDayOpen) );
180 | dayHigh.SetHiding( !(showDay && showDayHigh) );
181 | dayLow.SetHiding( !(showDay && showDayLow ) );
182 |
183 | #prevOpen.HideBubble();
184 | #prevHigh.HideBubble();
185 | #prevLow.HideBubble();
186 | #prevClose.HideBubble();
187 | #dayOpen.HideBubble();
188 | #dayHigh.HideBubble();
189 | #dayLow.HideBubble();
190 |
191 | # ------------------------------------------------------
192 | # Set plot look and feel
193 | # ------------------------------------------------------
194 |
195 | #def isMarketCloseTime = secondsFromTime( marketCloseTime ) == 0 && secondsTillTime( marketCloseTime ) == 0;
196 | def isMarketOpenTime = SecondsFromTime( marketOpenTime ) == 0 && SecondsTillTime( marketOpenTime ) == 0;
197 | def prevBubbleIsEnabled = isMarketOpenTime && showPrevBubbles;
198 | #def dayBubbleIsEnabled = isMarketOpenTime && showDayBubbles;
199 |
200 | # Create phantom plot to facilitate user color selection
201 |
202 | ohlc_colors = 0; # signals TOS platform to display color select widget
203 | ohlc_colors.SetHiding(1); # never needs to be displayed on a chart
204 | ohlc_colors.HideBubble();
205 | ohlc_colors.HideTitle();
206 |
207 | # Open Plot Look & Feel --------------------------------
208 |
209 | prevOpen.AssignValueColor( Color.DARK_GRAY ); # Strong Gray
210 | prevOpen.SetStyle( previousStyle );
211 | dayOpen.AssignValueColor( if close >= dayOpen then Color.GREEN else Color.RED );
212 | dayOpen.SetStyle( Curve.MEDIUM_DASH );
213 | AddChartBubble( !IsNaN( prevOpen ) && prevBubbleIsEnabled && showPreviousDay && showPreviousOpen,
214 | prevOpen, "PO", prevOpen.TakeValueColor() );
215 |
216 | # High Plot Look & Feel --------------------------------
217 |
218 | ohlc_colors.DefineColor("PH", CreateColor(255, 255, 0) ); # Strong Yellow
219 | ohlc_colors.DefineColor("H" , CreateColor(255, 255, 100) ); # Weak Yellow
220 |
221 | prevHigh.AssignValueColor( ohlc_colors.Color("PH") );
222 | dayHigh.AssignValueColor( ohlc_colors.Color("H" ) );
223 | prevHigh.SetStyle( previousStyle );
224 | dayHigh.SetStyle( dayStyle );
225 | AddChartBubble( !IsNaN( prevHigh ) && prevBubbleIsEnabled && showPreviousDay && showPreviousHigh,
226 | prevHigh, "PH", prevHigh.TakeValueColor() );
227 |
228 | # Low Plot Look & Feel ---------------------------------
229 |
230 | ohlc_colors.DefineColor("PL", CreateColor(255, 0, 255)); # Strong Magenta
231 | ohlc_colors.DefineColor("L" , CreateColor(255, 100, 255)); # Weak Magenta
232 |
233 | prevLow.AssignValueColor( ohlc_colors.Color("PL") );
234 | dayLow.AssignValueColor( ohlc_colors.Color("L" ) );
235 | prevLow.SetStyle( previousStyle );
236 | dayLow.SetStyle( dayStyle );
237 | AddChartBubble( !IsNaN( prevLow ) && prevBubbleIsEnabled && showPreviousDay && showPreviousLow,
238 | prevLow , "PL", prevLow.TakeValueColor(), no );
239 |
240 | # Close Plot Look & Feel -------------------------------
241 |
242 | prevClose.AssignValueColor( Color.DARK_ORANGE ); # Strong Orange
243 | prevClose.SetStyle( previousStyle );
244 | AddChartBubble( !IsNaN( prevClose ) && prevBubbleIsEnabled && showPreviousDay && showPreviousClose,
245 | prevClose, "PC", prevClose.TakeValueColor() );
--------------------------------------------------------------------------------
/thinkscripts_cq/PM_IV_Rank_CQ_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM IV Rank CQ\nCalculates the IV percentile rank over 252 trading days. Distilled version intended for custom quote thinkscript. Copy and paste this into the Custom Quote thinkscript code area.
3 | #
4 | # PM IV Rank CQ
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # Calculates the IV percentile rank over 252 trading days. Distilled version
9 | # intended for custom quote thinkscript. Copy and paste this into the Custom
10 | # Quote thinkscript code area. Note, this script colors the value based on
11 | # where it lays within the rank. Edit the lookback period and rank coloring
12 | # thresholds to fit your needs.
13 | #
14 | # LICENSE ---------------------------------------------------------------------
15 | #
16 | # This PM_IV_Rank_CQ script is free software distributed under the terms of the
17 | # MIT license reproduced here:
18 | #
19 | # The MIT License (MIT)
20 | #
21 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
22 | #
23 | # Permission is hereby granted, free of charge, to any person obtaining a copy
24 | # of this software and associated documentation files (the "Software"), to deal
25 | # in the Software without restriction, including without limitation the rights
26 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 | # copies of the Software, and to permit persons to whom the Software is
28 | # furnished to do so, subject to the following conditions:
29 | #
30 | # The above copyright notice and this permission notice shall be included in
31 | # all copies or substantial portions of the Software.
32 | #
33 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 | # THE SOFTWARE.
40 | #
41 | # =============================================================================
42 |
43 | #Wizard input: length
44 | #TODO: 2013-11-09 wizard keywords don't yet work in user created scripts, only builtin scripts
45 |
46 | #input data = imp_volatility; #TODO: 2013-11-09 Bug in TOS won't let this work, must use DEF for now
47 | def data = imp_volatility;
48 | input length = 252; #Hint length: 252 ~= 12 mth | 189 ~= 9 mth | 126 ~= 6 mth | 63 ~= 3 mth
49 | #def data_ = if !isNaN(data) then data else data_[1];
50 | def pegHi = if !isNaN(data) then data else Double.POSITIVE_INFINITY; # saturate gaps hi
51 | def pegLo = if !isNaN(data) then data else Double.NEGATIVE_INFINITY; # saturate gaps lo
52 | def hi = highest(pegLo,length);
53 | def lo = lowest(pegHi,length);
54 | plot perct = round((data - lo)*100 / (hi - lo),1); # fits column better at 1 sig.dig
55 | #def perct = if isNaN(data) then perct[1] else round((data - lo)*100 / (hi - lo),1);
56 | #plot rank = perct;
57 | perct.AssignValueColor( if 70 <= perct then Color.GREEN
58 | else if 50 <= perct and perct < 70 then Color.YELLOW
59 | else if 10 <= perct and perct < 50 then Color.GRAY
60 | else if perct < 10 then Color.RED
61 | else Color.GRAY
62 | );
63 |
--------------------------------------------------------------------------------
/thinkscripts_cq/PM_PercentChg_CQ_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Percent Change CQ\nCalculates the percent change in value from now and N days ago and colors the result based on user designated hi and lo alert thresholds. Distilled version intended for custom quote thinkscript. Copy an paste this into the Custom Quote thinkscript code area.
3 | #
4 | # PM Percent Change CQ
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # Calculates the percent change in value from now and N days ago and colors the
9 | # result based on user designated hi and lo alert thresholds. Distilled version
10 | # intended for custom quote thinkscript. Copy an paste this into the Custom
11 | # Quote thinkscript code area. Edit the data type, lookback period, and alert
12 | # thresholds to fit your needs.
13 | #
14 | # LICENSE ---------------------------------------------------------------------
15 | #
16 | # This PM_PercentChg_CQ script is free software distributed under the terms of
17 | # the MIT license reproduced here:
18 | #
19 | # The MIT License (MIT)
20 | #
21 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
22 | #
23 | # Permission is hereby granted, free of charge, to any person obtaining a copy
24 | # of this software and associated documentation files (the "Software"), to deal
25 | # in the Software without restriction, including without limitation the rights
26 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 | # copies of the Software, and to permit persons to whom the Software is
28 | # furnished to do so, subject to the following conditions:
29 | #
30 | # The above copyright notice and this permission notice shall be included in
31 | # all copies or substantial portions of the Software.
32 | #
33 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 | # THE SOFTWARE.
40 | #
41 | # =============================================================================
42 |
43 | #Wizard input: data
44 | #Wizard input: length
45 | #Wizard input: hi_alert
46 | #Wizard input: lo_alert
47 | #Wizard input: rounding
48 | #TODO: 2013-12-13 wizard keywords don't yet work in user created scripts, only builtin scripts
49 |
50 | #TODO: 2013-12-13 Adjust high and low alert for each stock as a function of SPY
51 |
52 | input data = close; #Hint data_type: Data on which to compute a % chg
53 | input length = 10; #Hint length: 252 ~= 12 mth
189 ~= 9 mth
126 ~= 6 mth
63 ~= 3 mth
54 | input hi_alert = 5.0; #Hint high_alert: Percent equal to or above which to change % chg display color
55 | input lo_alert = -5.0; #Hint low_alert: Percent equal to or below which to change % chg display color
56 | input rounding = 1; #Hint rounding: Number of decimal digits to which % chg value shall round
57 | plot pct_chg = Round(100 * (data / data[length] - 1), rounding);
58 | pct_chg.AssignValueColor( if pct_chg >= hi_alert then Color.UPTICK
59 | else if pct_chg <= lo_alert then Color.DOWNTICK
60 | else Color.GRAY
61 | );
62 |
--------------------------------------------------------------------------------
/thinkscripts_cq/PM_Price_Rank_CQ_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Price Rank CQ\nCalculates the price percentile rank over 252 trading days. Distilled version intended for custom quote thinkscript. Copy and paste this into the Custom Quote thinkscript code area.
3 | #
4 | # PM Price Rank CQ
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # Calculates the price percentile rank over 252 trading days. Distilled version
9 | # intended for custom quote thinkscript. Copy and paste this into the Custom
10 | # Quote thinkscript code area. Note, this script colors the value based on
11 | # where it lays within the rank. Edit the lookback period and rank coloring
12 | # thresholds to fit your needs.
13 | #
14 | # LICENSE ---------------------------------------------------------------------
15 | #
16 | # This PM_Price_Rank_CQ script is free software distributed under the terms of
17 | # the MIT license reproduced here:
18 | #
19 | # The MIT License (MIT)
20 | #
21 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
22 | #
23 | # Permission is hereby granted, free of charge, to any person obtaining a copy
24 | # of this software and associated documentation files (the "Software"), to deal
25 | # in the Software without restriction, including without limitation the rights
26 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 | # copies of the Software, and to permit persons to whom the Software is
28 | # furnished to do so, subject to the following conditions:
29 | #
30 | # The above copyright notice and this permission notice shall be included in
31 | # all copies or substantial portions of the Software.
32 | #
33 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 | # THE SOFTWARE.
40 | #
41 | # =============================================================================
42 |
43 | #Wizard input: data
44 | #Wizard input: length
45 | #TODO: 2013-11-09 wizard keywords don't yet work in user created scripts, only builtin scripts
46 |
47 | input data = close;
48 | input length = 252; #Hint length: 252 ~= 12 mth | 189 ~= 9 mth | 126 ~= 6 mth | 63 ~= 3 mth
49 | #def data_ = if !isNaN(data) then data else data_[1];
50 | def pegHi = if !isNaN(data) then data else Double.POSITIVE_INFINITY; # saturate gaps hi
51 | def pegLo = if !isNaN(data) then data else Double.NEGATIVE_INFINITY; # saturate gaps lo
52 | def hi = highest(pegLo,length);
53 | def lo = lowest(pegHi,length);
54 | plot perct = round((data - lo)*100 / (hi - lo),1); # fits column better at 1 sig.dig
55 | #def perct = if isNaN(data) then perct[1] else round((data - lo)*100 / (hi - lo),1);
56 | #plot rank = perct;
57 | perct.AssignValueColor( if 70 <= perct then Color.GREEN
58 | else if 50 <= perct and perct < 70 then Color.YELLOW
59 | else if 10 <= perct and perct < 50 then Color.GRAY
60 | else if perct < 10 then Color.RED
61 | else Color.GRAY
62 | );
63 |
--------------------------------------------------------------------------------
/thinkscripts_cq/PM_Rank_CQ_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Rank CQ\nCalculates the percentile rank over 252 trading days for desired fundamental data (IV, O, H, L, C, Volume, etc.). Distilled version intended for custom quote thinkscript. Copy and paste this into the Custom Quote thinkscript code area.
3 | #
4 | # PM Rank CQ
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # Calculates the percentile rank over 252 trading days for desired fundamental
9 | # data (IV, O, H, L, C, Volume, etc.). Distilled version intended for custom
10 | # quote thinkscript. Copy and paste this into the Custom Quote thinkscript code
11 | # area. Note, this script colors the value based on where it lays within the
12 | # rank. Edit the input data source or the lookback period and rank coloring
13 | # thresholds to fit your needs.
14 | #
15 | # Once TOS enables user created scripts to utilize the Wizard keywords, this
16 | # single script can be used in multiple custom quote or scan queries for
17 | # different desired fundamental data. As of 2013-11-09, the only workaround
18 | # is to reference this script as a CONDITION in the Conditional Wizard tab
19 | # and then augment the thinkscript in the thinkScript Editor tab to do
20 | # coloring, etc.
21 | #
22 | # IMPORTANT: Once referenced, TOS essentially creates an exact copy of the
23 | # referenced script and uses this copy. Thus any changes made to the original
24 | # DOES NOT PROPAGATE to the custom script. You have to re-reference the script
25 | # to propagate any changes that were made to the original.
26 | #
27 | # LICENSE ---------------------------------------------------------------------
28 | #
29 | # This PM_Rank_CQ script is free software distributed under the terms of the
30 | # MIT license reproduced here:
31 | #
32 | # The MIT License (MIT)
33 | #
34 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
35 | #
36 | # Permission is hereby granted, free of charge, to any person obtaining a copy
37 | # of this software and associated documentation files (the "Software"), to deal
38 | # in the Software without restriction, including without limitation the rights
39 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | # copies of the Software, and to permit persons to whom the Software is
41 | # furnished to do so, subject to the following conditions:
42 | #
43 | # The above copyright notice and this permission notice shall be included in
44 | # all copies or substantial portions of the Software.
45 | #
46 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52 | # THE SOFTWARE.
53 | #
54 | # =============================================================================
55 |
56 | #Wizard input: data
57 | #Wizard input: length
58 | #TODO: 2013-11-09 wizard keywords don't yet work in user created scripts, only builtin scripts
59 |
60 | input data = close; #Hint data: change to desired fundamental data (IV, close, volume, etc.)
61 | input length = 252; #Hint length: 252 ~= 12 mth | 189 ~= 9 mth | 126 ~= 6 mth | 63 ~= 3 mth
62 | #def data_ = if !isNaN(data) then data else data_[1];
63 | def pegHi = if !isNaN(data) then data else Double.POSITIVE_INFINITY; # saturate gaps hi
64 | def pegLo = if !isNaN(data) then data else Double.NEGATIVE_INFINITY; # saturate gaps lo
65 | def hi = highest(pegLo,length);
66 | def lo = lowest(pegHi,length);
67 | plot perct = round((data - lo)*100 / (hi - lo),1); # fits column better at 1 sig.dig
68 | #def perct = if isNaN(data) then perct[1] else round((data - lo)*100 / (hi - lo),1);
69 | #plot rank = perct;
70 |
71 | # Comment out the code below if only ever using this script as a reference in
72 | # custom quotes since this will execute but not do anything as a reference.
73 | perct.AssignValueColor( if 70 <= perct then Color.GREEN
74 | else if 50 <= perct and perct < 70 then Color.YELLOW
75 | else if 10 <= perct and perct < 50 then Color.GRAY
76 | else if perct < 10 then Color.RED
77 | else Color.GRAY
78 | );
79 |
--------------------------------------------------------------------------------
/thinkscripts_cq/PM_Rank_Coloring_CQ_STUDY.ts:
--------------------------------------------------------------------------------
1 | # =============================================================================
2 | #Hint: PM Rank Coloring CQ\nExample script to color output for custom quotes. Copy and paste this into the Custom Quote thinkscript code area.
3 | #
4 | # PM Rank Coloring CQ
5 | #
6 | # @author: Patrick Menard, @dranem05, dranem05@alum.mit.edu
7 | #
8 | # Example script to color output for custom quotes. Copy and paste this into
9 | # the Custom Quote thinkscript code area.
10 | #
11 | # LICENSE ---------------------------------------------------------------------
12 | #
13 | # This PM_Rank_Coloring_CQ script is free software distributed under the terms
14 | # of the MIT license reproduced here:
15 | #
16 | # The MIT License (MIT)
17 | #
18 | # Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
19 | #
20 | # Permission is hereby granted, free of charge, to any person obtaining a copy
21 | # of this software and associated documentation files (the "Software"), to deal
22 | # in the Software without restriction, including without limitation the rights
23 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 | # copies of the Software, and to permit persons to whom the Software is
25 | # furnished to do so, subject to the following conditions:
26 | #
27 | # The above copyright notice and this permission notice shall be included in
28 | # all copies or substantial portions of the Software.
29 | #
30 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 | # THE SOFTWARE.
37 | #
38 | # =============================================================================
39 |
40 | #Wizard input: data
41 | #Wizard input: length
42 | #plot rank = PM_Rank_CQ_(data, length);
43 | # TODO: 2013-11-09 wizard keywords don't yet work in user created scripts, only builtin scripts
44 | # TODO: 2013-11-09 directly referencing user created scripts via the reference keyword don't yet work on TOS
45 |
46 | plot rank = PM_Rank_CQ();
47 | rank.AssignValueColor( if 70 <= rank then Color.GREEN
48 | else if 50 <= rank and rank < 70 then Color.YELLOW
49 | else if 10 <= rank and rank < 50 then Color.GRAY
50 | else if rank < 10 then Color.RED
51 | else Color.GRAY
52 | );
53 |
--------------------------------------------------------------------------------