Source »
Moving Average - 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 Moving Average.
/// </summary>
public class Moving_Average : Indicator
{
/// <summary>
/// The default constructor.
/// </summary>
public Moving_Average()
{
}
/// <summary>
/// Sets the default parameters for the designated slot type.
/// </summary>
/// <param name="slotType">The slot type.</param>
public Moving_Average(SlotTypes slotType)
{
sIndicatorName = "Moving Average";
parameters = new IndicatorParam();
component = new IndicatorComp[] { };
afSpecValue = new float[] { };
bSeparatedChart = false;
bIsCalculated = false;
// 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 the market at the MA value "
};
else if (slotType == SlotTypes.OpenFilter)
parameters.ListParam[0].ItemList = new string[]
{
"The Moving Average rises",
"The Moving Average falls",
"The bar opens above the MA value",
"The bar opens below the MA value",
"The position opens above the MA value",
"The position opens below the MA value",
};
else if (slotType == SlotTypes.Close)
parameters.ListParam[0].ItemList = new string[]
{
"Exit the market at the MA value "
};
else if (slotType == SlotTypes.CloseFilter)
parameters.ListParam[0].ItemList = new string[]
{
"The Moving Average rises",
"The Moving Average falls",
"The bar closes below the MA value",
"The bar closes above the MA value",
};
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 Moving Average";
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 Moving Average smoothing";
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 Moving Average is based on";
// The NumericUpDown parameters.
parameters.NumParam[0].Caption = "Period";
parameters.NumParam[0].Value = 21;
parameters.NumParam[0].Min = 1;
parameters.NumParam[0].Max = 200;
parameters.NumParam[0].Enabled = true;
parameters.NumParam[0].ToolTip = "The Moving Average period";
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 = "How many 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
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 iPeriod = (int)parameters.NumParam[0].Value;
int iShift = (int)parameters.NumParam[1].Value;
int iPrvs = parameters.CheckParam[0].Checked ? 1 : 0;
// TimeExecution
if (price == BasePrice.Open && iPeriod == 1 && iShift == 0)
timeExecution = TimeExecution.Opening;
else if (price == BasePrice.Close && iPeriod == 1 && iShift == 0)
timeExecution = TimeExecution.Closing;
// Calculation
float[] afMA = MovingAverage(iPeriod, iShift, maMethod, Price(price));
int iFirstBar = iPeriod + iShift + 1 + iPrvs;
// Saving the components
if (slotType == SlotTypes.Open || slotType == SlotTypes.Close)
{
component = new IndicatorComp[2];
component[1] = new IndicatorComp();
component[1].Value = new float[Bars];
for (int iBar = 2; iBar < Bars; iBar++)
{
// Covers the cases when the price can pass through the MA without a signal
float fValue = afMA[iBar - iPrvs]; // Current value
float fValue1 = afMA[iBar - iPrvs - 1]; // Previous value
float fTempVal = fValue;
if ((fValue1 > High[iBar - 1] && fValue < Low[iBar]) || // It jumps bellow the current bar
(fValue1 < Low[iBar - 1] && fValue > High[iBar]) || // It jumps above the current bar
(Close[iBar - 1] < fValue && fValue < Open[iBar])|| // Positive gap
(Close[iBar - 1] > fValue && fValue > Open[iBar])) // Negative gap
fTempVal = Open[iBar];
component[1].Value[iBar] = fTempVal;
}
}
else
{
component = new IndicatorComp[3];
component[1] = new IndicatorComp();
component[1].ChartType = IndChartType.NoChart;
component[1].FirstBar = iFirstBar;
component[1].Value = new float[Bars];
component[2] = new IndicatorComp();
component[2].ChartType = IndChartType.NoChart;
component[2].FirstBar = iFirstBar;
component[2].Value = new float[Bars];
}
component[0] = new IndicatorComp();
component[0].CompName = "MA Value";
component[0].DataType = IndComponentType.IndicatorValue;
component[0].ChartType = IndChartType.Line;
component[0].ChartColor = Color.Red;
component[0].FirstBar = iFirstBar;
component[0].Value = afMA;
if (slotType == SlotTypes.Open)
{
component[1].CompName = "Position's opening price";
component[1].DataType = IndComponentType.OpenPrice;
}
else if (slotType == SlotTypes.OpenFilter)
{
component[1].DataType = IndComponentType.AllowOpenLong;
component[1].CompName = "Allows long positions opening";
component[2].DataType = IndComponentType.AllowOpenShort;
component[2].CompName = "Allows short positions opening";
}
else if (slotType == SlotTypes.Close)
{
component[1].CompName = "Position's closing price";
component[1].DataType = IndComponentType.ClosePrice;
}
else if (slotType == SlotTypes.CloseFilter)
{
component[1].DataType = IndComponentType.ForceCloseLong;
component[1].CompName = "Forces long positions closing";
component[2].DataType = IndComponentType.ForceCloseShort;
component[2].CompName = "Forces short positions closing";
}
if (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter)
{
switch (parameters.ListParam[0].Text)
{
case "The Moving Average rises":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = afMA[iBar - iPrvs - 1] < afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = afMA[iBar - iPrvs - 1] > afMA[iBar - iPrvs] ? 1 : 0;
}
break;
case "The Moving Average falls":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = afMA[iBar - iPrvs - 1] > afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = afMA[iBar - iPrvs - 1] < afMA[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar opens below the MA value":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = Open[iBar] < afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = Open[iBar] > afMA[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar opens above the MA value":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = Open[iBar] > afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = Open[iBar] < afMA[iBar - iPrvs] ? 1 : 0;
}
break;
case "The position opens above the MA value":
component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower;
component[0].UsePreviousBar = iPrvs;
component[1].DataType = IndComponentType.Other;
component[1].ShowInDynInfo = false;
component[2].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
break;
case "The position opens below the MA value":
component[0].PosPriceDependence = PositionPriceDependence.BuyLowerSelHigher;
component[0].UsePreviousBar = iPrvs;
component[1].DataType = IndComponentType.Other;
component[1].ShowInDynInfo = false;
component[2].DataType = IndComponentType.Other;
component[2].ShowInDynInfo = false;
break;
case "The bar closes below the MA value":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = Close[iBar] < afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = Close[iBar] > afMA[iBar - iPrvs] ? 1 : 0;
}
break;
case "The bar closes above the MA value":
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
component[1].Value[iBar] = Close[iBar] > afMA[iBar - iPrvs] ? 1 : 0;
component[2].Value[iBar] = Close[iBar] < afMA[iBar - iPrvs] ? 1 : 0;
}
break;
default:
break;
}
}
bIsCalculated = true;
}
}
}
Top