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