├── .gitattributes ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md └── scripts ├── ATRLabelSTUDY.ts ├── ATRPercentSTUDY.ts ├── ATRWithGapUpIndicatorSTUDY.ts ├── AccumulationDayPercentGainThresholdSTUDY.ts ├── AccumulationDistributionBarCountBreakoutSTUDY.ts ├── AccumulationDistributionBarCountMSSTUDY.ts ├── AccumulationDistributionBarCountSTUDY.ts ├── BuyableGapUpIndicatorSTUDY.ts ├── ClosePercentOfRangeSTUDY.ts ├── CoppockIndicatorSTUDY.ts ├── CumulativeIntradayVolumePercentChangeLabelSTUDY.ts ├── CumulativeIntradayVolumePercentChangeSTUDY.ts ├── DailyEMASTUDY.ts ├── EarningsPerShareSTUDY.ts ├── ExchangeListedNetHighLowSTUDY.ts ├── MinorHighLowIndicatorSTUDY.ts ├── PocketPivotSTUDY.ts ├── PocketPivotStrategyLESTRATEGY.ts ├── PocketPivotStrategyLXSTRATEGY.ts ├── RelativeStrengthWithNewHighIndicatorsSTUDY.ts ├── TwelveOfFifteenUpSTUDY.ts ├── UpDownVolumeRatioSTUDY.ts └── VolumePercentChangeFromAverageSTUDY.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.ts linguist-language=thinkScript 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ThinkOrSwimStudies 2 | 3 | Copyright 2014-2021 Scott J. Johnson (https://scottjjohnson.com) 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ThinkOrSwimStudies 2 | 3 | This project contains scripts that define new studies for use with TD Ameritrade's [ThinkOrSwim Desktop trading platform](https://www.tdameritrade.com/tools-and-platforms/thinkorswim/desktop.page). 4 | 5 | ## Features 6 | 7 | The scripts include: 8 | 9 | * AccumulationDayPercentGainThreshold - Tracks the minimum percent price gain required for an Accumulation Day per Market School rules. 10 | 11 | * AccumulationDistributionBarCount - Creates a chart of the count of days/weeks showing institutional accumulation and distribution. This is useful for measuring total accumulation/distribution in a base. 12 | 13 | * ATRLabel - Adds a label to a chart showing the average true range and current period range. 14 | 15 | * ATRPercent - Displays a chart showing the Average True Range over time as a percent of price. 16 | 17 | * ATRWithGapUpIndicator - Displays a chart showing the Average True Range over time as a percent of price. Large gaps up are highlighted in green. 18 | 19 | * BuyableGapUpIndicator - Adds a chart bubble indicating past buyable gaps-up. 20 | 21 | * ClosePercentOfRange - Displays a bar chart of the close price relative to the period's price range. 22 | 23 | * CoppockIndicator - Displays a chart of Coppock Indicator with bubbles at each buy signal. 24 | 25 | * CumulativeIntradayVolumePercentChange - Displays a chart of the percent change in volume since 1 market session ago. Intended to be used with volume symbols like $TVOLC/Q (NASDAQ Composite Total Volume) or $TVOLC (NYSE Composite Total volume). 26 | 27 | * CumulativeIntradayVolumePercentChangeLabel - Same as CumulativeIntradayVolumePercentChange except instead of a chart, the current value is written to label. 28 | 29 | * DailyEMA - Displays a chart of the Exponential Moving Average of the day's closing price. 30 | 31 | * EarningsPerShare - Displays a chart of a stock's Earnings Per Share. 32 | 33 | * ExchangeListedNetHighLow - Shows the number of new 52-week highs minus new 52-week lows by day for the selected exchange. 34 | 35 | * MinorHighLowIndicator - Adds a bubble when the day's high/low are the highest high/lowest low the past/future 9 sessions. 36 | 37 | * PocketPivot - Adds a bubble on the daily chart when the stock had a Pocket Pivot buy point. 38 | 39 | * RelativeStrengthWithNewHighIndicators - Displays a chart comparing price performance between two symbols. Useful for comparing one symbol to an index, for example. New High indicators are dots when relative strength is currently making a new high and relative strength made a new high before price. 40 | 41 | * TwelveOfFifteenUp - Adds a wedge on top of a candle where closing price was higher than the previous candle for at least 12 of last 15 candles. 42 | 43 | * UpDownVolumeRatio - Displays a chart of the ratio of the volume on up days versus down days. 44 | 45 | * VolumePercentChangeFromAverage - Displays a chart of the current period volume as a percentage of the 50-day moving average volume. 46 | 47 | The complete source code is available on GitHub: 48 | 49 | https://github.com/sjjohns/ThinkOrSwimStudies 50 | 51 | ## Disclaimer 52 | 53 | I (Scott Johnson) am not a certified financial advisor. I am not recommending any financial instruments to buy or sell. This project (ThinkOrSwimStudies) is for informational purposes only. It is not investment advice. Use this project at your own risk. All investing has a substantial risk of big losses. 54 | -------------------------------------------------------------------------------- /scripts/ATRLabelSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # ATRLabel 19 | # 20 | # Displays Average True Range over the last 40 periods and the current period 21 | # 22 | input ATRLength = 40; 23 | 24 | # historical ATR 25 | def ATRValue = Average(TrueRange(high, close, low), ATRLength); 26 | def ATRPercent = ATRValue / close * 100; 27 | 28 | # current period range 29 | def ATRLastBar = TrueRange(high, close, low); 30 | 31 | AddLabel(yes, ATRLength + " Period ATR = $" + Round(ATRValue, 2) + " (" + Round(ATRPercent, 2) + "%), Current Period Range = $" + Round(ATRLastBar, 2) + " (" + Round(ATRLastBar / close * 100, 2) + "%)", CreateColor(153, 153, 0)); 32 | -------------------------------------------------------------------------------- /scripts/ATRPercentSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2023 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # ATRPercent 19 | # 20 | # Calculates the ATR as a percentage of the closing price. 21 | # 22 | declare lower; 23 | 24 | input ATRLength = 40; 25 | input ATRPctMinBuyable = 1.90; # minimum ATR for stock to be buyable 26 | 27 | plot ATRPct = Round(Average(TrueRange(high, close, low)/close[1], ATRLength) * 100,2); 28 | ATRPct.SetPaintingStrategy(PaintingStrategy.HISTOGRAM); 29 | ATRPct.AssignValueColor(if ATRPct >= ATRPctMinBuyable then Color.GREEN else Color.RED); 30 | 31 | plot minBuyableLine = ATRPctMinBuyable; 32 | minBuyableLine.SetDefaultColor(Color.WHITE); 33 | 34 | -------------------------------------------------------------------------------- /scripts/ATRWithGapUpIndicatorSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # ATRWithGapUpIndicator 19 | # 20 | # Calculates the ATR and shows an indicator if there was a significant gap up 21 | # at the open. A gap up may be buyable if the opening gap up is > 75% of 40 22 | # period ATR and the volume >= 150% of the average volume over the last 40 23 | # sessions. 24 | # 25 | declare lower; 26 | 27 | input ATRLength = 40; 28 | input MinimumPercentGap = 75; # percent of average true range required to be a gap 29 | 30 | def ATR = Average(TrueRange(high, close, low), ATRLength); 31 | def GapUp = (open - high[1]); 32 | def GapUpEvent = GapUp >= ATR[1] * MinimumPercentGap / 100; 33 | 34 | plot Display = Round(ATR, 2); 35 | Display.AssignValueColor(if GapUpEvent >= 1 then Color.GREEN else Color.LIGHT_GRAY); 36 | Display.SetLineWeight(3); 37 | -------------------------------------------------------------------------------- /scripts/AccumulationDayPercentGainThresholdSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # AccumulationDayPercentGainThreshold 19 | # 20 | # Based on Market School rules, the minimum gain necessary for an Accumulation 21 | # Day as determined by the average gain on up days for the last 200 market 22 | # days. 23 | # 24 | declare lower; 25 | input Period = 200; 26 | 27 | def Up = If(close > close[1], (close - close[1])/close*100, 0); 28 | def Count = If(close > close[1], 1, 0); 29 | 30 | def UpTotalGain = Sum(Up, Period); 31 | def UpTotalDays = Sum(Count, Period); 32 | def AvgGainPct = UpTotalGain/UpTotalDays; 33 | 34 | def MinPctGain; 35 | 36 | if (AvgGainPct < 0.4) { 37 | MinPctGain = 0.7; 38 | } else if (AvgGainPct >= 0.4 and AvgGainPct < 0.55) { 39 | MinPctGain = 0.85; 40 | } else if (AvgGainPct >= 0.55 and AvgGainPct < 1.0) { 41 | MinPctGain = 1.0; 42 | } else if (AvgGainPct >= 1.0) { 43 | MinPctGain = 1.245; 44 | } else { 45 | MinPctGain = Double.NAN; 46 | } 47 | 48 | plot MinPctGainPlot = MinPctGain; 49 | MinPctGainPlot.AssignValueColor(Color.CYAN); 50 | MinPctGainPlot.SetLineWeight(3); 51 | 52 | plot AvgGainPlot = AvgGainPct; 53 | AvgGainPlot.AssignValueColor(Color.YELLOW); 54 | AvgGainPlot.SetLineWeight(2); 55 | AvgGainPlot.Hide(); # clutters chart so hide by default 56 | 57 | 58 | -------------------------------------------------------------------------------- /scripts/AccumulationDistributionBarCountBreakoutSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # AccumulationDistributionBarCountBreakout 19 | # 20 | # Counts the instances of accumulation and distribution in a stock over a 21 | # period of time. Based on Mike Scott's presentation at the IBD National Meetup 22 | # in May 2014. 23 | # http://ibdtv.investors.com/national-meetup-events/699580-.aspx 24 | # 25 | # I've tweaked the logic and parameters based on additional research. 26 | # 27 | # This study differs from AccumulationDistributionBarCount in that this one displays 28 | # separate counts for accumulation days, distribution days, and net accumulation/ 29 | # distribution (positive count - negative count). 30 | # 31 | # This study is designed to be applied with the aggregation period of days or weeks. 32 | # 33 | declare lower; 34 | 35 | input AvgVolumePeriod = 50; 36 | 37 | # 50 day average volume 38 | def AvgVolume = Average(volume, AvgVolumePeriod); 39 | 40 | # accumulation/distribution count 41 | def BarCountDataPos; 42 | def BarCountDataNeg; 43 | def PriceChange; 44 | def PriceHigh; 45 | def PriceLow; 46 | def PriceRange; 47 | def CloseRelativeToPriceRange; 48 | 49 | if (volume > AvgVolume) { 50 | PriceChange = close - close[1]; 51 | PriceHigh = max(high, close[1]); 52 | PriceLow = min(low, close[1]); 53 | PriceRange = PriceHigh - PriceLow; 54 | CloseRelativeToPriceRange = (close - PriceLow) / PriceRange; 55 | 56 | if (PriceChange > 0) { # positive close 57 | if (CloseRelativeToPriceRange >= 0.50) { # close in upper half of range is accumulation 58 | BarCountDataPos = 1; 59 | BarCountDataNeg = 0; 60 | } else { # close in lower half of range is stalling 61 | BarCountDataPos = 0; 62 | BarCountDataNeg = -1; 63 | } 64 | } else if (PriceChange < 0) { # negative close 65 | if (CloseRelativeToPriceRange < 0.38) { # close in lower 38% of range is distribution 66 | BarCountDataPos = 0; 67 | BarCountDataNeg = -1; 68 | } else { # support day, down but in upper 62% of bar 69 | BarCountDataPos = 1; 70 | BarCountDataNeg = 0; 71 | } 72 | } else { 73 | BarCountDataPos = 0; 74 | BarCountDataNeg = 0; 75 | } 76 | } else { 77 | PriceChange = 0; 78 | PriceHigh = 0; 79 | PriceLow = 0; 80 | PriceRange = 0; 81 | CloseRelativeToPriceRange = 0; 82 | 83 | BarCountDataPos = 0; 84 | BarCountDataNeg = 0; 85 | } 86 | 87 | # Plot the tick marks showing individual instances of accumulation or distribution 88 | plot BarCountPlot = (BarCountDataPos + BarCountDataNeg) * 100; 89 | BarCountPlot.setPaintingStrategy(PaintingStrategy.HISTOGRAM); 90 | def LineColor = if(BarCountDataPos > 0.0, 16, if(BarCountDataNeg < 0.0, 5, 17)); 91 | BarCountPlot.AssignValueColor(getColor(LineColor)); 92 | BarCountPlot.HideTitle(); 93 | 94 | # Plot of the sum of net a/d instances since the beginning of the chart 95 | plot BarSumPlot = TotalSum(BarCountDataPos + BarCountDataNeg); 96 | BarSumPlot.SetDefaultColor(Color.YELLOW); 97 | BarSumPlot.setLineWeight(2); 98 | 99 | # Plot of the reference line showing a net of zero a/d periods. 100 | plot ZeroLine = 0; 101 | ZeroLine.SetDefaultColor(Color.WHITE); 102 | ZeroLine.HideTitle(); 103 | 104 | # Plot of the sum of positive a/d instances since the beginning of the chart 105 | plot BarSumPlotPos = TotalSum(BarCountDataPos); 106 | BarSumPlotPos.SetDefaultColor(Color.CYAN); 107 | BarSumPlotPos.setLineWeight(2); 108 | 109 | # Plot of the sum of negative a/d instances since the beginning of the chart 110 | plot BarSumPlotNeg = TotalSum(BarCountDataNeg); 111 | BarSumPlotNeg.SetDefaultColor(Color.MAGENTA); 112 | BarSumPlotNeg.setLineWeight(2); 113 | 114 | # Plot of the sum of total a/d instances since the beginning of the chart 115 | plot BarSumPlotAbs = TotalSum(BarCountDataPos - BarCountDataNeg); 116 | BarSumPlotAbs.SetDefaultColor(Color.LIGHT_ORANGE); 117 | BarSumPlotAbs.setLineWeight(2); 118 | -------------------------------------------------------------------------------- /scripts/AccumulationDistributionBarCountMSSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # AccumulationDistributionBarCountMS 19 | # 20 | # Counts the instances of accumulation and distribution in a stock over a 21 | # period of time. Based on Mike Scott's presentation at the IBD National Meetup 22 | # in May 2014. 23 | # http://ibdtv.investors.com/national-meetup-events/699580-.aspx 24 | # 25 | # The parameters in this study match Mike's presentation. I've created a customized 26 | # version named AccumulationDistributionBarCount. 27 | # 28 | # This study is designed to be applied with the aggregation period of days or weeks. 29 | # 30 | declare lower; 31 | 32 | input AvgVolumePeriod = 50; 33 | 34 | # 50 day average volume 35 | def AvgVolume = Average(volume, AvgVolumePeriod); 36 | 37 | # accumulation/distribution count 38 | def BarCountData; 39 | def PriceChange; 40 | def PriceRange; 41 | def CloseRelativeToPriceRange; 42 | 43 | if (volume > AvgVolume) { 44 | PriceChange = close - close[1]; 45 | PriceRange = high - low; 46 | CloseRelativeToPriceRange = (close - low) / PriceRange; 47 | 48 | if (PriceChange > 0) { # positive close 49 | if (CloseRelativeToPriceRange >= 0.50) { # close in upper half of range is accumulation 50 | BarCountData = 1; 51 | } else { # close in lower half of range is stalling 52 | BarCountData = -1; 53 | } 54 | } else if (PriceChange < 0) { # negative close 55 | if (CloseRelativeToPriceRange < 0.40) { # close in lower 40% of range is distribution 56 | BarCountData = -1; 57 | } else { 58 | BarCountData = 1; # support day, down but in upper 60% of bar 59 | } 60 | } else { 61 | BarCountData = 0; 62 | } 63 | } else { 64 | PriceChange = 0; 65 | PriceRange = 0; 66 | CloseRelativeToPriceRange = 0; 67 | 68 | BarCountData = 0; 69 | } 70 | 71 | # Plot the tick marks showing individual instances of accumulation or distribution 72 | plot BarCountPlot = BarCountData * 100; 73 | BarCountPlot.setPaintingStrategy(PaintingStrategy.HISTOGRAM); 74 | def LineColor = if(BarCountData > 0.0, 16, if(BarCountData < 0.0, 5, 17)); 75 | BarCountPlot.AssignValueColor(getColor(LineColor)); 76 | BarCountPlot.HideTitle(); 77 | 78 | # Plot of the sum of a/d instances since the beginning of the chart 79 | plot BarSumPlot = TotalSum(BarCountData); 80 | BarSumPlot.SetDefaultColor(Color.YELLOW); 81 | BarSumPlot.setLineWeight(2); 82 | 83 | # Plot of the reference line showing a net of zero a/d periods. 84 | plot ZeroLine = 0; 85 | ZeroLine.SetDefaultColor(Color.WHITE); 86 | -------------------------------------------------------------------------------- /scripts/AccumulationDistributionBarCountSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # AccumulationDistributionBarCount 19 | # 20 | # Counts the instances of accumulation and distribution in a stock over a 21 | # period of time. Based on Mike Scott's presentation at the IBD National Meetup 22 | # in May 2014. 23 | # http://ibdtv.investors.com/national-meetup-events/699580-.aspx 24 | # 25 | # I've tweaked the logic and parameters based on additional research. 26 | # 27 | # A version of this study with Mike's original parameters is in 28 | # AccumulationDistributionBarCountMS. 29 | # 30 | # This study is designed to be applied with the aggregation period of days or weeks. 31 | # 32 | declare lower; 33 | 34 | input AvgVolumePeriod = 50; 35 | 36 | # 50 day average volume 37 | def AvgVolume = Average(volume, AvgVolumePeriod); 38 | 39 | # accumulation/distribution count 40 | def BarCountData; 41 | def PriceChange; 42 | def PriceHigh; 43 | def PriceLow; 44 | def PriceRange; 45 | def CloseRelativeToPriceRange; 46 | 47 | if (volume > AvgVolume) { 48 | PriceChange = close - close[1]; 49 | PriceHigh = max(high, close[1]); 50 | PriceLow = min(low, close[1]); 51 | PriceRange = PriceHigh - PriceLow; 52 | CloseRelativeToPriceRange = (close - PriceLow) / PriceRange; 53 | 54 | if (PriceChange > 0) { # positive close 55 | if (CloseRelativeToPriceRange >= 0.50) { # close in upper half of range is accumulation 56 | BarCountData = 1; 57 | } else { # close in lower half of range is stalling 58 | BarCountData = -1; 59 | } 60 | } else if (PriceChange < 0) { # negative close 61 | if (CloseRelativeToPriceRange < 0.38) { # close in lower 38% of range is distribution 62 | BarCountData = -1; 63 | } else { 64 | BarCountData = 1; # support day, down but in upper 62% of bar 65 | } 66 | } else { 67 | BarCountData = 0; 68 | } 69 | } else { 70 | PriceChange = 0; 71 | PriceHigh = 0; 72 | PriceLow = 0; 73 | PriceRange = 0; 74 | CloseRelativeToPriceRange = 0; 75 | 76 | BarCountData = 0; 77 | } 78 | 79 | # Plot the tick marks showing individual instances of accumulation or distribution 80 | plot BarCountPlot = BarCountData * 100; 81 | BarCountPlot.setPaintingStrategy(PaintingStrategy.HISTOGRAM); 82 | def LineColor = if(BarCountData > 0.0, 16, if(BarCountData < 0.0, 5, 17)); 83 | BarCountPlot.AssignValueColor(getColor(LineColor)); 84 | BarCountPlot.HideTitle(); 85 | 86 | # Plot of the sum of a/d instances since the beginning of the chart 87 | plot BarSumPlot = TotalSum(BarCountData); 88 | BarSumPlot.SetDefaultColor(Color.YELLOW); 89 | BarSumPlot.setLineWeight(2); 90 | 91 | # Plot of the reference line showing a net of zero a/d periods. 92 | plot ZeroLine = 0; 93 | ZeroLine.SetDefaultColor(Color.WHITE); 94 | -------------------------------------------------------------------------------- /scripts/BuyableGapUpIndicatorSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # BuyableGapUpIndicator 19 | # 20 | # Based on Gil Morales and Chris Kacher's rules for buyable gaps up. 21 | # http://www.traderplanet.com/articles/view/164232-gain-your-stock-edge-buyable-gap-up-strategy/ 22 | # 23 | # This study doesn't work intraday because the volume used is the actual volume 24 | # and not the projected end-of-day volume. Instead, this study is useful 25 | # in post-analysis to quickly find buyable gaps up. 26 | # 27 | # TODO: Add logic to handle the current period gaps up by projecting the full day volume 28 | # based on the current time and volume so far. 29 | # 30 | input AverageTrueRangeTimePeriod = 40; 31 | input BuyableGapPercentOfATR = 75; # percent of average true range to qualify for as a gap 32 | input AverageVolumeTimePeriod = 50; # calculate 50 day MA volume 33 | input BuyableGapUpMinVolumePercent = 150; # 150% of 50 day MA volume 34 | 35 | def AverageTrueRange = reference ATR(AverageTrueRangeTimePeriod, averageType = AverageType.SIMPLE); 36 | def OpeningPriceGap = open - high[1]; 37 | 38 | def AverageVolume = MovingAverage(AverageType.SIMPLE, volume, AverageVolumeTimePeriod ); 39 | 40 | def GapUp = (OpeningPriceGap >= AverageTrueRange * BuyableGapPercentOfATR / 100) and (volume > AverageVolume * BuyableGapUpMinVolumePercent / 100); 41 | 42 | AddChartBubble(GapUp > 0, low, “G", Color.GREEN, no); 43 | 44 | -------------------------------------------------------------------------------- /scripts/ClosePercentOfRangeSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # ClosePercentOfRange 19 | # 20 | # Calculates where in the time period range the stock closed. This study does 21 | # not consider prior close as with True Range. If the close percent of range 22 | # is greater than or equal to the threshold value, the bar is shown in Green 23 | # instead of Red. 24 | # 25 | declare lower; 26 | input thresholdPercent = 38; 27 | 28 | def todaysClosePctRange = (close - low) / (high - low) * 100; 29 | 30 | plot ClosePctOfRange = todaysClosePctRange; 31 | ClosePctOfRange.AssignValueColor(if todaysClosePctRange >= thresholdPercent then Color.GREEN else Color.RED); 32 | ClosePctOfRange.SetPaintingStrategy(PaintingStrategy.HISTOGRAM); 33 | -------------------------------------------------------------------------------- /scripts/CoppockIndicatorSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # CoppockIndicator 19 | # 20 | # Charts the Coppock Indicator described here: 21 | # https://en.wikipedia.org/wiki/Coppock_curve 22 | # 23 | # The Coppock can be used (along with other indicators like the Eureka Signal 24 | # and IBD6000 %Es) to identify points where the stock market trend changes 25 | # from down to up. The Coppock does not identify the beginning of downtrends. 26 | # 27 | # This study is designed to be applied to a major market index (e.g., SPX or 28 | # COMP) with an aggregation period of weeks or months. 29 | # 30 | declare lower; 31 | 32 | input RateOfChangeSlowPeriod = 14; 33 | input RateOfChangeFastPeriod = 11; 34 | input WeightedMAPeriod = 10; 35 | 36 | def AggregationPeriod = if (getAggregationPeriod() < AggregationPeriod.WEEK) then AggregationPeriod.WEEK else getAggregationPeriod(); 37 | 38 | def price = close(period = AggregationPeriod); 39 | 40 | def ROC1 = if price[RateOfChangeSlowPeriod]!=0 then (price/price[RateOfChangeSlowPeriod]-1)*100 else 0; 41 | def ROC2 = if price[RateOfChangeFastPeriod]!=0 then (price/price[RateOfChangeFastPeriod]-1)*100 else 0; 42 | 43 | plot Coppock = WMA(ROC1 + ROC2, WeightedMAPeriod); 44 | 45 | Coppock.assignValueColor(if Coppock>Coppock[1] then color.green else color.red); 46 | Coppock.SetDefaultColor(GetColor(1)); 47 | Coppock.setLineWeight(2); 48 | Coppock.HideBubble(); 49 | 50 | plot ZeroLine = 0; 51 | 52 | ZeroLine.SetDefaultColor(color.white); 53 | ZeroLine.SetLineWeight(1); 54 | ZeroLine.HideBubble(); 55 | ZeroLine.HideTitle(); 56 | 57 | AddChartBubble(Coppock[1] < 0 and Coppock > Coppock[1] and Coppock[1] < Coppock[2], Coppock, "Buy", Color.CYAN, no); 58 | -------------------------------------------------------------------------------- /scripts/CumulativeIntradayVolumePercentChangeLabelSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # CumulativeIntradayVolumePercentChangeLabel 19 | # 20 | # Displays a label with the percent change in cumulative intraday volume. 21 | # 22 | # The chart period should be less than one day. 23 | # 24 | # This study was designed to be used with TOS Total Volume symbols like $TVOLC/Q 25 | # (NASDAQ Composite Total Volume) or $TVOLC (NYSE Composite Total volume). The 26 | # OHLC "prices" for these symbols are actually cumulative daily volume. But this 27 | # study will show price percent change over the same time period if a stock or 28 | # ETF symbol is used. 29 | # 30 | 31 | input symbol = "$TVOLC/Q"; # NASDAQ Composite Total Volume 32 | 33 | # did this bar just start a new calendar day? 34 | def newDay = GetDay() <> GetDay()[1]; 35 | 36 | # get the index of today's first bar 37 | def newDayIndex = if newDay then 38 | 1 39 | else 40 | newDayIndex[1] + 1; 41 | 42 | # save the index of the previous day's first bar 43 | def prevNewDayIndex = if newDay then 44 | newDayIndex[1] 45 | else 46 | prevNewDayIndex[1] + 1; 47 | 48 | # number of bars in the prior day 49 | def indexOffset = prevNewDayIndex - newDayIndex + 1; 50 | 51 | # volume today 52 | def tempTodayVol = close(symbol = symbol); 53 | def todayVol = if IsNAN(tempTodayVol) then 54 | todayVol[1] 55 | else 56 | tempTodayVol; 57 | 58 | # volume yesterday 59 | def tempYesterdayVol = GetValue(close(symbol=symbol), indexOffset); 60 | def yesterdayVol = if IsNAN(tempYesterdayVol) then 61 | yesterdayVol[1] 62 | else 63 | tempYesterdayVol; 64 | 65 | def percentChange = (todayVol / yesterdayVol - 1) * 100; 66 | 67 | # % change label 68 | AddLabel(1, "Today's Volume % Chg (" + symbol + "): " + Round(percentChange,2) + "%", Color.WHITE); 69 | 70 | -------------------------------------------------------------------------------- /scripts/CumulativeIntradayVolumePercentChangeSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # CumulativeIntradayVolumePercentChange 19 | # 20 | # Displays a chart with the percent change in cumulative intraday volume. 21 | # 22 | # The chart period should be less than one day. 23 | # 24 | # This study was designed to be used with TOS Total Volume symbols like $TVOLC/Q 25 | # (NASDAQ Composite Total Volume) or $TVOLC (NYSE Composite Total volume). The 26 | # OHLC "prices" for these symbols are actually cumulative daily volume. But this 27 | # study will show price percent change over the same time period if a stock or 28 | # ETF symbol is used. 29 | # 30 | 31 | declare lower; 32 | 33 | # did this bar just start a new calendar day? 34 | def newDay = GetDay() <> GetDay()[1]; 35 | 36 | # get the index of today's first bar 37 | def newDayIndex = if newDay then 38 | 1 39 | else 40 | newDayIndex[1] + 1; 41 | 42 | # save the index of the previous day's first bar 43 | def prevNewDayIndex = if newDay then 44 | newDayIndex[1] 45 | else 46 | prevNewDayIndex[1] + 1; 47 | 48 | # number of bars in the prior day 49 | def indexOffset = prevNewDayIndex - newDayIndex + 1; 50 | 51 | # volume today and yesterday 52 | def todayVol = close; 53 | def yesterdayVol = GetValue(close, indexOffset); 54 | 55 | # % change 56 | plot s = (todayVol / yesterdayVol - 1) * 100; 57 | 58 | -------------------------------------------------------------------------------- /scripts/DailyEMASTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # DailyEMA 19 | # 20 | # Exponential Moving Average 21 | # 22 | 23 | input price = FundamentalType.CLOSE; 24 | input aggregationPeriod = AggregationPeriod.DAY; 25 | input length = 21; 26 | 27 | plot DailyEMA = ExpAverage(fundamental(price, period = aggregationPeriod), length); 28 | DailyEMA.SetPaintingStrategy(PaintingStrategy.HORIZONTAL); 29 | DailyEMA.SetDefaultColor(GetColor(1)); 30 | -------------------------------------------------------------------------------- /scripts/EarningsPerShareSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # EarningsPerShare 19 | # 20 | # Displays the company's earnings per share over the time period. If overlaying 21 | # this study on a price graph, right click the line and select "Use left axis" 22 | # to adjust the scale. 23 | # 24 | declare upper; 25 | 26 | plot Data = getActualEarnings(); 27 | Data.SetPaintingStrategy(PaintingStrategy.LINE); 28 | Data.SetLineWeight(2); 29 | Data.SetDefaultColor(Color.LIGHT_ORANGE); 30 | Data.EnableApproximation(); 31 | -------------------------------------------------------------------------------- /scripts/ExchangeListedNetHighLowSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2022 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # ExchangeListedNetHighLow 19 | # 20 | # Shows the number of new 52-week highs - new 52-week lows by day for the selected exchange. If the 21 | # number of lows is greater than the number of highs, the value will be negative. If highs are 22 | # greater, the number will be positive. Exchange = "ETF" shows net highs - lows for all ETFs listed 23 | # on the 4 exchanges. 24 | # 25 | # The TOS symbols don't appear to work at expected when the aggregation period is WEEK so this 26 | # study is only for daily charts. 27 | # 28 | declare lower; 29 | input exchange = {default "NYSE", "NASDAQ", "AMEX", "ARCA", "ETF"}; 30 | 31 | def ap = AggregationPeriod.DAY; 32 | def diff; 33 | switch (exchange){ 34 | case "NYSE": 35 | diff = close(Symbol = "$NYHGH", period = ap) - close(Symbol = "$NYLOW", period = ap); 36 | case "NASDAQ": 37 | diff = close(Symbol = "$NAHGH", period = ap) - close(Symbol = "$NALOW", period = ap); 38 | case "AMEX": 39 | diff = close(Symbol = "$AMHGH", period = ap) - close(Symbol = "$AMLOW", period = ap); 40 | case "ARCA": 41 | diff = close(Symbol = "$ARHGH", period = ap) - close(Symbol = "$ARLOW", period = ap); 42 | case "ETF": 43 | diff = close(Symbol = "$ETFHIGH", period = ap) - close(Symbol = "$ETFLOW", period = ap); 44 | } 45 | 46 | plot hlp = if IsNaN(close) then Double.NaN else diff; 47 | hlp.EnableApproximation(); 48 | hlp.SetPaintingStrategy(PaintingStrategy.HISTOGRAM); 49 | hlp.SetLineWeight(5); 50 | hlp.AssignValueColor(if hlp < 0 then Color.RED 51 | else if hlp > 0 then Color.GREEN 52 | else Color.CYAN); 53 | 54 | plot zero = 0.0; 55 | zero.SetDefaultColor(Color.WHITE); 56 | zero.SetLineWeight(1); 57 | zero.HideBubble(); 58 | zero.HideTitle(); 59 | -------------------------------------------------------------------------------- /scripts/MinorHighLowIndicatorSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # MinorHighLowIndicator 19 | # 20 | # Mark days with the highest high or lowest low in past/future N periods. 21 | declare upper; 22 | 23 | input interval = 9; 24 | 25 | def isMinorHigh = fold i = -interval to interval+1 with isHigh = 1 do (if getValue(high, i) > high then 0 else isHigh); 26 | def isMinorLow = fold j = -interval to interval+1 with isLow = 1 do (if getValue(low, j) < low then 0 else isLow); 27 | 28 | AddChartBubble(isMinorHigh == 1, high, RoundUp(high, 0), Color.LIGHT_GRAY, yes); 29 | AddChartBubble(isMinorLow == 1, low, RoundDown(low, 0), Color.LIGHT_GRAY, no); 30 | -------------------------------------------------------------------------------- /scripts/PocketPivotSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # PocketPivot 19 | # 20 | # Identifies up-day volume spikes that may be a buyable pocket pivot. Based on the 21 | # work of Gil Morales and Chris Kacher: 22 | # 23 | # http://www.wiley.com/WileyCDA/WileyTitle/productCd-0470616539,miniSiteCd-WILEYTRADING.html 24 | # http://www.wiley.com/WileyCDA/WileyTitle/productCd-1118273028,miniSiteCd-WILEYTRADING.html 25 | # http://www.aaiilosangeles.org/SkirballPresentations/Morales&Kacher091110.pdf 26 | # 27 | # This study checks price and volume to see if they met the pocket pivot 28 | # criteria. The other criteria (strong fundamentals, no wedging, constructive 29 | # basing, etc.) need to be evaluated separately. 30 | # 31 | # I made these additions/modifications to Gil's and Chris's vague and sometimes 32 | # conflicting definition of a pocket pivot: 33 | # 34 | # 1. Per Gil and Chris, the volume on the day of the pocket pivot must be 35 | # higher than any down day in the previous 10 days. But if the volume is 36 | # "choppy", then increase the period to 11 to 15 days. But they don't 37 | # define "choppy". For the purposes of this script, I define choppy when 38 | # the standard deviation of the volume is > 125% of the average. Update: I 39 | # removed the stddev logic since it didn't eliminate any obviously poor 40 | # pivots. I'm always looking at the volume on the previous 10 days. 41 | # 42 | # 2. I only count the pocket pivot if the stock closes in the upper 62% of the 43 | # day's price range. Up days that close lower in the range are considered 44 | # stalling. 45 | # 46 | # 3. Gil and Chris say daily price closes prior to the pivot should be "tight" 47 | # without any specifics. I defined tight as where the average percent price 48 | # change at close over the last 10 days is <= 1.5%. Update: I removed this 49 | # rule after backtesting against Gil's examples. 50 | # 51 | # 4. Gil and Chris have examples of pocket pivots off of the 50-day instead of 52 | # the 10-day. At that point the stock is extended from the 10-day. That 53 | # seems to conflict with the idea that a pocket pivot occurs after a quiet 54 | # period in the stock so I have not implemented rules for 50-day PPs here. 55 | # 56 | # 5. The low on the day of the pivot must be within 1.4% of the 10-day SMA or 57 | # the price must have moved up through the 10-day during that day. Several 58 | # of Gil/Chris's examples conflict. (Example: 1.24 in one example is 59 | # described as too extended, but there are others where 1.6 or even 2.5% 60 | # above the 10-day SMA isn't too extended. In the Trading Cockpit with the 61 | # O'Neil Disciples, Chapter 5.) I'm choosing to use a middle and slightly 62 | # conservative setting here. The more extended, the more risky the buy. 63 | # 64 | # 6. Pocket pivots should not be bought when then stock is below the 50- or 65 | # 200-day simple moving averages. I check only the 50-day here because when 66 | # I checked the 200-day, TOS was hiding the study for recent IPOs with less 67 | # than 200 days of price history. 68 | # 69 | input Period = 11; # normal volume lookback period (today + 10 prior days) 70 | input MaximumDistanceFrom10DaySMAPercent = 1.4; # Price on pivot day should be near the 10-day SMA. MAX = 1.6 Per FOSL1, 1.23 per PII, but RAX not extended at 1.61 and 1.64. 71 | 72 | # Volume functions 73 | def DownVolume = If(close < close[1], volume, 0); 74 | def HighestDownVolume = Highest(DownVolume, Period); 75 | 76 | def FiftyDayAverageVolume = MovingAverage(AverageType.SIMPLE, volume, 50); 77 | 78 | def IsVolumeGreaterHighestDownVolume = if (volume > HighestDownVolume) then 1 else 0; 79 | 80 | # Price functions 81 | def TenDaySMA = MovingAverage(AverageType.SIMPLE, close, 10); 82 | def FiftyDaySMA = MovingAverage(AverageType.SIMPLE, close, 50); 83 | 84 | def IsLowPriceNear10DaySMA = if ((AbsValue(low - TenDaySMA) / TenDaySMA) <= MaximumDistanceFrom10DaySMAPercent / 100) then 1 else 0; 85 | def DidPricePass10DaySMA = if (low <= TenDaySMA && close >= TenDaySMA) then 1 else 0; 86 | 87 | def IsPriceNear10DaySMA = if (IsLowPriceNear10DaySMA or DidPricePass10DaySMA) then 1 else 0; 88 | 89 | def IsPriceAtOrAbove50DaySMA = if (close >= FiftyDaySMA) then 1 else 0; 90 | 91 | def AveragePriceChangePercent = MovingAverage(AverageType.SIMPLE, AbsValue(close[1] - close[2]) / close[2], Period); 92 | 93 | def IsCloseInUpperHalfOfRange = close >= close[1] && close > ((high - low) * .38 + low); 94 | 95 | def IsPriceInTheProperRange = if (IsCloseInUpperHalfOfRange && IsPriceNear10DaySMA && IsPriceAtOrAbove50DaySMA) then 1 else 0; 96 | 97 | # add a chart bubble if then PP criteria are met 98 | AddChartBubble(IsVolumeGreaterHighestDownVolume && IsPriceInTheProperRange, low, "PP", Color.CYAN, no); 99 | -------------------------------------------------------------------------------- /scripts/PocketPivotStrategyLESTRATEGY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # PocketPivotStrategyLE 19 | # 20 | # Identifies Pocket Pivot buy points. This is a copy of the PocketPivot study. 21 | # Unfortunately I have to copy the entire logic here rather than just referencing 22 | # the study. See PocketPivotSTUDY.ts for a description of the study. 23 | # 24 | input Period = 11; # normal volume lookback period (today + 10 prior days) 25 | input MaximumDistanceFrom10DaySMAPercent = 1.4; # Price on pivot day should be near the 10-day SMA. MAX = 1.6 Per FOSL1, 1.23 per PII, but RAX not extended at 1.61 and 1.64. 26 | 27 | # Volume functions 28 | def DownVolume = If(close < close[1], volume, 0); 29 | def HighestDownVolume = Highest(DownVolume, Period); 30 | 31 | def FiftyDayAverageVolume = MovingAverage(AverageType.SIMPLE, volume, 50); 32 | 33 | def IsVolumeGreaterHighestDownVolume = if (volume > HighestDownVolume) then 1 else 0; 34 | 35 | # Price functions 36 | def TenDaySMA = MovingAverage(AverageType.SIMPLE, close, 10); 37 | def FiftyDaySMA = MovingAverage(AverageType.SIMPLE, close, 50); 38 | 39 | def IsLowPriceNear10DaySMA = if ((AbsValue(low - TenDaySMA) / TenDaySMA) <= MaximumDistanceFrom10DaySMAPercent / 100) then 1 else 0; 40 | def DidPricePass10DaySMA = if (low <= TenDaySMA && close >= TenDaySMA) then 1 else 0; 41 | 42 | def IsPriceNear10DaySMA = if (IsLowPriceNear10DaySMA or DidPricePass10DaySMA) then 1 else 0; 43 | 44 | def IsPriceAtOrAbove50DaySMA = if (close >= FiftyDaySMA) then 1 else 0; 45 | 46 | def AveragePriceChangePercent = MovingAverage(AverageType.SIMPLE, AbsValue(close[1] - close[2]) / close[2], Period); 47 | 48 | def IsCloseInUpperHalfOfRange = close >= close[1] && close > ((high - low) * .38 + low); 49 | 50 | def IsPriceInTheProperRange = if (IsCloseInUpperHalfOfRange && IsPriceNear10DaySMA && IsPriceAtOrAbove50DaySMA) then 1 else 0; 51 | 52 | # add a chart bubble if then PP criteria are met 53 | # AddChartBubble(IsVolumeGreaterHighestDownVolume && IsPriceInTheProperRange, low, "PP", Color.CYAN, no); 54 | 55 | # add a chart bubble if then PP criteria are met 56 | def buy = if (IsVolumeGreaterHighestDownVolume && IsPriceInTheProperRange) then 1 else 0; 57 | 58 | AddOrder(OrderType.BUY_AUTO, buy equals 1, tickColor = GetColor(0), arrowColor = GetColor(0), price = close, name = "Buy"); 59 | 60 | 61 | -------------------------------------------------------------------------------- /scripts/PocketPivotStrategyLXSTRATEGY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # PocketPivotStrategyLX 19 | # 20 | # Sell when we break the 10/50 day line on day 1 and then go below that day's intraday 21 | # low on a subsequent day. Also sell if we break the 50-day on volume more than 40% 22 | # above average. 23 | 24 | input MovingAverageLine = 50; # sell when violates 50 day SMA 25 | input HighVolumePercentage = 40; # if volume is greater or equal that this percentage 26 | # above the 50-day average volume then it counts 27 | # as a high volume day. 28 | 29 | def TodaysSMA = MovingAverage(AverageType.SIMPLE, close[1], MovingAverageLine); 30 | def YesterdaysSMA = MovingAverage(AverageType.SIMPLE, close[1], MovingAverageLine); 31 | 32 | # volume rule always uses the 50-day, but the SMA violation run can be 10- or 50-day 33 | def Todays50DaySMA = MovingAverage(AverageType.SIMPLE, close[1], 50); 34 | def AverageVolume = MovingAverage(AverageType.SIMPLE, volume[1], 50); 35 | 36 | def DidViolateSMA = if (low < low[1] && close[1] < YesterdaysSMA) then 1 else 0; 37 | def DidBreakSMAOnHighVolume = if (close AverageVolume * (1 + HighVolumePercentage/100)) then 1 else 0; 38 | 39 | def sell = if (DidViolateSMA or DidBreakSMAOnHighVolume) then 1 else 0; 40 | 41 | AddOrder(OrderType.SELL_AUTO, sell equals 1, tickColor = GetColor(1), arrowColor = GetColor(1), price = low[1], name = "Sell"); 42 | -------------------------------------------------------------------------------- /scripts/RelativeStrengthWithNewHighIndicatorsSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # RelativeStrengthWithNewHighIndicators 19 | # 20 | # Compares the price trend of the current symbol to another symbol. 21 | # 22 | # Pink circles indicate symbol's relative strength was making a new high before 23 | # making a new high in price. A blue circle over the last bar indicates relative 24 | # strength is currently at a new high (regardless of price). 25 | # 26 | declare lower; 27 | 28 | input comparisonSymbol = "SPX"; 29 | input barsToLookBackForHigh = 100; 30 | 31 | # 32 | # Relative Strength Plot 33 | # 34 | 35 | def comparisonClose = close(comparisonSymbol); 36 | def rs = if comparisonClose == 0 then 0 else close/comparisonClose; 37 | 38 | plot rsPlot = rs; 39 | rsPlot.setPaintingStrategy(PaintingStrategy.LINE); 40 | rsPlot.AssignValueColor(if rs > rs[1] then Color.Uptick else Color.DownTick); 41 | rsPlot.setLineWeight(2); 42 | rsPlot.HideBubble(); 43 | rsPlot.HideTitle(); 44 | 45 | # 46 | # RS New High Before Price Plot 47 | # 48 | 49 | def lastBar = !IsNaN(close) && IsNaN(close[-1]); 50 | def highestRS = Highest(rs, barsToLookBackForHigh); 51 | def todayIsNewHighRS = if rs >= highestRS then rs else -1; 52 | 53 | def highestClosePrice = Highest(close, barsToLookBackForHigh); 54 | def todayIsNewHighClosePrice = if close >= highestClosePrice then rs else -1; 55 | 56 | def rsNewHighBeforePrice = !lastBar && todayIsNewHighRS > 0 && todayIsNewHighClosePrice == -1; 57 | 58 | plot rsNewHighBeforePricePlot = if (rsNewHighBeforePrice, rs * 1, Double.NAN); 59 | rsNewHighBeforePricePlot.setPaintingStrategy(PaintingStrategy.Points); 60 | rsNewHighBeforePricePlot.setDefaultColor(Color.Dark_Orange); 61 | rsNewHighBeforePricePlot.setLineWeight(5); 62 | rsNewHighBeforePricePlot.HideBubble(); 63 | rsNewHighBeforePricePlot.HideTitle(); 64 | 65 | # 66 | # Current RS at New High Plot 67 | # 68 | 69 | def showBlueIndicator = if (lastBar && todayIsNewHighRS > 0, rs * 1.0001, Double.NAN); 70 | 71 | plot currentRSAtNewHigh = showBlueIndicator; 72 | currentRSAtNewHigh.setPaintingStrategy(PaintingStrategy.Points); 73 | currentRSAtNewHigh.setDefaultColor(CreateColor(111,189,232)); # medium blue 74 | currentRSAtNewHigh.setLineWeight(5); 75 | currentRSAtNewHigh.HideBubble(); 76 | currentRSAtNewHigh.HideTitle(); 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /scripts/TwelveOfFifteenUpSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # TwelveOfFifteenUp 19 | # 20 | # Adds a wedge on top of a candle where closing price was higher than the 21 | # previous candle for 12 of 15 candles (the current candle 22 | # plus the previous 14 candles.) 23 | # 24 | declare upper; 25 | 26 | input lookbackPeriod = 15; 27 | input minimumDaysUp = 12; 28 | 29 | def priceUp = fold i = 0 to lookbackPeriod with count do count + if getValue(close, i, lookbackPeriod - 1) > getValue(close, i + 1, lookbackPeriod) then 1 else 0; 30 | 31 | plot upPlot = priceUp >= minimumDaysUp; 32 | upPlot.setDefaultColor(Color.Yellow); 33 | upPlot.setPaintingStrategy(PaintingStrategy.BOOLEAN_WEDGE_UP); 34 | upPlot.setStyle(Curve.Points); 35 | -------------------------------------------------------------------------------- /scripts/UpDownVolumeRatioSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # UpDownVolumeRatio 19 | # 20 | # Ratio of the volume on up days versus down days. Higher numbers indicate 21 | # more accumulation by large investors which is a positive. Low numbers 22 | # indicate distribution. 23 | # 24 | input Period = 50; 25 | input MinimumUDVolumeForBuy = 1.00; 26 | 27 | def Up = If(close > close[1], volume, 0); 28 | def Down = If(close <= close[1], volume, 0); 29 | def UpAvgVol = MovingAverage(AverageType.SIMPLE, Up, Period); 30 | def DownAvgVol = MovingAverage(AverageType.SIMPLE, Down, Period); 31 | 32 | plot UpDownVol = Round(UpAvgVol / DownAvgVol, 2); 33 | 34 | UpDownVol.AssignValueColor(Color.CYAN); 35 | UpDownVol.SetLineWeight(3); 36 | 37 | # this line represents the minimum U/D Volume for a buy 38 | plot MinUDVolLine = MinimumUDVolumeForBuy; 39 | MinUDVolLine.AssignValueColor(Color.WHITE); 40 | MinUDVolLine.SetLineWeight(2); 41 | MinUDVolLine.HideBubble(); 42 | -------------------------------------------------------------------------------- /scripts/VolumePercentChangeFromAverageSTUDY.ts: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Scott J. Johnson (https://scottjjohnson.com) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS-IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # 18 | # VolumePercentChangeFromAverage 19 | # 20 | # Shows the current bar volume as a percentage change of the average volume 21 | # over the last X bars. Volume equal to or higher than the threshold is shown 22 | # in yellow. 23 | # 24 | declare lower; 25 | declare zerobase; 26 | 27 | input period = 50; # interval over which the average volume is calculated 28 | input highVolumeThresholdPercent = 40; # 40% above average 29 | 30 | plot VolumePercent = (volume / Average(volume, period) - 1 ) * 100; 31 | VolumePercent.AssignValueColor(if VolumePercent >= highVolumeThresholdPercent then GetColor(4) else GetColor(1)); 32 | VolumePercent.SetPaintingStrategy(PaintingStrategy.HISTOGRAM); 33 | VolumePercent.SetLineWeight(2); 34 | VolumePercent.HideBubble(); 35 | 36 | plot zero = 0.0; 37 | zero.SetDefaultColor(Color.WHITE); 38 | zero.SetLineWeight(1); 39 | zero.HideBubble(); 40 | zero.HideTitle(); 41 | --------------------------------------------------------------------------------