├── 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 |
--------------------------------------------------------------------------------