├── LICENSE ├── README.md ├── README_Images └── traders-dynamic-index-mtf-h1-h4.png ├── TradersDynamicIndex.cs ├── TradersDynamicIndex.mq4 └── TradersDynamicIndex.mq5 /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Traders Dynamic Index 2 | 3 | Traders Dynamic Index (TDI) is a custom MT4/MT5/cTrader indicator coded by EarnForex.com. The indicator is adapted from the earlier version by Dean Malone. Traders Dynamic Index uses RSI and MA calculations to display the current market situation from multiple points of view. 4 | 5 | The indicator supports all sorts of alerts, including arrows in the main window of the chart when one of the signals appears. It is also capable of displaying higher timeframe values on a lower timeframe chart. 6 | 7 | ![Traders Dynamic Index with multi-timeframe display of the H4 period over an H1 chart](https://github.com/EarnForex/Traders-Dynamic-Index/blob/main/README_Images/traders-dynamic-index-mtf-h1-h4.png) 8 | 9 | More information about this custom MetaTrader/cTrader indicator is available here: https://www.earnforex.com/indicators/Traders-Dynamic-Index/ 10 | 11 | Any contributions to the code are welcome! 12 | -------------------------------------------------------------------------------- /README_Images/traders-dynamic-index-mtf-h1-h4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EarnForex/Traders-Dynamic-Index/faee171b3dd03d7d98537787c37d0737509cce09/README_Images/traders-dynamic-index-mtf-h1-h4.png -------------------------------------------------------------------------------- /TradersDynamicIndex.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Based on TradersDynamicIndex.mq4 by Dean Malone 3 | // 4 | // Shows trend direction, strength, and volatility. 5 | // Green line - RSI Price line. 6 | // Red line - Trade Signal line. 7 | // Blue lines - Volatility Band. 8 | // Yellow line - Market Base line. 9 | // 10 | // Version 1.08 11 | // Copyright 2025, EarnForex.com 12 | // https://www.earnforex.com/metatrader-indicators/Traders-Dynamic-Index/ 13 | // ------------------------------------------------------------------------------- 14 | using System; 15 | using cAlgo.API; 16 | using cAlgo.API.Indicators; 17 | 18 | namespace cAlgo.Indicators 19 | { 20 | [Levels(32, 50, 68)] 21 | [Indicator(AccessRights = AccessRights.None)] 22 | public class TradersDynamicIndex : Indicator 23 | { 24 | public enum ENUM_CANDLE_TO_CHECK 25 | { 26 | Current = 0, 27 | Previous = 1 28 | } 29 | 30 | [Parameter("RSI Period (8-25)", DefaultValue = 13, MinValue = 1)] 31 | public int RSI_Period { get; set; } 32 | 33 | [Parameter()] 34 | public DataSeries Source { get; set; } 35 | 36 | [Parameter("Volatility Band (20-40)", DefaultValue = 34, MinValue = 1)] 37 | public int Volatility_Band { get; set; } 38 | 39 | [Parameter("Standard Deviations (1-3)", DefaultValue = 1.6185, MinValue = 0)] 40 | public double StdDev { get; set; } 41 | 42 | [Parameter("RSI Price MA Period", DefaultValue = 2, MinValue = 1)] 43 | public int RSI_Price_Line { get; set; } 44 | 45 | [Parameter("Price MA Type", DefaultValue = MovingAverageType.Simple)] 46 | public MovingAverageType RSI_Price_Type { get; set; } 47 | 48 | [Parameter("Trade Signal MA Period", DefaultValue = 7, MinValue = 1)] 49 | public int Trade_Signal_Line { get; set; } 50 | 51 | [Parameter("Signal MA Type", DefaultValue = MovingAverageType.Simple)] 52 | public MovingAverageType Trade_Signal_Type { get; set; } 53 | 54 | [Parameter("Upper timeframe")] 55 | public TimeFrame UpperTimeframe { get; set; } 56 | 57 | [Parameter("Enable email alerts", DefaultValue = false)] 58 | public bool EnableEmailAlerts { get; set; } 59 | 60 | [Parameter("AlertEmail: Email From", DefaultValue = "")] 61 | public string AlertEmailFrom { get; set; } 62 | 63 | [Parameter("AlertEmail: Email To", DefaultValue = "")] 64 | public string AlertEmailTo { get; set; } 65 | 66 | [Parameter("Enable arrows", DefaultValue = false)] 67 | public bool EnableArrowAlerts { get; set; } 68 | 69 | [Parameter("Enable alerts when the red line crosses the yellow line?", DefaultValue = false)] 70 | public bool EnableRedYellowCrossAlert { get; set; } 71 | 72 | [Parameter("Enable alerts when the green line crosses the blue line above 68 or below 32?", DefaultValue = false)] 73 | public bool EnableHookAlert { get; set; } 74 | 75 | [Parameter("Enable alerts when the green line crosses the red line?", DefaultValue = false)] 76 | public bool EnableGreenRedCrossAlert { get; set; } 77 | 78 | [Parameter("Enable alerts when the green line crosses the red line while above/below yellow line?", DefaultValue = false)] 79 | public bool EnableGreenRedCrossWithYellowAlert { get; set; } 80 | 81 | [Parameter("Enable alerts when the yellow line crosses the green line?", DefaultValue = false)] 82 | public bool EnableYellowGreenCrossAlert { get; set; } 83 | 84 | [Parameter(DefaultValue = ENUM_CANDLE_TO_CHECK.Previous)] 85 | public ENUM_CANDLE_TO_CHECK TriggerCandle { get; set; } 86 | 87 | [Parameter(DefaultValue = "Green")] 88 | public string RedYellowCrossArrowBullishColor { get; set; } 89 | 90 | [Parameter(DefaultValue = "Red")] 91 | public string RedYellowCrossArrowBearishColor { get; set; } 92 | 93 | [Parameter(DefaultValue = "Green")] 94 | public string HookArrowBullishColor { get; set; } 95 | 96 | [Parameter(DefaultValue = "Red")] 97 | public string HookArrowBearishColor { get; set; } 98 | 99 | [Parameter(DefaultValue = "Green")] 100 | public string GreenRedCrossArrowBullishColor { get; set; } 101 | 102 | [Parameter(DefaultValue = "Red")] 103 | public string GreenRedCrossArrowBearishColor { get; set; } 104 | 105 | [Parameter(DefaultValue = "Green")] 106 | public string YellowGreenCrossArrowBullishColor { get; set; } 107 | 108 | [Parameter(DefaultValue = "Red")] 109 | public string YellowGreenCrossArrowBearishColor { get; set; } 110 | 111 | [Parameter(DefaultValue = "TDI-")] 112 | public string ArrowPrefix { get; set; } 113 | 114 | [Output("Upper Volatility Band", LineColor = "MediumBlue")] 115 | public IndicatorDataSeries UpZone { get; set; } 116 | 117 | [Output("Lower Volatility Band", LineColor = "MediumBlue")] 118 | public IndicatorDataSeries DnZone { get; set; } 119 | 120 | [Output("Middle Volatility Band", LineColor = "Yellow", Thickness = 2)] 121 | public IndicatorDataSeries MdZone { get; set; } 122 | 123 | [Output("RSI Price Line", LineColor = "Green", Thickness = 2)] 124 | public IndicatorDataSeries MaBuf { get; set; } 125 | 126 | [Output("Trade Signal Line", LineColor = "Red", Thickness = 2)] 127 | public IndicatorDataSeries MbBuf { get; set; } 128 | 129 | // Output buffers: 130 | private RelativeStrengthIndex RSI; 131 | private MovingAverage MA_Price; 132 | private MovingAverage MA_Signal; 133 | private BollingerBands VolatilityBands; 134 | 135 | // MTF: 136 | private bool UseUpperTimeFrame; 137 | private Bars customBars; 138 | 139 | // Alerts: 140 | private DateTime LastAlertTimeRedYellow, LastAlertTimeHook, LastAlertTimeGreenRed, LastAlertTimeYellowGreen, unix_epoch; 141 | private int prev_index = -1; 142 | private int int_tc; 143 | 144 | protected override void Initialize() 145 | { 146 | if (UpperTimeframe <= TimeFrame) 147 | { 148 | Print("UpperTimeframe <= current timeframe. Ignored."); 149 | UseUpperTimeFrame = false; 150 | customBars = Bars; 151 | } 152 | else 153 | { 154 | UseUpperTimeFrame = true; 155 | customBars = MarketData.GetBars(UpperTimeframe); 156 | } 157 | 158 | RSI = Indicators.RelativeStrengthIndex(customBars.ClosePrices, RSI_Period); 159 | VolatilityBands = Indicators.BollingerBands(RSI.Result, Volatility_Band, StdDev, MovingAverageType.Simple); 160 | MA_Price = Indicators.MovingAverage(RSI.Result, RSI_Price_Line, RSI_Price_Type); 161 | MA_Signal = Indicators.MovingAverage(RSI.Result, Trade_Signal_Line, Trade_Signal_Type); 162 | 163 | unix_epoch = new DateTime(1970, 1, 1, 0, 0, 0); 164 | LastAlertTimeRedYellow = unix_epoch; 165 | LastAlertTimeHook = unix_epoch; 166 | LastAlertTimeGreenRed = unix_epoch; 167 | LastAlertTimeYellowGreen = unix_epoch; 168 | 169 | int_tc = (int)TriggerCandle; 170 | } 171 | 172 | public override void Calculate(int index) 173 | { 174 | int customIndex = index; 175 | int cnt = 0; // How many bars of the current timeframe should be recalculated. 176 | if (UseUpperTimeFrame) 177 | { 178 | customIndex = customBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]); 179 | // Find how many current timeframe bars should be recalculated: 180 | while (customBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index - cnt]) == customIndex) 181 | { 182 | cnt++; 183 | } 184 | } 185 | else 186 | { 187 | cnt = 1; // Non-MTF. 188 | if (customIndex <= RSI_Period) return; // Too early to calculate anything. 189 | } 190 | 191 | for (int i = 0; i < cnt; i++) // Making sure to rewrite previous lower timeframe candles with the updated upper one. 192 | { 193 | UpZone[index - i] = VolatilityBands.Top[customIndex]; 194 | DnZone[index - i] = VolatilityBands.Bottom[customIndex]; 195 | MdZone[index - i] = VolatilityBands.Main[customIndex]; 196 | MaBuf[index - i] = MA_Price.Result[customIndex]; 197 | MbBuf[index - i] = MA_Signal.Result[customIndex]; 198 | } 199 | 200 | // Arrows 201 | if (EnableArrowAlerts) 202 | { 203 | int lower_i = Bars.OpenTimes.GetIndexByTime(customBars.OpenTimes[customIndex - int_tc]); 204 | if (EnableRedYellowCrossAlert) 205 | { 206 | if ((MA_Signal.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc - 1] <= VolatilityBands.Main[customIndex - int_tc - 1])) 207 | { 208 | Chart.DrawIcon(ArrowPrefix + "RY" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.UpTriangle, lower_i, Bars.LowPrices[lower_i], Color.FromName(RedYellowCrossArrowBullishColor)); 209 | } 210 | else Chart.RemoveObject(ArrowPrefix + "RY" + Bars.OpenTimes[lower_i].ToString()); 211 | if ((MA_Signal.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc - 1] >= VolatilityBands.Main[customIndex - int_tc - 1])) 212 | { 213 | Chart.DrawIcon(ArrowPrefix + "RY" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.DownTriangle, lower_i, Bars.HighPrices[lower_i], Color.FromName(RedYellowCrossArrowBearishColor)); 214 | } 215 | else Chart.RemoveObject(ArrowPrefix + "RY" + Bars.OpenTimes[lower_i].ToString()); 216 | } 217 | if (EnableHookAlert) 218 | { 219 | if ((MA_Price.Result[customIndex - int_tc] < VolatilityBands.Top[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= VolatilityBands.Top[customIndex - int_tc - 1]) && ((MA_Price.Result[customIndex - int_tc] > 68) || (MA_Price.Result[customIndex - int_tc - 1] > 68)) && ((VolatilityBands.Top[customIndex - int_tc] > 68) || (VolatilityBands.Top[customIndex - int_tc - 1] > 68))) 220 | { 221 | Chart.DrawIcon(ArrowPrefix + "H" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.DownArrow, lower_i, Bars.HighPrices[lower_i], Color.FromName(HookArrowBearishColor)); 222 | } 223 | else Chart.RemoveObject(ArrowPrefix + "H" + Bars.OpenTimes[lower_i].ToString()); 224 | if ((MA_Price.Result[customIndex - int_tc] >= VolatilityBands.Bottom[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] < VolatilityBands.Bottom[customIndex - int_tc - 1]) && ((MA_Price.Result[customIndex - int_tc] < 32) || (MA_Price.Result[customIndex - int_tc - 1] < 32)) && ((VolatilityBands.Bottom[customIndex - int_tc] < 32) || (VolatilityBands.Bottom[customIndex - int_tc - 1] < 32))) 225 | { 226 | Chart.DrawIcon(ArrowPrefix + "H" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.UpArrow, lower_i, Bars.LowPrices[lower_i], Color.FromName(HookArrowBullishColor)); 227 | } 228 | else Chart.RemoveObject(ArrowPrefix + "H" + Bars.OpenTimes[lower_i].ToString()); 229 | } 230 | if (EnableGreenRedCrossAlert) 231 | { 232 | if ((MA_Price.Result[customIndex - int_tc] < MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= MA_Signal.Result[customIndex - int_tc - 1])) 233 | { 234 | Chart.DrawIcon(ArrowPrefix + "GR" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Diamond, lower_i, Bars.HighPrices[lower_i], Color.FromName(HookArrowBearishColor)); 235 | } 236 | else Chart.RemoveObject(ArrowPrefix + "GR" + Bars.OpenTimes[lower_i].ToString()); 237 | if ((MA_Price.Result[customIndex - int_tc] > MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= MA_Signal.Result[customIndex - int_tc - 1])) 238 | { 239 | Chart.DrawIcon(ArrowPrefix + "GR" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Diamond, lower_i, Bars.LowPrices[lower_i], Color.FromName(HookArrowBullishColor)); 240 | } 241 | else Chart.RemoveObject(ArrowPrefix + "GR" + Bars.OpenTimes[lower_i].ToString()); 242 | } 243 | if (EnableGreenRedCrossWithYellowAlert) 244 | { 245 | if ((MA_Price.Result[customIndex - int_tc] < MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= MA_Signal.Result[customIndex - int_tc - 1]) && (MA_Price.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc])) 246 | { 247 | Chart.DrawIcon(ArrowPrefix + "GRY" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Diamond, lower_i, Bars.HighPrices[lower_i], Color.FromName(HookArrowBearishColor)); 248 | } 249 | else Chart.RemoveObject(ArrowPrefix + "GRY" + Bars.OpenTimes[lower_i].ToString()); 250 | if ((MA_Price.Result[customIndex - int_tc] > MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= MA_Signal.Result[customIndex - int_tc - 1]) && (MA_Price.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc])) 251 | { 252 | Chart.DrawIcon(ArrowPrefix + "GRY" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Diamond, lower_i, Bars.LowPrices[lower_i], Color.FromName(HookArrowBullishColor)); 253 | } 254 | else Chart.RemoveObject(ArrowPrefix + "GRY" + Bars.OpenTimes[lower_i].ToString()); 255 | } 256 | if (EnableYellowGreenCrossAlert) 257 | { 258 | if ((MA_Price.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= VolatilityBands.Main[customIndex - int_tc - 1])) 259 | { 260 | Chart.DrawIcon(ArrowPrefix + "YG" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Star, lower_i, Bars.HighPrices[lower_i], Color.FromName(HookArrowBearishColor)); 261 | } 262 | else Chart.RemoveObject(ArrowPrefix + "YG" + Bars.OpenTimes[lower_i].ToString()); 263 | if ((MA_Price.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= VolatilityBands.Main[customIndex - int_tc - 1])) 264 | { 265 | Chart.DrawIcon(ArrowPrefix + "YG" + Bars.OpenTimes[lower_i].ToString(), ChartIconType.Star, lower_i, Bars.LowPrices[lower_i], Color.FromName(HookArrowBullishColor)); 266 | } 267 | else Chart.RemoveObject(ArrowPrefix + "YG" + Bars.OpenTimes[lower_i].ToString()); 268 | } 269 | } 270 | 271 | // Alerts 272 | if (!EnableEmailAlerts) return; // No need to go further. 273 | if ((!EnableRedYellowCrossAlert) && (!EnableHookAlert) && (!EnableGreenRedCrossAlert) && (!EnableYellowGreenCrossAlert)) return; 274 | 275 | string Text = ""; 276 | if ((EnableRedYellowCrossAlert) && (LastAlertTimeRedYellow > unix_epoch) && (customBars.OpenTimes.LastValue > LastAlertTimeRedYellow)) 277 | { 278 | if ((MA_Signal.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc - 1] <= VolatilityBands.Main[customIndex - int_tc - 1])) 279 | { 280 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Bullish cross"; 281 | DoAlert(customIndex, Text); 282 | LastAlertTimeRedYellow = customBars.OpenTimes.LastValue; 283 | } 284 | else if ((MA_Signal.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc - 1] >= VolatilityBands.Main[customIndex - int_tc - 1])) 285 | { 286 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Bearish cross"; 287 | DoAlert(customIndex, Text); 288 | LastAlertTimeRedYellow = customBars.OpenTimes.LastValue; 289 | } 290 | } 291 | if ((EnableHookAlert) && (LastAlertTimeHook > unix_epoch) && (customBars.OpenTimes.LastValue > LastAlertTimeHook)) 292 | { 293 | if ((MA_Price.Result[customIndex - int_tc] < VolatilityBands.Top[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= VolatilityBands.Top[customIndex - int_tc - 1]) && ((MA_Price.Result[customIndex - int_tc] > 68) || (MA_Price.Result[customIndex - int_tc - 1] > 68)) && ((VolatilityBands.Top[customIndex - int_tc] > 68) || (VolatilityBands.Top[customIndex - int_tc - 1] > 68))) 294 | { 295 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Hook cross down"; 296 | DoAlert(customIndex, Text); 297 | LastAlertTimeHook = customBars.OpenTimes.LastValue; 298 | } 299 | else if ((MA_Price.Result[customIndex - int_tc] >= VolatilityBands.Bottom[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] < VolatilityBands.Bottom[customIndex - int_tc - 1]) && ((MA_Price.Result[customIndex - int_tc] < 32) || (MA_Price.Result[customIndex - int_tc - 1] < 32)) && ((VolatilityBands.Bottom[customIndex - int_tc] < 32) || (VolatilityBands.Bottom[customIndex - int_tc - 1] < 32))) 300 | { 301 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Hook cross up"; 302 | DoAlert(customIndex, Text); 303 | LastAlertTimeHook = customBars.OpenTimes.LastValue; 304 | } 305 | } 306 | if ((EnableGreenRedCrossAlert) && (LastAlertTimeGreenRed > unix_epoch) && (customBars.OpenTimes.LastValue > LastAlertTimeGreenRed)) 307 | { 308 | if ((MA_Price.Result[customIndex - int_tc] < MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= MA_Signal.Result[customIndex - int_tc - 1])) 309 | { 310 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed red one from above"; 311 | DoAlert(customIndex, Text); 312 | LastAlertTimeGreenRed = customBars.OpenTimes.LastValue; 313 | } 314 | else if ((MA_Price.Result[customIndex - int_tc] > MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= MA_Signal.Result[customIndex - int_tc - 1])) 315 | { 316 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed red one from below"; 317 | DoAlert(customIndex, Text); 318 | LastAlertTimeGreenRed = customBars.OpenTimes.LastValue; 319 | } 320 | } 321 | if ((EnableGreenRedCrossWithYellowAlert) && (LastAlertTimeGreenRed > unix_epoch) && (customBars.OpenTimes.LastValue > LastAlertTimeGreenRed)) 322 | { 323 | if ((MA_Price.Result[customIndex - int_tc] < MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= MA_Signal.Result[customIndex - int_tc - 1]) && (MA_Price.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc])) 324 | { 325 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed red one from above while both below yellow"; 326 | DoAlert(customIndex, Text); 327 | LastAlertTimeGreenRed = customBars.OpenTimes.LastValue; 328 | } 329 | else if ((MA_Price.Result[customIndex - int_tc] > MA_Signal.Result[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= MA_Signal.Result[customIndex - int_tc - 1]) && (MA_Price.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Signal.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc])) 330 | { 331 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed red one from below while both above yellow"; 332 | DoAlert(customIndex, Text); 333 | LastAlertTimeGreenRed = customBars.OpenTimes.LastValue; 334 | } 335 | } 336 | if ((EnableYellowGreenCrossAlert) && (LastAlertTimeYellowGreen > unix_epoch) && (customBars.OpenTimes.LastValue > LastAlertTimeYellowGreen)) 337 | { 338 | if ((MA_Price.Result[customIndex - int_tc] < VolatilityBands.Main[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] >= VolatilityBands.Main[customIndex - int_tc - 1])) 339 | { 340 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed yellow one from above"; 341 | DoAlert(customIndex, Text); 342 | LastAlertTimeYellowGreen = customBars.OpenTimes.LastValue; 343 | } 344 | else if ((MA_Price.Result[customIndex - int_tc] > VolatilityBands.Main[customIndex - int_tc]) && (MA_Price.Result[customIndex - int_tc - 1] <= VolatilityBands.Main[customIndex - int_tc - 1])) 345 | { 346 | Text = "TDI Alert: " + Symbol.Name + " - " + TimeFrame.Name + " - Green line crossed yellow one from below"; 347 | DoAlert(customIndex, Text); 348 | LastAlertTimeYellowGreen = customBars.OpenTimes.LastValue; 349 | } 350 | } 351 | 352 | if ((LastAlertTimeRedYellow == unix_epoch) && (prev_index == index)) LastAlertTimeRedYellow = customBars.OpenTimes.LastValue; 353 | if ((LastAlertTimeHook == unix_epoch) && (prev_index == index)) LastAlertTimeHook = customBars.OpenTimes.LastValue; 354 | if ((LastAlertTimeGreenRed == unix_epoch) && (prev_index == index)) LastAlertTimeGreenRed = customBars.OpenTimes.LastValue; 355 | if ((LastAlertTimeYellowGreen == unix_epoch) && (prev_index == index)) LastAlertTimeYellowGreen = customBars.OpenTimes.LastValue; 356 | prev_index = index; 357 | } 358 | 359 | protected override void OnDestroy() 360 | { 361 | if (EnableArrowAlerts) 362 | { 363 | var icons = Chart.FindAllObjects(ChartObjectType.Icon); 364 | for (int i = icons.Length - 1; i >= 0; i--) 365 | { 366 | if (icons[i].Name.StartsWith(ArrowPrefix)) 367 | { 368 | Chart.RemoveObject(icons[i].Name); 369 | } 370 | } 371 | } 372 | } 373 | 374 | private void DoAlert(int customIndex, string text) 375 | { 376 | text += "\nCurrent rate = " + Symbol.Bid.ToString() + "/" + Symbol.Ask.ToString() + 377 | "\nIndicator buffers:\nVB High = " + VolatilityBands.Top[customIndex - int_tc].ToString() + 378 | "\nMarket Base Line = " + VolatilityBands.Main[customIndex - int_tc].ToString() + 379 | "\nVB Low = " + VolatilityBands.Bottom[customIndex - int_tc].ToString() + 380 | "\nRSI Price Line = " + MA_Price.Result[customIndex - int_tc].ToString() + 381 | "\nTrade Signal Line = " + MA_Signal.Result[customIndex - int_tc].ToString(); 382 | Notifications.SendEmail(AlertEmailFrom, AlertEmailTo, "TDI Alert - " + Symbol.Name + " @ " + TimeFrame.Name, text); 383 | } 384 | } 385 | } -------------------------------------------------------------------------------- /TradersDynamicIndex.mq4: -------------------------------------------------------------------------------- 1 | //+------------------------------------------------------------------+ 2 | //| TraderDynamicIndex.mq4 | 3 | //| Copyright © 2025, EarnForex | 4 | //| https://www.earnforex.com | 5 | //| Based on indicator by Dean Malone (2006) | 6 | //+------------------------------------------------------------------+ 7 | #property copyright "www.EarnForex.com, 2025" 8 | #property link "https://www.earnforex.com/metatrader-indicators/Traders-Dynamic-Index/" 9 | #property version "1.08" 10 | #property strict 11 | 12 | #property description "Shows trend direction, strength, and volatility." 13 | #property description "Green line - RSI Price line." 14 | #property description "Red line - Trade Signal line." 15 | #property description "Blue lines - Volatility Band." 16 | #property description "Yellow line - Market Base line." 17 | 18 | #property indicator_separate_window 19 | #property indicator_buffers 6 20 | #property indicator_level1 32 21 | #property indicator_level2 50 22 | #property indicator_level3 68 23 | #property indicator_minimum 0 24 | #property indicator_maximum 100 25 | #property indicator_levelcolor clrDimGray 26 | #property indicator_levelstyle STYLE_DOT 27 | #property indicator_levelwidth 1 28 | #property indicator_color1 clrNONE 29 | #property indicator_type1 DRAW_NONE 30 | #property indicator_color2 clrMediumBlue 31 | #property indicator_label2 "VB High" 32 | #property indicator_type2 DRAW_LINE 33 | #property indicator_color3 clrYellow 34 | #property indicator_label3 "Market Base Line" 35 | #property indicator_type3 DRAW_LINE 36 | #property indicator_width3 2 37 | #property indicator_color4 clrMediumBlue 38 | #property indicator_label4 "VB Low" 39 | #property indicator_type4 DRAW_LINE 40 | #property indicator_color5 clrGreen 41 | #property indicator_label5 "RSI Price Line" 42 | #property indicator_type5 DRAW_LINE 43 | #property indicator_width5 2 44 | #property indicator_color6 clrRed 45 | #property indicator_label6 "Trade Signal Line" 46 | #property indicator_type6 DRAW_LINE 47 | #property indicator_width6 2 48 | 49 | enum enum_arrow_type 50 | { 51 | Buy, 52 | Sell 53 | }; 54 | 55 | enum enum_candle_to_check 56 | { 57 | Current, 58 | Previous 59 | }; 60 | 61 | input string ____Main = ""; 62 | input int RSI_Period = 13; // RSI_Period: 8-25 63 | input ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE; 64 | input int Volatility_Band = 34; // Volatility_Band: 20-40 65 | input double StdDev = 1.6185; // Standard Deviations: 1-3 66 | input int RSI_Price_Line = 2; 67 | input ENUM_MA_METHOD RSI_Price_Type = MODE_SMA; 68 | input int Trade_Signal_Line = 7; 69 | input ENUM_MA_METHOD Trade_Signal_Type = MODE_SMA; 70 | input ENUM_TIMEFRAMES UpperTimeframe = PERIOD_CURRENT; // UpperTimeframe: If above current will display values from that timeframe. 71 | input string ____Alerts = ""; 72 | input bool EnableNativeAlerts = false; 73 | input bool EnableEmailAlerts = false; 74 | input bool EnablePushAlerts = false; 75 | input bool EnableArrowAlerts = false; 76 | input bool EnableRedYellowCrossAlert = true; // EnableRedYellowCrossAlert: yellow/red lines alerts. 77 | input bool EnableHookAlert = false; // EnableHookAlert: Enable green line hook alerts. 78 | input bool EnableGreenRedCrossAlert = false; // EnableGreenRedCrossAlert: green/red lines alerts. 79 | input bool EnableGreenRedCrossWithYellowAlert = false; // EnableGreenRedCrossWithYellowAlert: green/red with yellow lines alerts. 80 | input bool EnableYellowGreenCrossAlert = false; // EnableYellowGreenCrossAlert: yellow/green lines alerts. 81 | input enum_candle_to_check TriggerCandle = Previous; 82 | input string ____Arrows = ""; 83 | input color RedYellowCrossArrowBullishColor = clrGreen; 84 | input color RedYellowCrossArrowBearishColor = clrRed; 85 | input color HookArrowBullishColor = clrGreen; 86 | input color HookArrowBearishColor = clrRed; 87 | input color GreenRedCrossArrowBullishColor = clrGreen; 88 | input color GreenRedCrossArrowBearishColor = clrRed; 89 | input color YellowGreenCrossArrowBullishColor = clrGreen; 90 | input color YellowGreenCrossArrowBearishColor = clrRed; 91 | input uchar RedYellowCrossArrowBullishCode = 233; 92 | input uchar RedYellowCrossArrowBearishCode = 234; 93 | input uchar HookArrowBullishCode = 71; 94 | input uchar HookArrowBearishCode = 72; 95 | input uchar GreenRedCrossArrowBullishCode = 200; 96 | input uchar GreenRedCrossArrowBearishCode = 201; 97 | input uchar YellowGreenCrossArrowBullishCode = 226; 98 | input uchar YellowGreenCrossArrowBearishCode = 225; 99 | input int ArrowSize = 1; 100 | input string ArrowPrefix = "TDI-"; 101 | 102 | double RSIBuf[], UpZone[], MdZone[], DnZone[], MaBuf[], MbBuf[]; 103 | double _RSIBuf[], _UpZone[], _MdZone[], _DnZone[], _MaBuf[], _MbBuf[]; // For upper timeframe data. 104 | 105 | datetime AlertPlayed = 0, HookAlertPlayed = 0, RedGreenAlertPlayed = 0, YellowGreenAlertPlayed = 0; 106 | 107 | int OnInit() 108 | { 109 | if (PeriodSeconds(UpperTimeframe) < PeriodSeconds()) 110 | { 111 | Print("Upper timeframe cannot be lower than the current timeframe."); 112 | return INIT_PARAMETERS_INCORRECT; 113 | } 114 | 115 | IndicatorShortName("TDI (" + IntegerToString(RSI_Period) + ", " + IntegerToString(Volatility_Band) + ", " + IntegerToString(RSI_Price_Line) + ", " + IntegerToString(Trade_Signal_Line) + ")"); 116 | 117 | SetIndexBuffer(0, RSIBuf); 118 | SetIndexBuffer(1, UpZone); 119 | SetIndexBuffer(2, MdZone); // Yellow 120 | SetIndexBuffer(3, DnZone); 121 | SetIndexBuffer(4, MaBuf); // Green 122 | SetIndexBuffer(5, MbBuf); // Red 123 | 124 | if (UpperTimeframe != Period()) 125 | { 126 | IndicatorBuffers(12); 127 | SetIndexBuffer(6, _RSIBuf); 128 | SetIndexBuffer(7, _UpZone); 129 | SetIndexBuffer(8, _MdZone); 130 | SetIndexBuffer(9, _DnZone); 131 | SetIndexBuffer(10, _MaBuf); 132 | SetIndexBuffer(11, _MbBuf); 133 | } 134 | 135 | IndicatorDigits(1); 136 | 137 | return INIT_SUCCEEDED; 138 | } 139 | 140 | void OnDeinit(const int reason) 141 | { 142 | ObjectsDeleteAll(ChartID(), ArrowPrefix, 0, OBJ_ARROW); 143 | } 144 | 145 | int OnCalculate(const int rates_total, 146 | const int prev_calculated, 147 | const datetime& time[], 148 | const double& open[], 149 | const double& high[], 150 | const double& low[], 151 | const double& close[], 152 | const long& tick_volume[], 153 | const long& volume[], 154 | const int& spread[] 155 | ) 156 | { 157 | int counted_bars = IndicatorCounted(); 158 | if (counted_bars > 0) counted_bars--; 159 | int limit = Bars - 1 - counted_bars; 160 | if (PeriodSeconds(UpperTimeframe) == PeriodSeconds(Period())) 161 | { 162 | if (FillIndicatorBuffers((ENUM_TIMEFRAMES)Period(), limit, RSIBuf, UpZone, DnZone, MdZone, MaBuf, MbBuf) < 0) return 0; // Bad value returned. Data not yet ready. Recalculate everything. 163 | } 164 | else 165 | { 166 | static int upper_prev_counted = 0; 167 | if (upper_prev_counted > 0) upper_prev_counted--; 168 | int upper_limit = iBars(Symbol(), UpperTimeframe) - 1 - upper_prev_counted; 169 | if (upper_limit > Bars - Volatility_Band) upper_limit = Bars - Volatility_Band; // Buffers cannot hold more than the current period's bars worth of data! 170 | upper_prev_counted = FillIndicatorBuffers(UpperTimeframe, upper_limit, _RSIBuf, _UpZone, _DnZone, _MdZone, _MaBuf, _MbBuf); 171 | if (upper_prev_counted < -1) return 0; // Bad value returned. Data not yet ready. Recalculate everything. 172 | for (int i = 0, j = 0; Time[i] >= iTime(Symbol(), UpperTimeframe, upper_limit); i++) 173 | { 174 | while ((iTime(Symbol(), UpperTimeframe, j) > Time[i]) && (j < iBars(Symbol(), UpperTimeframe))) j++; 175 | if (j >= iBars(Symbol(), UpperTimeframe)) break; 176 | RSIBuf[i] = _RSIBuf[j]; 177 | UpZone[i] = _UpZone[j]; 178 | DnZone[i] = _DnZone[j]; 179 | MdZone[i] = _MdZone[j]; 180 | MaBuf[i] = _MaBuf[j]; 181 | MbBuf[i] = _MbBuf[j]; 182 | if (i + 1 == Bars) break; 183 | } 184 | } 185 | 186 | if (EnableRedYellowCrossAlert) 187 | { 188 | if ((MbBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MbBuf[TriggerCandle + 1] <= MdZone[TriggerCandle + 1]) && (AlertPlayed != Time[0])) 189 | { 190 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Bullish cross"); 191 | if (EnableEmailAlerts) 192 | { 193 | RefreshRates(); 194 | SendMail("TDI Alert: BUY " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 195 | } 196 | if (EnablePushAlerts) SendNotification("TDI Alert: BUY " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 197 | AlertPlayed = Time[0]; 198 | } 199 | if ((MbBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MbBuf[TriggerCandle + 1] >= MdZone[TriggerCandle + 1]) && (AlertPlayed != Time[0])) 200 | { 201 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Bearish cross"); 202 | if (EnableEmailAlerts) 203 | { 204 | RefreshRates(); 205 | SendMail("TDI Alert: SELL " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 206 | } 207 | if (EnablePushAlerts) SendNotification("TDI Alert: SELL " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 208 | AlertPlayed = Time[0]; 209 | } 210 | } 211 | 212 | if (EnableHookAlert) 213 | { 214 | // Green line crosses upper blue line from above when both are above level 68. 215 | if ((MaBuf[TriggerCandle] < UpZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= UpZone[TriggerCandle + 1]) && ((MaBuf[TriggerCandle] > 68) || (MaBuf[TriggerCandle + 1] > 68)) && ((UpZone[TriggerCandle] > 68) || (UpZone[TriggerCandle + 1] > 68)) && (HookAlertPlayed != Time[0])) 216 | { 217 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Bearish Hook"); 218 | if (EnableEmailAlerts) 219 | { 220 | RefreshRates(); 221 | SendMail("TDI Hook Alert: SELL " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 222 | } 223 | if (EnablePushAlerts) SendNotification("TDI Hook Alert: SELL " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 224 | HookAlertPlayed = Time[0]; 225 | } 226 | // Green line crosses lower blue line from below when both are below level 32. 227 | else if ((MaBuf[TriggerCandle] > DnZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= DnZone[TriggerCandle + 1]) && ((MaBuf[TriggerCandle] < 32) || (MaBuf[TriggerCandle + 1] < 32)) && ((DnZone[TriggerCandle] < 32) || (DnZone[TriggerCandle + 1] < 32)) && (HookAlertPlayed != Time[0])) 228 | { 229 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Bullish Hook"); 230 | if (EnableEmailAlerts) 231 | { 232 | RefreshRates(); 233 | SendMail("TDI Hook Alert: BUY " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 234 | } 235 | if (EnablePushAlerts) SendNotification("TDI Hook Alert: BUY " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 236 | HookAlertPlayed = Time[0]; 237 | } 238 | } 239 | 240 | if (EnableGreenRedCrossAlert) 241 | { 242 | // Green line crosses red one from above. 243 | if ((MaBuf[TriggerCandle] < MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MbBuf[TriggerCandle + 1]) && (RedGreenAlertPlayed != Time[0])) 244 | { 245 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed red one from above"); 246 | if (EnableEmailAlerts) 247 | { 248 | RefreshRates(); 249 | SendMail("TDI: Green line crossed red one from above - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 250 | } 251 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from above - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 252 | RedGreenAlertPlayed = Time[0]; 253 | } 254 | // Green line crosses red one from below. 255 | else if ((MaBuf[TriggerCandle] > MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MbBuf[TriggerCandle + 1]) && (RedGreenAlertPlayed != Time[0])) 256 | { 257 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed red one from below"); 258 | if (EnableEmailAlerts) 259 | { 260 | RefreshRates(); 261 | SendMail("TDI: Green line crossed red one from below - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 262 | } 263 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from below - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 264 | RedGreenAlertPlayed = Time[0]; 265 | } 266 | } 267 | 268 | if (EnableGreenRedCrossWithYellowAlert) 269 | { 270 | // Green line crosses red one from above and both are below the yellow line. 271 | if ((MaBuf[TriggerCandle] < MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MbBuf[TriggerCandle + 1]) && (MaBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MbBuf[TriggerCandle] < MdZone[TriggerCandle]) && (RedGreenAlertPlayed != Time[0])) 272 | { 273 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed red one from above while both below yellow"); 274 | if (EnableEmailAlerts) 275 | { 276 | RefreshRates(); 277 | SendMail("TDI: Green line crossed red one from above while both below yellow - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 278 | } 279 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from above while both below yellow - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 280 | RedGreenAlertPlayed = Time[0]; 281 | } 282 | // Green line crosses red one from below and both are above the yellow line. 283 | else if ((MaBuf[TriggerCandle] > MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MbBuf[TriggerCandle + 1]) && (MaBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MbBuf[TriggerCandle] > MdZone[TriggerCandle]) && (RedGreenAlertPlayed != Time[0])) 284 | { 285 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed red one from below while both above yellow"); 286 | if (EnableEmailAlerts) 287 | { 288 | RefreshRates(); 289 | SendMail("TDI: Green line crossed red one from below while both above yellow - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 290 | } 291 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from below while both above yellow - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 292 | RedGreenAlertPlayed = Time[0]; 293 | } 294 | } 295 | 296 | if (EnableYellowGreenCrossAlert) 297 | { 298 | // Green line crosses yellow one from above. 299 | if ((MaBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MdZone[TriggerCandle + 1]) && (YellowGreenAlertPlayed != Time[0])) 300 | { 301 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed yellow one from above"); 302 | if (EnableEmailAlerts) 303 | { 304 | RefreshRates(); 305 | SendMail("TDI: Green line crossed yellow one from above - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 306 | } 307 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed yellow one from above - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 308 | YellowGreenAlertPlayed = Time[0]; 309 | } 310 | // Green line crosses yellow one from below. 311 | else if ((MaBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MdZone[TriggerCandle + 1]) && (YellowGreenAlertPlayed != Time[0])) 312 | { 313 | if (EnableNativeAlerts) Alert(_Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period) + " - Green line crossed yellow one from below"); 314 | if (EnableEmailAlerts) 315 | { 316 | RefreshRates(); 317 | SendMail("TDI: Green line crossed yellow one from below - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period), "Current rate = " + DoubleToString(Bid, _Digits) + "/" + DoubleToString(Ask, _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 318 | } 319 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed yellow one from below - " + _Symbol + " @ " + TimeframeToString((ENUM_TIMEFRAMES)_Period)); 320 | YellowGreenAlertPlayed = Time[0]; 321 | } 322 | } 323 | 324 | return rates_total; 325 | } 326 | 327 | // Standard Deviation function. 328 | double StDev(double& Data[], const int Per) 329 | { 330 | return MathSqrt(Variance(Data, Per)); 331 | } 332 | 333 | // Math Variance function. 334 | double Variance(double& Data[], const int Per) 335 | { 336 | double sum = 0, ssum = 0; 337 | for (int i = 0; i < Per; i++) 338 | { 339 | sum += Data[i]; 340 | ssum += MathPow(Data[i], 2); 341 | } 342 | return ((ssum * Per - sum * sum) / (Per * (Per - 1))); 343 | } 344 | 345 | // For alerts. 346 | string TimeframeToString(ENUM_TIMEFRAMES P) 347 | { 348 | return StringSubstr(EnumToString(P), 7); 349 | } 350 | 351 | void PutArrow(const double price, const datetime time, enum_arrow_type dir, const color colour, const uchar arrow_code, const string text) 352 | { 353 | string name = ArrowPrefix + "Arrow" + IntegerToString(arrow_code) + TimeToString(time); 354 | if (ObjectFind(ChartID(), name) > -1) return; 355 | ENUM_ARROW_ANCHOR anchor; 356 | if (dir == Buy) 357 | { 358 | anchor = ANCHOR_TOP; 359 | } 360 | else 361 | { 362 | anchor = ANCHOR_BOTTOM; 363 | } 364 | ObjectCreate(ChartID(), name, OBJ_ARROW, 0, time, price); 365 | ObjectSetInteger(0, name, OBJPROP_ARROWCODE, arrow_code); 366 | ObjectSetInteger(0, name, OBJPROP_WIDTH, ArrowSize); 367 | ObjectSetInteger(0, name, OBJPROP_COLOR, colour); 368 | ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); 369 | ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); 370 | ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor); 371 | ObjectSetString(0, name, OBJPROP_TOOLTIP, text); 372 | } 373 | 374 | void RemoveArrow(const datetime time, const uchar arrow_code) 375 | { 376 | string name = ArrowPrefix + "Arrow" + IntegerToString(arrow_code) + TimeToString(time); 377 | ObjectDelete(0, name); 378 | } 379 | 380 | // Returns the number processed bars. 381 | int FillIndicatorBuffers(ENUM_TIMEFRAMES period, int limit, double& rsibuf[], double& upzone[], double& dnzone[], double& mdzone[], double& mabuf[], double& mbbuf[]) 382 | { 383 | double MA, RSI[]; 384 | ArrayResize(RSI, Volatility_Band); 385 | int bars = iBars(Symbol(), period); 386 | int adjusted_limit = MathMax(MathMax(limit, Trade_Signal_Line), RSI_Price_Line); 387 | for (int i = adjusted_limit; i >= 0; i--) 388 | { 389 | rsibuf[i] = iRSI(NULL, period, RSI_Period, RSI_Price, i); 390 | MA = 0; 391 | for (int x = i; x < i + Volatility_Band; x++) 392 | { 393 | if (x > bars - 1) break; 394 | if ((rsibuf[x] > 100) || (rsibuf[x] < 0)) return -1; // Bad RSI value. Try later. 395 | RSI[x - i] = rsibuf[x]; 396 | MA += rsibuf[x] / Volatility_Band; 397 | } 398 | double SD = StdDev * StDev(RSI, Volatility_Band); 399 | upzone[i] = MA + SD; 400 | dnzone[i] = MA - SD; 401 | mdzone[i] = (upzone[i] + dnzone[i]) / 2; 402 | } 403 | for (int i = limit; i >= 0; i--) 404 | { 405 | mabuf[i] = iMAOnArray(rsibuf, 0, RSI_Price_Line, 0, RSI_Price_Type, i); 406 | mbbuf[i] = iMAOnArray(rsibuf, 0, Trade_Signal_Line, 0, Trade_Signal_Type, i); 407 | 408 | if (EnableArrowAlerts) 409 | { 410 | if (i + TriggerCandle + 1 >= iBars(Symbol(), period)) continue; // Check if there is enough bars. 411 | // Lower timeframe bar index: 412 | int lower_i = iBarShift(Symbol(), Period(), iTime(Symbol(), period, i + TriggerCandle), false); 413 | if (EnableRedYellowCrossAlert) 414 | { 415 | if ((mbbuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle + 1] <= mdzone[i + TriggerCandle + 1])) 416 | { 417 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, RedYellowCrossArrowBullishColor, RedYellowCrossArrowBullishCode, "Bullish cross"); 418 | } 419 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), RedYellowCrossArrowBullishCode); 420 | if ((mbbuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle + 1] >= mdzone[i + TriggerCandle + 1])) 421 | { 422 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, RedYellowCrossArrowBearishColor, RedYellowCrossArrowBearishCode, "Bearish cross"); 423 | } 424 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), RedYellowCrossArrowBearishCode); 425 | } 426 | if (EnableHookAlert) 427 | { 428 | // Green line crosses upper blue line from above when both are above level 68. 429 | if ((mabuf[i + TriggerCandle] < upzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= upzone[i + TriggerCandle + 1]) && ((mabuf[i + TriggerCandle] > 68) || (mabuf[i + TriggerCandle + 1] > 68)) && ((upzone[i + TriggerCandle] > 68) || (upzone[i + TriggerCandle + 1] > 68))) 430 | { 431 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, HookArrowBearishColor, HookArrowBearishCode, "Bearish Hook"); 432 | } 433 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), HookArrowBearishCode); 434 | // Green line crosses lower blue line from below when both are below level 32. 435 | if ((mabuf[i + TriggerCandle] > dnzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= dnzone[i + TriggerCandle + 1]) && ((mabuf[i + TriggerCandle] < 32) || (mabuf[i + TriggerCandle + 1] < 32)) && ((dnzone[i + TriggerCandle] < 32) || (dnzone[i + TriggerCandle + 1] < 32))) 436 | { 437 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, HookArrowBullishColor, HookArrowBullishCode, "Bullish Hook"); 438 | } 439 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), HookArrowBullishCode); 440 | } 441 | if (EnableGreenRedCrossAlert) 442 | { 443 | // Green line crosses red one from above. 444 | if ((mabuf[i + TriggerCandle] < mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mbbuf[i + TriggerCandle + 1])) 445 | { 446 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, GreenRedCrossArrowBearishColor, GreenRedCrossArrowBearishCode, "Green line crossed red one from above"); 447 | } 448 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBearishCode); 449 | // Green line crosses red one from below. 450 | if ((mabuf[i + TriggerCandle] > mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mbbuf[i + TriggerCandle + 1])) 451 | { 452 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, GreenRedCrossArrowBullishColor, GreenRedCrossArrowBullishCode, "Green line crossed red one from below"); 453 | } 454 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBullishCode); 455 | } 456 | if (EnableGreenRedCrossWithYellowAlert) 457 | { 458 | // Green line crosses red one from above and both are below the yellow line. 459 | if ((mabuf[i + TriggerCandle] < mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mbbuf[i + TriggerCandle + 1]) && (mabuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle] < mdzone[i + TriggerCandle])) 460 | { 461 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, GreenRedCrossArrowBearishColor, GreenRedCrossArrowBearishCode, "Green line crossed red one from above while both below yellow"); 462 | } 463 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBearishCode); 464 | // Green line crosses red one from below and both are above the yellow line. 465 | if ((mabuf[i + TriggerCandle] > mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mbbuf[i + TriggerCandle + 1]) && (mabuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle] > mdzone[i + TriggerCandle])) 466 | { 467 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, GreenRedCrossArrowBullishColor, GreenRedCrossArrowBullishCode, "Green line crossed red one from below while both above yellow"); 468 | } 469 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBullishCode); 470 | } 471 | if (EnableYellowGreenCrossAlert) 472 | { 473 | // Green line crosses yellow one from above. 474 | if ((mabuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mdzone[i + TriggerCandle + 1])) 475 | { 476 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, YellowGreenCrossArrowBearishColor, YellowGreenCrossArrowBullishCode, "Green line crossed yellow one from above"); 477 | } 478 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), YellowGreenCrossArrowBullishCode); 479 | // Green line crosses yellow one from below. 480 | if ((mabuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mdzone[i + TriggerCandle + 1])) 481 | { 482 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, YellowGreenCrossArrowBullishColor, YellowGreenCrossArrowBearishCode, "Green line crossed yellow one from below"); 483 | } 484 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), YellowGreenCrossArrowBearishCode); 485 | } 486 | } 487 | } 488 | return bars; 489 | } 490 | //+------------------------------------------------------------------+ -------------------------------------------------------------------------------- /TradersDynamicIndex.mq5: -------------------------------------------------------------------------------- 1 | //+------------------------------------------------------------------+ 2 | //| TradersDynamicIndex.mq5 | 3 | //| Copyright © 2025, EarnForex | 4 | //| https://www.earnforex.com | 5 | //| Based on indicator by Dean Malone (2006) | 6 | //+------------------------------------------------------------------+ 7 | #property copyright "www.EarnForex.com, 2025" 8 | #property link "https://www.earnforex.com/metatrader-indicators/Traders-Dynamic-Index/" 9 | #property version "1.08" 10 | 11 | #property description "Shows trend direction, strength, and volatility." 12 | #property description "Green line - RSI Price line." 13 | #property description "Red line - Trade Signal line." 14 | #property description "Blue lines - Volatility Band." 15 | #property description "Yellow line - Market Base line." 16 | 17 | #property indicator_separate_window 18 | #property indicator_buffers 12 // 6 + 6 possible with upper timeframe. 19 | #property indicator_plots 5 20 | #property indicator_level1 32 21 | #property indicator_level2 50 22 | #property indicator_level3 68 23 | #property indicator_minimum 0 24 | #property indicator_maximum 100 25 | #property indicator_levelcolor clrDimGray 26 | #property indicator_levelstyle STYLE_DOT 27 | #property indicator_levelwidth 1 28 | #property indicator_color1 clrMediumBlue 29 | #property indicator_label1 "VB High" 30 | #property indicator_type1 DRAW_LINE 31 | #property indicator_color2 clrYellow 32 | #property indicator_label2 "Market Base Line" 33 | #property indicator_type2 DRAW_LINE 34 | #property indicator_width2 2 35 | #property indicator_color3 clrMediumBlue 36 | #property indicator_label3 "VB Low" 37 | #property indicator_type3 DRAW_LINE 38 | #property indicator_color4 clrGreen 39 | #property indicator_label4 "RSI Price Line" 40 | #property indicator_type4 DRAW_LINE 41 | #property indicator_width4 2 42 | #property indicator_color5 clrRed 43 | #property indicator_label5 "Trade Signal Line" 44 | #property indicator_type5 DRAW_LINE 45 | #property indicator_width5 2 46 | 47 | enum enum_arrow_type 48 | { 49 | Buy, 50 | Sell 51 | }; 52 | 53 | enum enum_candle_to_check 54 | { 55 | Current, 56 | Previous 57 | }; 58 | 59 | input group "Main"; 60 | input int RSI_Period = 13; // RSI_Period: 8-25 61 | input ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE; 62 | input int Volatility_Band = 34; // Volatility_Band: 20-40 63 | input double StdDev = 1.6185; // Standard Deviations: 1-3 64 | input int RSI_Price_Line = 2; 65 | input ENUM_MA_METHOD RSI_Price_Type = MODE_SMA; 66 | input int Trade_Signal_Line = 7; 67 | input ENUM_MA_METHOD Trade_Signal_Type = MODE_SMA; 68 | input ENUM_TIMEFRAMES UpperTimeframe = PERIOD_CURRENT; // UpperTimeframe: If above current will display values from that timeframe. 69 | input group "Alerts"; 70 | input bool EnableNativeAlerts = false; 71 | input bool EnableEmailAlerts = false; 72 | input bool EnablePushAlerts = false; 73 | input bool EnableArrowAlerts = false; 74 | input bool EnableRedYellowCrossAlert = true; // EnableRedYellowCrossAlert: yellow/red lines alerts. 75 | input bool EnableHookAlert = false; // EnableHookAlert: Enable green line hook alerts. 76 | input bool EnableGreenRedCrossAlert = false; // EnableGreenRedCrossAlert: green/red lines alerts. 77 | input bool EnableGreenRedCrossWithYellowAlert = false; // EnableGreenRedCrossWithYellowAlert: green/red with yellow lines alerts. 78 | input bool EnableYellowGreenCrossAlert = false; // EnableYellowGreenCrossAlert: yellow/green lines alerts. 79 | input enum_candle_to_check TriggerCandle = Previous; 80 | input group "Arrows"; 81 | input color RedYellowCrossArrowBullishColor = clrGreen; 82 | input color RedYellowCrossArrowBearishColor = clrRed; 83 | input color HookArrowBullishColor = clrGreen; 84 | input color HookArrowBearishColor = clrRed; 85 | input color GreenRedCrossArrowBullishColor = clrGreen; 86 | input color GreenRedCrossArrowBearishColor = clrRed; 87 | input color YellowGreenCrossArrowBullishColor = clrGreen; 88 | input color YellowGreenCrossArrowBearishColor = clrRed; 89 | input uchar RedYellowCrossArrowBullishCode = 233; 90 | input uchar RedYellowCrossArrowBearishCode = 234; 91 | input uchar HookArrowBullishCode = 71; 92 | input uchar HookArrowBearishCode = 72; 93 | input uchar GreenRedCrossArrowBullishCode = 200; 94 | input uchar GreenRedCrossArrowBearishCode = 201; 95 | input uchar YellowGreenCrossArrowBullishCode = 226; 96 | input uchar YellowGreenCrossArrowBearishCode = 225; 97 | input int ArrowSize = 1; 98 | input string ArrowPrefix = "TDI-"; 99 | 100 | double RSIBuf[], UpZone[], MdZone[], DnZone[], MaBuf[], MbBuf[]; 101 | double _RSIBuf[], _UpZone[], _MdZone[], _DnZone[], _MaBuf[], _MbBuf[]; // For upper timeframe data. 102 | 103 | int MaxPeriod = 0; 104 | 105 | datetime AlertPlayed = 0, HookAlertPlayed = 0, RedGreenAlertPlayed = 0, YellowGreenAlertPlayed = 0; 106 | 107 | int RSI_handle; 108 | 109 | int OnInit() 110 | { 111 | if (PeriodSeconds(UpperTimeframe) < PeriodSeconds()) 112 | { 113 | Print("Upper timeframe cannot be lower than the current timeframe."); 114 | return INIT_PARAMETERS_INCORRECT; 115 | } 116 | 117 | IndicatorSetString(INDICATOR_SHORTNAME, "TDI (" + IntegerToString(RSI_Period) + "," + IntegerToString(Volatility_Band) + "," + IntegerToString(RSI_Price_Line) + "," + IntegerToString(Trade_Signal_Line) + ")"); 118 | 119 | SetIndexBuffer(0, UpZone, INDICATOR_DATA); 120 | SetIndexBuffer(1, MdZone, INDICATOR_DATA); 121 | SetIndexBuffer(2, DnZone, INDICATOR_DATA); 122 | SetIndexBuffer(3, MaBuf, INDICATOR_DATA); 123 | SetIndexBuffer(4, MbBuf, INDICATOR_DATA); 124 | SetIndexBuffer(5, RSIBuf, INDICATOR_CALCULATIONS); 125 | 126 | ArraySetAsSeries(UpZone, true); 127 | ArraySetAsSeries(MdZone, true); 128 | ArraySetAsSeries(DnZone, true); 129 | ArraySetAsSeries(MaBuf, true); 130 | ArraySetAsSeries(MbBuf, true); 131 | ArraySetAsSeries(RSIBuf, true); 132 | 133 | PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); 134 | PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0); 135 | PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0); 136 | PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0); 137 | PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0); 138 | 139 | if (PeriodSeconds(UpperTimeframe) != PeriodSeconds(Period())) 140 | { 141 | SetIndexBuffer(6, _RSIBuf, INDICATOR_CALCULATIONS); 142 | SetIndexBuffer(7, _UpZone, INDICATOR_CALCULATIONS); 143 | SetIndexBuffer(8, _MdZone, INDICATOR_CALCULATIONS); 144 | SetIndexBuffer(9, _DnZone, INDICATOR_CALCULATIONS); 145 | SetIndexBuffer(10, _MaBuf, INDICATOR_CALCULATIONS); 146 | SetIndexBuffer(11, _MbBuf, INDICATOR_CALCULATIONS); 147 | ArraySetAsSeries(_UpZone, true); 148 | ArraySetAsSeries(_MdZone, true); 149 | ArraySetAsSeries(_DnZone, true); 150 | ArraySetAsSeries(_MaBuf, true); 151 | ArraySetAsSeries(_MbBuf, true); 152 | ArraySetAsSeries(_RSIBuf, true); 153 | } 154 | 155 | IndicatorSetInteger(INDICATOR_DIGITS, 1); 156 | 157 | RSI_handle = iRSI(Symbol(), UpperTimeframe, RSI_Period, RSI_Price); 158 | 159 | MaxPeriod = Volatility_Band + RSI_Period; 160 | 161 | PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MaxPeriod); 162 | PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MaxPeriod); 163 | PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MaxPeriod); 164 | PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MaxPeriod + RSI_Price_Line); 165 | PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MaxPeriod + Trade_Signal_Line); 166 | 167 | return INIT_SUCCEEDED; 168 | } 169 | 170 | void OnDeinit(const int reason) 171 | { 172 | ObjectsDeleteAll(ChartID(), ArrowPrefix, 0, OBJ_ARROW); 173 | } 174 | 175 | int OnCalculate(const int rates_total, 176 | const int prev_calculated, 177 | const datetime& Time[], 178 | const double& open[], 179 | const double& High[], 180 | const double& Low[], 181 | const double& close[], 182 | const long& tick_volume[], 183 | const long& volume[], 184 | const int& spread[] 185 | ) 186 | { 187 | ArraySetAsSeries(Time, true); 188 | ArraySetAsSeries(Low, true); 189 | ArraySetAsSeries(High, true); 190 | 191 | int counted_bars = prev_calculated; 192 | if (counted_bars > 0) counted_bars--; 193 | 194 | // Too few bars to work with. 195 | if (rates_total < MaxPeriod) return 0; 196 | 197 | int limit = rates_total - 1 - counted_bars; 198 | if (limit > rates_total - MaxPeriod - 1) limit = rates_total - MaxPeriod - 1; 199 | 200 | if (PeriodSeconds(UpperTimeframe) == PeriodSeconds(Period())) 201 | { 202 | if (FillIndicatorBuffers((ENUM_TIMEFRAMES)Period(), limit, RSIBuf, UpZone, DnZone, MdZone, MaBuf, MbBuf) == -1) return 0; // No RSI data yet. 203 | } 204 | else 205 | { 206 | static int upper_prev_counted = 0; 207 | if (upper_prev_counted > 0) upper_prev_counted--; 208 | int upper_limit = iBars(Symbol(), UpperTimeframe) - 1 - upper_prev_counted; 209 | if (upper_limit > iBars(Symbol(), UpperTimeframe) - MaxPeriod - 1) upper_limit = iBars(Symbol(), UpperTimeframe) - MaxPeriod - 1; 210 | if (upper_limit > rates_total - Volatility_Band) upper_limit = rates_total - Volatility_Band; // Buffers cannot hold more than the current period's bars worth of data! 211 | upper_prev_counted = FillIndicatorBuffers(UpperTimeframe, upper_limit, _RSIBuf, _UpZone, _DnZone, _MdZone, _MaBuf, _MbBuf); 212 | if (upper_prev_counted == -1) return 0; // No RSI data yet. 213 | for (int i = 0, j = 0; Time[i] >= iTime(Symbol(), UpperTimeframe, upper_limit); i++) 214 | { 215 | while ((iTime(Symbol(), UpperTimeframe, j) > Time[i]) && (j < iBars(Symbol(), UpperTimeframe))) j++; 216 | if (j >= iBars(Symbol(), UpperTimeframe)) break; 217 | RSIBuf[i] = _RSIBuf[j]; 218 | UpZone[i] = _UpZone[j]; 219 | DnZone[i] = _DnZone[j]; 220 | MdZone[i] = _MdZone[j]; 221 | MaBuf[i] = _MaBuf[j]; 222 | MbBuf[i] = _MbBuf[j]; 223 | if (i + 1 == rates_total) break; 224 | } 225 | } 226 | 227 | if (EnableRedYellowCrossAlert) 228 | { 229 | if ((MbBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MbBuf[TriggerCandle + 1] <= MdZone[TriggerCandle + 1]) && (AlertPlayed != Time[0])) 230 | { 231 | if (EnableNativeAlerts) Alert("Bullish cross"); 232 | if (EnableEmailAlerts) 233 | { 234 | SendMail("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 235 | } 236 | if (EnablePushAlerts) SendNotification("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period)); 237 | AlertPlayed = Time[0]; 238 | } 239 | if ((MbBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MbBuf[TriggerCandle + 1] >= MdZone[TriggerCandle + 1]) && (AlertPlayed != Time[0])) 240 | { 241 | if (EnableNativeAlerts) Alert("Bearish cross"); 242 | if (EnableEmailAlerts) 243 | { 244 | SendMail("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 245 | } 246 | if (EnablePushAlerts) SendNotification("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period)); 247 | AlertPlayed = Time[0]; 248 | } 249 | } 250 | 251 | if (EnableHookAlert) 252 | { 253 | // Green line crosses upper blue line from above when both are above level 68. 254 | if ((MaBuf[TriggerCandle] < UpZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= UpZone[TriggerCandle + 1]) && ((MaBuf[TriggerCandle] > 68) || (MaBuf[TriggerCandle + 1] > 68)) && ((UpZone[TriggerCandle] > 68) || (UpZone[TriggerCandle + 1] > 68)) && (HookAlertPlayed != Time[0])) 255 | { 256 | if (EnableNativeAlerts) Alert("Bearish Hook"); 257 | if (EnableEmailAlerts) 258 | { 259 | SendMail("TDI Hook Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 260 | } 261 | if (EnablePushAlerts) SendNotification("TDI Hook Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period)); 262 | HookAlertPlayed = Time[0]; 263 | } 264 | // Green line crosses lower blue line from below when both are below level 32. 265 | else if ((MaBuf[TriggerCandle] > DnZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= DnZone[TriggerCandle + 1]) && ((MaBuf[TriggerCandle] < 32) || (MaBuf[TriggerCandle + 1] < 32)) && ((DnZone[TriggerCandle] < 32) || (DnZone[TriggerCandle + 1] < 32)) && (HookAlertPlayed != Time[0])) 266 | { 267 | if (EnableNativeAlerts) Alert("Bullish Hook"); 268 | if (EnableEmailAlerts) 269 | { 270 | SendMail("TDI Hook Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 271 | } 272 | if (EnablePushAlerts) SendNotification("TDI Hook Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period)); 273 | HookAlertPlayed = Time[0]; 274 | } 275 | } 276 | 277 | if (EnableGreenRedCrossAlert) 278 | { 279 | // Green line crosses red one from above. 280 | if ((MaBuf[TriggerCandle] < MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MbBuf[TriggerCandle + 1]) && (RedGreenAlertPlayed != Time[0])) 281 | { 282 | if (EnableNativeAlerts) Alert("Green line crossed red one from above"); 283 | if (EnableEmailAlerts) 284 | { 285 | SendMail("TDI: Green line crossed red one from above - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 286 | } 287 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from above - " + _Symbol + " @ " + PeriodToString(_Period)); 288 | RedGreenAlertPlayed = Time[0]; 289 | } 290 | // Green line crosses red one from below. 291 | else if ((MaBuf[TriggerCandle] > MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MbBuf[TriggerCandle + 1]) && (RedGreenAlertPlayed != Time[0])) 292 | { 293 | if (EnableNativeAlerts) Alert("Green line crossed red one from below"); 294 | if (EnableEmailAlerts) 295 | { 296 | SendMail("TDI: Green line crossed red one from below - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 297 | } 298 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from below - " + _Symbol + " @ " + PeriodToString(_Period)); 299 | RedGreenAlertPlayed = Time[0]; 300 | } 301 | } 302 | 303 | if (EnableGreenRedCrossWithYellowAlert) 304 | { 305 | // Green line crosses red one from above and both are below the yellow line. 306 | if ((MaBuf[TriggerCandle] < MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MbBuf[TriggerCandle + 1]) && (MaBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MbBuf[TriggerCandle] < MdZone[TriggerCandle]) && (RedGreenAlertPlayed != Time[0])) 307 | { 308 | if (EnableNativeAlerts) Alert("Green line crossed red one from above while both below yellow"); 309 | if (EnableEmailAlerts) 310 | { 311 | SendMail("TDI: Green line crossed red one from above while both below yellow - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 312 | } 313 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from above while both below yellow - " + _Symbol + " @ " + PeriodToString(_Period)); 314 | RedGreenAlertPlayed = Time[0]; 315 | } 316 | // Green line crosses red one from below and both are above the yellow line. 317 | else if ((MaBuf[TriggerCandle] > MbBuf[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MbBuf[TriggerCandle + 1]) && (MaBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MbBuf[TriggerCandle] > MdZone[TriggerCandle]) && (RedGreenAlertPlayed != Time[0])) 318 | { 319 | if (EnableNativeAlerts) Alert("Green line crossed red one from below while both above yellow"); 320 | if (EnableEmailAlerts) 321 | { 322 | SendMail("TDI: Green line crossed red one from below while both above yellow - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 323 | } 324 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed red one from below while both above yellow - " + _Symbol + " @ " + PeriodToString(_Period)); 325 | RedGreenAlertPlayed = Time[0]; 326 | } 327 | } 328 | 329 | if (EnableYellowGreenCrossAlert) 330 | { 331 | // Green line crosses yellow one from above. 332 | if ((MaBuf[TriggerCandle] < MdZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] >= MdZone[TriggerCandle + 1]) && (YellowGreenAlertPlayed != Time[0])) 333 | { 334 | if (EnableNativeAlerts) Alert("Green line crossed yellow one from above"); 335 | if (EnableEmailAlerts) 336 | { 337 | SendMail("TDI: Green line crossed yellow one from above - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 338 | } 339 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed yellow one from above - " + _Symbol + " @ " + PeriodToString(_Period)); 340 | YellowGreenAlertPlayed = Time[0]; 341 | } 342 | // Green line crosses yellow one from below. 343 | else if ((MaBuf[TriggerCandle] > MdZone[TriggerCandle]) && (MaBuf[TriggerCandle + 1] <= MdZone[TriggerCandle + 1]) && (YellowGreenAlertPlayed != Time[0])) 344 | { 345 | if (EnableNativeAlerts) Alert("Green line crossed yellow one from below"); 346 | if (EnableEmailAlerts) 347 | { 348 | SendMail("TDI: Green line crossed yellow one from below - " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[TriggerCandle], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[TriggerCandle], 1) + "\nVB Low = " + DoubleToString(DnZone[TriggerCandle], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[TriggerCandle], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[TriggerCandle], 1)); 349 | } 350 | if (EnablePushAlerts) SendNotification("TDI: Green line crossed yellow one from below - " + _Symbol + " @ " + PeriodToString(_Period)); 351 | YellowGreenAlertPlayed = Time[0]; 352 | } 353 | } 354 | 355 | return rates_total; 356 | } 357 | 358 | // Standard Deviation function. 359 | double StDev(double& Data[], int Per) 360 | { 361 | return MathSqrt(Variance(Data, Per)); 362 | } 363 | 364 | // Math Variance function. 365 | double Variance(double& Data[], int Per) 366 | { 367 | double sum = 0, ssum = 0; 368 | for (int i = 0; i < Per; i++) 369 | { 370 | sum += Data[i]; 371 | ssum += MathPow(Data[i], 2); 372 | } 373 | return ((ssum * Per - sum * sum) / (Per * (Per - 1))); 374 | } 375 | 376 | //+------------------------------------------------------------------+ 377 | //| Based on http://www.mql5.com/en/articles/81 | 378 | //| Simplified SMA calculation. | 379 | //+------------------------------------------------------------------+ 380 | double iMAOnArray(double &Array[], int total, int iMAPeriod, int ma_shift, ENUM_MA_METHOD ma_method, int Shift) 381 | { 382 | double buf[]; 383 | if ((total > 0) && (total <= iMAPeriod)) return(0); 384 | if (total == 0) total = ArraySize(Array); 385 | if (ArrayResize(buf, total) < 0) return(0); 386 | 387 | switch(ma_method) 388 | { 389 | // Simplified SMA. No longer works with ma_shift parameter. 390 | case MODE_SMA: 391 | { 392 | double sum = 0; 393 | for (int i = Shift; i < Shift + iMAPeriod; i++) 394 | sum += Array[i] / iMAPeriod; 395 | return sum; 396 | } 397 | case MODE_EMA: 398 | { 399 | double pr = 2.0 / (iMAPeriod + 1); 400 | int pos = total - 2; 401 | while (pos >= 0) 402 | { 403 | if (pos == total - 2) buf[pos + 1] = Array[pos + 1]; 404 | buf[pos] = Array[pos] * pr + buf[pos + 1] * (1 - pr); 405 | pos--; 406 | } 407 | return buf[Shift + ma_shift]; 408 | } 409 | case MODE_SMMA: 410 | { 411 | double sum = 0; 412 | int i, k, pos; 413 | pos = total - iMAPeriod; 414 | while (pos >= 0) 415 | { 416 | if (pos == total - iMAPeriod) 417 | { 418 | for (i = 0, k = pos; i < iMAPeriod; i++, k++) 419 | { 420 | sum += Array[k]; 421 | buf[k] = 0; 422 | } 423 | } 424 | else sum = buf[pos + 1] * (iMAPeriod - 1) + Array[pos]; 425 | buf[pos] = sum / iMAPeriod; 426 | pos--; 427 | } 428 | return buf[Shift + ma_shift]; 429 | } 430 | case MODE_LWMA: 431 | { 432 | double sum = 0.0, lsum = 0.0; 433 | double price; 434 | int i, weight = 0, pos = total - 1; 435 | for (i = 1; i <= iMAPeriod; i++, pos--) 436 | { 437 | price = Array[pos]; 438 | sum += price * i; 439 | lsum += price; 440 | weight += i; 441 | } 442 | pos++; 443 | i = pos + iMAPeriod; 444 | while (pos >= 0) 445 | { 446 | buf[pos] = sum / weight; 447 | if (pos == 0) break; 448 | pos--; 449 | i--; 450 | price = Array[pos]; 451 | sum = sum - lsum + price * iMAPeriod; 452 | lsum -= Array[i]; 453 | lsum += price; 454 | } 455 | return buf[Shift + ma_shift]; 456 | } 457 | default: 458 | return 0; 459 | } 460 | return 0; 461 | } 462 | 463 | // For alerts. 464 | string PeriodToString(const ENUM_TIMEFRAMES per) 465 | { 466 | return StringSubstr(EnumToString(per), 7); 467 | } 468 | 469 | void PutArrow(const double price, const datetime time, enum_arrow_type dir, const color colour, const uchar arrow_code, const string text) 470 | { 471 | string name = ArrowPrefix + "Arrow" + IntegerToString(arrow_code) + TimeToString(time); 472 | if (ObjectFind(ChartID(), name) > -1) return; 473 | ENUM_ARROW_ANCHOR anchor; 474 | if (dir == Buy) 475 | { 476 | anchor = ANCHOR_TOP; 477 | } 478 | else 479 | { 480 | anchor = ANCHOR_BOTTOM; 481 | } 482 | ObjectCreate(ChartID(), name, OBJ_ARROW, 0, time, price); 483 | ObjectSetInteger(0, name, OBJPROP_ARROWCODE, arrow_code); 484 | ObjectSetInteger(0, name, OBJPROP_WIDTH, ArrowSize); 485 | ObjectSetInteger(0, name, OBJPROP_COLOR, colour); 486 | ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); 487 | ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); 488 | ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor); 489 | ObjectSetString(0, name, OBJPROP_TOOLTIP, text); 490 | } 491 | 492 | void RemoveArrow(const datetime time, const uchar arrow_code) 493 | { 494 | string name = ArrowPrefix + "Arrow" + IntegerToString(arrow_code) + TimeToString(time); 495 | ObjectDelete(0, name); 496 | } 497 | 498 | // Returns the number processed bars. 499 | int FillIndicatorBuffers(ENUM_TIMEFRAMES period, int limit, double& rsibuf[], double& upzone[], double& dnzone[], double& mdzone[], double& mabuf[], double& mbbuf[]) 500 | { 501 | double MA, RSI[]; 502 | ArrayResize(RSI, Volatility_Band); 503 | int i = MathMax(MathMax(limit, RSI_Price_Line), Trade_Signal_Line); // Cannot calculate everything with at least so many RSI bars. 504 | int bars = iBars(Symbol(), period); 505 | 506 | int RSI_bars = CopyBuffer(RSI_handle, 0, 0, i + Volatility_Band, rsibuf); // No need to copy all RSI for too old bars. 507 | 508 | if (RSI_bars < i + Volatility_Band) return -1; 509 | 510 | // Calculate BB on RSI. 511 | while (i >= 0) 512 | { 513 | MA = 0; 514 | for (int x = i; x < i + Volatility_Band; x++) 515 | { 516 | if ((rsibuf[x] > 100) || (rsibuf[x] < 0)) return -1; // Bad RSI value. Try later. 517 | RSI[x - i] = rsibuf[x]; 518 | MA += rsibuf[x] / Volatility_Band; 519 | } 520 | double SD = StdDev * StDev(RSI, Volatility_Band); 521 | upzone[i] = MA + SD; 522 | dnzone[i] = MA - SD; 523 | mdzone[i] = (upzone[i] + dnzone[i]) / 2; 524 | 525 | i--; 526 | } 527 | 528 | // Calculate MAs of RSI. 529 | for (int i = limit; i >= 0; i--) 530 | { 531 | mabuf[i] = iMAOnArray(rsibuf, 0, RSI_Price_Line, 0, RSI_Price_Type, i); 532 | mbbuf[i] = iMAOnArray(rsibuf, 0, Trade_Signal_Line, 0, Trade_Signal_Type, i); 533 | 534 | if (EnableArrowAlerts) 535 | { 536 | if (i + TriggerCandle + 1 >= iBars(Symbol(), period)) continue; // Check if there is enough bars. 537 | // Lower timeframe bar index: 538 | int lower_i = iBarShift(Symbol(), Period(), iTime(Symbol(), period, i + TriggerCandle), false); 539 | if (EnableRedYellowCrossAlert) 540 | { 541 | if ((mbbuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle + 1] <= mdzone[i + TriggerCandle + 1])) 542 | { 543 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, RedYellowCrossArrowBullishColor, RedYellowCrossArrowBullishCode, "Bullish cross"); 544 | } 545 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), RedYellowCrossArrowBullishCode); 546 | if ((mbbuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle + 1] >= mdzone[i + TriggerCandle + 1])) 547 | { 548 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, RedYellowCrossArrowBearishColor, RedYellowCrossArrowBearishCode, "Bearish cross"); 549 | } 550 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), RedYellowCrossArrowBearishCode); 551 | } 552 | if (EnableHookAlert) 553 | { 554 | // Green line crosses upper blue line from above when both are above level 68. 555 | if ((mabuf[i + TriggerCandle] < upzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= upzone[i + TriggerCandle + 1]) && ((mabuf[i + TriggerCandle] > 68) || (mabuf[i + TriggerCandle + 1] > 68)) && ((upzone[i + TriggerCandle] > 68) || (upzone[i + TriggerCandle + 1] > 68))) 556 | { 557 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, HookArrowBearishColor, HookArrowBearishCode, "Bearish Hook"); 558 | } 559 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), HookArrowBearishCode); 560 | // Green line crosses lower blue line from below when both are below level 32. 561 | if ((mabuf[i + TriggerCandle] > dnzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= dnzone[i + TriggerCandle + 1]) && ((mabuf[i + TriggerCandle] < 32) || (mabuf[i + TriggerCandle + 1] < 32)) && ((dnzone[i + TriggerCandle] < 32) || (dnzone[i + TriggerCandle + 1] < 32))) 562 | { 563 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, HookArrowBullishColor, HookArrowBullishCode, "Bullish Hook"); 564 | } 565 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), HookArrowBullishCode); 566 | } 567 | if (EnableGreenRedCrossAlert) 568 | { 569 | // Green line crosses red one from above. 570 | if ((mabuf[i + TriggerCandle] < mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mbbuf[i + TriggerCandle + 1])) 571 | { 572 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, GreenRedCrossArrowBearishColor, GreenRedCrossArrowBearishCode, "Green line crossed red one from above"); 573 | } 574 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBearishCode); 575 | // Green line crosses red one from below. 576 | if ((mabuf[i + TriggerCandle] > mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mbbuf[i + TriggerCandle + 1])) 577 | { 578 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, GreenRedCrossArrowBullishColor, GreenRedCrossArrowBullishCode, "Green line crossed red one from below"); 579 | } 580 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBullishCode); 581 | } 582 | if (EnableGreenRedCrossWithYellowAlert) 583 | { 584 | // Green line crosses red one from above and both are below the yellow line. 585 | if ((mabuf[i + TriggerCandle] < mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mbbuf[i + TriggerCandle + 1]) && (mabuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle] < mdzone[i + TriggerCandle])) 586 | { 587 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, GreenRedCrossArrowBearishColor, GreenRedCrossArrowBearishCode, "Green line crossed red one from above while both below yellow"); 588 | } 589 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBearishCode); 590 | // Green line crosses red one from below and both are above the yellow line. 591 | if ((mabuf[i + TriggerCandle] > mbbuf[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mbbuf[i + TriggerCandle + 1]) && (mabuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mbbuf[i + TriggerCandle] > mdzone[i + TriggerCandle])) 592 | { 593 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, GreenRedCrossArrowBullishColor, GreenRedCrossArrowBullishCode, "Green line crossed red one from below while both above yellow"); 594 | } 595 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), GreenRedCrossArrowBullishCode); 596 | } 597 | if (EnableYellowGreenCrossAlert) 598 | { 599 | // Green line crosses yellow one from above. 600 | if ((mabuf[i + TriggerCandle] < mdzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] >= mdzone[i + TriggerCandle + 1])) 601 | { 602 | PutArrow(iHigh(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Sell, YellowGreenCrossArrowBearishColor, YellowGreenCrossArrowBullishCode, "Green line crossed yellow one from above"); 603 | } 604 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), YellowGreenCrossArrowBullishCode); 605 | // Green line crosses yellow one from below. 606 | if ((mabuf[i + TriggerCandle] > mdzone[i + TriggerCandle]) && (mabuf[i + TriggerCandle + 1] <= mdzone[i + TriggerCandle + 1])) 607 | { 608 | PutArrow(iLow(Symbol(), Period(), lower_i), iTime(Symbol(), period, i + TriggerCandle), Buy, YellowGreenCrossArrowBullishColor, YellowGreenCrossArrowBearishCode, "Green line crossed yellow one from below"); 609 | } 610 | else RemoveArrow(iTime(Symbol(), period, i + TriggerCandle), YellowGreenCrossArrowBearishCode); 611 | } 612 | } 613 | } 614 | return bars; 615 | } 616 | //+------------------------------------------------------------------+ --------------------------------------------------------------------------------