Forex Indicators
Forex Software Forex Strategy Builder Forex Strategy Trader Strategies Blog Forum
Overview Download Rates Source Help Power Up Awards

Technical Indicators » Donchian Channel

01 // Donchian Channel Indicator
02 // Last changed on 2009-12-15
03 // Part of Forex Strategy Trader
04 // Website http://forexsb.com/
05 // Copyright (c) 2006 - 2009 Miroslav Popov - All rights reserved.
06 // This code or any part of it cannot be used in other applications without a permission.
07 
08 using System.Drawing;
09 
10 namespace Forex_Strategy_Builder
11 {
12     /// <summary>
13     /// Donchian Channel Indicator
14     /// </summary>
15     public class Donchian_Channel : Indicator
16     {
17         /// <summary>
18         /// Sets the default indicator parameters for the designated slot type
19         /// </summary>
20         public Donchian_Channel(SlotTypes slotType)
21         {
22             // General properties
23             IndicatorName = "Donchian Channel";
24             PossibleSlots = SlotTypes.Open | SlotTypes.OpenFilter | SlotTypes.Close | SlotTypes.CloseFilter;
25 
26             // Setting up the indicator parameters
27             IndParam = new IndicatorParam();
28             IndParam.IndicatorName = IndicatorName;
29             IndParam.SlotType      = slotType;
30 
31             // The ComboBox parameters
32             IndParam.ListParam[0].Caption = "Logic";
33             if (slotType == SlotTypes.Open)
34                 IndParam.ListParam[0].ItemList = new string[]
35                 {
36                     "Enter long at the Upper Band",
37                     "Enter long at the Lower Band"
38                 };
39             else if (slotType == SlotTypes.OpenFilter)
40                 IndParam.ListParam[0].ItemList = new string[]
41                 {
42                     "The bar opens below the Upper Band",
43                     "The bar opens above the Upper Band",
44                     "The bar opens below the Lower Band",
45                     "The bar opens above the Lower Band",
46                     "The position opens below the Upper Band",
47                     "The position opens above the Upper Band",
48                     "The position opens below the Lower Band",
49                     "The position opens above the Lower Band",
50                     "The bar opens below the Upper Band after opening above it",
51                     "The bar opens above the Upper Band after opening below it",
52                     "The bar opens below the Lower Band after opening above it",
53                     "The bar opens above the Lower Band after opening below it",
54                 };
55             else if (slotType == SlotTypes.Close)
56                 IndParam.ListParam[0].ItemList = new string[]
57                 {
58                     "Exit long at the Upper Band",
59                     "Exit long at the Lower Band"
60                 };
61             else if (slotType == SlotTypes.CloseFilter)
62                 IndParam.ListParam[0].ItemList = new string[]
63                 {
64                     "The bar closes below the Upper Band",
65                     "The bar closes above the Upper Band",
66                     "The bar closes below the Lower Band",
67                     "The bar closes above the Lower Band"
68                 };
69             else
70                 IndParam.ListParam[0].ItemList = new string[]
71                 {
72                     "Not Defined"
73                 };
74             IndParam.ListParam[0].Index = 0;
75             IndParam.ListParam[0].Text    = IndParam.ListParam[0].ItemList[IndParam.ListParam[0].Index];
76             IndParam.ListParam[0].Enabled = true;
77             IndParam.ListParam[0].ToolTip = "Logic of application of the Donchian Channel.";
78 
79             IndParam.ListParam[1].Caption  = "Base price";
80             IndParam.ListParam[1].ItemList = new string[] { "High & Low" };
81             IndParam.ListParam[1].Index    = 0;
82             IndParam.ListParam[1].Text     = IndParam.ListParam[1].ItemList[IndParam.ListParam[1].Index];
83             IndParam.ListParam[1].Enabled  = true;
84 
85             // The NumericUpDown parameters
86             IndParam.NumParam[0].Caption = "Period";
87             IndParam.NumParam[0].Value   = 10;
88             IndParam.NumParam[0].Min     = 1;
89             IndParam.NumParam[0].Max     = 200;
90             IndParam.NumParam[0].Enabled = true;
91             IndParam.NumParam[0].ToolTip = "The width of the range we are looking for an extreme in.";
92 
93             IndParam.NumParam[1].Caption = "Shift";
94             IndParam.NumParam[1].Value   = 0;
95             IndParam.NumParam[1].Min     = 0;
96             IndParam.NumParam[1].Max     = 200;
97             IndParam.NumParam[1].Enabled = true;
98             IndParam.NumParam[1].ToolTip = "The number of bars to shift with.";
99 
100             // The CheckBox parameters
101             IndParam.CheckParam[0].Caption = "Use previous bar value";
102             IndParam.CheckParam[0].Checked = PrepareUsePrevBarValueCheckBox(slotType);
103             IndParam.CheckParam[0].Enabled = true;
104             IndParam.CheckParam[0].ToolTip = "Use the indicator value from the previous bar.";
105 
106             return;
107         }
108 
109         /// <summary>
110         /// Calculates the indicator's components
111         /// </summary>
112         public override void Calculate(SlotTypes slotType)
113         {
114             // Reading the parameters
115             int iPeriod = (int)IndParam.NumParam[0].Value;
116             int iShift  = (int)IndParam.NumParam[1].Value;
117             int iPrvs   = IndParam.CheckParam[0].Checked ? 1 : 0;
118 
119             // Calculation
120             double[] adUpBand  = new double[Bars];
121             double[] adDnBand  = new double[Bars];
122 
123             int iFirstBar = iPeriod + iShift + iPrvs + 2;
124 
125             for (int iBar = iFirstBar; iBar < Bars - iShift; iBar++)
126             {
127                 double dMax = double.MinValue;
128                 double dMin = double.MaxValue;
129                 for (int i = 0; i < iPeriod; i++)
130                 {
131                     if (High[iBar - i] > dMax) dMax = High[iBar - i];
132                     if (Low[iBar - i]  < dMin) dMin = Low[iBar - i];
133                 }
134                 adUpBand[iBar + iShift] = dMax;
135                 adDnBand[iBar + iShift] = dMin;
136             }
137 
138             // Saving the components
139             Component = new IndicatorComp[4];
140 
141             Component[0] = new IndicatorComp();
142             Component[0].CompName   = "Upper Band";
143             Component[0].DataType   = IndComponentType.IndicatorValue;
144             Component[0].ChartType  = IndChartType.Line;
145             Component[0].ChartColor = Color.Blue;
146             Component[0].FirstBar   = iFirstBar;
147             Component[0].Value      = adUpBand;
148 
149             Component[1] = new IndicatorComp();
150             Component[1].CompName   = "Lower Band";
151             Component[1].DataType   = IndComponentType.IndicatorValue;
152             Component[1].ChartType  = IndChartType.Line;
153             Component[1].ChartColor = Color.Blue;
154             Component[1].FirstBar   = iFirstBar;
155             Component[1].Value      = adDnBand;
156 
157             Component[2] = new IndicatorComp();
158             Component[2].ChartType  = IndChartType.NoChart;
159             Component[2].FirstBar   = iFirstBar;
160             Component[2].Value      = new double[Bars];
161 
162             Component[3] = new IndicatorComp();
163             Component[3].ChartType  = IndChartType.NoChart;
164             Component[3].FirstBar   = iFirstBar;
165             Component[3].Value      = new double[Bars];
166 
167             // Sets the Component's type.
168             if (slotType == SlotTypes.Open)
169             {
170                 Component[2].DataType = IndComponentType.OpenLongPrice;
171                 Component[2].CompName = "Long position entry price";
172                 Component[3].DataType = IndComponentType.OpenShortPrice;
173                 Component[3].CompName = "Short position entry price";
174             }
175             else if (slotType == SlotTypes.OpenFilter)
176             {
177                 Component[2].DataType = IndComponentType.AllowOpenLong;
178                 Component[2].CompName = "Is long entry allowed";
179                 Component[3].DataType = IndComponentType.AllowOpenShort;
180                 Component[3].CompName = "Is short entry allowed";
181             }
182             else if (slotType == SlotTypes.Close)
183             {
184                 Component[2].DataType = IndComponentType.CloseLongPrice;
185                 Component[2].CompName = "Long position closing price";
186                 Component[3].DataType = IndComponentType.CloseShortPrice;
187                 Component[3].CompName = "Short position closing price";
188             }
189             else if (slotType == SlotTypes.CloseFilter)
190             {
191                 Component[2].DataType = IndComponentType.ForceCloseLong;
192                 Component[2].CompName = "Close out long position";
193                 Component[3].DataType = IndComponentType.ForceCloseShort;
194                 Component[3].CompName = "Close out short position";
195             }
196 
197             if (slotType == SlotTypes.Open || slotType == SlotTypes.Close)
198             {
199                 if (iPeriod > 1)
200                 {
201                     for (int iBar = iFirstBar; iBar < Bars; iBar++)
202                     {   // Covers the cases when the price can pass through the band without a signal.
203                         double dOpen = Open[iBar]; // Current open price
204 
205                         // Upper band
206                         double dValueUp   = adUpBand[iBar - iPrvs];     // Current value
207                         double dValueUp1  = adUpBand[iBar - iPrvs - 1]; // Previous value
208                         double dTempValUp = dValueUp;
209 
210                         if ((dValueUp1 > High[iBar - 1] && dValueUp < dOpen) || // The Open price jumps above the
211                             indicator
212                             (dValueUp1 < Low[iBar -  1] && dValueUp > dOpen) || // The Open price jumps below the
213                              indicator
214                             (Close[iBar - 1] < dValueUp && dValueUp < dOpen) || // The Open price is in a positive gap
215                             (Close[iBar - 1] > dValueUp && dValueUp > dOpen))   // The Open price is in a negative gap
216                             dTempValUp = dOpen; // The entry/exit level is moved to Open price
217 
218                         // Lower band
219                         double dValueDown   = adDnBand[iBar - iPrvs];     // Current value
220                         double dValueDown1  = adDnBand[iBar - iPrvs - 1]; // Previous value
221                         double dTempValDown = dValueDown;
222 
223                         if ((dValueDown1 > High[iBar - 1] && dValueDown < dOpen) || // The Open price jumps above the
224                             indicator
225                             (dValueDown1 < Low[iBar  - 1] && dValueDown > dOpen) || // The Open price jumps below the
226                              indicator
227                             (Close[iBar - 1] < dValueDown && dValueDown < dOpen) || // The Open price is in a positive
228                              gap
229                             (Close[iBar - 1] > dValueDown && dValueDown > dOpen))   // The Open price is in a negative
230                              gap
231                             dTempValDown = dOpen; // The entry/exit level is moved to Open price
232 
233                         if (IndParam.ListParam[0].Text == "Enter long at the Upper Band" ||
234                             IndParam.ListParam[0].Text == "Exit long at the Upper Band")
235                         {
236                             Component[2].Value[iBar] = dTempValUp;
237                             Component[3].Value[iBar] = dTempValDown;
238                         }
239                         else
240                         {
241                             Component[2].Value[iBar] = dTempValDown;
242                             Component[3].Value[iBar] = dTempValUp;
243                         }
244                     }
245                 }
246                 else
247                 {
248                     for (int iBar = 2; iBar < Bars; iBar++)
249                     {
250                         if (IndParam.ListParam[0].Text == "Enter long at the Upper Band" ||
251                             IndParam.ListParam[0].Text == "Exit long at the Upper Band")
252                         {
253                             Component[2].Value[iBar] = adUpBand[iBar - iPrvs];
254                             Component[3].Value[iBar] = adDnBand[iBar - iPrvs];
255                         }
256                         else
257                         {
258                             Component[2].Value[iBar] = adDnBand[iBar - iPrvs];
259                             Component[3].Value[iBar] = adUpBand[iBar - iPrvs];
260                         }
261                     }
262                 }
263             }
264             else
265             {
266                 switch (IndParam.ListParam[0].Text)
267                 {
268                     case "The bar opens below the Upper Band":
269                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
270                                            BandIndLogic.The_bar_opens_below_the_Upper_Band);
271                         break;
272 
273                     case "The bar opens above the Upper Band":
274                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
275                                            BandIndLogic.The_bar_opens_above_the_Upper_Band);
276                         break;
277 
278                     case "The bar opens below the Lower Band":
279                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
280                                            BandIndLogic.The_bar_opens_below_the_Lower_Band);
281                         break;
282 
283                     case "The bar opens above the Lower Band":
284                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
285                                            BandIndLogic.The_bar_opens_above_the_Lower_Band);
286                         break;
287 
288                     case "The bar opens below the Upper Band after opening above it":
289                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
290                                            BandIndLogic.The_bar_opens_below_the_Upper_Band_after_opening_above_it);
291                         break;
292 
293                     case "The bar opens above the Upper Band after opening below it":
294                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
295                                            BandIndLogic.The_bar_opens_above_the_Upper_Band_after_opening_below_it);
296                         break;
297 
298                     case "The bar opens below the Lower Band after opening above it":
299                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
300                                            BandIndLogic.The_bar_opens_below_the_Lower_Band_after_opening_above_it);
301                         break;
302 
303                     case "The bar opens above the Lower Band after opening below it":
304                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
305                                            BandIndLogic.The_bar_opens_above_the_Lower_Band_after_opening_below_it);
306                         break;
307 
308                     case "The position opens above the Upper Band":
309                         Component[0].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
310                         Component[1].PosPriceDependence = PositionPriceDependence.PriceSellLower;
311                         Component[0].UsePreviousBar = iPrvs;
312                         Component[1].UsePreviousBar = iPrvs;
313                         Component[2].DataType = IndComponentType.Other;
314                         Component[3].DataType = IndComponentType.Other;
315                         Component[2].ShowInDynInfo = false;
316                         Component[3].ShowInDynInfo = false;
317                         break;
318 
319                     case "The position opens below the Upper Band":
320                         Component[0].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
321                         Component[1].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
322                         Component[0].UsePreviousBar = iPrvs;
323                         Component[1].UsePreviousBar = iPrvs;
324                         Component[2].DataType = IndComponentType.Other;
325                         Component[3].DataType = IndComponentType.Other;
326                         Component[2].ShowInDynInfo = false;
327                         Component[3].ShowInDynInfo = false;
328                         break;
329 
330                     case "The position opens above the Lower Band":
331                         Component[0].PosPriceDependence = PositionPriceDependence.PriceSellLower;
332                         Component[1].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
333                         Component[0].UsePreviousBar = iPrvs;
334                         Component[1].UsePreviousBar = iPrvs;
335                         Component[2].DataType = IndComponentType.Other;
336                         Component[3].DataType = IndComponentType.Other;
337                         Component[2].ShowInDynInfo = false;
338                         Component[3].ShowInDynInfo = false;
339                         break;
340 
341                     case "The position opens below the Lower Band":
342                         Component[0].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
343                         Component[1].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
344                         Component[0].UsePreviousBar = iPrvs;
345                         Component[1].UsePreviousBar = iPrvs;
346                         Component[2].DataType = IndComponentType.Other;
347                         Component[3].DataType = IndComponentType.Other;
348                         Component[2].ShowInDynInfo = false;
349                         Component[3].ShowInDynInfo = false;
350                         break;
351 
352                     case "The bar closes below the Upper Band":
353                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
354                                            BandIndLogic.The_bar_closes_below_the_Upper_Band);
355                         break;
356 
357                     case "The bar closes above the Upper Band":
358                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
359                                            BandIndLogic.The_bar_closes_above_the_Upper_Band);
360                         break;
361 
362                     case "The bar closes below the Lower Band":
363                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
364                                            BandIndLogic.The_bar_closes_below_the_Lower_Band);
365                         break;
366 
367                     case "The bar closes above the Lower Band":
368                         BandIndicatorLogic(iFirstBar, iPrvs, adUpBand, adDnBand, ref Component[2], ref Component[3],
369                                            BandIndLogic.The_bar_closes_above_the_Lower_Band);
370                         break;
371 
372                     default:
373                         break;
374                 }
375             }
376 
377             return;
378         }
379 
380         /// <summary>
381         /// Sets the indicator logic description
382         /// </summary>
383         public override void SetDescription(SlotTypes slotType)
384         {
385             switch (IndParam.ListParam[0].Text)
386             {
387                 case "Enter long at the Upper Band":
388                     EntryPointLongDescription  = "at the Upper Band of " + ToString();
389                     EntryPointShortDescription = "at the Lower Band of " + ToString();
390                     break;
391 
392                 case "Enter long at the Lower Band":
393                     EntryPointLongDescription  = "at the Lower Band of " + ToString();
394                     EntryPointShortDescription = "at the Upper Band of " + ToString();
395                     break;
396 
397                 case "Exit long at the Upper Band":
398                     ExitPointLongDescription  = "at the Upper Band of " + ToString();
399                     ExitPointShortDescription = "at the Lower Band of " + ToString();
400                     break;
401 
402                 case "Exit long at the Lower Band":
403                     ExitPointLongDescription  = "at the Lower Band of " + ToString();
404                     ExitPointShortDescription = "at the Upper Band of " + ToString();
405                     break;
406 
407                 case "The bar opens below the Upper Band":
408                     EntryFilterLongDescription  = "the bar opens below the Upper Band of " + ToString();
409                     EntryFilterShortDescription = "the bar opens above the Lower Band of " + ToString();
410                     break;
411 
412                 case "The bar opens above the Upper Band":
413                     EntryFilterLongDescription  = "the bar opens above the Upper Band of " + ToString();
414                     EntryFilterShortDescription = "the bar opens below the Lower Band of " + ToString();
415                     break;
416 
417                 case "The bar opens below the Lower Band":
418                     EntryFilterLongDescription  = "the bar opens below the Lower Band of " + ToString();
419                     EntryFilterShortDescription = "the bar opens above the Upper Band of " + ToString();
420                     break;
421 
422                 case "The bar opens above the Lower Band":
423                     EntryFilterLongDescription  = "the bar opens above the Lower Band of " + ToString();
424                     EntryFilterShortDescription = "the bar opens below the Upper Band of " + ToString();
425                     break;
426 
427                 case "The position opens above the Upper Band":
428                     EntryFilterLongDescription  = "the position opening price is higher than the Upper Band of " +
429                                                   ToString();
430                     EntryFilterShortDescription = "the position opening price is lower than the Lower Band of "  +
431                                                   ToString();
432                     break;
433 
434                 case "The position opens below the Upper Band":
435                     EntryFilterLongDescription  = "the position opening price is lower than the Upper Band of "  +
436                                                   ToString();
437                     EntryFilterShortDescription = "the position opening price is higher than the Lower Band of " +
438                                                   ToString();
439                     break;
440 
441                 case "The position opens above the Lower Band":
442                     EntryFilterLongDescription  = "the position opening price is higher than the Lower Band of " +
443                                                   ToString();
444                     EntryFilterShortDescription = "the position opening price is lower than the Upper Band of "  +
445                                                   ToString();
446                     break;
447 
448                 case "The position opens below the Lower Band":
449                     EntryFilterLongDescription  = "the position opening price is lower than the Lower Band of "  +
450                                                   ToString();
451                     EntryFilterShortDescription = "the position opening price is higher than the Upper Band of " +
452                                                   ToString();
453                     break;
454 
455                 case "The bar opens below the Upper Band after opening above it":
456                     EntryFilterLongDescription  = "the bar opens below the Upper Band of " + ToString() + " after the
457                                                   previous bar has opened above it";
458                     EntryFilterShortDescription = "the bar opens above the Lower Band of " + ToString() + " after the
459                                                   previous bar has opened below it";
460                     break;
461 
462                 case "The bar opens above the Upper Band after opening below it":
463                     EntryFilterLongDescription  = "the bar opens above the Upper Band of " + ToString() + " after the
464                                                   previous bar has opened below it";
465                     EntryFilterShortDescription = "the bar opens below the Lower Band of " + ToString() + " after the
466                                                   previous bar has opened above it";
467                     break;
468 
469                 case "The bar opens below the Lower Band after opening above it":
470                     EntryFilterLongDescription  = "the bar opens below the Lower Band of " + ToString() + " after the
471                                                   previous bar has opened above it";
472                     EntryFilterShortDescription = "the bar opens above the Upper Band of " + ToString() + " after the
473                                                   previous bar has opened below it";
474                     break;
475 
476                 case "The bar opens above the Lower Band after opening below it":
477                     EntryFilterLongDescription  = "the bar opens above the Lower Band of " + ToString() + " after the
478                                                   previous bar has opened below it";
479                     EntryFilterShortDescription = "the bar opens below the Upper Band of " + ToString() + " after the
480                                                   previous bar has opened above it";
481                     break;
482 
483                 case "The bar closes below the Upper Band":
484                     ExitFilterLongDescription  = "the bar closes below the Upper Band of " + ToString();
485                     ExitFilterShortDescription = "the bar closes above the Lower Band of " + ToString();
486                     break;
487 
488                 case "The bar closes above the Upper Band":
489                     ExitFilterLongDescription  = "the bar closes above the Upper Band of " + ToString();
490                     ExitFilterShortDescription = "the bar closes below the Lower Band of " + ToString();
491                     break;
492 
493                 case "The bar closes below the Lower Band":
494                     ExitFilterLongDescription  = "the bar closes below the Lower Band of " + ToString();
495                     ExitFilterShortDescription = "the bar closes above the Upper Band of " + ToString();
496                     break;
497 
498                 case "The bar closes above the Lower Band":
499                     ExitFilterLongDescription  = "the bar closes above the Lower Band of " + ToString();
500                     ExitFilterShortDescription = "the bar closes below the Upper Band of " + ToString();
501                     break;
502 
503                 default:
504                     break;
505             }
506 
507             return;
508         }
509 
510         /// <summary>
511         /// Indicator to string
512         /// </summary>
513         public override string ToString()
514         {
515             string sString = IndicatorName +
516                 (IndParam.CheckParam[0].Checked ? "* (" : " (") +
517                 IndParam.NumParam[0].ValueToString + ", " + // Period
518                 IndParam.NumParam[1].ValueToString + ")";   // Shift
519 
520             return sString;
521         }
522     }
523 }

Top

There are no comments yet

Leave a Comment


?
?