├── README.md ├── Spike.cs ├── RStrongWeak.cs ├── UpTrendDownTrend.cs ├── OpeningRange.cs ├── TDCombo.cs ├── TDSequential.cs └── Demark Indicators Tested.py /README.md: -------------------------------------------------------------------------------- 1 | ## Repo for putting my stock market algos 2 | 3 | ### RStrongWeak : 4 | Is for measuring the relative strength and weakness of the stocks universe observed using ninjatrader FREE software. 5 | 6 | ### Opening Range: 7 | Is for returning the opening range of the stocks universe observed since wider ranges at the opening is an indication of a a stock that might trend during the entire trading day, must be used with NinjaTrader. 8 | 9 | ### Demark Indicators: 10 | Is a complete algo for trading a univsese of stocks based on the demark studies, TD Sequential, Combo, and D-wave, it appeared to not work at all but maybe you can tune it with other methods of your own, must work with Quantopian free web trading. 11 | 12 | 13 | ### Spike 14 | Compares the current stock's price to the standard deviaton of the last 20 bars, if the difference is significant then there is a sudden interent in the stock (mostly due to news) 15 | 16 | ### TDSequential 17 | The legendary indicators that measures exhaustion in the trend of a stock to idenitity turning points/counter trend 18 | 19 | ### TdCombo 20 | Same as the squential with a variation in the countdown phase 21 | 22 | ### upTrendDownTrend 23 | Measure which stocks are up/downtrending to give you an eagle view of all stocks. -------------------------------------------------------------------------------- /Spike.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | #endregion 12 | 13 | // This namespace holds all indicators and is required. Do not change it. 14 | namespace NinjaTrader.Indicator 15 | { 16 | /// 17 | /// Spike in price 18 | /// 19 | [Description("Spike in price")] 20 | public class Spike : Indicator 21 | { 22 | #region Variables 23 | // Wizard generated variables 24 | private int period = 20; // Default setting for Period 25 | // User defined variables (add any user defined variables below) 26 | double pClose; 27 | double StdevOfTheLast20Days; 28 | #endregion 29 | 30 | /// 31 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 32 | /// 33 | protected override void Initialize() 34 | { 35 | Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "SpikePlot")); 36 | Overlay = false; 37 | CalculateOnBarClose = false; 38 | 39 | } 40 | 41 | 42 | 43 | /// 44 | /// Called on each bar update event (incoming tick) 45 | /// 46 | protected override void OnBarUpdate() 47 | { 48 | // Use this method for calculating your indicator values. Assign a value to each 49 | // plot below by replacing 'Close[0]' with your own formula. 50 | if (CurrentBar <20) return; 51 | 52 | pClose = Close[1]; 53 | StdevOfTheLast20Days = StdDev(13)[0]; 54 | 55 | //SpikePlot.Set(( Math.Abs( Math.Abs((MarketData.Ask.Price)-pClose)) / StdevOfTheLast20Days )); 56 | SpikePlot.Set((( Math.Abs( Math.Abs(Close[0]-pClose)) / StdevOfTheLast20Days ))*1); 57 | 58 | } 59 | 60 | #region Properties 61 | [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove 62 | [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove 63 | public DataSeries SpikePlot 64 | { 65 | get { return Values[0]; } 66 | } 67 | #endregion 68 | } 69 | } 70 | 71 | #region NinjaScript generated code. Neither change nor remove. 72 | // This namespace holds all indicators and is required. Do not change it. 73 | namespace NinjaTrader.Indicator 74 | { 75 | public partial class Indicator : IndicatorBase 76 | { 77 | private Spike[] cacheSpike = null; 78 | 79 | private static Spike checkSpike = new Spike(); 80 | 81 | /// 82 | /// Spike in price 83 | /// 84 | /// 85 | public Spike Spike() 86 | { 87 | return Spike(Input); 88 | } 89 | 90 | /// 91 | /// Spike in price 92 | /// 93 | /// 94 | public Spike Spike(Data.IDataSeries input) 95 | { 96 | if (cacheSpike != null) 97 | for (int idx = 0; idx < cacheSpike.Length; idx++) 98 | if (cacheSpike[idx].EqualsInput(input)) 99 | return cacheSpike[idx]; 100 | 101 | lock (checkSpike) 102 | { 103 | if (cacheSpike != null) 104 | for (int idx = 0; idx < cacheSpike.Length; idx++) 105 | if (cacheSpike[idx].EqualsInput(input)) 106 | return cacheSpike[idx]; 107 | 108 | Spike indicator = new Spike(); 109 | indicator.BarsRequired = BarsRequired; 110 | indicator.CalculateOnBarClose = CalculateOnBarClose; 111 | #if NT7 112 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 113 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 114 | #endif 115 | indicator.Input = input; 116 | Indicators.Add(indicator); 117 | indicator.SetUp(); 118 | 119 | Spike[] tmp = new Spike[cacheSpike == null ? 1 : cacheSpike.Length + 1]; 120 | if (cacheSpike != null) 121 | cacheSpike.CopyTo(tmp, 0); 122 | tmp[tmp.Length - 1] = indicator; 123 | cacheSpike = tmp; 124 | return indicator; 125 | } 126 | } 127 | } 128 | } 129 | 130 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 131 | namespace NinjaTrader.MarketAnalyzer 132 | { 133 | public partial class Column : ColumnBase 134 | { 135 | /// 136 | /// Spike in price 137 | /// 138 | /// 139 | [Gui.Design.WizardCondition("Indicator")] 140 | public Indicator.Spike Spike() 141 | { 142 | return _indicator.Spike(Input); 143 | } 144 | 145 | /// 146 | /// Spike in price 147 | /// 148 | /// 149 | public Indicator.Spike Spike(Data.IDataSeries input) 150 | { 151 | return _indicator.Spike(input); 152 | } 153 | } 154 | } 155 | 156 | // This namespace holds all strategies and is required. Do not change it. 157 | namespace NinjaTrader.Strategy 158 | { 159 | public partial class Strategy : StrategyBase 160 | { 161 | /// 162 | /// Spike in price 163 | /// 164 | /// 165 | [Gui.Design.WizardCondition("Indicator")] 166 | public Indicator.Spike Spike() 167 | { 168 | return _indicator.Spike(Input); 169 | } 170 | 171 | /// 172 | /// Spike in price 173 | /// 174 | /// 175 | public Indicator.Spike Spike(Data.IDataSeries input) 176 | { 177 | if (InInitialize && input == null) 178 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 179 | 180 | return _indicator.Spike(input); 181 | } 182 | } 183 | } 184 | #endregion 185 | -------------------------------------------------------------------------------- /RStrongWeak.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | #endregion 12 | 13 | // This namespace holds all indicators and is required. Do not change it. 14 | namespace NinjaTrader.Indicator 15 | { 16 | /// 17 | /// Show the Relative Strength and Weakness of A Stock Universe 18 | /// 19 | [Description("Show the Relative Strength and Weakness of A Stock Universe")] 20 | public class RStrongWeak : Indicator 21 | { 22 | #region Variables 23 | // Wizard generated variables 24 | // User defined variables (add any user defined variables below) 25 | 26 | double openingPriceStock; 27 | double currentPriceStock; 28 | 29 | double openingPriceIndex; 30 | double currentPriceIndex; 31 | 32 | #endregion 33 | 34 | /// 35 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 36 | /// 37 | protected override void Initialize() 38 | { 39 | CalculateOnBarClose = false; 40 | Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "Plot0")); 41 | Overlay = false; 42 | Add("SPY", PeriodType.Day, 1); 43 | } 44 | 45 | /// 46 | /// Called on each bar update event (incoming tick) 47 | /// 48 | protected override void OnBarUpdate() 49 | { 50 | // Use this method for calculating your indicator values. Assign a value to each 51 | // plot below by replacing 'Close[0]' with your own formula. 52 | 53 | if (CurrentBar <1) return; 54 | 55 | // get the openinng price of a stock from the daily 56 | openingPriceStock = Opens[0][0]; 57 | //Print(openingPriceStock); 58 | 59 | currentPriceStock = Closes[0][0]; 60 | //Print(currentPriceStock); 61 | 62 | openingPriceIndex = Opens[1][0]; 63 | //Print(openingPriceIndex); 64 | 65 | currentPriceIndex = Closes[1][0]; 66 | //Print(currentPriceIndex); 67 | 68 | Plot0.Set( (currentPriceStock/openingPriceStock) / (currentPriceIndex/openingPriceIndex) ); 69 | } 70 | 71 | #region Properties 72 | [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove 73 | [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove 74 | public DataSeries Plot0 75 | { 76 | get { return Values[0]; } 77 | } 78 | 79 | #endregion 80 | } 81 | } 82 | 83 | #region NinjaScript generated code. Neither change nor remove. 84 | // This namespace holds all indicators and is required. Do not change it. 85 | namespace NinjaTrader.Indicator 86 | { 87 | public partial class Indicator : IndicatorBase 88 | { 89 | private RStrongWeak[] cacheRStrongWeak = null; 90 | 91 | private static RStrongWeak checkRStrongWeak = new RStrongWeak(); 92 | 93 | /// 94 | /// Show the Relative Strength and Weakness of A Stock Universe 95 | /// 96 | /// 97 | public RStrongWeak RStrongWeak() 98 | { 99 | return RStrongWeak(Input); 100 | } 101 | 102 | /// 103 | /// Show the Relative Strength and Weakness of A Stock Universe 104 | /// 105 | /// 106 | public RStrongWeak RStrongWeak(Data.IDataSeries input) 107 | { 108 | if (cacheRStrongWeak != null) 109 | for (int idx = 0; idx < cacheRStrongWeak.Length; idx++) 110 | if (cacheRStrongWeak[idx].EqualsInput(input)) 111 | return cacheRStrongWeak[idx]; 112 | 113 | lock (checkRStrongWeak) 114 | { 115 | if (cacheRStrongWeak != null) 116 | for (int idx = 0; idx < cacheRStrongWeak.Length; idx++) 117 | if (cacheRStrongWeak[idx].EqualsInput(input)) 118 | return cacheRStrongWeak[idx]; 119 | 120 | RStrongWeak indicator = new RStrongWeak(); 121 | indicator.BarsRequired = BarsRequired; 122 | indicator.CalculateOnBarClose = CalculateOnBarClose; 123 | #if NT7 124 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 125 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 126 | #endif 127 | indicator.Input = input; 128 | Indicators.Add(indicator); 129 | indicator.SetUp(); 130 | 131 | RStrongWeak[] tmp = new RStrongWeak[cacheRStrongWeak == null ? 1 : cacheRStrongWeak.Length + 1]; 132 | if (cacheRStrongWeak != null) 133 | cacheRStrongWeak.CopyTo(tmp, 0); 134 | tmp[tmp.Length - 1] = indicator; 135 | cacheRStrongWeak = tmp; 136 | return indicator; 137 | } 138 | } 139 | } 140 | } 141 | 142 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 143 | namespace NinjaTrader.MarketAnalyzer 144 | { 145 | public partial class Column : ColumnBase 146 | { 147 | /// 148 | /// Show the Relative Strength and Weakness of A Stock Universe 149 | /// 150 | /// 151 | [Gui.Design.WizardCondition("Indicator")] 152 | public Indicator.RStrongWeak RStrongWeak() 153 | { 154 | return _indicator.RStrongWeak(Input); 155 | } 156 | 157 | /// 158 | /// Show the Relative Strength and Weakness of A Stock Universe 159 | /// 160 | /// 161 | public Indicator.RStrongWeak RStrongWeak(Data.IDataSeries input) 162 | { 163 | return _indicator.RStrongWeak(input); 164 | } 165 | } 166 | } 167 | 168 | // This namespace holds all strategies and is required. Do not change it. 169 | namespace NinjaTrader.Strategy 170 | { 171 | public partial class Strategy : StrategyBase 172 | { 173 | /// 174 | /// Show the Relative Strength and Weakness of A Stock Universe 175 | /// 176 | /// 177 | [Gui.Design.WizardCondition("Indicator")] 178 | public Indicator.RStrongWeak RStrongWeak() 179 | { 180 | return _indicator.RStrongWeak(Input); 181 | } 182 | 183 | /// 184 | /// Show the Relative Strength and Weakness of A Stock Universe 185 | /// 186 | /// 187 | public Indicator.RStrongWeak RStrongWeak(Data.IDataSeries input) 188 | { 189 | if (InInitialize && input == null) 190 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 191 | 192 | return _indicator.RStrongWeak(input); 193 | } 194 | } 195 | } 196 | #endregion 197 | -------------------------------------------------------------------------------- /UpTrendDownTrend.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | #endregion 12 | 13 | // This namespace holds all indicators and is required. Do not change it. 14 | namespace NinjaTrader.Indicator 15 | { 16 | /// 17 | /// Gives the Slope of the Linear Regression 18 | /// 19 | [Description("Gives the Slope of the Linear Regression")] 20 | public class UpTrendDownTrend : Indicator 21 | { 22 | #region Variables 23 | // Wizard generated variables 24 | private int period = 10; // Default setting for Period 25 | // User defined variables (add any user defined variables below) 26 | private DataSeries seriesOfLinReg; 27 | #endregion 28 | 29 | /// 30 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 31 | /// 32 | protected override void Initialize() 33 | { 34 | Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "Plot0")); 35 | Overlay = false; 36 | seriesOfLinReg = new DataSeries(this); 37 | } 38 | 39 | /// 40 | /// Called on each bar update event (incoming tick) 41 | /// 42 | protected override void OnBarUpdate() 43 | { 44 | // Use this method for calculating your indicator values. Assign a value to each 45 | // plot below by replacing 'Close[0]' with your own formula. 46 | 47 | // get the slope of the linear regression 48 | seriesOfLinReg.Set(LinRegSlope(9)[0]); 49 | 50 | // plot the SMA of the linear regression slope and multiply by 100 51 | Plot0.Set(((SMA(seriesOfLinReg,20)[0])*100)); 52 | } 53 | 54 | #region Properties 55 | [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove 56 | [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove 57 | public DataSeries Plot0 58 | { 59 | get { return Values[0]; } 60 | } 61 | 62 | [Description("")] 63 | [GridCategory("Parameters")] 64 | public int Period 65 | { 66 | get { return period; } 67 | set { period = Math.Max(1, value); } 68 | } 69 | #endregion 70 | } 71 | } 72 | 73 | #region NinjaScript generated code. Neither change nor remove. 74 | // This namespace holds all indicators and is required. Do not change it. 75 | namespace NinjaTrader.Indicator 76 | { 77 | public partial class Indicator : IndicatorBase 78 | { 79 | private UpTrendDownTrend[] cacheUpTrendDownTrend = null; 80 | 81 | private static UpTrendDownTrend checkUpTrendDownTrend = new UpTrendDownTrend(); 82 | 83 | /// 84 | /// Gives the Slope of the Linear Regression 85 | /// 86 | /// 87 | public UpTrendDownTrend UpTrendDownTrend(int period) 88 | { 89 | return UpTrendDownTrend(Input, period); 90 | } 91 | 92 | /// 93 | /// Gives the Slope of the Linear Regression 94 | /// 95 | /// 96 | public UpTrendDownTrend UpTrendDownTrend(Data.IDataSeries input, int period) 97 | { 98 | if (cacheUpTrendDownTrend != null) 99 | for (int idx = 0; idx < cacheUpTrendDownTrend.Length; idx++) 100 | if (cacheUpTrendDownTrend[idx].Period == period && cacheUpTrendDownTrend[idx].EqualsInput(input)) 101 | return cacheUpTrendDownTrend[idx]; 102 | 103 | lock (checkUpTrendDownTrend) 104 | { 105 | checkUpTrendDownTrend.Period = period; 106 | period = checkUpTrendDownTrend.Period; 107 | 108 | if (cacheUpTrendDownTrend != null) 109 | for (int idx = 0; idx < cacheUpTrendDownTrend.Length; idx++) 110 | if (cacheUpTrendDownTrend[idx].Period == period && cacheUpTrendDownTrend[idx].EqualsInput(input)) 111 | return cacheUpTrendDownTrend[idx]; 112 | 113 | UpTrendDownTrend indicator = new UpTrendDownTrend(); 114 | indicator.BarsRequired = BarsRequired; 115 | indicator.CalculateOnBarClose = CalculateOnBarClose; 116 | #if NT7 117 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 118 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 119 | #endif 120 | indicator.Input = input; 121 | indicator.Period = period; 122 | Indicators.Add(indicator); 123 | indicator.SetUp(); 124 | 125 | UpTrendDownTrend[] tmp = new UpTrendDownTrend[cacheUpTrendDownTrend == null ? 1 : cacheUpTrendDownTrend.Length + 1]; 126 | if (cacheUpTrendDownTrend != null) 127 | cacheUpTrendDownTrend.CopyTo(tmp, 0); 128 | tmp[tmp.Length - 1] = indicator; 129 | cacheUpTrendDownTrend = tmp; 130 | return indicator; 131 | } 132 | } 133 | } 134 | } 135 | 136 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 137 | namespace NinjaTrader.MarketAnalyzer 138 | { 139 | public partial class Column : ColumnBase 140 | { 141 | /// 142 | /// Gives the Slope of the Linear Regression 143 | /// 144 | /// 145 | [Gui.Design.WizardCondition("Indicator")] 146 | public Indicator.UpTrendDownTrend UpTrendDownTrend(int period) 147 | { 148 | return _indicator.UpTrendDownTrend(Input, period); 149 | } 150 | 151 | /// 152 | /// Gives the Slope of the Linear Regression 153 | /// 154 | /// 155 | public Indicator.UpTrendDownTrend UpTrendDownTrend(Data.IDataSeries input, int period) 156 | { 157 | return _indicator.UpTrendDownTrend(input, period); 158 | } 159 | } 160 | } 161 | 162 | // This namespace holds all strategies and is required. Do not change it. 163 | namespace NinjaTrader.Strategy 164 | { 165 | public partial class Strategy : StrategyBase 166 | { 167 | /// 168 | /// Gives the Slope of the Linear Regression 169 | /// 170 | /// 171 | [Gui.Design.WizardCondition("Indicator")] 172 | public Indicator.UpTrendDownTrend UpTrendDownTrend(int period) 173 | { 174 | return _indicator.UpTrendDownTrend(Input, period); 175 | } 176 | 177 | /// 178 | /// Gives the Slope of the Linear Regression 179 | /// 180 | /// 181 | public Indicator.UpTrendDownTrend UpTrendDownTrend(Data.IDataSeries input, int period) 182 | { 183 | if (InInitialize && input == null) 184 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 185 | 186 | return _indicator.UpTrendDownTrend(input, period); 187 | } 188 | } 189 | } 190 | #endregion 191 | -------------------------------------------------------------------------------- /OpeningRange.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | #endregion 12 | 13 | // This namespace holds all indicators and is required. Do not change it. 14 | namespace NinjaTrader.Indicator 15 | { 16 | /// 17 | /// Return Today's range / average range for the last X days 18 | /// 19 | [Description("Return Today's range / average range for the last X days")] 20 | public class OpeningRange : Indicator 21 | { 22 | #region Variables 23 | // Wizard generated variables 24 | // User defined variables (add any user defined variables below) 25 | private DataSeries dvRange; 26 | double todaysRange; 27 | double currentReading; 28 | #endregion 29 | 30 | /// 31 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 32 | /// 33 | protected override void Initialize() 34 | { 35 | Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "Plot0")); 36 | Overlay = false; 37 | BarsRequired = 7800; // Do not plot until the 7800th bar on the chart 38 | CalculateOnBarClose = true; 39 | 40 | dvRange = new DataSeries(this,MaximumBarsLookBack.Infinite); 41 | 42 | } 43 | 44 | /// 45 | /// Called on each bar update event (incoming tick) 46 | /// 47 | protected override void OnBarUpdate() 48 | { 49 | // Use this method for calculating your indicator values. Assign a value to each 50 | // plot below by replacing 'Close[0]' with your own formula. 51 | 52 | 53 | 54 | getAvgRangeForLastXDays(); 55 | 56 | if (CurrentBars[0] < 7800){ 57 | // return 0 readings. so that when calling this indicator from another indicator you can choose the Readings above a specific 58 | //number safely. (no old <7800 undeeded comparison is disturbing the filteration) 59 | 60 | Value.Set(0); 61 | // exit the indicator 62 | return; 63 | }else 64 | 65 | 66 | Value.Set(compareRelativeRange()); 67 | 68 | } 69 | 70 | // get the range if the time is 94500 for the last X days 71 | void getAvgRangeForLastXDays(){ 72 | 73 | dvRange.Set( ToTime(Time[0]) == 094500 ? (MAX(High,15)[0] - MIN(Low,15)[0] ) :0 ); 74 | 75 | } 76 | 77 | // Compare the relative range, today's range / average range for the last X days 78 | double compareRelativeRange(){ 79 | 80 | // get today's range if the current time is 094559 81 | if( ToTime(Time[0]) <= 094559 ){ 82 | todaysRange = (MAX(High,15)[0] - MIN(Low,15)[0] ); 83 | } 84 | 85 | // return the ratio 86 | currentReading = todaysRange / (SUM(dvRange,7800)[0]/20); 87 | return todaysRange / (SUM(dvRange,7800)[0]/20); 88 | } 89 | #region Properties 90 | [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove 91 | [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove 92 | public DataSeries Plot0 93 | { 94 | get { return Values[0]; } 95 | } 96 | 97 | #endregion 98 | } 99 | } 100 | 101 | #region NinjaScript generated code. Neither change nor remove. 102 | // This namespace holds all indicators and is required. Do not change it. 103 | namespace NinjaTrader.Indicator 104 | { 105 | public partial class Indicator : IndicatorBase 106 | { 107 | private OpeningRange[] cacheOpeningRange = null; 108 | 109 | private static OpeningRange checkOpeningRange = new OpeningRange(); 110 | 111 | /// 112 | /// Return Today's range / average range for the last X days 113 | /// 114 | /// 115 | public OpeningRange OpeningRange() 116 | { 117 | return OpeningRange(Input); 118 | } 119 | 120 | /// 121 | /// Return Today's range / average range for the last X days 122 | /// 123 | /// 124 | public OpeningRange OpeningRange(Data.IDataSeries input) 125 | { 126 | if (cacheOpeningRange != null) 127 | for (int idx = 0; idx < cacheOpeningRange.Length; idx++) 128 | if (cacheOpeningRange[idx].EqualsInput(input)) 129 | return cacheOpeningRange[idx]; 130 | 131 | lock (checkOpeningRange) 132 | { 133 | if (cacheOpeningRange != null) 134 | for (int idx = 0; idx < cacheOpeningRange.Length; idx++) 135 | if (cacheOpeningRange[idx].EqualsInput(input)) 136 | return cacheOpeningRange[idx]; 137 | 138 | OpeningRange indicator = new OpeningRange(); 139 | indicator.BarsRequired = BarsRequired; 140 | indicator.CalculateOnBarClose = CalculateOnBarClose; 141 | #if NT7 142 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 143 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 144 | #endif 145 | indicator.Input = input; 146 | Indicators.Add(indicator); 147 | indicator.SetUp(); 148 | 149 | OpeningRange[] tmp = new OpeningRange[cacheOpeningRange == null ? 1 : cacheOpeningRange.Length + 1]; 150 | if (cacheOpeningRange != null) 151 | cacheOpeningRange.CopyTo(tmp, 0); 152 | tmp[tmp.Length - 1] = indicator; 153 | cacheOpeningRange = tmp; 154 | return indicator; 155 | } 156 | } 157 | } 158 | } 159 | 160 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 161 | namespace NinjaTrader.MarketAnalyzer 162 | { 163 | public partial class Column : ColumnBase 164 | { 165 | /// 166 | /// Return Today's range / average range for the last X days 167 | /// 168 | /// 169 | [Gui.Design.WizardCondition("Indicator")] 170 | public Indicator.OpeningRange OpeningRange() 171 | { 172 | return _indicator.OpeningRange(Input); 173 | } 174 | 175 | /// 176 | /// Return Today's range / average range for the last X days 177 | /// 178 | /// 179 | public Indicator.OpeningRange OpeningRange(Data.IDataSeries input) 180 | { 181 | return _indicator.OpeningRange(input); 182 | } 183 | } 184 | } 185 | 186 | // This namespace holds all strategies and is required. Do not change it. 187 | namespace NinjaTrader.Strategy 188 | { 189 | public partial class Strategy : StrategyBase 190 | { 191 | /// 192 | /// Return Today's range / average range for the last X days 193 | /// 194 | /// 195 | [Gui.Design.WizardCondition("Indicator")] 196 | public Indicator.OpeningRange OpeningRange() 197 | { 198 | return _indicator.OpeningRange(Input); 199 | } 200 | 201 | /// 202 | /// Return Today's range / average range for the last X days 203 | /// 204 | /// 205 | public Indicator.OpeningRange OpeningRange(Data.IDataSeries input) 206 | { 207 | if (InInitialize && input == null) 208 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 209 | 210 | return _indicator.OpeningRange(input); 211 | } 212 | } 213 | } 214 | #endregion 215 | -------------------------------------------------------------------------------- /TDCombo.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | using System.Collections; 12 | #endregion 13 | 14 | // This namespace holds all indicators and is required. Do not change it. 15 | namespace NinjaTrader.Indicator 16 | { 17 | /// 18 | /// 19 | /// 20 | [Description("")] 21 | public class TDCombo : Indicator 22 | { 23 | #region Variables 24 | // Wizard generated variables 25 | // User defined variables (add any user defined variables below) 26 | Font nFont = new Font("Tahoma", 8, FontStyle.Regular); 27 | Font ArrowFont = new Font("Stencil", 8, FontStyle.Bold); 28 | 29 | Font nFont2 = new Font("Arial", 8, FontStyle.Regular); 30 | 31 | // Buy setup variables 32 | int[] bSetupBarsTime = new int[10]; 33 | int bSetupCounter; 34 | int bSC; 35 | bool isBuySetup = false; 36 | 37 | double[] buySetupLowsArr = new double[10]; 38 | int bArrowCounter; 39 | bool bSetupArrow=false; 40 | 41 | double lastBuySetupRange; 42 | double pBuySetupThigh; 43 | double pBuySetupTlow; 44 | 45 | 46 | // Buy countdown variables 47 | double[] bCDBarsLows = new double[14]; 48 | int bCountDownCounter; 49 | int bCDC; 50 | bool isBuyCountDownStarted = false; 51 | double lastBCDClose; 52 | 53 | ArrayList bCountDownBarsLows = new ArrayList(); 54 | ArrayList bCountDownBarsHighs = new ArrayList(); 55 | ArrayList bCountDownBarsPCloses = new ArrayList(); 56 | 57 | // Sell setup variables 58 | int[] sSetupBarsTime = new int[10]; 59 | int sSetupCounter; 60 | int sSC; 61 | bool isSellSetup = false; 62 | double[] sellSetupHighsArr = new double[10]; 63 | int sArrowCounter; 64 | bool sSetupArrow = false; 65 | double lastSCDClose; 66 | 67 | double lastSellSetupRange; 68 | double pSellSetupThigh; 69 | double pSellSetupTlow; 70 | 71 | // Sell countdown variables 72 | double[] sCDBarsHighs = new double[14]; 73 | int sCountDownCounter; 74 | int sCDC; 75 | bool isSellCountDownStarted = false; 76 | 77 | ArrayList sCountDownBarsHighs = new ArrayList(); 78 | ArrayList sCountDownBarsLows = new ArrayList(); 79 | ArrayList sCountDownBarsPCloses = new ArrayList(); 80 | 81 | // Variables for both 82 | int TDSTCounter; 83 | int TDRiskCounter; 84 | 85 | #endregion 86 | 87 | /// 88 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 89 | /// 90 | protected override void Initialize() 91 | { 92 | Overlay = true; 93 | CalculateOnBarClose = true; 94 | } 95 | 96 | /// 97 | /// Called on each bar update event (incoming tick) 98 | /// 99 | protected override void OnBarUpdate() 100 | { 101 | // Use this method for calculating your indicator values. Assign a value to each 102 | // plot below by replacing 'Close[0]' with your own formula. 103 | getNextSetup(); 104 | getNextCountDown(); 105 | 106 | ifBuySetupPerfectedDrawArrow(); // dont draw since its a combo and I always combine sequential with combo 107 | ifSellSetupPerfectedDrawArrow(); // dont draw since its a combo and I always combine sequential with combo 108 | } 109 | 110 | // Countdown function 111 | 112 | void getNextCountDown(){ 113 | 114 | //------------------------------ BUY COUNTDOWN ---------------------------------------- 115 | if(isBuySetup == true){ 116 | 117 | isBuyCountDownStarted = true; // we have a buy countdown started; 118 | 119 | if(bCountDownCounter<13 ){ // search for a buy countdown as long as the bars found are less than 13 120 | 121 | // save the current bar's Low,High and Previous Close wether it a coundown bar or not, to use it later with TD Risk Level 122 | bCountDownBarsLows.Add(Low[0]); 123 | bCountDownBarsHighs.Add(High[0]); 124 | bCountDownBarsPCloses.Add(Close[1]); 125 | 126 | 127 | if(bCountDownCounter == 0){ 128 | 129 | for(int i=8; i>=0; i--){ 130 | if(bCountDownCounter == 0){ // if this is the first bar, condition is different since we won't look to compare the last coundown bar's close 131 | if(Close[i] <= Low[i+2] && Low[i] <= Low[i+1] && Close[i] < Close[i+1]){ 132 | bCountDownCounter++; 133 | bCDC++; 134 | bCDBarsLows[bCountDownCounter] =Low[i]; 135 | 136 | lastBCDClose = Close[i]; // save the last BCD close 137 | // Draw the numbers based on the buy countdown counter 138 | DrawText("Bc"+bCDC,true,""+bCountDownCounter, i,Low[i],-nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 139 | } 140 | }else if(bCountDownCounter != 0){ 141 | 142 | if(Close[i] <= Low[i+2] && Low[i] <= Low[i+1] && Close[i] < lastBCDClose && Close[i] < Close[i+1]){ 143 | bCountDownCounter++; 144 | bCDC++; 145 | bCDBarsLows[bCountDownCounter] =Low[i]; 146 | 147 | lastBCDClose = Close[i]; // save the last BCD close 148 | // Draw the numbers based on the buy countdown counter 149 | DrawText("Bc"+bCDC,true,""+bCountDownCounter, i,Low[i],-nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 150 | } 151 | } 152 | } 153 | } 154 | 155 | if(bCountDownCounter >0 && Close[0] <= Low[2] && Low[0] <= Low[1] && Close[0] < lastBCDClose && Close[0] < Close[1] ){ 156 | bCountDownCounter++; 157 | bCDC++; 158 | bCDBarsLows[bCountDownCounter] =Low[0]; 159 | lastBCDClose = Close[0]; // save the last BCD close 160 | DrawText("Bc"+bCDC,true,""+bCountDownCounter, 0,Low[0],-nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 161 | } 162 | 163 | 164 | 165 | } 166 | // if we have a finished buy countdown then reset the counter 167 | if(bCountDownCounter==13){ 168 | bCountDownCounter = 0; // reset the counter 169 | isBuySetup = false; // reset the buysetup status to false to prevent counting countdown unless a new buy setup finishes 170 | isBuyCountDownStarted = false; // DONT NO IF ITS USEFULL 171 | lastBCDClose = 0; // DONT NO IF ITS USEFULL 172 | // For drawing the countdown risk level 173 | drawBuyCountDownTDRisk(); 174 | deleteBCTDRiskArrays(); 175 | 176 | } 177 | } 178 | 179 | //----------------------------- SELL COUNTDOWN ------------------------------------------ 180 | if(isSellSetup == true){ 181 | 182 | isSellCountDownStarted = true; // we have a sell countdown started; 183 | 184 | if(sCountDownCounter<13 ){ // search for a sell countdown as long as the bars found are less than 13 185 | 186 | // save the current bar's Low,High and Previous Close wether it a coundown bar or not, to use it later with TD Risk Level 187 | sCountDownBarsLows.Add(Low[0]); 188 | sCountDownBarsHighs.Add(High[0]); 189 | sCountDownBarsPCloses.Add(Close[1]); 190 | 191 | if(sCountDownCounter == 0){ 192 | 193 | for(int i=8; i>=0; i--){ 194 | if(sCountDownCounter == 0){ // if this is the first bar, condition is different since we won't look to compare the last coundown bar's close 195 | if(Close[i] >= High[i+2] && High[i] >= High[i+1] && Close[i] > Close[i+1]){ 196 | sCountDownCounter++; 197 | sCDC++; 198 | sCDBarsHighs[sCountDownCounter] =High[i]; 199 | 200 | lastSCDClose = Close[i]; // save the last BCD close 201 | // Draw the numbers based on the buy countdown counter 202 | DrawText("Sc"+sCDC,true,""+sCountDownCounter, i,High[i],nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 203 | } 204 | }else if(sCountDownCounter != 0){ 205 | 206 | if(Close[i] >= High[i+2] && High[i] >= High[i+1] && Close[i] > lastSCDClose && Close[i] > Close[i+1]){ 207 | sCountDownCounter++; 208 | sCDC++; 209 | sCDBarsHighs[sCountDownCounter] =High[i]; 210 | 211 | lastSCDClose = Close[i]; // save the last BCD close 212 | // Draw the numbers based on the buy countdown counter 213 | DrawText("Sc"+sCDC,true,""+sCountDownCounter, i,High[i],nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 214 | } 215 | } 216 | } 217 | } 218 | 219 | if(sCountDownCounter >0 && Close[0] >= High[2] && High[0] >= High[1] && Close[0] > lastSCDClose && Close[0] > Close[1] ){ 220 | sCountDownCounter++; 221 | sCDC++; 222 | sCDBarsHighs[sCountDownCounter] =High[0]; 223 | lastSCDClose = Close[0]; // save the last BCD close 224 | DrawText("Sc"+sCDC,true,""+sCountDownCounter, 0,High[0],nFont.Height*2,Color.White,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 225 | } 226 | 227 | 228 | 229 | } 230 | // if we have a finished sell countdown then reset the counter 231 | if(sCountDownCounter==13){ 232 | sCountDownCounter = 0; // reset the counter 233 | isSellSetup = false; // reset the sell setup status to false to prevent counting countdown unless a new buy setup finishes 234 | isSellCountDownStarted = false; // DONT NO IF ITS USEFULL 235 | lastSCDClose = 0; // DONT NO IF ITS USEFULL 236 | // For drawing the countdown risk level 237 | drawSellCountDownTDRisk(); 238 | deleteSCTDRiskArrays(); 239 | } 240 | } 241 | 242 | 243 | } 244 | 245 | /*------------------------------------------------*/ 246 | 247 | // setup function 248 | 249 | void getNextSetup(){ 250 | if (CurrentBar < 9) return; 251 | 252 | /* ---------- BUY SETUP PHASE ---------------------------------------------- */ 253 | 254 | // search for a buy setup as long as the bars found are less than 9 255 | if(bSetupCounter<9 ){ 256 | 257 | // if we have a setup evolving and the current bar doesnt meet the condtion then reset counter and delete previously drawn texts 258 | if(bSetupCounter>=1 && (Close[0]< Close[4] != true) ){ 259 | 260 | // delete unfinished setup 261 | for(int i=1; i<=bSetupCounter; i++){ 262 | // CANCELED // dont draw since its a combo and I always combine sequential with combo // CANCELED 263 | DrawText("B"+(bSC-(i-1)),true, "",bSetupBarsTime[i] ,Low[bSetupBarsTime[i]] , -nFont.Height,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 264 | DrawText("B"+(bSC-(i-1)),true, "",0 ,0 , -nFont.Height,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 265 | } 266 | 267 | bSetupCounter = 0; //reset counter 268 | } 269 | 270 | // ensures that the first bar of the setup has got a price flip 271 | if(bSetupCounter==0 && Close[0]< Close[4] && Close[1] > Close[5]){ 272 | 273 | bSetupCounter++; // counter from 1 to 9 274 | bSC++; // counter for the unique name of the tags 275 | buySetupLowsArr[bSetupCounter] = Low[0]; // save the current low into the buy setup array 276 | bSetupBarsTime[bSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 277 | 278 | // Draw the numbers based on the buy setup counter 279 | // CANCELED // dont draw since its a combo and I always combine sequential with combo // CANCELED 280 | DrawText("B"+bSC,true,""+bSetupCounter, 0,Low[0],-nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 281 | 282 | // else if the counter is above 0 then continue with ordinary conditions 283 | }else{if(bSetupCounter>=1){ 284 | 285 | 286 | // check if we have a bar meets the condition to add to the buy setup 287 | if( Close[0]< Close[4]){ 288 | 289 | bSetupCounter++; // counter from 1 to 9 290 | 291 | bSC++; // counter for the unique name of the tags 292 | buySetupLowsArr[bSetupCounter] = Low[0]; // save the current low into the buy setup array 293 | 294 | bSetupBarsTime[bSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 295 | 296 | // Draw the numbers based on the buy setup counter 297 | // CANCELED // dont draw since its a combo and I always combine sequential with combo 298 | DrawText("B"+bSC,true,""+bSetupCounter, 0,Low[0],-nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 299 | } 300 | } 301 | } 302 | // if we have a finished buy setup and buy count down is already started but not yet finished and countdown cancellation qualifier I or II is active then reset the count down 303 | //if(bSetupCounter==9 && isBuyCountDownStarted == true ){ 304 | if( (bSetupCounter==9 && isBuyCountDownStarted == true) 305 | && (((getSetupRange("b") >= lastBuySetupRange) && (getSetupRange("b") / lastBuySetupRange <= 1.618) 306 | || getSetupHighLow("h") <= pBuySetupThigh && getSetupHighLow("l") >= pBuySetupTlow)) ){ 307 | 308 | //delete the previusly drawn buy count down 309 | for(int i=1; i<=bCountDownCounter; i++){ 310 | 311 | DrawText("Bc"+(bCDC-(i-1)),true,"",0,bCDBarsLows[i],-nFont.Height*2,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 312 | } 313 | 314 | bCountDownCounter = 0; // reset the sell countdown counter 315 | 316 | deleteBCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 317 | } 318 | 319 | 320 | // if we have a finished buy setup and sell count down is already started but not yet finished then reset the sell count down 321 | // and delete the previusly drawn sell count down 322 | if(bSetupCounter==9 && isSellCountDownStarted == true ){ 323 | 324 | //delete the previusly drawn count down 325 | for(int i=1; i<=sCountDownCounter; i++){ 326 | DrawText("Sc"+(sCDC-(i-1)),true,"",0,0,nFont.Height*2,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 327 | } 328 | 329 | 330 | isSellSetup = false; // this stops the sell countdown from continueing 331 | isSellCountDownStarted = false; // SEEMS USELESS 332 | sCountDownCounter = 0; // reset the sell countdown counter 333 | deleteSCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 334 | 335 | } 336 | 337 | // if we have a finished buy setup then reset the counter 338 | if(bSetupCounter==9){ 339 | bSetupCounter = 0; // reset the counter 340 | isBuySetup = true; // turn on th buysetup switch so countdown can begin 341 | bSetupArrow = false; // set to false to searh for a perfected buy setup(Up Arrow) again starting from this recent finished setup 342 | // CANCELED // dont draw since its a combo and I always combine sequential with combo 343 | drawBuyTDST(); // draw the Buy TDST 344 | drawBuyTDRisk(); // draw the TD buy Risk level 345 | lastBuySetupRange = getSetupRange("b"); // save the current setup range into the lastBuySetupRange variable 346 | //isBearishFlip = false; 347 | } 348 | 349 | 350 | } 351 | 352 | 353 | /* ----------------------------------------------------------------------------------*/ 354 | 355 | /*---------------SELL SETUP PHASE ---------------------------------------------------*/ 356 | 357 | // search for a sell setup as long as the bars found are less than 9 358 | if(sSetupCounter<9 ){ 359 | 360 | // if we have a setup evolving and the current bar doesnt meet the condtion then reset counter and delete previously drawn texts 361 | if(sSetupCounter>=1 && (Close[0]> Close[4] != true) ){ 362 | 363 | // delete unfinished setup 364 | for(int i=1; i<=sSetupCounter; i++){ 365 | DrawText("S"+(sSC-(i-1)),true, "",sSetupBarsTime[i] ,High[sSetupBarsTime[i]] , +nFont.Height,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 366 | } 367 | 368 | sSetupCounter = 0; //reset counter 369 | 370 | } 371 | 372 | // ensures that the first bar of the setup has got a price flip 373 | if(sSetupCounter==0 && Close[0]> Close[4] && Close[1] < Close[5]){ 374 | 375 | sSetupCounter++; // counter from 1 to 9 376 | sSC++; // counter for the unique name of the tags 377 | sellSetupHighsArr[sSetupCounter] = High[0]; // save the current low into the buy setup array 378 | 379 | sSetupBarsTime[sSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 380 | 381 | 382 | // Draw the numbers based on the sell setup counter 383 | // CANCELED // dont draw since its a combo and I always combine sequential with combo 384 | DrawText("S"+sSC,true,""+sSetupCounter, 0,High[0],+nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 385 | 386 | // else if the counter is above 0 then continue with ordinary conditions 387 | }else{ if(sSetupCounter>=1){ 388 | 389 | // check if we have a bar meets the condition to add to the sell setup 390 | if( Close[0]> Close[4]){ 391 | 392 | sSetupCounter++; // counter from 1 to 9 393 | sSC++; // counter for the unique name of the tags 394 | sellSetupHighsArr[sSetupCounter] = High[0]; // save the current low into the buy setup array 395 | 396 | sSetupBarsTime[sSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 397 | 398 | // Draw the numbers based on the sell setup counter 399 | // CANCELED // dont draw since its a combo and I always combine sequential with combo 400 | DrawText("S"+sSC,true,""+sSetupCounter, 0,High[0],+nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 401 | } 402 | } 403 | } 404 | // if we have a finished sell setup and a sell count down is already started but not yet finished and countdown cancellation qualifier I or II is active, then reset the count down 405 | //if(sSetupCounter==9 && isSellCountDownStarted == true ){ 406 | 407 | if( (sSetupCounter==9 && isSellCountDownStarted == true) && 408 | (((getSetupRange("s") >= lastSellSetupRange) && (getSetupRange("s") / lastSellSetupRange <= 1.618) ) 409 | ||(getSetupHighLow("h") <= pSellSetupThigh && getSetupHighLow("l") >= pSellSetupTlow)) ){ 410 | 411 | //delete the previusly drawn sell count down 412 | for(int i=1; i<=sCountDownCounter; i++){ 413 | DrawText("Sc"+(sCDC-(i-1)),true,"",0,0,nFont.Height*2,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 414 | } 415 | 416 | sCountDownCounter = 0; // reset the sell countdown counter 417 | deleteSCTDRiskArrays(); // delete the sell countdown Td Risk Level Arraylists 418 | } 419 | 420 | // if we have a finished sell setup and buy count down is already started but not yet finished then reset the buy count down 421 | // and delete the previusly drawn buy count down 422 | if(sSetupCounter==9 && isBuyCountDownStarted == true ){ 423 | 424 | //delete the previusly drawn count down 425 | for(int i=1; i<=bCountDownCounter; i++){ 426 | DrawText("Bc"+(bCDC-(i-1)),true,"",0,0,-nFont.Height*2,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 427 | } 428 | 429 | isBuySetup = false; // this stops the sell countdown from continueing 430 | isBuyCountDownStarted = false; // SEEMS USELESS 431 | bCountDownCounter = 0; // reset the sell countdown counter 432 | 433 | deleteBCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 434 | 435 | } 436 | 437 | // if we have a finished sell setup then reset the counter 438 | if(sSetupCounter==9){ 439 | sSetupCounter = 0; // reset the counter 440 | isSellSetup = true; // turn on th sellsetup switch so countdown can begin 441 | sSetupArrow = false; // set to false to searh for a perfected sell setup(Down Arrow) again starting from this recent finished setup 442 | // CANCELED // dont draw since its a combo and I always combine sequential with combo 443 | drawSellTDST(); // draw the Sell TDST 444 | drawSellTDRisk(); // Draw sell TD Risk level 445 | lastSellSetupRange = getSetupRange("s"); // save the current setup range into the lastBuySetupRange variable 446 | } 447 | } 448 | 449 | /* ------------------------------------------------------------------------*/ 450 | 451 | } 452 | 453 | // Check if the current buy setup is perfected, if yes then draw an up arrow 454 | void ifBuySetupPerfectedDrawArrow(){ 455 | if(isBuySetup==true && bSetupArrow == false && ( (Close[0] <= buySetupLowsArr[6] && Close[0] <= buySetupLowsArr[7]) || (Close[1] <= buySetupLowsArr[6] && Close[1] <= buySetupLowsArr[7]) ) ){ 456 | //IArrowUp arrow = DrawArrowUp(""+bArrowCounter, true, 0, Low[0]- TickSize * 40, Color.DarkViolet); 457 | DrawText("bArrow"+bArrowCounter,true,"˄",0,Low[0],-ArrowFont.Height/2,Color.Aqua,ArrowFont,StringAlignment.Center,Color.Black,Color.Black,10); 458 | bArrowCounter++; // increment the counter for the tags 459 | bSetupArrow = true; // indicates that an arrow has been drawn so not to search and try to draw another one for the recent setup 460 | 461 | 462 | } 463 | } 464 | 465 | // Check if the current sell setup is perfected, if yes then draw a down arrow 466 | void ifSellSetupPerfectedDrawArrow(){ 467 | 468 | if(isSellSetup==true && sSetupArrow == false && ( (Close[0] >= sellSetupHighsArr[6] && Close[0] >= sellSetupHighsArr[7]) || (Close[1] >= buySetupLowsArr[6] && Close[1] >= buySetupLowsArr[7]) ) ){ 469 | //IArrowDown arrow = DrawArrowDown(""+sArrowCounter, true, 0, High[0] +TickSize * 40, Color.DarkViolet); 470 | DrawText("SArrow"+sArrowCounter,true,"˅",0,High[0],ArrowFont.Height/2,Color.Aqua,ArrowFont,StringAlignment.Center,Color.Black,Color.Black,10); 471 | sArrowCounter++; // increment the counter for the tags 472 | sSetupArrow = true; // indicates that an arrow has been drawn so not to search and try to draw another one for the recent setup 473 | } 474 | } 475 | 476 | 477 | // Draw a buy TDST line 478 | void drawBuyTDST(){ 479 | double trueHigh = High[8]; 480 | 481 | // loop through the entire BuySetup bars and get the true high 482 | for(int i=1; i<9; i++){ 483 | 484 | if(High[i] > trueHigh ){ 485 | trueHigh = High[i]; 486 | } 487 | } 488 | 489 | // if the previous close is > than the highest high then it is the true high 490 | if(trueHigh < Close[9]){ 491 | trueHigh = Close[9]; 492 | } 493 | 494 | TDSTCounter++; // increment the TDST counter 495 | 496 | DrawLine("BTDST"+TDSTCounter,true,8,trueHigh,-2,trueHigh,Color.DarkGray,DashStyle.Dash,2); 497 | 498 | } 499 | 500 | 501 | // Draw a Sell TDST line 502 | void drawSellTDST(){ 503 | double trueLow = Low[8]; 504 | 505 | // loop through the entire BuySetup bars and get the true low 506 | for(int i=1; i<9; i++){ 507 | 508 | if(Low[i] < trueLow ){ 509 | trueLow = Low[i]; 510 | } 511 | } 512 | 513 | // if the previous close is < than the lowest low then its the true low 514 | if(trueLow > Close[9]){ 515 | trueLow = Close[9]; 516 | } 517 | 518 | TDSTCounter++; // increment the TDST counter 519 | 520 | DrawLine("BTDST"+TDSTCounter,true,8,trueLow,-2,trueLow,Color.DarkGray,DashStyle.Dash,2); 521 | 522 | } 523 | 524 | // get the range of the recent finished setup 525 | double getSetupRange(String x){ 526 | double trueLow = Low[8]; 527 | double trueHigh = High[8]; 528 | 529 | // loop through the entire BuySetup bars and get the true low 530 | for(int i=1; i<9; i++){ 531 | 532 | if(Low[i] < trueLow ){ 533 | trueLow = Low[i]; 534 | } 535 | } 536 | 537 | // if the previous close is < than the lowest low then its the true low 538 | if(trueLow > Close[9]){ 539 | trueLow = Close[9]; 540 | } 541 | 542 | 543 | 544 | // loop through the entire BuySetup bars and get the true high 545 | for(int i=1; i<9; i++){ 546 | 547 | if(High[i] > trueHigh ){ 548 | trueHigh = High[i]; 549 | } 550 | } 551 | 552 | // if the previous close is > than the highest high then it is the true high 553 | if(trueHigh < Close[9]){ 554 | trueHigh = Close[9]; 555 | } 556 | 557 | // save the true high and true low into the variables based on the type of setup passed (x) 558 | if(x == "b"){ 559 | pBuySetupThigh = trueHigh ; 560 | pBuySetupTlow = trueLow; 561 | 562 | }else{ 563 | if(x == "s"){ 564 | pSellSetupThigh = trueHigh ; 565 | pSellSetupTlow = trueLow; 566 | } 567 | } 568 | 569 | return trueHigh - trueLow; 570 | 571 | } 572 | 573 | 574 | // get the high / low of the recent finished setup 575 | double getSetupHighLow(String x){ 576 | double trueLow = Low[8]; 577 | double trueHigh = High[8]; 578 | 579 | // loop through the entire BuySetup bars and get the true low 580 | for(int i=1; i<9; i++){ 581 | 582 | if(Low[i] < trueLow ){ 583 | trueLow = Low[i]; 584 | } 585 | } 586 | 587 | // if the previous close is < than the lowest low then its the true low 588 | if(trueLow > Close[9]){ 589 | trueLow = Close[9]; 590 | } 591 | 592 | 593 | 594 | // loop through the entire BuySetup bars and get the true high 595 | for(int i=1; i<9; i++){ 596 | 597 | if(High[i] > trueHigh ){ 598 | trueHigh = High[i]; 599 | } 600 | } 601 | 602 | // if the previous close is > than the highest high then it is the true high 603 | if(trueHigh < Close[9]){ 604 | trueHigh = Close[9]; 605 | } 606 | 607 | // save the true high and true low into the variables based on the type of setup passed (x) 608 | if(x == "h"){ 609 | return trueHigh; 610 | 611 | }else{ 612 | 613 | return trueLow; 614 | 615 | } 616 | 617 | } 618 | 619 | // get the range of the truehigh/truelow of TD Risk Level Calculations 620 | double getTrueHLrange(String x){ 621 | double trueLow = Low[0]; 622 | double higheOfTrueLow=High[0]; 623 | 624 | double trueHigh = High[0]; 625 | double lowOfTrueHigh=Low[0]; 626 | 627 | // loop through the entire BuySetup bars and get the true low 628 | for(int i=1; i<9; i++){ 629 | 630 | if(Low[i] < trueLow ){ 631 | trueLow = Low[i]; 632 | higheOfTrueLow = High[i]; 633 | } 634 | } 635 | 636 | // if the previous close is < than the lowest low then its the true low 637 | if(trueLow > Close[1]){ 638 | trueLow = Close[1]; 639 | higheOfTrueLow = High[1]; 640 | } 641 | 642 | 643 | 644 | // loop through the entire BuySetup bars and get the true high 645 | for(int i=1; i<9; i++){ 646 | 647 | if(High[i] > trueHigh ){ 648 | trueHigh = High[i]; 649 | lowOfTrueHigh = Low[i]; 650 | } 651 | } 652 | 653 | // if the previous close is > than the highest high then it is the true high 654 | if(trueHigh < Close[1]){ 655 | trueHigh = Close[1]; 656 | lowOfTrueHigh = Low[1]; 657 | } 658 | 659 | // save the true high and true low into the variables based on the type of setup passed (x) 660 | if(x == "b"){ 661 | return (higheOfTrueLow - trueLow); 662 | }else 663 | 664 | if(x == "s"){ 665 | return (trueHigh - lowOfTrueHigh); 666 | }else 667 | return 0; 668 | 669 | } 670 | 671 | 672 | 673 | // Draw a buy TD Risk Level 674 | void drawBuyTDRisk(){ 675 | double trueLow = Low[0]; 676 | double positinToDrawAt; 677 | // loop through the entire BuySetup bars and get the true low 678 | for(int i=1; i<9; i++){ 679 | 680 | if(Low[i] < trueLow ){ 681 | trueLow = Low[i]; 682 | } 683 | } 684 | 685 | // if the previous close is < than the lowest low then its the true low 686 | if(trueLow > Close[1]){ 687 | trueLow = Close[1]; 688 | } 689 | 690 | TDRiskCounter++; // increment the TDRisk Level counter 691 | positinToDrawAt = trueLow-getTrueHLrange("b"); 692 | 693 | DrawLine("BTDRisk"+TDRiskCounter,true,1,positinToDrawAt,0,positinToDrawAt,Color.Aqua,DashStyle.Solid,1); 694 | 695 | // Draw the last TD Buy Risk Level at the to right of the panel 696 | DrawTextFixed("TDRiskLevelText","Buy Risk L" + " : " + positinToDrawAt.ToString(),TextPosition.TopLeft,Color.Orange,nFont2,Color.Orange,Color.Black,10 ); 697 | 698 | } 699 | 700 | 701 | // Draw a Sell TD Risk Level 702 | void drawSellTDRisk(){ 703 | double trueHigh = High[0]; 704 | double positinToDrawAt; 705 | // loop through the entire BuySetup bars and get the true high 706 | for(int i=1; i<9; i++){ 707 | 708 | if(High[i] > trueHigh ){ 709 | trueHigh = High[i]; 710 | } 711 | } 712 | 713 | // if the previous close is > than the highest high then it is the true high 714 | if(trueHigh < Close[1]){ 715 | trueHigh = Close[1]; 716 | } 717 | 718 | TDRiskCounter++; // increment the TDRisk Level counter 719 | 720 | 721 | //positinToDrawAt = trueHigh; 722 | positinToDrawAt = trueHigh+getTrueHLrange("s"); 723 | 724 | 725 | DrawLine("STDRisk"+TDRiskCounter,true,1,positinToDrawAt,0,positinToDrawAt,Color.Aqua,DashStyle.Solid,1); 726 | 727 | // Draw the level at the center of every TD Sell Risk Level 728 | //DrawText("TDRiskLevelText"+TDRiskLevelTextCounter, true,positinToDrawAt.ToString(),1,positinToDrawAt, 0,Color.Aqua, nFont, StringAlignment.Center, Color.Transparent, Color.Black, 10); 729 | 730 | // Draw the last TD Sell Risk Level at the to right of the panel 731 | DrawTextFixed("TDRiskLevelText","Sell Risk L" + " : " +positinToDrawAt.ToString(),TextPosition.TopLeft,Color.Orange,nFont2,Color.Orange,Color.Black,10 ); 732 | 733 | } 734 | 735 | // Draw the Buy CountDown TD Risk Level 736 | void drawBuyCountDownTDRisk(){ 737 | double lowestLow = Convert.ToDouble(bCountDownBarsLows[1]); 738 | 739 | int indexOfLowestLow=1; 740 | double trueRange; 741 | 742 | for(int i=0; i< bCountDownBarsLows.Count; i++){ 743 | if ( Convert.ToDouble(bCountDownBarsLows[i]) < lowestLow ){ 744 | lowestLow = Convert.ToDouble(bCountDownBarsLows[i]); 745 | indexOfLowestLow = i; 746 | } 747 | 748 | } 749 | 750 | double highestHigh = Convert.ToDouble(bCountDownBarsHighs[indexOfLowestLow]); 751 | double pClose = Convert.ToDouble(bCountDownBarsPCloses[indexOfLowestLow]); 752 | 753 | trueRange = (Math.Max(Math.Max(highestHigh - lowestLow , pClose - lowestLow) , highestHigh -pClose )) ; 754 | 755 | TDRiskCounter++; // increment the TDRisk Level counter 756 | DrawLine("BCTDRisk"+TDRiskCounter,true,1,(lowestLow-trueRange),0,(lowestLow-trueRange),Color.White,DashStyle.Solid,1); 757 | 758 | // Draw the last TD Buy CountDown Risk Level at the to right of the panel 759 | DrawTextFixed("TDRiskLevelText","Buy CD Risk L" + " : " + (lowestLow-trueRange).ToString(),TextPosition.TopLeft,Color.Orange,nFont2,Color.Orange,Color.Black,10 ); 760 | 761 | 762 | } 763 | 764 | // delete the buy countdown td risk arraylists 765 | void deleteBCTDRiskArrays(){ 766 | bCountDownBarsLows.Clear(); 767 | bCountDownBarsHighs.Clear(); 768 | bCountDownBarsPCloses.Clear(); 769 | } 770 | 771 | // Draw the Sell CountDown TD Risk Level 772 | void drawSellCountDownTDRisk(){ 773 | double highestHigh = Convert.ToDouble(sCountDownBarsHighs[1]); 774 | 775 | int indexOfHighestHigh=1; 776 | double trueRange; 777 | 778 | for(int i=0; i< sCountDownBarsHighs.Count; i++){ 779 | if ( Convert.ToDouble(sCountDownBarsHighs[i]) > highestHigh ){ 780 | highestHigh = Convert.ToDouble(sCountDownBarsHighs[i]); 781 | indexOfHighestHigh = i; 782 | } 783 | 784 | } 785 | 786 | double lowestLow = Convert.ToDouble(sCountDownBarsLows[indexOfHighestHigh]); 787 | double pClose = Convert.ToDouble(sCountDownBarsPCloses[indexOfHighestHigh]); 788 | 789 | trueRange = (Math.Max(Math.Max(highestHigh - lowestLow , pClose - lowestLow) , highestHigh -pClose )) ; 790 | 791 | TDRiskCounter++; // increment the TDRisk Level counter 792 | DrawLine("SCTDRisk"+TDRiskCounter,true,1,(highestHigh+trueRange),0,(highestHigh+trueRange),Color.White,DashStyle.Solid,1); 793 | 794 | // Draw the last TD Sell CountDown Risk Level at the to right of the panel 795 | DrawTextFixed("TDRiskLevelText","Sell CD Risk L" + " : " + (highestHigh+trueRange).ToString(),TextPosition.TopLeft,Color.Orange,nFont2,Color.Orange,Color.Black,10 ); 796 | 797 | 798 | } 799 | 800 | // delete the Sell countdown td risk arraylists 801 | void deleteSCTDRiskArrays(){ 802 | sCountDownBarsLows.Clear(); 803 | sCountDownBarsHighs.Clear(); 804 | sCountDownBarsPCloses.Clear(); 805 | } 806 | 807 | 808 | 809 | 810 | 811 | #region Properties 812 | 813 | #endregion 814 | } 815 | } 816 | 817 | #region NinjaScript generated code. Neither change nor remove. 818 | // This namespace holds all indicators and is required. Do not change it. 819 | namespace NinjaTrader.Indicator 820 | { 821 | public partial class Indicator : IndicatorBase 822 | { 823 | private TDCombo[] cacheTDCombo = null; 824 | 825 | private static TDCombo checkTDCombo = new TDCombo(); 826 | 827 | /// 828 | /// 829 | /// 830 | /// 831 | public TDCombo TDCombo() 832 | { 833 | return TDCombo(Input); 834 | } 835 | 836 | /// 837 | /// 838 | /// 839 | /// 840 | public TDCombo TDCombo(Data.IDataSeries input) 841 | { 842 | if (cacheTDCombo != null) 843 | for (int idx = 0; idx < cacheTDCombo.Length; idx++) 844 | if (cacheTDCombo[idx].EqualsInput(input)) 845 | return cacheTDCombo[idx]; 846 | 847 | lock (checkTDCombo) 848 | { 849 | if (cacheTDCombo != null) 850 | for (int idx = 0; idx < cacheTDCombo.Length; idx++) 851 | if (cacheTDCombo[idx].EqualsInput(input)) 852 | return cacheTDCombo[idx]; 853 | 854 | TDCombo indicator = new TDCombo(); 855 | indicator.BarsRequired = BarsRequired; 856 | indicator.CalculateOnBarClose = CalculateOnBarClose; 857 | #if NT7 858 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 859 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 860 | #endif 861 | indicator.Input = input; 862 | Indicators.Add(indicator); 863 | indicator.SetUp(); 864 | 865 | TDCombo[] tmp = new TDCombo[cacheTDCombo == null ? 1 : cacheTDCombo.Length + 1]; 866 | if (cacheTDCombo != null) 867 | cacheTDCombo.CopyTo(tmp, 0); 868 | tmp[tmp.Length - 1] = indicator; 869 | cacheTDCombo = tmp; 870 | return indicator; 871 | } 872 | } 873 | } 874 | } 875 | 876 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 877 | namespace NinjaTrader.MarketAnalyzer 878 | { 879 | public partial class Column : ColumnBase 880 | { 881 | /// 882 | /// 883 | /// 884 | /// 885 | [Gui.Design.WizardCondition("Indicator")] 886 | public Indicator.TDCombo TDCombo() 887 | { 888 | return _indicator.TDCombo(Input); 889 | } 890 | 891 | /// 892 | /// 893 | /// 894 | /// 895 | public Indicator.TDCombo TDCombo(Data.IDataSeries input) 896 | { 897 | return _indicator.TDCombo(input); 898 | } 899 | } 900 | } 901 | 902 | // This namespace holds all strategies and is required. Do not change it. 903 | namespace NinjaTrader.Strategy 904 | { 905 | public partial class Strategy : StrategyBase 906 | { 907 | /// 908 | /// 909 | /// 910 | /// 911 | [Gui.Design.WizardCondition("Indicator")] 912 | public Indicator.TDCombo TDCombo() 913 | { 914 | return _indicator.TDCombo(Input); 915 | } 916 | 917 | /// 918 | /// 919 | /// 920 | /// 921 | public Indicator.TDCombo TDCombo(Data.IDataSeries input) 922 | { 923 | if (InInitialize && input == null) 924 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 925 | 926 | return _indicator.TDCombo(input); 927 | } 928 | } 929 | } 930 | #endregion 931 | -------------------------------------------------------------------------------- /TDSequential.cs: -------------------------------------------------------------------------------- 1 | #region Using declarations 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Drawing.Drawing2D; 7 | using System.Xml.Serialization; 8 | using NinjaTrader.Cbi; 9 | using NinjaTrader.Data; 10 | using NinjaTrader.Gui.Chart; 11 | using System.Threading; 12 | using System.Collections; 13 | #endregion 14 | 15 | 16 | 17 | 18 | 19 | // This namespace holds all indicators and is required. Do not change it. 20 | namespace NinjaTrader.Indicator 21 | { 22 | /// 23 | /// Enter the description of your new custom indicator here 24 | /// 25 | [Description("Enter the description of your new custom indicator here")] 26 | public class TDSequential : Indicator 27 | { 28 | #region Variables 29 | // Wizard generated variables 30 | // User defined variables (add any user defined variables below) 31 | 32 | Font nFont = new Font("Tahoma", 8, FontStyle.Regular); 33 | Font ArrowFont = new Font("Stencil", 8, FontStyle.Bold); 34 | 35 | // Buy setup variables 36 | int[] bSetupBarsTime = new int[10]; 37 | int bSetupCounter; 38 | int bSC; 39 | bool isBuySetup = false; 40 | 41 | double[] buySetupLowsArr = new double[10]; 42 | int bArrowCounter; 43 | bool bSetupArrow=false; 44 | 45 | double lastBuySetupRange; 46 | double pBuySetupThigh; 47 | double pBuySetupTlow; 48 | 49 | 50 | // Buy countdown variables 51 | double[] bCDBarsLows = new double[14]; 52 | int bCountDownCounter; 53 | int bCDC; 54 | bool isBuyCountDownStarted = false; 55 | int bCDPlusC; 56 | 57 | ArrayList bCountDownBarsLows = new ArrayList(); 58 | ArrayList bCountDownBarsHighs = new ArrayList(); 59 | ArrayList bCountDownBarsPCloses = new ArrayList(); 60 | 61 | 62 | // Sell setup variables 63 | int[] sSetupBarsTime = new int[10]; 64 | int sSetupCounter; 65 | int sSC; 66 | bool isSellSetup = false; 67 | double[] sellSetupHighsArr = new double[10]; 68 | int sArrowCounter; 69 | bool sSetupArrow = false; 70 | 71 | double lastSellSetupRange; 72 | double pSellSetupThigh; 73 | double pSellSetupTlow; 74 | 75 | 76 | // Sell countdown variables 77 | double[] sCDBarsHighs = new double[14]; 78 | int sCountDownCounter; 79 | int sCDC; 80 | bool isSellCountDownStarted = false; 81 | int sCDPlusC; 82 | 83 | ArrayList sCountDownBarsHighs = new ArrayList(); 84 | ArrayList sCountDownBarsLows = new ArrayList(); 85 | ArrayList sCountDownBarsPCloses = new ArrayList(); 86 | 87 | 88 | //STEALTH Sell CountDown 89 | double[] SLTHsCDBarsHighs = new double[14]; 90 | int SLTHsCountDownCounter; 91 | bool isSellSTEALTH = false; 92 | int STEALTHTagCounter; 93 | // Variables for both 94 | int TDSTCounter; 95 | int TDRiskCounter; 96 | 97 | #endregion 98 | 99 | /// 100 | /// This method is used to configure the indicator and is called once before any bar data is loaded. 101 | /// 102 | protected override void Initialize() 103 | { 104 | Overlay = true; 105 | 106 | // Calculate on the close of each bar 107 | CalculateOnBarClose = true; 108 | } 109 | 110 | /// 111 | /// Called on each bar update event (incoming tick) 112 | /// 113 | protected override void OnBarUpdate() 114 | { 115 | 116 | getNextSetup(); 117 | getNextCountDown(); 118 | 119 | // sellCountDownStealth(); 120 | 121 | 122 | ifBuySetupPerfectedDrawArrow(); 123 | ifSellSetupPerfectedDrawArrow(); 124 | 125 | } 126 | 127 | // Countdown function 128 | 129 | void getNextCountDown(){ 130 | 131 | //------------------------------ BUY COUNTDOWN ---------------------------------------- 132 | if(isBuySetup == true){ 133 | 134 | isBuyCountDownStarted = true; // we have a buy countdown started; 135 | 136 | if(bCountDownCounter<13 ){ // search for a buy countdown as long as the bars found are less than 13 137 | 138 | // save the current bar's Low,High and Previous Close wether it a coundown bar or not, to use it later with TD Risk Level 139 | bCountDownBarsLows.Add(Low[0]); 140 | bCountDownBarsHighs.Add(High[0]); 141 | bCountDownBarsPCloses.Add(Close[1]); 142 | 143 | if(bCountDownCounter == 12){ //do we already have bar 12 and looking for bar 13 now? 144 | if(Close[0]< Low[2] && Close[0]< bCDBarsLows[8] ){ 145 | bCountDownCounter++; // counter from 1 to 13 146 | bCDC++; // counter for the unique name of the tags 147 | 148 | bCDBarsLows[bCountDownCounter] = Low[0]; // we have a countdown evolving get the current bar low 149 | 150 | // Draw the numbers based on the buy countdown counter 151 | DrawText("Bc"+bCDC,true,""+bCountDownCounter, 0,Low[0],-nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 152 | 153 | }else if(Close[0] < Low[2] ){ 154 | //bCountDownCounter++; // dont increment the counter since 13 is not there yet just + sign 155 | 156 | bCDPlusC++; // counter for the unique name of the stars tags 157 | 158 | // Draw the + signs 159 | DrawText("BcPlus"+bCDPlusC,true,"+", 0,Low[0],-((nFont.Height*2)-(nFont.Height/2)),Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 160 | 161 | } 162 | }else{ 163 | 164 | if(Close[0] < Low[2]) { 165 | bCountDownCounter++; // counter from 1 to 13 166 | bCDC++; // counter for the unique name of the tags 167 | 168 | bCDBarsLows[bCountDownCounter] =Low[0]; 169 | 170 | // Draw the numbers based on the buy countdown counter 171 | //DrawText("Bc"+bCDC,true,""+bCountDownCounter, 0,Low[0],-nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 172 | DrawText("Bc"+bCDC,true,""+bCountDownCounter, 0,Low[0],-((nFont.Height*2)-(nFont.Height/2)),Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 173 | 174 | } 175 | } 176 | } 177 | // if we have a finished buy countdown then reset the counter 178 | if(bCountDownCounter==13){ 179 | bCountDownCounter = 0; // reset the counter 180 | isBuySetup = false; // reset the buysetup status to false to prevent counting countdown unless a new buy setup finishes 181 | isBuyCountDownStarted = false; // DONT NO IF ITS USEFULL 182 | bCDPlusC = 0; // reset the buy countdown pluses counter 183 | // For drawing the countdown risk level 184 | drawBuyCountDownTDRisk(); 185 | deleteBCTDRiskArrays(); 186 | } 187 | } 188 | 189 | //----------------------------- SELL COUNTDOWN ------------------------------------------ 190 | if(isSellSetup == true){ 191 | 192 | isSellCountDownStarted = true; // we have a sell countdown started; 193 | 194 | if(sCountDownCounter<13 ){ // search for a sell countdown as long as the bars found are less than 13 195 | 196 | // save the current bar's Low,High and Previous Close wether it a coundown bar or not, to use it later with TD Risk Level 197 | sCountDownBarsLows.Add(Low[0]); 198 | sCountDownBarsHighs.Add(High[0]); 199 | sCountDownBarsPCloses.Add(Close[1]); 200 | 201 | if(sCountDownCounter == 12){ //do we already have bar 12 and looking for bar 13 now? 202 | if(Close[0]> High[2] && Close[0]> sCDBarsHighs[8] ){ 203 | sCountDownCounter++; // counter from 1 to 13 204 | sCDC++; // counter for the unique name of the tags 205 | 206 | 207 | sCDBarsHighs[sCountDownCounter] = High[0]; // we have a countdown evolving get the current bar index based on time 208 | 209 | // Draw the numbers based on the buy countdown counter 210 | DrawText("Sc"+sCDC,true,""+sCountDownCounter, 0,High[0],nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 211 | 212 | }else if(Close[0] > High[2] ){ 213 | //bCountDownCounter++; // dont increment the counter since 13 is not there yet just + sign 214 | sCDPlusC++; // counter for the unique name of the stars tags 215 | 216 | // Draw the + signs 217 | DrawText("ScPlus"+sCDPlusC,true,"+", 0,High[0],((nFont.Height*2)-(nFont.Height/2)),Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 218 | } 219 | 220 | }else{ 221 | 222 | if(Close[0] > High[2]) { 223 | sCountDownCounter++; // counter from 1 to 13 224 | sCDC++; // counter for the unique name of the tags 225 | 226 | sCDBarsHighs[sCountDownCounter] = High[0]; // we have a countdown evolving get the current bar index based on time 227 | 228 | // Draw the numbers based on the sell countdown counter 229 | DrawText("Sc"+sCDC,true,""+sCountDownCounter, 0,High[0],((nFont.Height*2)-(nFont.Height/2)),Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 230 | } 231 | } 232 | 233 | } 234 | 235 | // if we have a finished sell countdown then reset the counter 236 | if(sCountDownCounter==13){ 237 | sCountDownCounter = 0; // reset the counter 238 | isSellSetup = false; // reset the sell setup status to false to prevent counting countdown unless a new buy setup finishes 239 | isSellCountDownStarted = false; // DONT NO IF ITS USEFULL 240 | sCDPlusC = 0; // reset the buy countdown pluses counter 241 | // For drawing the countdown risk level 242 | drawSellCountDownTDRisk(); 243 | deleteSCTDRiskArrays(); 244 | } 245 | } 246 | 247 | 248 | } 249 | 250 | /*------------------------------------------------*/ 251 | 252 | // setup function 253 | 254 | void getNextSetup(){ 255 | if (CurrentBar < 9) return; 256 | 257 | /* ---------- BUY SETUP PHASE ---------------------------------------------- */ 258 | 259 | // search for a buy setup as long as the bars found are less than 9 260 | if(bSetupCounter<9 ){ 261 | 262 | // if we have a setup evolving and the current bar doesnt meet the condtion then reset counter and delete previously drawn texts 263 | if(bSetupCounter>=1 && (Close[0]< Close[4] != true) ){ 264 | 265 | // delete unfinished setup 266 | for(int i=1; i<=bSetupCounter; i++){ 267 | DrawText("B"+(bSC-(i-1)),true, "",bSetupBarsTime[i] ,Low[bSetupBarsTime[i]] , -nFont.Height,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 268 | //DrawText("B"+(bSC-(i-1)),true, "",0 ,0 , -nFont.Height,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 269 | } 270 | 271 | bSetupCounter = 0; //reset counter 272 | } 273 | 274 | // ensures that the first bar of the setup has got a price flip 275 | if(bSetupCounter==0 && Close[0]< Close[4] && Close[1] > Close[5]){ 276 | 277 | bSetupCounter++; // counter from 1 to 9 278 | bSC++; // counter for the unique name of the tags 279 | buySetupLowsArr[bSetupCounter] = Low[0]; // save the current low into the buy setup array 280 | bSetupBarsTime[bSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 281 | 282 | // Draw the numbers based on the buy setup counter 283 | DrawText("B"+bSC,true,""+bSetupCounter, 0,Low[0],-nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 284 | 285 | // else if the counter is above 0 then continue with ordinary conditions 286 | }else{if(bSetupCounter>=1){ 287 | 288 | 289 | // check if we have a bar meets the condition to add to the buy setup 290 | if( Close[0]< Close[4]){ 291 | 292 | bSetupCounter++; // counter from 1 to 9 293 | 294 | bSC++; // counter for the unique name of the tags 295 | buySetupLowsArr[bSetupCounter] = Low[0]; // save the current low into the buy setup array 296 | 297 | bSetupBarsTime[bSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 298 | 299 | // Draw the numbers based on the buy setup counter 300 | DrawText("B"+bSC,true,""+bSetupCounter, 0,Low[0],-nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 301 | } 302 | } 303 | } 304 | // if we have a finished buy setup and buy count down is already started but not yet finished and countdown cancellation qualifier I or II is active then reset the count down 305 | //if(bSetupCounter==9 && isBuyCountDownStarted == true ){ 306 | if( (bSetupCounter==9 && isBuyCountDownStarted == true) 307 | && (((getSetupRange("b") >= lastBuySetupRange) && (getSetupRange("b") / lastBuySetupRange <= 1.618) 308 | || getSetupHighLow("h") <= pBuySetupThigh && getSetupHighLow("l") >= pBuySetupTlow)) ){ 309 | 310 | //delete the previusly drawn buy count down 311 | for(int i=1; i<=bCountDownCounter; i++){ 312 | 313 | DrawText("Bc"+(bCDC-(i-1)),true,"",0,bCDBarsLows[i],-nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 314 | } 315 | // delete the previously drawn stars 316 | for(int i=1; i<=bCDPlusC; i++){ 317 | DrawText("BcPlus"+(bCDPlusC-(i-1)),true,"",0,0,-nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 318 | } 319 | 320 | bCountDownCounter = 0; // reset the buy countdown counter 321 | bCDPlusC = 0; // reset the buy countdown pluses counter 322 | 323 | deleteBCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 324 | } 325 | 326 | 327 | // if we have a finished buy setup and sell count down is already started but not yet finished then reset the sell count down 328 | // and delete the previusly drawn sell count down 329 | if(bSetupCounter==9 && isSellCountDownStarted == true ){ 330 | 331 | //delete the previusly drawn count down 332 | for(int i=1; i<=sCountDownCounter; i++){ 333 | DrawText("Sc"+(sCDC-(i-1)),true,"",0,0,nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 334 | } 335 | // delete the previously drawn stars 336 | for(int i=1; i<=sCDPlusC; i++){ 337 | DrawText("ScPlus"+(sCDPlusC-(i-1)),true,"",0,0,nFont.Height*3,Color.DarkGreen,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 338 | } 339 | 340 | isSellSetup = false; // this stops the sell countdown from continueing 341 | isSellCountDownStarted = false; // SEEMS USELESS 342 | sCountDownCounter = 0; // reset the sell countdown counter 343 | deleteSCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 344 | 345 | } 346 | 347 | // if we have a finished buy setup then reset the counter 348 | if(bSetupCounter==9){ 349 | bSetupCounter = 0; // reset the counter 350 | isBuySetup = true; // turn on th buysetup switch so countdown can begin 351 | bSetupArrow = false; // set to false to searh for a perfected buy setup(Up Arrow) again starting from this recent finished setup 352 | drawBuyTDST(); // draw the Buy TDST 353 | drawBuyTDRisk(); // draw the TD buy Risk level 354 | lastBuySetupRange = getSetupRange("b"); // save the current setup range into the lastBuySetupRange variable 355 | //isBearishFlip = false; 356 | } 357 | 358 | 359 | } 360 | 361 | 362 | /* ----------------------------------------------------------------------------------*/ 363 | 364 | /*---------------SELL SETUP PHASE ---------------------------------------------------*/ 365 | 366 | // search for a sell setup as long as the bars found are less than 9 367 | if(sSetupCounter<9 ){ 368 | 369 | // if we have a setup evolving and the current bar doesnt meet the condtion then reset counter and delete previously drawn texts 370 | if(sSetupCounter>=1 && (Close[0]> Close[4] != true) ){ 371 | 372 | // delete unfinished setup 373 | for(int i=1; i<=sSetupCounter; i++){ 374 | DrawText("S"+(sSC-(i-1)),true, "",sSetupBarsTime[i] ,High[sSetupBarsTime[i]] , +nFont.Height,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 375 | } 376 | 377 | sSetupCounter = 0; //reset counter 378 | 379 | } 380 | 381 | // ensures that the first bar of the setup has got a price flip 382 | if(sSetupCounter==0 && Close[0]> Close[4] && Close[1] < Close[5]){ 383 | 384 | sSetupCounter++; // counter from 1 to 9 385 | sSC++; // counter for the unique name of the tags 386 | sellSetupHighsArr[sSetupCounter] = High[0]; // save the current low into the buy setup array 387 | 388 | sSetupBarsTime[sSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 389 | 390 | 391 | // Draw the numbers based on the sell setup counter 392 | DrawText("S"+sSC,true,""+sSetupCounter, 0,High[0],+nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 393 | 394 | // else if the counter is above 0 then continue with ordinary conditions 395 | }else{ if(sSetupCounter>=1){ 396 | 397 | // check if we have a bar meets the condition to add to the sell setup 398 | if( Close[0]> Close[4]){ 399 | 400 | sSetupCounter++; // counter from 1 to 9 401 | sSC++; // counter for the unique name of the tags 402 | sellSetupHighsArr[sSetupCounter] = High[0]; // save the current low into the buy setup array 403 | 404 | sSetupBarsTime[sSetupCounter] = CurrentBar - Bars.GetBar(Time[0]); // we have a setup evolving get the current bar index based on time 405 | 406 | // Draw the numbers based on the sell setup counter 407 | DrawText("S"+sSC,true,""+sSetupCounter, 0,High[0],+nFont.Height,Color.Aqua,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 408 | } 409 | } 410 | } 411 | // if we have a finished sell setup and a sell count down is already started but not yet finished and countdown cancellation qualifier I or II is active, then reset the count down 412 | //if(sSetupCounter==9 && isSellCountDownStarted == true ){ 413 | ///* 414 | if( (sSetupCounter==9 && isSellCountDownStarted == true) && 415 | (((getSetupRange("s") >= lastSellSetupRange) && (getSetupRange("s") / lastSellSetupRange <= 1.618) ) 416 | ||(getSetupHighLow("h") <= pSellSetupThigh && getSetupHighLow("l") >= pSellSetupTlow)) ){ 417 | 418 | //delete the previously drawn sell count down 419 | for(int i=1; i<=sCountDownCounter; i++){ 420 | DrawText("Sc"+(sCDC-(i-1)),true,"",0,0,nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 421 | } 422 | // delete the previously drawn stars 423 | for(int i=1; i<=sCDPlusC; i++){ 424 | DrawText("ScPlus"+(sCDPlusC-(i-1)),true,"",0,0,nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 425 | } 426 | 427 | sCountDownCounter = 0; // reset the sell countdown counter 428 | sCDPlusC = 0; // reset the sell countdown pluses counter 429 | 430 | // Activate STEALTH Mode 431 | 432 | isSellSTEALTH = true; // activated 433 | SLTHsCountDownCounter = sCountDownCounter; // copy sCountDownCounter into SLTHsCountDownCounter before resetting it 434 | //SLTHsCDBarsHighs = sCDBarsHighs.CopyTo(SLTHsCDBarsHighs,14); // NOT SURE 435 | // sCDBarsHighs.CopyTo(SLTHsCDBarsHighs,0);// NOT SURE 436 | copyArrayToArray(); 437 | 438 | sCountDownCounter = 0; // reset the sell countdown counter 439 | deleteSCTDRiskArrays(); // delete the sell countdown Td Risk Level Arraylists 440 | 441 | 442 | } 443 | //*/ 444 | // if we have a finished sell setup and buy count down is already started but not yet finished then reset the buy count down 445 | // and delete the previusly drawn buy count down 446 | if(sSetupCounter==9 && isBuyCountDownStarted == true ){ 447 | 448 | //delete the previusly drawn count down 449 | for(int i=1; i<=bCountDownCounter; i++){ 450 | DrawText("Bc"+(bCDC-(i-1)),true,"",0,0,-nFont.Height*2,Color.DeepPink,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 451 | } 452 | // delete the previously drawn stars 453 | for(int i=1; i<=bCDPlusC; i++){ 454 | DrawText("BcPlus"+(bCDPlusC-(i-1)),true,"",0,0,-nFont.Height*3,Color.DarkGreen,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 455 | } 456 | 457 | isBuySetup = false; // this stops the sell countdown from continueing 458 | isBuyCountDownStarted = false; // SEEMS USELESS 459 | bCountDownCounter = 0; // reset the sell countdown counter 460 | 461 | deleteBCTDRiskArrays(); // delete the buy countdown Td Risk Level Arraylists 462 | 463 | 464 | } 465 | 466 | // if we have a finished sell setup then reset the counter 467 | if(sSetupCounter==9){ 468 | sSetupCounter = 0; // reset the counter 469 | isSellSetup = true; // turn on th sellsetup switch so countdown can begin 470 | sSetupArrow = false; // set to false to searh for a perfected sell setup(Down Arrow) again starting from this recent finished setup 471 | drawSellTDST(); // draw the Sell TDST 472 | drawSellTDRisk(); // Draw sell TD Risk level 473 | lastSellSetupRange = getSetupRange("s"); // save the current setup range into the lastBuySetupRange variable 474 | } 475 | } 476 | 477 | /* ------------------------------------------------------------------------*/ 478 | 479 | } 480 | 481 | // Check if the current buy setup is perfected, if yes then draw an up arrow 482 | void ifBuySetupPerfectedDrawArrow(){ 483 | 484 | if(isBuySetup==true && bSetupArrow == false && ( (Close[0] <= buySetupLowsArr[6] && Close[0] <= buySetupLowsArr[7]) || (Close[1] <= buySetupLowsArr[6] && Close[1] <= buySetupLowsArr[7]) ) ){ 485 | //IArrowUp arrow = DrawArrowUp(""+bArrowCounter, true, 0, Low[0]- TickSize * 40, Color.DarkViolet); 486 | DrawText("bArrow"+bArrowCounter,true,"˄",0,Low[0],-ArrowFont.Height/2,Color.Aqua,ArrowFont,StringAlignment.Center,Color.Black,Color.Black,10); 487 | bArrowCounter++; // increment the counter for the tags 488 | bSetupArrow = true; // indicates that an arrow has been drawn so not to search and try to draw another one for the recent setup 489 | 490 | } 491 | } 492 | 493 | // Check if the current sell setup is perfected, if yes then draw a down arrow 494 | void ifSellSetupPerfectedDrawArrow(){ 495 | 496 | if(isSellSetup==true && sSetupArrow == false && ( (Close[0] >= sellSetupHighsArr[6] && Close[0] >= sellSetupHighsArr[7]) || (Close[1] >= buySetupLowsArr[6] && Close[1] >= buySetupLowsArr[7]) ) ){ 497 | //IArrowDown arrow = DrawArrowDown(""+sArrowCounter, true, 0, High[0] +TickSize * 40, Color.DarkViolet); 498 | DrawText("SArrow"+sArrowCounter,true,"˅",0,High[0],ArrowFont.Height/2,Color.Aqua,ArrowFont,StringAlignment.Center,Color.Black,Color.Black,10); 499 | sArrowCounter++; // increment the counter for the tags 500 | sSetupArrow = true; // indicates that an arrow has been drawn so not to search and try to draw another one for the recent setup 501 | } 502 | } 503 | 504 | 505 | // Draw a buy TDST line 506 | void drawBuyTDST(){ 507 | double trueHigh = High[8]; 508 | 509 | // loop through the entire BuySetup bars and get the true high 510 | for(int i=1; i<9; i++){ 511 | 512 | if(High[i] > trueHigh ){ 513 | trueHigh = High[i]; 514 | } 515 | } 516 | 517 | // if the previous close is > than the highest high then it is the true high 518 | if(trueHigh < Close[9]){ 519 | trueHigh = Close[9]; 520 | } 521 | 522 | TDSTCounter++; // increment the TDST counter 523 | 524 | DrawLine("BTDST"+TDSTCounter,true,8,trueHigh,-2,trueHigh,Color.DarkGray,DashStyle.Dash,2); 525 | 526 | } 527 | 528 | 529 | // Draw a Sell TDST line 530 | void drawSellTDST(){ 531 | double trueLow = Low[8]; 532 | 533 | // loop through the entire BuySetup bars and get the true low 534 | for(int i=1; i<9; i++){ 535 | 536 | if(Low[i] < trueLow ){ 537 | trueLow = Low[i]; 538 | } 539 | } 540 | 541 | // if the previous close is < than the lowest low then its the true low 542 | if(trueLow > Close[9]){ 543 | trueLow = Close[9]; 544 | } 545 | 546 | TDSTCounter++; // increment the TDST counter 547 | 548 | DrawLine("STDST"+TDSTCounter,true,8,trueLow,-2,trueLow,Color.DarkGray,DashStyle.Dash,2); 549 | 550 | 551 | } 552 | 553 | // get the range of the recent finished setup 554 | double getSetupRange(String x){ 555 | double trueLow = Low[8]; 556 | double trueHigh = High[8]; 557 | 558 | // loop through the entire BuySetup bars and get the true low 559 | for(int i=1; i<9; i++){ 560 | 561 | if(Low[i] < trueLow ){ 562 | trueLow = Low[i]; 563 | } 564 | } 565 | 566 | // if the previous close is < than the lowest low then its the true low 567 | if(trueLow > Close[9]){ 568 | trueLow = Close[9]; 569 | } 570 | 571 | 572 | 573 | // loop through the entire BuySetup bars and get the true high 574 | for(int i=1; i<9; i++){ 575 | 576 | if(High[i] > trueHigh ){ 577 | trueHigh = High[i]; 578 | } 579 | } 580 | 581 | // if the previous close is > than the highest high then it is the true high 582 | if(trueHigh < Close[9]){ 583 | trueHigh = Close[9]; 584 | } 585 | 586 | // save the true high and true low into the variables based on the type of setup passed (x) 587 | if(x == "b"){ 588 | pBuySetupThigh = trueHigh ; 589 | pBuySetupTlow = trueLow; 590 | 591 | }else{ 592 | if(x == "s"){ 593 | pSellSetupThigh = trueHigh ; 594 | pSellSetupTlow = trueLow; 595 | } 596 | } 597 | 598 | return trueHigh - trueLow; 599 | 600 | } 601 | 602 | 603 | // get the high / low of the recent finished setup 604 | double getSetupHighLow(String x){ 605 | double trueLow = Low[8]; 606 | double trueHigh = High[8]; 607 | 608 | // loop through the entire BuySetup bars and get the true low 609 | for(int i=1; i<9; i++){ 610 | 611 | if(Low[i] < trueLow ){ 612 | trueLow = Low[i]; 613 | } 614 | } 615 | 616 | // if the previous close is < than the lowest low then its the true low 617 | if(trueLow > Close[9]){ 618 | trueLow = Close[9]; 619 | } 620 | 621 | 622 | 623 | // loop through the entire BuySetup bars and get the true high 624 | for(int i=1; i<9; i++){ 625 | 626 | if(High[i] > trueHigh ){ 627 | trueHigh = High[i]; 628 | } 629 | } 630 | 631 | // if the previous close is > than the highest high then it is the true high 632 | if(trueHigh < Close[9]){ 633 | trueHigh = Close[9]; 634 | } 635 | 636 | // save the true high and true low into the variables based on the type of setup passed (x) 637 | if(x == "h"){ 638 | return trueHigh; 639 | 640 | }else{ 641 | 642 | return trueLow; 643 | 644 | } 645 | 646 | } 647 | 648 | 649 | // Stealth sell countdown 650 | void sellCountDownStealth(){ 651 | if(isSellSTEALTH == true){ 652 | 653 | if(SLTHsCountDownCounter<13 ){ // search for a sell countdown as long as the bars found are less than 13 654 | 655 | if(SLTHsCountDownCounter == 12){ //do we already have bar 12 and looking for bar 13 now? 656 | if(Close[0]> High[2] && Close[0]> SLTHsCDBarsHighs[8] ){ 657 | // if(Close[0]> High[2] ){ 658 | SLTHsCountDownCounter++; // counter from 1 to 13 659 | 660 | SLTHsCDBarsHighs[SLTHsCountDownCounter] = High[0]; // we have a countdown evolving get the current bar index based on time 661 | } 662 | 663 | 664 | }else{ 665 | 666 | if(Close[0] > High[2]) { 667 | 668 | SLTHsCountDownCounter++; // counter from 1 to 13 669 | SLTHsCDBarsHighs[SLTHsCountDownCounter] = High[0]; // we have a countdown evolving get the current bar index based on time 670 | } 671 | } 672 | 673 | } 674 | 675 | // if we have a finished sell countdown then reset the counter 676 | if(SLTHsCountDownCounter==13){ 677 | STEALTHTagCounter++; 678 | DrawText("SLTHSc"+STEALTHTagCounter,true,"R", 0,High[0],nFont.Height*2,Color.Black,nFont,StringAlignment.Center,Color.Black,Color.Black,10); 679 | 680 | SLTHsCountDownCounter = 0; // reset the counter 681 | isSellSTEALTH = false; 682 | 683 | } 684 | } 685 | } 686 | 687 | void copyArrayToArray(){ 688 | for(int i=0; i<14; i++){ 689 | SLTHsCDBarsHighs[i] = sCDBarsHighs[i]; 690 | // Print(sCDBarsHighs[i]); 691 | // Print(SLTHsCDBarsHighs[i]); 692 | } 693 | } 694 | 695 | 696 | // get the range of the truehigh/truelow of TD Risk Level Calculations 697 | double getTrueHLrange(String x){ 698 | double trueLow = Low[0]; 699 | double higheOfTrueLow=High[0]; 700 | 701 | double trueHigh = High[0]; 702 | double lowOfTrueHigh=Low[0]; 703 | 704 | // loop through the entire BuySetup bars and get the true low 705 | for(int i=1; i<9; i++){ 706 | 707 | if(Low[i] < trueLow ){ 708 | trueLow = Low[i]; 709 | higheOfTrueLow = High[i]; 710 | } 711 | } 712 | 713 | // if the previous close is < than the lowest low then its the true low 714 | if(trueLow > Close[1]){ 715 | trueLow = Close[1]; 716 | higheOfTrueLow = High[1]; 717 | } 718 | 719 | 720 | 721 | // loop through the entire BuySetup bars and get the true high 722 | for(int i=1; i<9; i++){ 723 | 724 | if(High[i] > trueHigh ){ 725 | trueHigh = High[i]; 726 | lowOfTrueHigh = Low[i]; 727 | } 728 | } 729 | 730 | // if the previous close is > than the highest high then it is the true high 731 | if(trueHigh < Close[1]){ 732 | trueHigh = Close[1]; 733 | lowOfTrueHigh = Low[1]; 734 | } 735 | 736 | // save the true high and true low into the variables based on the type of setup passed (x) 737 | if(x == "b"){ 738 | return (higheOfTrueLow - trueLow); 739 | }else 740 | 741 | if(x == "s"){ 742 | return (trueHigh - lowOfTrueHigh); 743 | }else 744 | return 0; 745 | 746 | 747 | 748 | 749 | } 750 | // Draw a buy TD Risk Level 751 | void drawBuyTDRisk(){ 752 | double trueLow = Low[0]; 753 | double positinToDrawAt; 754 | // loop through the entire BuySetup bars and get the true low 755 | for(int i=1; i<9; i++){ 756 | 757 | if(Low[i] < trueLow ){ 758 | trueLow = Low[i]; 759 | } 760 | } 761 | 762 | // if the previous close is < than the lowest low then its the true low 763 | if(trueLow > Close[1]){ 764 | trueLow = Close[1]; 765 | } 766 | 767 | TDRiskCounter++; // increment the TDRisk Level counter 768 | positinToDrawAt = trueLow-getTrueHLrange("b"); 769 | 770 | DrawLine("BTDRisk"+TDRiskCounter,true,1,positinToDrawAt,0,positinToDrawAt,Color.Aqua,DashStyle.Solid,1); 771 | 772 | } 773 | 774 | 775 | // Draw a Sell TD Risk Level 776 | void drawSellTDRisk(){ 777 | double trueHigh = High[0]; 778 | double positinToDrawAt; 779 | // loop through the entire BuySetup bars and get the true high 780 | for(int i=1; i<9; i++){ 781 | 782 | if(High[i] > trueHigh ){ 783 | trueHigh = High[i]; 784 | } 785 | } 786 | 787 | // if the previous close is > than the highest high then it is the true high 788 | if(trueHigh < Close[1]){ 789 | trueHigh = Close[1]; 790 | } 791 | 792 | TDRiskCounter++; // increment the TDRisk Level counter 793 | //positinToDrawAt = trueHigh; 794 | positinToDrawAt = trueHigh+getTrueHLrange("s"); 795 | 796 | 797 | DrawLine("STDRisk"+TDRiskCounter,true,1,positinToDrawAt,0,positinToDrawAt,Color.Aqua,DashStyle.Solid,1); 798 | 799 | } 800 | // Draw the Buy CountDown TD Risk Level 801 | void drawBuyCountDownTDRisk(){ 802 | double lowestLow = Convert.ToDouble(bCountDownBarsLows[1]); 803 | 804 | int indexOfLowestLow=1; 805 | double trueRange; 806 | 807 | for(int i=0; i< bCountDownBarsLows.Count; i++){ 808 | if ( Convert.ToDouble(bCountDownBarsLows[i]) < lowestLow ){ 809 | lowestLow = Convert.ToDouble(bCountDownBarsLows[i]); 810 | indexOfLowestLow = i; 811 | } 812 | 813 | } 814 | 815 | double highestHigh = Convert.ToDouble(bCountDownBarsHighs[indexOfLowestLow]); 816 | double pClose = Convert.ToDouble(bCountDownBarsPCloses[indexOfLowestLow]); 817 | 818 | trueRange = (Math.Max(Math.Max(highestHigh - lowestLow , pClose - lowestLow) , highestHigh -pClose )) ; 819 | 820 | TDRiskCounter++; // increment the TDRisk Level counter 821 | DrawLine("BCTDRisk"+TDRiskCounter,true,1,(lowestLow-trueRange),0,(lowestLow-trueRange),Color.DeepPink,DashStyle.Solid,1); 822 | 823 | 824 | } 825 | 826 | // delete the buy countdown td risk arraylists 827 | void deleteBCTDRiskArrays(){ 828 | bCountDownBarsLows.Clear(); 829 | bCountDownBarsHighs.Clear(); 830 | bCountDownBarsPCloses.Clear(); 831 | } 832 | 833 | // Draw the Sell CountDown TD Risk Level 834 | void drawSellCountDownTDRisk(){ 835 | double highestHigh = Convert.ToDouble(sCountDownBarsHighs[1]); 836 | 837 | int indexOfHighestHigh=1; 838 | double trueRange; 839 | 840 | for(int i=0; i< sCountDownBarsHighs.Count; i++){ 841 | if ( Convert.ToDouble(sCountDownBarsHighs[i]) > highestHigh ){ 842 | highestHigh = Convert.ToDouble(sCountDownBarsHighs[i]); 843 | indexOfHighestHigh = i; 844 | } 845 | 846 | } 847 | 848 | double lowestLow = Convert.ToDouble(sCountDownBarsLows[indexOfHighestHigh]); 849 | double pClose = Convert.ToDouble(sCountDownBarsPCloses[indexOfHighestHigh]); 850 | 851 | trueRange = (Math.Max(Math.Max(highestHigh - lowestLow , pClose - lowestLow) , highestHigh -pClose )) ; 852 | 853 | TDRiskCounter++; // increment the TDRisk Level counter 854 | DrawLine("SCTDRisk"+TDRiskCounter,true,1,(highestHigh+trueRange),0,(highestHigh+trueRange),Color.DeepPink,DashStyle.Solid,1); 855 | 856 | 857 | } 858 | 859 | // delete the Sell countdown td risk arraylists 860 | void deleteSCTDRiskArrays(){ 861 | sCountDownBarsLows.Clear(); 862 | sCountDownBarsHighs.Clear(); 863 | sCountDownBarsPCloses.Clear(); 864 | } 865 | #region Properties 866 | 867 | #endregion 868 | } 869 | } 870 | 871 | #region NinjaScript generated code. Neither change nor remove. 872 | // This namespace holds all indicators and is required. Do not change it. 873 | namespace NinjaTrader.Indicator 874 | { 875 | public partial class Indicator : IndicatorBase 876 | { 877 | private TDSequential[] cacheTDSequential = null; 878 | 879 | private static TDSequential checkTDSequential = new TDSequential(); 880 | 881 | /// 882 | /// Enter the description of your new custom indicator here 883 | /// 884 | /// 885 | public TDSequential TDSequential() 886 | { 887 | return TDSequential(Input); 888 | } 889 | 890 | /// 891 | /// Enter the description of your new custom indicator here 892 | /// 893 | /// 894 | public TDSequential TDSequential(Data.IDataSeries input) 895 | { 896 | if (cacheTDSequential != null) 897 | for (int idx = 0; idx < cacheTDSequential.Length; idx++) 898 | if (cacheTDSequential[idx].EqualsInput(input)) 899 | return cacheTDSequential[idx]; 900 | 901 | lock (checkTDSequential) 902 | { 903 | if (cacheTDSequential != null) 904 | for (int idx = 0; idx < cacheTDSequential.Length; idx++) 905 | if (cacheTDSequential[idx].EqualsInput(input)) 906 | return cacheTDSequential[idx]; 907 | 908 | TDSequential indicator = new TDSequential(); 909 | indicator.BarsRequired = BarsRequired; 910 | indicator.CalculateOnBarClose = CalculateOnBarClose; 911 | #if NT7 912 | indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; 913 | indicator.MaximumBarsLookBack = MaximumBarsLookBack; 914 | #endif 915 | indicator.Input = input; 916 | Indicators.Add(indicator); 917 | indicator.SetUp(); 918 | 919 | TDSequential[] tmp = new TDSequential[cacheTDSequential == null ? 1 : cacheTDSequential.Length + 1]; 920 | if (cacheTDSequential != null) 921 | cacheTDSequential.CopyTo(tmp, 0); 922 | tmp[tmp.Length - 1] = indicator; 923 | cacheTDSequential = tmp; 924 | return indicator; 925 | } 926 | } 927 | } 928 | } 929 | 930 | // This namespace holds all market analyzer column definitions and is required. Do not change it. 931 | namespace NinjaTrader.MarketAnalyzer 932 | { 933 | public partial class Column : ColumnBase 934 | { 935 | /// 936 | /// Enter the description of your new custom indicator here 937 | /// 938 | /// 939 | [Gui.Design.WizardCondition("Indicator")] 940 | public Indicator.TDSequential TDSequential() 941 | { 942 | return _indicator.TDSequential(Input); 943 | } 944 | 945 | /// 946 | /// Enter the description of your new custom indicator here 947 | /// 948 | /// 949 | public Indicator.TDSequential TDSequential(Data.IDataSeries input) 950 | { 951 | return _indicator.TDSequential(input); 952 | } 953 | } 954 | } 955 | 956 | // This namespace holds all strategies and is required. Do not change it. 957 | namespace NinjaTrader.Strategy 958 | { 959 | public partial class Strategy : StrategyBase 960 | { 961 | /// 962 | /// Enter the description of your new custom indicator here 963 | /// 964 | /// 965 | [Gui.Design.WizardCondition("Indicator")] 966 | public Indicator.TDSequential TDSequential() 967 | { 968 | return _indicator.TDSequential(Input); 969 | } 970 | 971 | /// 972 | /// Enter the description of your new custom indicator here 973 | /// 974 | /// 975 | public Indicator.TDSequential TDSequential(Data.IDataSeries input) 976 | { 977 | if (InInitialize && input == null) 978 | throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); 979 | 980 | return _indicator.TDSequential(input); 981 | } 982 | } 983 | } 984 | #endregion 985 | -------------------------------------------------------------------------------- /Demark Indicators Tested.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import talib 3 | # Put any initialization logic here. The context object will be passed to 4 | # the other methods in your algorithm. 5 | def initialize(context): 6 | #set_universe(universe.DollarVolumeUniverse(floor_percentile=98, ceiling_percentile=100)) 7 | context.stocks = [sid(23175),sid(24),sid(43694),sid(22954),sid(26322),sid(114),sid(630),sid(149),sid(168),sid(8572),sid(270),sid(300) 8 | ,sid(14328), sid(659),sid(43495),sid(368),sid(27676),sid(16841),sid(23103),sid(448),sid(455),sid(460),sid(698), 9 | sid(794),sid(3806),sid(20330),sid(980),sid(11100),sid(22660),sid(1376),sid(13176), 10 | sid(26960),sid(1406),sid(1539), sid(44747),sid(2190),sid(12652) 11 | ,sid(2602),sid(2427),sid(2470), 12 | sid(10594),sid(2564),sid(9540),sid(44989),sid(2587),sid(2618),sid(21382),sid(27543),sid(43512), 13 | sid(42950),sid(2765),sid(2853),sid(2854),sid(32902),sid(3136),sid(3212),sid(9736),sid(46631), 14 | sid(47208),sid(20088),sid(3460),sid(41047),sid(3496), 15 | sid(216),sid(3620),sid(25090),sid(3647),sid(22651), 16 | sid(3718),sid(3766),sid(21774),sid(10187),sid(8655),sid(4031), 17 | sid(46053),sid(4151),sid(48317),sid(49229),sid(4263),sid(4315),sid(4373),sid(12909), 18 | sid(4487),sid(12691),sid(22096),sid(41451),sid(4537),sid(32146),sid(12350)] 19 | 20 | context.index = sid(8554) 21 | # Trading guard to not trade leveraged ETFs 22 | set_do_not_order_list(security_lists.leveraged_etf_list) 23 | 24 | # Make a separate algo for each stock. 25 | context.algos_1Min = [Demark(stock) for stock in context.stocks] 26 | 27 | 28 | # the leverage buffer to stop trading if leverage exceeds 29 | context.leverage_buffer = 2.5 30 | # what is the percentage to risk per position 31 | context.percent_per_pos = 0.9 32 | context.leverage1 = 0 33 | 34 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | # Will be called on every trade event for the securities you specify. 36 | def handle_data(context, data): 37 | #record(cash = context.portfolio.cash) 38 | 39 | context.leverage1 = context.account.leverage 40 | record (leverage = context.leverage1) 41 | 42 | # Call each individual algorithm's handle_data method. 43 | for algo in context.algos_1Min: 44 | algo.handle_data(context,data ,context.algos_1Min.index(algo)) 45 | 46 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | class Demark(object): 49 | 50 | def __init__(self,stock): 51 | 52 | self.stock = stock 53 | # to hold the wave3 projection targets 54 | self.wave3_up_proj = 0 55 | self.wave3_down_proj = 0 56 | 57 | # to hold the stop levels 58 | self.stop_b = 0 59 | self.stop_s = 0 60 | 61 | self.bars_since_last_setup = 0 62 | # TD Sequential Phases 63 | self.setup_phase = 'na' 64 | self.setup_phase2 = 'na' 65 | self.count_down_started = 'na' 66 | 67 | # to be used to determine what was the last countdown finished 68 | self.count_down_last_finished = 'na' 69 | 70 | # Current and previous counter since last setup 71 | self.__S9_pos_Bcd = 0 72 | self.__S9_pos_Scd = 0 73 | self.__S9_pos_combo_Scd = 9 74 | self.__S9_pos_combo_Bcd = 9 75 | 76 | # Current & Previous setup ranges with corrosponding Heighs an Lows 77 | self.__c_setup_range = 0 78 | self.__p_setup_range = 0 79 | self.__c_s_h = 0 80 | self.__c_s_l = 0 81 | self.__p_s_h = 0 82 | self.__p_s_l = 0 83 | 84 | # Current and Previous TDST levels variables 85 | self.curr_TDST_sell = 0 86 | self.curr_TDST_buy = 0 87 | self.prev_TDST_sell = 0 88 | self.prev_TDST_buy = 0 89 | 90 | # Arrays to hold the high/low prices of the setup's bars 91 | self.__Ss_Arr = np.zeros(9) 92 | self.__Bs_Arr = np.zeros(9) 93 | # Arrays to hold the closes of the setup's bars 94 | self.Ss_clos_arr= np.zeros(9) 95 | self.Bs_clos_arr= np.zeros(9) 96 | 97 | # To hold the count of the sell/buy setup 98 | self.scount = 0 99 | self.bcount = 0 100 | 101 | # To hold the count of the sell/buy countdown 102 | self.bcd_counter = 0 103 | self.scd_counter = 0 104 | 105 | # To hold the 13 bar close 106 | self.Bcd13_close = 0 107 | self.Scd13_close = 0 108 | 109 | # To hold the high/low of the 8th bar countdown 110 | self.eighth_high_low = 0 111 | 112 | # TDRisk Levels 113 | self.Td_s_risk_s = 0 114 | self.Td_s_risk_b = 0 115 | self.Td_cd_risk_s = 0 116 | self.Td_cd_risk_b = 0 117 | 118 | #~~~ variables for upTrend wave 119 | self.d_waves_upt = {'wave0':False,'wave1':False, 'wave2':False , 'wave3':False, 'wave4':False, \ 120 | 'wave5':False, 'waveA':False, 'waveB':False, 'waveC':False} 121 | 122 | self.d_w_points_upt = {'wave0_low':0, 'wave1_high':0, 'wave2_low':0, 'wave3_high':0, 'wave4_low':0,\ 123 | 'wave5_high':0, 'waveA_low':0, 'waveB_high':0, 'waveC_low':0} 124 | 125 | self.d_waveC_lock_upt = False 126 | 127 | #~~~ variables for downTrend wave 128 | self.d_waves_downt = {'wave0':False,'wave1':False, 'wave2':False , 'wave3':False, 'wave4':False, \ 129 | 'wave5':False, 'waveA':False, 'waveB':False, 'waveC':False} 130 | 131 | self.d_w_points_downt = {'wave0_high':0, 'wave1_low':0, 'wave2_high':0, 'wave3_low':0, 'wave4_high':0,\ 132 | 'wave5_low':0, 'waveA_high':0, 'waveB_low':0, 'waveC_high':0} 133 | 134 | self.d_waveC_lock_downt = False 135 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136 | 137 | def handle_data(self,context,data,index): 138 | 139 | if get_open_orders(self.stock): 140 | return 141 | 142 | cash = context.portfolio.cash 143 | price = data[self.stock].price 144 | 145 | order_share = context.portfolio.positions[self.stock].amount 146 | 147 | if order_share > 0: 148 | 149 | if price >= self.wave3_up_proj: 150 | order_target(self.stock,0) 151 | 152 | log.info('{0}: closing long PROFIT at {1}, selling {2} shares'.format( 153 | self.stock.symbol, price, order_share 154 | )) 155 | 156 | 157 | elif price <= self.stop_b : 158 | order_target(self.stock,0) 159 | 160 | log.info('{0}: closing long LOSS at {1}, selling {2} shares'.format( 161 | self.stock.symbol, price, order_share 162 | )) 163 | 164 | 165 | # Trailing Stop 166 | elif price - self.stop_b > 2.617 : 167 | self.stop_b = self.stop_b + 0.65 168 | print ('stop changed = ',self.stop_b) 169 | 170 | 171 | elif order_share < 0: 172 | 173 | if price <= self.wave3_down_proj: 174 | order_target(self.stock,0) 175 | 176 | log.info('{0}: covering short PROFIT at {1}, buying {2} shares'.format( 177 | self.stock.symbol,price, order_share 178 | )) 179 | 180 | 181 | elif price >= self.stop_s: 182 | order_target(self.stock,0) 183 | 184 | log.info('{0}: covering short LOSS at {1}, buying {2} shares'.format( 185 | self.stock.symbol, price, order_share 186 | )) 187 | 188 | 189 | # Trailing Stop 190 | elif self.stop_s - price > 2.617 : 191 | self.stop_s = self.stop_s - 0.65 192 | print ('stop changed = ',self.stop_s) 193 | 194 | else: 195 | 196 | if context.leverage1 > context.leverage_buffer: 197 | return 198 | 199 | 200 | prices_minute = history(15, '1d', 'price')[self.stock] 201 | rsi_minute = talib.RSI(prices_minute,14) 202 | 203 | prices_index = history(15,'1d','price')[context.index] 204 | rsi_index = talib.RSI(prices_index,14) 205 | 206 | self.d_wave_upt(self.stock) 207 | self.d_wave_downt(self.stock) 208 | self.td_setup(self.stock) 209 | self.td_seq_cd(self.stock,'b') 210 | self.td_seq_cd(self.stock,'s') 211 | 212 | prices_dailyMA = history(51,'1d','price')[self.stock] 213 | MA200 = talib.MA( prices_dailyMA,50) 214 | 215 | 216 | # Trading guard to not trade leveraged ETFs 217 | if self.stock.symbol not in security_lists.leveraged_etf_list: 218 | 219 | if (self.d_waves_upt['wave2'] == True and self.d_waves_upt['wave3'] == False\ 220 | or self.d_waves_upt['wave4'] == True and self.d_waves_upt['wave5'] == False)\ 221 | and rsi_minute[-1] > 40\ 222 | and (self.is9_tradable_lite_v2(self.stock,'b') or self.is13_tradable(self.stock,'b')): 223 | 224 | # Determine the projected level, wether wave 2 or wave 4 225 | if self.d_waves_upt['wave2'] == True and self.d_waves_upt['wave3'] == False: 226 | 227 | self.wave3_up_proj = self.td_wave_projection(3,'u') 228 | 229 | else: 230 | self.wave3_up_proj = self.td_wave_projection(5,'u') 231 | 232 | # determine what is the stop level, based on setup or cd 233 | if self.count_down_last_finished == 'na': 234 | self.stop_b = self.Td_s_risk_b - 0.618 235 | else: 236 | self.stop_b = self.Td_cd_risk_b - 0.618 237 | 238 | 239 | # is it 3 to 1, then enter else, return 240 | if (self.wave3_up_proj - price) / (price - self.stop_b) > 3: 241 | 242 | # Use floor division to get a whole number of shares 243 | target_shares = cash*context.percent_per_pos // price 244 | 245 | order_target(self.stock,+target_shares) 246 | #order_target(self.stock,-target_shares,style=StopOrder(self.Td_s_risk_b)) 247 | 248 | log.info('{0}: Price at {1}, buying {2} shares.'.format( 249 | self.stock.symbol, price, target_shares 250 | )) 251 | 252 | print ('wave5_up_proj=',self.wave3_up_proj) 253 | print ('stop = ',self.stop_b) 254 | 255 | else: 256 | return 257 | 258 | 259 | if (self.d_waves_downt['wave2'] == True and self.d_waves_downt['wave3'] == False\ 260 | or self.d_waves_downt['wave4'] == True and self.d_waves_downt['wave5'] == False)\ 261 | and rsi_minute[-1] < 60\ 262 | and (self.is9_tradable_lite_v2(self.stock,'s') or self.is13_tradable(self.stock,'s')): 263 | 264 | # Determine the projected level, wether wave 2 or wave 4 265 | if self.d_waves_downt['wave2'] == True and self.d_waves_downt['wave3'] == False: 266 | 267 | self.wave3_down_proj = self.td_wave_projection(3,'d') 268 | 269 | else: 270 | self.wave3_down_proj = self.td_wave_projection(5,'d') 271 | 272 | # determine what is the stop level, based on setup or cd 273 | if self.count_down_last_finished == 'na': 274 | self.stop_s = self.Td_s_risk_s + 0.618 275 | else: 276 | self.stop_s = self.Td_cd_risk_s + 0.618 277 | 278 | # is it 3 to 1, then enter else, return 279 | if (price - self.wave3_down_proj) / (self.stop_s - price) > 3: 280 | 281 | # Use floor division to get a whole number of shares 282 | target_shares = cash*context.percent_per_pos // price 283 | 284 | order_target(self.stock,-target_shares) 285 | #order_target(self.stock,+target_shares,style=StopOrder(self.Td_s_risk_s)) 286 | 287 | log.info('{0}: Price at {1}, shorting {2} shares.'.format( 288 | self.stock.symbol, price, target_shares 289 | )) 290 | 291 | print ('wave3_down_proj=',self.wave3_down_proj ) 292 | print ('stop = ',self.stop_s) 293 | 294 | else: 295 | return 296 | 297 | 298 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 299 | def td_setup(self,stock): 300 | 301 | if self.bars_since_last_setup == 9: 302 | 303 | close_history = history(14,'1d','close_price')[stock] 304 | low_history = history(9,'1d','low')[stock] 305 | high_history = history(9,'1d','high')[stock] 306 | 307 | #~~~~~~~~~~ Sell Setup 308 | scount = 0 309 | for i in range(-1,-10,-1): 310 | 311 | if close_history[i] > close_history[i-4]: 312 | scount += 1 313 | 314 | # ensures that the first bar of the setup has got a price flip 315 | if scount == 9 and close_history[i-1] >= close_history[i-5]: 316 | scount = 0 317 | 318 | if scount == 9: 319 | self.__Ss_Arr[:] = high_history[:] 320 | self.Ss_clos_arr[:]= close_history[5:] 321 | #if we have a previous Ss and its countdown is not finished then, current setup is Ss2 322 | if self.setup_phase == 'Ss': 323 | self.setup_phase2 = 'Ss2' 324 | else: 325 | self.setup_phase2 = 'na' 326 | 327 | self.setup_phase = 'Ss' 328 | self.count_down_last_finished = 'na' 329 | 330 | # save the previous TDST level 331 | self.prev_TDST_sell = self.curr_TDST_sell 332 | # get the TDST of the current setup 333 | self.curr_TDST_sell = min( low_history.min(), close_history[-1:-11:-1].min() ) 334 | 335 | # set the Td._s_risk_s 336 | index = high_history.argmax() 337 | self.Td_s_risk_s = (high_history.max() - low_history[index]) + high_history.max() 338 | 339 | # get the current setup range 340 | self.__get_c_s_range(low_history,high_history) 341 | self.bars_since_last_setup = 0 342 | return 'Ss' 343 | 344 | #~~~~~~~~~~ Buy Setup 345 | bcount = 0 346 | for i in range(-1,-10,-1): 347 | 348 | if close_history[i] < close_history[i-4]: 349 | bcount += 1 350 | 351 | # ensures that the first bar of the setup has got a price flip 352 | if bcount == 9 and close_history[i-1] <= close_history[i-5]: 353 | bcount = 0 354 | 355 | if bcount == 9: 356 | self.__Bs_Arr[:] = low_history[:] 357 | self.Bs_clos_arr[:]= close_history[5:] 358 | #if we have a previous Bs and its countdown is not finished then, current setup is Bs2 359 | if self.setup_phase == 'Bs': 360 | self.setup_phase2 = 'Bs2' 361 | else: 362 | self.setup_phase2 = 'na' 363 | 364 | self.setup_phase = 'Bs' 365 | self.count_down_last_finished = 'na' 366 | 367 | # save the previous TDST level 368 | self.prev_TDST_buy = self.curr_TDST_buy 369 | # get the TDST of the current setup 370 | self.curr_TDST_buy = max(high_history.max(), close_history[-1:-11:-1].max()) 371 | 372 | # set the Td_s_risk_b 373 | index = low_history.argmin() 374 | self.Td_s_risk_b = low_history.min() - (high_history[index] - low_history.min()) 375 | 376 | # get the current setup range 377 | self.__get_c_s_range(low_history,high_history) 378 | self.bars_since_last_setup = 0 379 | return 'Bs' 380 | else: 381 | self.bars_since_last_setup += 1 382 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 383 | def td_seq_cd(self,stock,x): 384 | 385 | self.__is_c_cd_canceled(stock) 386 | 387 | #~~~~~~~ Sell CountDown 388 | if x == 's': 389 | if self.setup_phase == 'Ss': 390 | 391 | self.__S9_pos_Bcd = 0 392 | self.__S9_pos_Scd += 1 393 | self.count_down_started = 'Scd' 394 | 395 | #~~~~~~~~~~ 396 | # save the current setup range to be used for the cancellation qualifiers I,II 397 | self.__p_s_h = self.__c_s_h 398 | self.__p_s_l = self.__c_s_l 399 | self.__p_setup_range = self.__c_setup_range 400 | 401 | # if the lookback not yet >= 13 then exit 402 | if self.__S9_pos_Scd < 13: 403 | return 404 | 405 | #~~~~~~~~~~ Stock Series 406 | current_close = history(self.__S9_pos_Scd,'1d','close_price')[stock] 407 | high_2bars_Ago = history(self.__S9_pos_Scd+2,'1d','high')[stock] 408 | low_history = history(self.__S9_pos_Scd,'1d','low')[stock] 409 | 410 | #~~~~~~~~~~ Sell CountDown Logic 411 | scd_counter = 0 412 | for i in range(self.__S9_pos_Scd): 413 | 414 | if scd_counter == 12: 415 | if current_close[i] > high_2bars_Ago[i] and current_close[i] > eighth_high_low: 416 | scd_counter += 1 417 | 418 | elif current_close[i] > high_2bars_Ago[i]: 419 | scd_counter += 1 420 | 421 | if scd_counter == 8: 422 | eighth_high_low =high_2bars_Ago[i+2] 423 | 424 | if scd_counter == 13: 425 | self.setup_phase = 'na' 426 | self.count_down_started = 'na' 427 | self.count_down_last_finished = 'Scd' 428 | self.Scd13_close = current_close[-1] 429 | scd_counter= 0 430 | # TD CD Risk Level 431 | index = high_2bars_Ago[2:].argmax() 432 | self.Td_cd_risk_s = (high_2bars_Ago[2:].max() - low_history[index]) + high_2bars_Ago[2:].max() 433 | 434 | self.__S9_pos_Scd = 0 435 | self.setup_phase2 = 'na' 436 | return 'Scd' 437 | 438 | #~~~~~~~ Buy CountDown 439 | elif x == 'b' : 440 | if self.setup_phase == 'Bs' : 441 | 442 | self.__S9_pos_Scd = 0 443 | self.__S9_pos_Bcd += 1 444 | self.count_down_started = 'Bcd' 445 | 446 | #~~~~~~~~~~ 447 | # save the current setup range to be used for the cancellation qualifiers I,II 448 | self.__p_s_h = self.__c_s_h 449 | self.__p_s_l = self.__c_s_l 450 | self.__p_setup_range = self.__c_setup_range 451 | 452 | # if the lookback not yet >= 13 then exit 453 | if self.__S9_pos_Bcd < 13: 454 | return 455 | 456 | #~~~~~~~~~~ Stock Series 457 | current_close = history(self.__S9_pos_Bcd,'1d','close_price')[stock] 458 | low_2bars_Ago = history(self.__S9_pos_Bcd+2,'1d','low')[stock] 459 | high_history = history(self.__S9_pos_Bcd,'1d','high')[stock] 460 | 461 | #~~~~~~~~~~ Buy CountDown Logic 462 | bcd_counter = 0 463 | for i in range(self.__S9_pos_Bcd): 464 | 465 | if bcd_counter == 12: 466 | if current_close[i] < low_2bars_Ago[i] and current_close[i] < eighth_high_low : 467 | 468 | bcd_counter += 1 469 | 470 | elif current_close[i] < low_2bars_Ago[i]: 471 | bcd_counter += 1 472 | 473 | if bcd_counter == 8: 474 | eighth_high_low =low_2bars_Ago[i+2] 475 | 476 | if bcd_counter == 13: 477 | self.setup_phase = 'na' 478 | self.count_down_started = 'na' 479 | self.count_down_last_finished = 'Bcd' 480 | self.Bcd13_close = current_close[-1] 481 | bcd_counter = 0 482 | # TD CD Risk Level 483 | index = low_2bars_Ago[2:].argmin() 484 | self.Td_cd_risk_b = (high_history[index]- low_2bars_Ago[2:].min()) - low_2bars_Ago[2:].min() 485 | 486 | self.__S9_pos_Bcd = 0 487 | self.setup_phase2 = 'na' 488 | return 'Bcd' 489 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 490 | def td_combo_cd(self,stock,x): 491 | 492 | self.__is_c_cd_combo_canceled(stock) 493 | 494 | #~~~~~~~ Sell CountDown 495 | if x == 's': 496 | if self.setup_phase == 'Ss': 497 | 498 | self.__S9_pos_combo_Bcd = 9 499 | self.__S9_pos_combo_Scd += 1 500 | self.count_down_started = 'Scd' 501 | 502 | #~~~~~~~~~~ 503 | # save the current setup range to be used for the cancellation qualifiers I,II 504 | self.__p_s_h = self.__c_s_h 505 | self.__p_s_l = self.__c_s_l 506 | self.__p_setup_range = self.__c_setup_range 507 | 508 | # if the lookback not yet >= 13 then exit 509 | if self.__S9_pos_combo_Scd < 13: 510 | return 511 | 512 | #~~~~~~~~~~ Stock Series 513 | close_history = history(self.__S9_pos_combo_Scd+1,'1d','close_price')[stock] 514 | high_2bars_Ago = history(self.__S9_pos_combo_Scd+2,'1d','high')[stock] 515 | low_history = history(self.__S9_pos_combo_Scd+1,'1d','low')[stock] 516 | 517 | #~~~~~~~~~~ Sell CountDown Logic 518 | scd_counter = 0 519 | prev_combo_cd_close = 0 520 | for i in range(1,self.__S9_pos_combo_Scd): 521 | 522 | if scd_counter == 0: 523 | if close_history[i] >= high_2bars_Ago[i-1] and high_2bars_Ago[i+1] >= high_2bars_Ago[i]\ 524 | and close_history[i] >= close_history[i-1]: 525 | 526 | scd_counter += 1 527 | prev_combo_cd_close = close_history[i] 528 | 529 | else: 530 | if close_history[i] >= high_2bars_Ago[i-1] and high_2bars_Ago[i+1] >= high_2bars_Ago[i]\ 531 | and close_history[i] >= close_history[i-1] and close_history[i] > prev_combo_cd_close: 532 | 533 | scd_counter += 1 534 | prev_combo_cd_close = close_history[i] 535 | 536 | if scd_counter == 13: 537 | self.setup_phase = 'na' 538 | self.count_down_started = 'na' 539 | self.count_down_last_finished = 'Scd' 540 | self.Scd13_close = close_history[-1] 541 | scd_counter= 0 542 | # TD CD Risk Level 543 | index = high_2bars_Ago[2:].argmax() 544 | self.Td_cd_risk_s = (high_2bars_Ago[2:].max() - low_history[index]) + high_2bars_Ago[2:].max() 545 | 546 | self.__S9_pos_combo_Scd = 9 547 | self.setup_phase2 = 'na' 548 | return 'Scd' 549 | 550 | #~~~~~~~ Buy CountDown 551 | elif x == 'b' : 552 | if self.setup_phase == 'Bs' : 553 | 554 | self.__S9_pos_combo_Scd = 9 555 | self.__S9_pos_combo_Bcd += 1 556 | self.count_down_started = 'Bcd' 557 | 558 | #~~~~~~~~~~ 559 | # save the current setup range to be used for the cancellation qualifiers I,II 560 | self.__p_s_h = self.__c_s_h 561 | self.__p_s_l = self.__c_s_l 562 | self.__p_setup_range = self.__c_setup_range 563 | 564 | # if the lookback not yet >= 13 then exit 565 | if self.__S9_pos_combo_Bcd < 13: 566 | return 567 | 568 | #~~~~~~~~~~ Stock Series 569 | close_history = history(self.__S9_pos_combo_Bcd+1,'1d','close_price')[stock] 570 | low_2bars_Ago = history(self.__S9_pos_combo_Bcd+2,'1d','low')[stock] 571 | high_history = history(self.__S9_pos_combo_Bcd,'1d','high')[stock] 572 | 573 | #~~~~~~~~~~ Buy CountDown Logic 574 | bcd_counter = 0 575 | for i in range(1,self.__S9_pos_Bcd): 576 | 577 | if bcd_counter == 0: 578 | if close_history[i] <= low_2bars_Ago[i-1] and low_2bars_Ago[i+1] <= low_2bars_Ago[i]\ 579 | and close_history[i] <= close_history[i-1]: 580 | 581 | bcd_counter += 1 582 | prev_combo_cd_close = close_history[i] 583 | 584 | elif close_history[i] <= low_2bars_Ago[i-1] and low_2bars_Ago[i+1] <= low_2bars_Ago[i]\ 585 | and close_history[i] <= close_history[i-1] and close_history[i] < prev_combo_cd_close: 586 | 587 | bcd_counter += 1 588 | prev_combo_cd_close = close_history[i] 589 | 590 | if bcd_counter == 13: 591 | self.setup_phase = 'na' 592 | self.count_down_started = 'na' 593 | self.count_down_last_finished = 'Bcd' 594 | self.Bcd13_close = close_history[-1] 595 | bcd_counter = 0 596 | # TD CD Risk Level 597 | index = low_2bars_Ago[2:].argmin() 598 | self.Td_cd_risk_b = (high_history[index]- low_2bars_Ago[2:].min()) - low_2bars_Ago[2:].min() 599 | 600 | self.__S9_pos_combo_Bcd = 9 601 | self.setup_phase2 = 'na' 602 | return 'Bcd' 603 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 604 | def is_setup_perf(self,stock,x): 605 | """ 606 | Check if the latest setup is perfected at the time this method is called 607 | 608 | 0 1 2 3 4 5 6 7 8 #Array Index 609 | 1 2 3 4 5 6 7 8 9 #Setup bars 610 | """ 611 | #if setup passed is sell 612 | if x == 's': 613 | high_history = history(2,'1d','high')[stock] 614 | 615 | if high_history[-1] >= self.__Ss_Arr[5] and high_history[-1] >= self.__Ss_Arr[6]\ 616 | or high_history[-2] >= self.__Ss_Arr[5] and high_history[-2] >= self.__Ss_Arr[6]: 617 | return True 618 | 619 | # elif setup passed is buy 620 | elif x == 'b': 621 | low_history = history(2,'1d', 'low')[stock] 622 | 623 | if low_history[-1] <= self.__Bs_Arr[5] and low_history[-1] <= self.__Bs_Arr[6]\ 624 | or low_history[-2] <= self.__Bs_Arr[5] and low_history[-2] <= self.__Bs_Arr[6]: 625 | return True 626 | 627 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 628 | def d_wave_upt(self,stock): 629 | i = -1 630 | close_history = history(34,'1d','close_price')[stock] 631 | 632 | if self.d_waves_upt['wave0'] == False and close_history[-1] < close_history[-2:-21-i:-1].min(): 633 | self.d_waves_upt['wave0'] = True 634 | self.d_w_points_upt['wave0_low'] = close_history[-1] 635 | 636 | # Guard 637 | if self.d_waves_upt['wave0'] == True and self.d_waves_upt['wave2'] == False \ 638 | and close_history[-1] < self.d_w_points_upt['wave0_low']: 639 | self.d_w_points_upt['wave0_low'] = close_history[-1] 640 | 641 | 642 | if self.d_waves_upt['wave1'] == False and self.d_waves_upt['wave0'] == True \ 643 | and close_history[-1] > close_history[-2:-13-i:-1].max()\ 644 | and close_history[-1] > self.d_w_points_upt['wave0_low']: # Guard 645 | 646 | self.d_waves_upt['wave1'] = True 647 | self.d_w_points_upt['wave1_high'] = close_history[-1] 648 | 649 | if self.d_waves_upt['wave2'] == False and self.d_waves_upt['wave1'] == True: 650 | 651 | if close_history[-1] < close_history[-2:-8-i:-1].min(): 652 | self.d_waves_upt['wave2'] = True 653 | self.d_w_points_upt['wave2_low'] = close_history[-1] 654 | 655 | # elif current close > the high of wave1, then shift wave1 to the right 656 | elif close_history[-1] > self.d_w_points_upt['wave1_high']: 657 | self.d_w_points_upt['wave1_high'] = close_history[-1] 658 | 659 | # If current close violates the low of wave0, then cancel 660 | # all previous waves and start new wave count 661 | if self.d_waves_upt['wave2'] == True and (close_history[-1] < self.d_w_points_upt['wave0_low']): 662 | 663 | self.d_waves_upt['wave0'] = False 664 | self.d_waves_upt['wave1'] = False 665 | self.d_waves_upt['wave2'] = False 666 | self.d_w_points_upt['wave0_low'] = 0 667 | self.d_w_points_upt['wave1_high'] = 0 668 | self.d_w_points_upt['wave2_low'] = 0 669 | 670 | 671 | if self.d_waves_upt['wave3']== False and self.d_waves_upt['wave2']== True: 672 | if close_history[-1] > close_history[-2:-21-i:-1].max()\ 673 | and close_history[-1] > self.d_w_points_upt['wave1_high']: 674 | 675 | self.d_waves_upt['wave3'] = True 676 | self.d_w_points_upt['wave3_high'] = close_history[-1] 677 | 678 | # elif current close < the low of wave2 then shift wave2 to the right 679 | elif close_history[-1] < self.d_w_points_upt['wave2_low']: 680 | self.d_w_points_upt['wave2_low'] = close_history[-1] 681 | 682 | if self.d_waves_upt['wave4']== False and self.d_waves_upt['wave3']== True : 683 | 684 | if close_history[-1] < close_history[-2:-13-i:-1].min(): 685 | self.d_waves_upt['wave4'] = True 686 | self.d_w_points_upt['wave4_low'] = close_history[-1] 687 | 688 | # elif current close > the high of wave3, then shift wave3 to the right 689 | elif close_history[-1] > self.d_w_points_upt['wave3_high']: 690 | self.d_w_points_upt['wave3_high'] = close_history[-1] 691 | 692 | # if current close violates the low of wave2, then wave2 is shifted to the right 693 | if self.d_waves_upt['wave4']== True and close_history[-1] < self.d_w_points_upt['wave2_low']: 694 | 695 | self.d_waves_upt['wave3'] = False 696 | self.d_waves_upt['wave4'] = False 697 | self.d_w_points_upt['wave3_high'] = 0 698 | self.d_w_points_upt['wave4_low'] = 0 699 | 700 | self.d_w_points_upt['wave2_low'] = close_history[-1] 701 | 702 | if self.d_waves_upt['wave5']== False and self.d_waves_upt['wave4'] == True : 703 | 704 | if close_history[-1] > close_history[-2:-34-i:-1].max() \ 705 | and close_history[-1] > self.d_w_points_upt['wave3_high']: 706 | 707 | self.d_waves_upt['wave5'] = True 708 | self.d_w_points_upt['wave5_high'] = close_history[-1] 709 | 710 | # elif current close < the low of wave 4, then shift wave4 to the right 711 | elif close_history[-1] < self.d_w_points_upt['wave4_low']: 712 | self.d_w_points_upt['wave4_low'] = close_history[-1] 713 | 714 | if self.d_waves_upt['waveA']== False and self.d_waves_upt['wave5']== True: 715 | 716 | if close_history[-1] < close_history[-2:-13-i:-1].min(): 717 | self.d_waves_upt['waveA'] = True 718 | self.d_w_points_upt['waveA_low'] = close_history[-1] 719 | 720 | # elif current close > the high of wave5 then shift wave5 to the right 721 | elif close_history[-1] > self.d_w_points_upt['wave5_high']: 722 | self.d_w_points_upt['wave5_high'] = close_history[-1] 723 | 724 | if self.d_waves_upt['waveB']== False and self.d_waves_upt['waveA']== True: 725 | 726 | if close_history[-1] > close_history[-2:-8-i:-1].max(): 727 | self.d_waves_upt['waveB'] = True 728 | self.d_w_points_upt['waveB_high'] = close_history[-1] 729 | 730 | # elif current close > the high of wave5 then shift wave5 to the right 731 | elif close_history[-1] > self.d_w_points_upt['wave5_high']: 732 | self.d_w_points_upt['wave5_high'] = close_history[-1] 733 | self.d_waves_upt['waveA'] = False 734 | self.d_w_points_upt['waveA_low'] = 0 735 | 736 | # elif current close < the low of waveA, then shift waveA to the right ##TESTING STILL## 737 | elif close_history[-1] < self.d_w_points_upt['waveA_low']: 738 | self.d_w_points_upt['waveA_low'] = close_history[-1] 739 | 740 | if self.d_waves_upt['waveC'] == False and self.d_waves_upt['waveB']== True: 741 | 742 | if close_history[-1] < close_history[-2:-21-i:-1].min(): 743 | self.d_waves_upt['waveC']= True 744 | self.d_w_points_upt['waveC_low'] = close_history[-1] 745 | 746 | # elif current close > the high of wave5 then shift wave5 to the right 747 | elif close_history[-1] > self.d_w_points_upt['wave5_high']: 748 | self.d_w_points_upt['wave5_high'] = close_history[-1] 749 | self.d_waves_upt['waveA'] = False 750 | self.d_waves_upt['waveB'] = False 751 | self.d_w_points_upt['waveA_low'] = 0 752 | self.d_w_points_upt['waveB_high'] = 0 753 | 754 | #elif current close > the high of waveB, then shift waveB to the right ##TESTING STILL## 755 | elif close_history[-1] > self.d_w_points_upt['waveB_high']: 756 | self.d_w_points_upt['waveB_high'] = close_history[-1] 757 | 758 | if self.d_waveC_lock_upt == False and self.d_waves_upt['waveC']== True: 759 | 760 | # if current close < the low of waveA, then lock wave5 761 | if close_history[-1] < self.d_w_points_upt['waveA_low']: 762 | self.d_waveC_lock_upt = True 763 | # set the d_waves values to False, and the d_w_points to 0 764 | for val in self.d_waves_upt: 765 | self.d_waves_upt[val] = False 766 | for val in self.d_w_points_upt: 767 | self.d_w_points_upt[val] = 0 768 | 769 | # set the d_waveC_lock to False 770 | self.d_waveC_lock_upt = False 771 | 772 | # If the current close > than the wave 5 high, then shift wave5 to the right 773 | # and cancel waveA, waveB and waveC 774 | elif close_history[-1] > self.d_w_points_upt['wave5_high']: 775 | self.d_w_points_upt['wave5_high'] = close_history[-1] 776 | self.d_waves_upt['waveA'] = False 777 | self.d_waves_upt['waveB'] = False 778 | self.d_waves_upt['waveC'] = False 779 | self.d_w_points_upt['waveA_low'] = 0 780 | self.d_w_points_upt['waveB_high'] = 0 781 | self.d_w_points_upt['waveC_low'] = 0 782 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 783 | def d_wave_downt(self,stock): 784 | i = -1 785 | close_history = history(34,'1d','close_price')[stock] 786 | 787 | if self.d_waves_downt['wave0'] == False and close_history[-1] > close_history[-2:-21-i:-1].max(): 788 | self.d_waves_downt['wave0'] = True 789 | self.d_w_points_downt['wave0_high'] = close_history[-1] 790 | 791 | # Guard 792 | if self.d_waves_downt['wave0'] == True and self.d_waves_downt['wave2'] == False \ 793 | and close_history[-1] > self.d_w_points_downt['wave0_high']: 794 | self.d_w_points_downt['wave0_high'] = close_history[-1] 795 | 796 | 797 | if self.d_waves_downt['wave1'] == False and self.d_waves_downt['wave0'] == True \ 798 | and close_history[-1] < close_history[-2:-13-i:-1].min()\ 799 | and close_history[-1] < self.d_w_points_downt['wave0_high']: # Guard 800 | 801 | self.d_waves_downt['wave1'] = True 802 | self.d_w_points_downt['wave1_low'] = close_history[-1] 803 | 804 | if self.d_waves_downt['wave2'] == False and self.d_waves_downt['wave1'] == True: 805 | 806 | if close_history[-1] > close_history[-2:-8-i:-1].max(): 807 | self.d_waves_downt['wave2'] = True 808 | self.d_w_points_downt['wave2_high'] = close_history[-1] 809 | 810 | # elif current close > the high of wave1, then shift wave1 to the right 811 | elif close_history[-1] < self.d_w_points_downt['wave1_low']: 812 | self.d_w_points_downt['wave1_low'] = close_history[-1] 813 | 814 | # If current close violates the low of wave0, then cancel 815 | # all previous waves and start new wave count 816 | if self.d_waves_downt['wave2'] == True and (close_history[-1] > self.d_w_points_downt['wave0_high']): 817 | 818 | self.d_waves_downt['wave0'] = False 819 | self.d_waves_downt['wave1'] = False 820 | self.d_waves_downt['wave2'] = False 821 | self.d_w_points_downt['wave0_high'] = 0 822 | self.d_w_points_downt['wave1_low'] = 0 823 | self.d_w_points_downt['wave2_high'] = 0 824 | 825 | 826 | if self.d_waves_downt['wave3']== False and self.d_waves_downt['wave2']== True: 827 | if close_history[-1] < close_history[-2:-21-i:-1].min()\ 828 | and close_history[-1] < self.d_w_points_downt['wave1_low']: 829 | 830 | self.d_waves_downt['wave3'] = True 831 | self.d_w_points_downt['wave3_low'] = close_history[-1] 832 | 833 | # elif current close < the low of wave2 then shift wave2 to the right 834 | elif close_history[-1] > self.d_w_points_downt['wave2_high']: 835 | self.d_w_points_downt['wave2_high'] = close_history[-1] 836 | 837 | if self.d_waves_downt['wave4']== False and self.d_waves_downt['wave3']== True : 838 | 839 | if close_history[-1] > close_history[-2:-13-i:-1].max(): 840 | self.d_waves_downt['wave4'] = True 841 | self.d_w_points_downt['wave4_high'] = close_history[-1] 842 | 843 | # elif current close > the high of wave3, then shift wave3 to the right 844 | elif close_history[-1] < self.d_w_points_downt['wave3_low']: 845 | self.d_w_points_downt['wave3_low'] = close_history[-1] 846 | 847 | # if current close violates the low of wave2, then wave2 is shifted to the right 848 | if self.d_waves_downt['wave4']== True and close_history[-1] > self.d_w_points_downt['wave2_high']: 849 | 850 | self.d_waves_downt['wave3'] = False 851 | self.d_waves_downt['wave4'] = False 852 | self.d_w_points_downt['wave3_low'] = 0 853 | self.d_w_points_downt['wave4_high'] = 0 854 | 855 | self.d_w_points_downt['wave2_high'] = close_history[-1] 856 | 857 | if self.d_waves_downt['wave5']== False and self.d_waves_downt['wave4'] == True : 858 | 859 | if close_history[-1] < close_history[-2:-34-i:-1].min() \ 860 | and close_history[-1] < self.d_w_points_downt['wave3_low']: 861 | 862 | self.d_waves_downt['wave5'] = True 863 | self.d_w_points_downt['wave5_low'] = close_history[-1] 864 | 865 | # elif current close < the low of wave 4, then shift wave4 to the right 866 | elif close_history[-1] > self.d_w_points_downt['wave4_high']: 867 | self.d_w_points_downt['wave4_high'] = close_history[-1] 868 | 869 | if self.d_waves_downt['waveA']== False and self.d_waves_downt['wave5']== True: 870 | 871 | if close_history[-1] > close_history[-2:-13-i:-1].max(): 872 | self.d_waves_downt['waveA'] = True 873 | self.d_w_points_downt['waveA_high'] = close_history[-1] 874 | 875 | # elif current close > the high of wave5 then shift wave5 to the right 876 | elif close_history[-1] < self.d_w_points_downt['wave5_low']: 877 | self.d_w_points_downt['wave5_low'] = close_history[-1] 878 | 879 | if self.d_waves_downt['waveB']== False and self.d_waves_downt['waveA']== True: 880 | 881 | if close_history[-1] < close_history[-2:-8-i:-1].min(): 882 | self.d_waves_downt['waveB'] = True 883 | self.d_w_points_downt['waveB_low'] = close_history[-1] 884 | 885 | # elif current close > the high of wave5 then shift wave5 to the right 886 | elif close_history[-1] < self.d_w_points_downt['wave5_low']: 887 | self.d_w_points_downt['wave5_low'] = close_history[-1] 888 | self.d_waves_downt['waveA'] = False 889 | self.d_w_points_downt['waveA_high'] = 0 890 | 891 | # elif current close > the high of waveA, then shift waveA to the right ##TESTING STILL## 892 | elif close_history[-1] > self.d_w_points_downt['waveA_high']: 893 | self.d_w_points_downt['waveA_high'] = close_history[-1] 894 | 895 | 896 | if self.d_waves_downt['waveC'] == False and self.d_waves_downt['waveB']== True: 897 | 898 | if close_history[-1] > close_history[-2:-21-i:-1].max(): 899 | self.d_waves_downt['waveC']= True 900 | self.d_w_points_downt['waveC_high'] = close_history[-1] 901 | 902 | # elif current close > the high of wave5 then shift wave5 to the right 903 | elif close_history[-1] < self.d_w_points_downt['wave5_low']: 904 | self.d_w_points_downt['wave5_low'] = close_history[-1] 905 | self.d_waves_downt['waveA'] = False 906 | self.d_waves_downt['waveB'] = False 907 | self.d_w_points_downt['waveA_high'] = 0 908 | self.d_w_points_downt['waveB_low'] = 0 909 | 910 | #elif current close < the low of waveB, then shift waveB to the right ##TESTING STILL## 911 | elif close_history[-1] < self.d_w_points_downt['waveB_low']: 912 | self.d_w_points_downt['waveB_low'] = close_history[-1] 913 | 914 | 915 | if self.d_waveC_lock_downt == False and self.d_waves_downt['waveC']== True: 916 | 917 | # if current close < the low of waveA, then lock wave5 918 | if close_history[-1] > self.d_w_points_downt['waveA_high']: 919 | self.d_waveC_lock_downt = True 920 | # set the d_waves values to False, and the d_w_points to 0 921 | for val in self.d_waves_downt: 922 | self.d_waves_downt[val] = False 923 | for val in self.d_w_points_downt: 924 | self.d_w_points_downt[val] = 0 925 | 926 | # set the d_waveC_lock to False 927 | self.d_waveC_lock_downt = False 928 | 929 | # If the current close > than the wave 5 high, then shift wave5 to the right 930 | # and cancel waveA, waveB and waveC 931 | elif close_history[-1] < self.d_w_points_downt['wave5_low']: 932 | self.d_w_points_downt['wave5_low'] = close_history[-1] 933 | self.d_waves_downt['waveA'] = False 934 | self.d_waves_downt['waveB'] = False 935 | self.d_waves_downt['waveC'] = False 936 | self.d_w_points_downt['waveA_high'] = 0 937 | self.d_w_points_downt['waveB_low'] = 0 938 | self.d_w_points_downt['waveC_high'] = 0 939 | 940 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 941 | def td_wave_projection(self,waveProjCount,x): 942 | """ 943 | Returns the up projection level for the passed desired wave 944 | """ 945 | if x == 'u': 946 | if waveProjCount == 3: 947 | wave3Proj = self.d_w_points_upt['wave0_low'] + ((self.d_w_points_upt['wave1_high'] - self.d_w_points_upt['wave0_low']) * 1.618 ) 948 | return wave3Proj 949 | 950 | elif waveProjCount == 5: 951 | wave5Proj = self.d_w_points_upt['wave2_low'] + ((self.d_w_points_upt['wave3_high'] - self.d_w_points_upt['wave2_low']) * 1.618 ) 952 | return wave5Proj 953 | 954 | elif x == 'd': 955 | if waveProjCount == 3: 956 | wave3Proj = self.d_w_points_downt['wave0_high'] - ((self.d_w_points_downt['wave0_high'] - self.d_w_points_downt['wave1_low']) * 1.618 ) 957 | return wave3Proj 958 | 959 | elif waveProjCount == 5: 960 | wave5Proj = self.d_w_points_downt['wave2_high'] - ((self.d_w_points_downt['wave2_high'] - self.d_w_points_downt['wave3_low']) * 1.618 ) 961 | return wave5Proj 962 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 963 | def is9_tradable(self,stock,x): 964 | """ 965 | Check if the latest setup s/b is perfected and any of its closes is not above/below 966 | the previous TDST, 967 | and the max/min close of the recent setup is in close proximity of the prev TDST < 0.25 968 | and current price is not >/< than the previous TDST, 969 | and the space between current_price - curr_TDST is bigger by 5 or more than the space 970 | between the td risk and the current price 971 | """ 972 | current_price = history(1,'1d','price')[stock] 973 | 974 | if x == 's': 975 | 976 | if self.setup_phase == 'Ss' and self.is_setup_perf(stock,'s') == True\ 977 | and (self.Ss_clos_arr < self.prev_TDST_buy).all() \ 978 | and self.prev_TDST_buy - self.Ss_clos_arr.max() < 0.25 \ 979 | and current_price[-1] < self.Td_s_risk_s : 980 | #and current_price[-1] - self.curr_TDST_sell / self.Td_s_risk_s - current_price[-1] >= 5: 981 | 982 | return True 983 | else: 984 | return False 985 | 986 | elif x == 'b': 987 | 988 | #if self.setup_phase == 'Bs' \ 989 | if self.setup_phase == 'Bs' and self.is_setup_perf(stock,'b') == True\ 990 | and (self.Bs_clos_arr > self.prev_TDST_sell).all() \ 991 | and self.Bs_clos_arr.max() - self.prev_TDST_sell < 0.25 \ 992 | and current_price[-1] > self.Td_s_risk_b: 993 | #and self.curr_TDST_buy - current_price[-1] / current_price[-1] - self.Td_s_risk_s >= 5: 994 | 995 | return True 996 | else: 997 | return False 998 | 999 | 1000 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1001 | def is9_tradable_lite(self,stock,x): 1002 | """ 1003 | Check if the latest setup s/b is perfected and any of its closes is not above/below 1004 | the previous TDST, 1005 | and the max/min close of the recent setup is in close proximity of the prev TDST < 0.25 1006 | and current price is not >/< than the previous TDST, 1007 | and the space between current_price - curr_TDST is bigger by 5 or more than the space 1008 | between the td risk and the current price 1009 | """ 1010 | current_price = history(1,'1d','price')[stock] 1011 | 1012 | if x == 's': 1013 | 1014 | if self.setup_phase == 'Ss' and self.is_setup_perf(stock,'s') == True\ 1015 | and current_price[-1] < self.Td_s_risk_s : 1016 | #and current_price[-1] - self.curr_TDST_sell / self.Td_s_risk_s - current_price[-1] >= 5: 1017 | 1018 | return True 1019 | else: 1020 | return False 1021 | 1022 | elif x == 'b': 1023 | 1024 | #if self.setup_phase == 'Bs' \ 1025 | if self.setup_phase == 'Bs' and self.is_setup_perf(stock,'b') == True\ 1026 | and current_price[-1] > self.Td_s_risk_b: 1027 | #and self.curr_TDST_buy - current_price[-1] / current_price[-1] - self.Td_s_risk_s >= 5: 1028 | 1029 | return True 1030 | else: 1031 | return False 1032 | 1033 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1034 | def is9_tradable_lite_v2(self,stock,x): 1035 | """ 1036 | Check if the latest setup s/b is perfected and any of its closes is not above/below 1037 | the previous TDST, 1038 | and the max/min close of the recent setup is in close proximity of the prev TDST < 0.25 1039 | and current price is not >/< than the previous TDST, 1040 | and the space between current_price - curr_TDST is bigger by 5 or more than the space 1041 | between the td risk and the current price 1042 | """ 1043 | current_price = history(1,'1d','price')[stock] 1044 | 1045 | if x == 's': 1046 | 1047 | if self.setup_phase == 'Ss' and current_price[-1] < self.Td_s_risk_s\ 1048 | and current_price[-1] > self.curr_TDST_sell: 1049 | #and current_price[-1] - self.curr_TDST_sell / self.Td_s_risk_s - current_price[-1] >= 5: 1050 | 1051 | return True 1052 | else: 1053 | return False 1054 | 1055 | elif x == 'b': 1056 | 1057 | if self.setup_phase == 'Bs' and current_price[-1] > self.Td_s_risk_b\ 1058 | and current_price[-1] < self.curr_TDST_buy: 1059 | #and self.curr_TDST_buy - current_price[-1] / current_price[-1] - self.Td_s_risk_s >= 5: 1060 | 1061 | return True 1062 | else: 1063 | return False 1064 | 1065 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1066 | def is13_tradable(self,stock,x): 1067 | """ 1068 | Check if we have a 13 bar, Scd or Bcd as disired passed direction 's'/'b' 1069 | and check if its below/above the td risk cd level (is still a valid CD) 1070 | """ 1071 | current_price = history(1,'1d','price')[stock] 1072 | 1073 | if x == 's': 1074 | if self.count_down_last_finished == 'Scd' and current_price[-1] < self.Td_cd_risk_s\ 1075 | and (self.Scd13_close - current_price[-1]) / (self.Td_cd_risk_s - self.Scd13_close) < 1.618 : 1076 | return True 1077 | else: 1078 | return False 1079 | 1080 | elif x == 'b': 1081 | if self.count_down_last_finished == 'Bcd' and current_price[-1] > self.Td_cd_risk_b\ 1082 | and (current_price[-1] - self.Bcd13_close) / (self.Bcd13_close - self.Td_cd_risk_b ) < 1.618: 1083 | return True 1084 | else: 1085 | return False 1086 | 1087 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1088 | def __get_c_s_range(self,low_history,high_history): 1089 | """ 1090 | Get the current setup range 1091 | """ 1092 | self.__c_s_h = high_history.max() 1093 | self.__c_s_l = low_history.min() 1094 | 1095 | self.__c_setup_range = self.__c_s_h - self.__c_s_l 1096 | 1097 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1098 | def __is_c_cd_canceled(self,stock): 1099 | """" 1100 | if we have a finished sell/buy setup and a sell/buy count down is already started but not yet finished and countdown 1101 | cancellation qualifier I or II is active, then reset the count down 1102 | """ 1103 | 1104 | if self.count_down_started == 'Scd' and self.setup_phase2 == 'Ss2': 1105 | 1106 | # qualifier I or qualifier II? then cancel the current countdown 1107 | if self.__c_setup_range >= self.__p_setup_range \ 1108 | and self.__c_setup_range / self.__p_setup_range <= 1.618 \ 1109 | or self.__c_s_h <= self.__p_s_h and self.__c_s_l >= self.__p_s_l: 1110 | 1111 | self.setup_phase2 = 'na' 1112 | self.count_down_started = 'na' 1113 | self.__S9_pos_Scd = 0 1114 | self.scd_counter = 0 1115 | 1116 | elif self.count_down_started == 'Bcd' and self.setup_phase2 == 'Bs2': 1117 | 1118 | # qualifier I or qualifier II? then cancel the current countdown 1119 | if self.__c_setup_range >= self.__p_setup_range \ 1120 | and self.__c_setup_range / self.__p_setup_range <= 1.618 \ 1121 | or self.__c_s_h <= self.__p_s_h and self.__c_s_l >= self.__p_s_l: 1122 | 1123 | self.setup_phase2 = 'na' 1124 | self.count_down_started = 'na' 1125 | self.__S9_pos_Bcd = 0 1126 | self.bcd_counter = 0 1127 | 1128 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1129 | def __is_c_cd_combo_canceled(self,stock): 1130 | """" 1131 | if we have a finished sell/buy setup and a sell/buy count down is already started but not yet finished and countdown 1132 | cancellation qualifier I or II is active, then reset the count down 1133 | """ 1134 | 1135 | if self.count_down_started == 'Scd' and self.setup_phase2 == 'Ss2': 1136 | 1137 | # qualifier I or qualifier II? then cancel the current countdown 1138 | if self.__c_setup_range >= self.__p_setup_range \ 1139 | and self.__c_setup_range / self.__p_setup_range <= 1.618 \ 1140 | or self.__c_s_h <= self.__p_s_h and self.__c_s_l >= self.__p_s_l: 1141 | 1142 | self.setup_phase2 = 'na' 1143 | self.count_down_started = 'na' 1144 | self.__S9_pos_combo_Scd = 0 1145 | 1146 | elif self.count_down_started == 'Bcd' and self.setup_phase2 == 'Bs2': 1147 | 1148 | # qualifier I or qualifier II? then cancel the current countdown 1149 | if self.__c_setup_range >= self.__p_setup_range \ 1150 | and self.__c_setup_range / self.__p_setup_range <= 1.618 \ 1151 | or self.__c_s_h <= self.__p_s_h and self.__c_s_l >= self.__p_s_l: 1152 | 1153 | self.setup_phase2 = 'na' 1154 | self.count_down_started = 'na' 1155 | self.__S9_pos_combo_Bcd = 0 1156 | 1157 | 1158 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1159 | --------------------------------------------------------------------------------