Source »
Steady Bands - 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 Steady Bands
/// </summary>
public class Steady_Bands : Indicator
{
/// <summary>
/// The default constructor.
/// </summary>
public Steady_Bands()
{
}
/// <summary>
/// Sets the default parameters for the designated slot type.
/// </summary>
/// <param name="slotType">The slot type.</param>
public Steady_Bands(SlotTypes slotType)
{
sIndicatorName = "Steady Bands";
parameters = new IndicatorParam();
component = new IndicatorComp[] { };
afSpecValue = new float[] { };
bSeparatedChart = false;
bIsCalculated = false;
typeOfIndicator = TypeOfIndicator.Additional;
// 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 indicator";
parameters.ListParam[1].Caption = "Smoothing method";
parameters.ListParam[1].ItemList = Enum.GetNames(typeof(MAMethod));
parameters.ListParam[1].Index = 0;
parameters.ListParam[1].Text = parameters.ListParam[1].ItemList[parameters.ListParam[1].Index];
parameters.ListParam[1].Enabled = true;
parameters.ListParam[1].ToolTip = "The method of smoothing of central Moving Average";
parameters.ListParam[2].Caption = "Base price";
parameters.ListParam[2].ItemList = Enum.GetNames(typeof(BasePrice));
parameters.ListParam[2].Index = 3;
parameters.ListParam[2].Text = parameters.ListParam[2].ItemList[parameters.ListParam[2].Index];
parameters.ListParam[2].Enabled = true;
parameters.ListParam[2].ToolTip = "The price the central Moving Average is based on";
// The NumericUpDown parameters.
parameters.NumParam[0].Caption = "MA period";
parameters.NumParam[0].Value = 20;
parameters.NumParam[0].Min = 1;
parameters.NumParam[0].Max = 200;
parameters.NumParam[0].Enabled = true;
parameters.NumParam[0].ToolTip = "The central Moving Average period";
parameters.NumParam[1].Caption = "Margin in pips";
parameters.NumParam[1].Value = 40;
parameters.NumParam[1].Min = 0;
parameters.NumParam[1].Max = 200;
parameters.NumParam[1].Point = 0;
parameters.NumParam[1].Enabled = true;
parameters.NumParam[1].ToolTip = "Determines the distance between the ME and the Up (Down) Band";
// 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
MAMethod maMethod = (MAMethod )Enum.GetValues(typeof(MAMethod )).GetValue(parameters.ListParam[1].Index);
BasePrice price = (BasePrice)Enum.GetValues(typeof(BasePrice)).GetValue(parameters.ListParam[2].Index);
int nMA = (int)parameters.NumParam[0].Value;
float fMargin = parameters.NumParam[1].Value;
int iPrvs = parameters.CheckParam[0].Checked ? 1 : 0;
// Calculation
float[] afMA = MovingAverage(nMA, 0, maMethod, Price(price));
float[] afUpBand = new float[Bars];
float[] afDnBand = new float[Bars];
int iFirstBar = nMA + 1 + iPrvs;
for (int iBar = nMA; iBar < Bars; iBar++)
{
afUpBand[iBar] = afMA[iBar] + fMargin * Point;
afDnBand[iBar] = afMA[iBar] - fMargin * Point;
}
// Saving the components
component = new IndicatorComp[5];
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 = "Moving Average";
component[1].DataType = IndComponentType.IndicatorValue;
component[1].ChartType = IndChartType.Line;
component[1].ChartColor = Color.Yellow;
component[1].FirstBar = iFirstBar;
component[1].Value = afMA;
component[2] = new IndicatorComp();
component[2].CompName = "Down Band";
component[2].DataType = IndComponentType.IndicatorValue;
component[2].ChartType = IndChartType.Line;
component[2].ChartColor = Color.Blue;
component[2].FirstBar = iFirstBar;
component[2].Value = afDnBand;
component[3] = new IndicatorComp();
component[3].ChartType = IndChartType.NoChart;
component[3].FirstBar = iFirstBar;
component[3].Value = new float[Bars];
component[4] = new IndicatorComp();
component[4].ChartType = IndChartType.NoChart;
component[4].FirstBar = iFirstBar;
component[4].Value = new float[Bars];
// Sets the component's type.
if (slotType == SlotTypes.Open)
{
component[3].DataType = IndComponentType.OpenLongPrice;
component[3].CompName = "Long positions opening price";
component[4].DataType = IndComponentType.OpenShortPrice;
component[4].CompName = "Short positions opening price";
}
else if (slotType == SlotTypes.OpenFilter)
{
component[3].DataType = IndComponentType.AllowOpenLong;
component[3].CompName = "Allows long positions opening";
component[4].DataType = IndComponentType.AllowOpenShort;
component[4].CompName = "Allows short positions opening";
}
else if (slotType == SlotTypes.Close)
{
component[3].DataType = IndComponentType.CloseLongPrice;
component[3].CompName = "Long positions closing price";
component[4].DataType = IndComponentType.CloseShortPrice;
component[4].CompName = "Short positions closing price";
}
else if (slotType == SlotTypes.CloseFilter)
{
component[3].DataType = IndComponentType.ForceCloseLong;
component[3].CompName = "Forces long positions closing";
component[4].DataType = IndComponentType.ForceCloseShort;
component[4].CompName = "Forces short positions closing";
}
if (slotType == SlotTypes.Open || slotType == SlotTypes.Close)
{
if (nMA > 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[3].Value[iBar] = fTempValUp;
component[4].Value[iBar] = fTempValDown;
}
else
{
component[3].Value[iBar] = fTempValDown;
component[4].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[3].Value[iBar] = afUpBand[iBar - iPrvs];
component[4].Value[iBar] = afDnBand[iBar - iPrvs];
}
else
{
component[3].Value[iBar] = afDnBand[iBar - iPrvs];
component[4].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[3].Value[iBar] = Open[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Open[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Open[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Open[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
component[4].Value[iBar] = Open[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
case "The position opens above the Up Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
component[2].PosPriceDependence = PositionPriceDependence.PriceSellLower;
component[0].UsePreviousBar = iPrvs;
component[2].UsePreviousBar = iPrvs;
component[3].DataType = IndComponentType.Other;
component[4].DataType = IndComponentType.Other;
component[3].ShowInDynInfo = false;
component[4].ShowInDynInfo = false;
break;
case "The position opens below the Up Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
component[2].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
component[0].UsePreviousBar = iPrvs;
component[2].UsePreviousBar = iPrvs;
component[3].DataType = IndComponentType.Other;
component[4].DataType = IndComponentType.Other;
component[3].ShowInDynInfo = false;
component[4].ShowInDynInfo = false;
break;
case "The position opens above the Down Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceSellLower;
component[2].PosPriceDependence = PositionPriceDependence.PriceBuyHigher;
component[0].UsePreviousBar = iPrvs;
component[2].UsePreviousBar = iPrvs;
component[3].DataType = IndComponentType.Other;
component[4].DataType = IndComponentType.Other;
component[3].ShowInDynInfo = false;
component[4].ShowInDynInfo = false;
break;
case "The position opens below the Down Band":
component[0].PosPriceDependence = PositionPriceDependence.PriceSellHigher;
component[2].PosPriceDependence = PositionPriceDependence.PriceBuyLower;
component[0].UsePreviousBar = iPrvs;
component[2].UsePreviousBar = iPrvs;
component[3].DataType = IndComponentType.Other;
component[4].DataType = IndComponentType.Other;
component[3].ShowInDynInfo = false;
component[4].ShowInDynInfo = false;
break;
case "The bar closes below the Up Band":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[3].Value[iBar] = Close[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Close[iBar] > afUpBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Close[iBar] < afDnBand[iBar - iPrvs] ? 1 : 0;
component[4].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[3].Value[iBar] = Close[iBar] > afDnBand[iBar - iPrvs] ? 1 : 0;
component[4].Value[iBar] = Close[iBar] < afUpBand[iBar - iPrvs] ? 1 : 0;
}
break;
default:
break;
}
}
bIsCalculated = true;
return;
}
}
}
Top