├── .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 length
  • period: 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 markup
  • and 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 | --------------------------------------------------------------------------------