Source »
Donchian Channel - source code
// Forex Strategy Builder
// Copyright (c) 2006 - 2008 Miroslav Popov - All rights reserved!
// http://forexsb.com
// info(a)forexsb.com
//
// Last changed on: 2007-06-12
using System;
using System.Drawing;
namespace Forex_Strategy_Builder
{
/// <summary>
/// Indicator Donchian Channel
/// </summary>
public class Donchian_Channel : Indicator
{
/// <summary>
/// The default constructor.
/// </summary>
public Donchian_Channel()
{
}
/// <summary>
/// Sets the default parameters for the designated slot type.
/// </summary>
/// <param name="slotType">The slot type.</param>
public Donchian_Channel(SlotTypes slotType)
{
sIndicatorName = "Donchian Channel";
parameters = new IndicatorParam();
component = new IndicatorComp[] { };
afSpecValue = new float[] { };
bSeparatedChart = false;
bIsCalculated = false;
typeOfIndicator = TypeOfIndicator.Indicator;
// The indicator name.
parameters.IndicatorName = sIndicatorName;
// The slot type.
parameters.SlotType = slotType;
// The ComboBox parameters.
parameters.ListParam[0].Caption = "Logic";
if (slotType == SlotTypes.Open)
parameters.ListParam[0].ItemList = new string[]
{
"Enter long at the Up Band",
"Enter long at the Down Band"
};
else if (slotType == SlotTypes.OpenFilter)
parameters.ListParam[0].ItemList = new string[]
{
"The bar opens below the Up Band",
"The bar opens above the Up Band",
"The bar opens below the Down Band",
"The bar opens above the Down Band",
"The position opens below the Up Band",
"The position opens above the Up Band",
"The position opens below the Down Band",
"The position opens above the Down Band"
};
else if (slotType == SlotTypes.Close)
parameters.ListParam[0].ItemList = new string[]
{
"Exit long at the Up Band",
"Exit long at the Down Band"
};
else if (slotType == SlotTypes.CloseFilter)
parameters.ListParam[0].ItemList = new string[]
{
"The bar closes below the Up Band",
"The bar closes above the Up Band",
"The bar closes below the Down Band",
"The bar closes above the Down Band"
};
parameters.ListParam[0].Index = 0;
parameters.ListParam[0].Text = parameters.ListParam[0].ItemList[parameters.ListParam[0].Index];
parameters.ListParam[0].Enabled = true;
parameters.ListParam[0].ToolTip = "Logic of application of the Donchian Channel";
parameters.ListParam[1].Caption = "Base price";
parameters.ListParam[1].ItemList = new string[] { "High & Low" };
parameters.ListParam[1].Index = 0;
parameters.ListParam[1].Text = parameters.ListParam[1].ItemList[parameters.ListParam[1].Index];
parameters.ListParam[1].Enabled = true;
// The NumericUpDown parameters.
parameters.NumParam[0].Caption = "Period";
parameters.NumParam[0].Value = 10;
parameters.NumParam[0].Min = 1;
parameters.NumParam[0].Max = 200;
parameters.NumParam[0].Enabled = true;
parameters.NumParam[0].ToolTip = "The width of the range we are looking for an extreme in";
parameters.NumParam[1].Caption = "Shift";
parameters.NumParam[1].Value = 0;
parameters.NumParam[1].Min = 0;
parameters.NumParam[1].Max = 200;
parameters.NumParam[1].Enabled = true;
parameters.NumParam[1].ToolTip = "The number of bars to shift with";
// The CheckBox parameters.
parameters.CheckParam[0].Caption = "Use previous bar value";
parameters.CheckParam[0].Checked = Data.Strategy.PrepareUsePrevBarValueCheckBox(slotType);
parameters.CheckParam[0].Enabled = true;
parameters.CheckParam[0].ToolTip = "Use the indicator value from the previous bar";
}
/// <summary>
/// Calculates the indicator's components.
/// </summary>
/// <param name="slotType">The slot type.</param>
public override void Calculate(SlotTypes slotType)
{
if (parameters.SlotType == SlotTypes.NotDefined) return;
// Reading the parameters
int iPeriod = (int)parameters.NumParam[0].Value;
int iShift = (int)parameters.NumParam[1].Value;
int iPrvs = parameters.CheckParam[0].Checked ? 1 : 0;
// Calculation
float[] afUpBand = new float[Bars];
float[] afDnBand = new float[Bars];
int iFirstBar = iPeriod + iShift + 1 + iPrvs;
for (int iBar = iFirstBar; iBar < Bars - iShift; iBar++)
{
float fMax = float.MinValue;
float fMin = float.MaxValue;
for (int i = 0; i < iPeriod; i++)
{
if (High[iBar - i] > fMax) fMax = High[iBar - i];
if (Low[iBar - i] < fMin) fMin = Low[iBar - i];
}
afUpBand[iBar + iShift] = fMax;
afDnBand[iBar + iShift] = fMin;
}
// Saving the components
component = new IndicatorComp[4];
component[0] = new IndicatorComp();
component[0].CompName = "Up Band";
component[0].DataType = IndComponentType.IndicatorValue;
component[0].ChartType = IndChartType.Line;
component[0].ChartColor = Color.Blue;
component[0].FirstBar = iFirstBar;
component[0].Value = afUpBand;
component[1] = new IndicatorComp();
component[1].CompName = "Down Band";
component[1].DataType = IndComponentType.IndicatorValue;
component[1].ChartType = IndChartType.Line;
component[1].ChartColor = Color.Blue;
component[1].FirstBar = iFirstBar;
component[1].Value = afDnBand;
component[2] = new IndicatorComp();
component[2].ChartType = IndChartType.NoChart;
component[2].FirstBar = iFirstBar;
component[2].Value = new float[Bars];
component[3] = new IndicatorComp();
component[3].ChartType = IndChartType.NoChart;
component[3].FirstBar = iFirstBar;
component[3].Value = new float[Bars];
// Sets the component's type.
if (slotType == SlotTypes.Open)
{
component[2].DataType = IndComponentType.OpenLongPrice;
component[2].CompName = "Long positions opening price";
component[3].DataType = IndComponentType.OpenShortPrice;
component[3].CompName = "Short positions opening price";
}
else if (slotType == SlotTypes.OpenFilter)
{
component[2].DataType = IndComponentType.AllowOpenLong;
component[2].CompName = "Allows long positions opening";
component[3].DataType = IndComponentType.AllowOpenShort;
component[3].CompName = "Allows short positions opening";
}
else if (slotType == SlotTypes.Close)
{
component[2].DataType = IndComponentType.CloseLongPrice;
component[2].CompName = "Long positions closing price";
component[3].DataType = IndComponentType.CloseShortPrice;
component[3].CompName = "Short positions closing price";
}
else if (slotType == SlotTypes.CloseFilter)
{
component[2].DataType = IndComponentType.ForceCloseLong;
component[2].CompName = "Forces long positions closing";
component[3].DataType = IndComponentType.ForceCloseShort;
component[3].CompName = "Forces short positions closing";
}
if (slotType == SlotTypes.Open || slotType == SlotTypes.Close)
{
if (iPeriod > 1)
{
for (int iBar = 2; iBar < Bars; iBar++)
{
// Covers the cases when the price can pass through the band without a signal
float fValueUp = afUpBand[iBar - iPrvs]; // Current value
float fValueUp1 = afUpBand[iBar - iPrvs - 1]; // Previous value
float fTempValUp = fValueUp;
if ((fValueUp1 > High[iBar - 1] && fValueUp < Low[iBar]) || // It jumps below the current bar
(fValueUp1 < Low[iBar - 1] && fValueUp > High[iBar]) || // It jumps above the current bar
(Close[iBar - 1] < fValueUp && fValueUp < Open[iBar])|| // Positive gap
(Close[iBar - 1] > fValueUp && fValueUp > Open[iBar])) // Negative gap
fTempValUp = Open[iBar];
float fValueDown = afDnBand[iBar - iPrvs]; // Current value
float fValueDown1 = afDnBand[iBar - iPrvs - 1]; // Previous value
float fTempValDown = fValueDown;
if ((fValueDown1 > High[iBar - 1] && fValueDown < Low[iBar]) || // It jumps below the current bar
(fValueDown1 < Low[iBar - 1] && fValueDown > High[iBar]) || // It jumps above the current bar
(Close[iBar - 1] < fValueDown && fValueDown < Open[iBar])|| // Positive gap
(Close[iBar - 1] > fValueDown && fValueDown > Open[iBar])) // Negative gap
fTempValDown = Open[iBar];
if (parameters.ListParam[0].Text == "Enter long at the Up Band" ||
parameters.ListParam[0].Text == "Exit long at the Up Band")
{
component[2].Value[iBar] = fTempValUp;
component[3].Value[iBar] = fTempValDown;
}
else
{
component[2].Value[iBar] = fTempValDown;
component[3].Value[iBar] = fTempValUp;
}
}
}
else
{
for (int iBar = 2; iBar < Bars; iBar++)
{
if (parameters.ListParam[0].Text == "Enter long at the Up Band" ||
parameters.ListParam[0].Text == "Exit long at the Up Band")
{
component[2].Value[iBar] = afUpBand[iBar - iPrvs];
component[3].Value[iBar] = afDnBand[iBar - iPrvs];
}
else
{
component[2].Value[iBar] = afDnBand[iBar - iPrvs];
component[3].Value[iBar] = afUpBand[iBar - iPrvs];
}
}
}
}
else
{
switch (parameters.ListParam[0].Text)
{
case "The bar opens below the Up Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Open[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Open[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar opens above the Up Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Open[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Open[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar opens below the Down Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Open[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Open[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar opens above the Down Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Open[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Open[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The position opens above the Up Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
component[1].PosPriceDependence = PositionPriceDependence.PriceSellLower;
component[0].UsePreviousBar = iPrvs;
component[1].UsePreviousBar = iPrvs;
component[2].DataType = IndComponentType.Other;
component[3].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
component[3].ShowInDynInfo = false;
break;
case "The position opens below the Up Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
component[1].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
component[0].UsePreviousBar = iPrvs;
component[1].UsePreviousBar = iPrvs;
component[2].DataType = IndComponentType.Other;
component[3].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
component[3].ShowInDynInfo = false;
break;
case "The position opens above the Down Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceSellLower;
component[1].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
component[0].UsePreviousBar = iPrvs;
component[1].UsePreviousBar = iPrvs;
component[2].DataType = IndComponentType.Other;
component[3].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
component[3].ShowInDynInfo = false;
break;
case "The position opens below the Down Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
component[1].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
component[0].UsePreviousBar = iPrvs;
component[1].UsePreviousBar = iPrvs;
component[2].DataType = IndComponentType.Other;
component[3].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
component[3].ShowInDynInfo = false;
break;
case "The bar closes below the Up Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Close[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Close[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar closes above the Up Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Close[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Close[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar closes below the Down Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Close[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Close[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar closes above the Down Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[2].Value[iBar] = Close[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
component[3].Value[iBar] = Close[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
default:
break;
}
}
bIsCalculated = true;
return;
}
}
}
Top