// The top of every source code file must include this required line
#include "sierrachart.h"
// #include "scstudyfunctions.h"
// #include "scstudyfunctions.cpp"

//DLL Name also required for initialization; can be SCDLLInit instead of SCDLLName.
//format: SCDLLName("Your DLL Name Here")

SCDLLName("FlexMACD")

/*==========================================================================*/
SCFloatArrayRef SimpleMovAvgSkipZeros_S(SCFloatArrayRef In, SCFloatArrayRef Out, int Index, int Length)
{
	int count = 0;
	float Sum = 0.0f;

	if (Length > Index + 1)
		Length = Index + 1;

	for(int ArrayIndex= Index - Length + 1; ArrayIndex <= Index; ArrayIndex++)
	{
		float Value = In[ArrayIndex];

		if (Value != 0.0f)
		{
			Sum += Value;
			count++;
		}
	}

	if (count > 0)
	{
		Out[Index] = Sum / count;
	}
	else
	{
		Out[Index] = 0.0f;
	}

	return Out;
}


/*==========================================================================*/
SCFloatArrayRef MovingAvg(SCStudyGraphRef sc, SCFloatArrayRef In, SCFloatArrayRef Out, unsigned int MovingAverageType, int Index, int Length)
{
	
	if (Length < 1 || Index < 0)
        return Out;
			
	if (Length == 1 || Index == 0)
	{ 
        Out[Index] = In[Index];
		return Out;	
	}	
	
	
	switch (MovingAverageType)
	{
		case MOVAVGTYPE_EXPONENTIAL:
		return sc.ExponentialMovAvg(In, Out, Index, Length);
		
		case MOVAVGTYPE_LINEARREGRESSION:
		return sc.LinearRegressionIndicator(In, Out, Index, Length);
		
		default:  // Unknown moving average type
		case MOVAVGTYPE_SIMPLE:
		return sc.SimpleMovAvg(In, Out, Index, Length);
		
		case MOVAVGTYPE_WEIGHTED:
		return sc.WeightedMovingAverage(In, Out, Index, Length);
		
		case MOVAVGTYPE_WILDERS:
		return sc.WildersMovingAverage(In, Out, Index, Length);

		case MOVAVGTYPE_SIMPLE_SKIP_ZEROS:
		return SimpleMovAvgSkipZeros_S(In, Out, Index, Length);

		case MOVAVGTYPE_SMOOTHED:
		return sc.SmoothedMovingAverage(In, Out, Index, Length);

	}
}

SCFloatArrayRef Flex_MACD(SCStudyGraphRef sc, SCFloatArrayRef In, SCFloatArrayRef FastMAOut, SCFloatArrayRef SlowMAOut, 
				SCFloatArrayRef MACDOut, SCFloatArrayRef SigMAOut, SCFloatArrayRef MACDHistOut,
				int Index, int FastMALength, int SlowMALength, int SigMALength, 
				int FastMovAvgType,   int SlowMovAvgType,   int SigMovAvgType )
{
	MovingAvg(sc,In,FastMAOut,FastMovAvgType,Index,FastMALength);
	MovingAvg(sc,In,SlowMAOut,SlowMovAvgType,Index,SlowMALength);
	MACDOut[Index] = FastMAOut[Index] - SlowMAOut[Index];

	MovingAvg(sc,MACDOut,SigMAOut, SigMovAvgType,Index,SigMALength);
	MACDHistOut[Index] = MACDOut[Index] - SigMAOut[Index];
	

	return MACDOut;
}



SCSFExport scsf_FlexMACD(SCStudyInterfaceRef sc)
{

	SCSubgraphRef MACD		= sc.Subgraph[0];
	SCSubgraphRef Signal	= sc.Subgraph[1];	
	SCSubgraphRef Histogram	= sc.Subgraph[2];
	SCSubgraphRef ZeroLine	= sc.Subgraph[3];	

	SCSubgraphRef MACDTemp	= sc.Subgraph[4];	



	
	SCInputRef InputData		= sc.Input[0];
	SCInputRef FastLength		= sc.Input[1];
	SCInputRef SlowLength		= sc.Input[2];
	SCInputRef SignalLength		= sc.Input[3];
	SCInputRef FastMAType 		= sc.Input[4];
	SCInputRef SlowMAType 		= sc.Input[5];
	SCInputRef SignalMAType 	= sc.Input[6];
	SCInputRef InvertMACD 		= sc.Input[7];
	SCInputRef InvertSig 		= sc.Input[8];
	SCInputRef InvertHist 		= sc.Input[9];	
	SCInputRef InvertStudy		= sc.Input[10];	

	
	if(sc.SetDefaults)
	{
		sc.GraphName = "Flex MACD";
		sc.AutoLoop					= 1;

		sc.GraphRegion				= 1;
		sc.ValueFormat				= 3;
		
		
		
		MACD.Name = "Main";
		MACD.DrawStyle = DRAWSTYLE_LINE;
		MACD.DrawZeros = true;
		MACD.PrimaryColor = RGB(0,128,255);
		MACD.LineWidth = 2;
		
		Signal.Name	= "Sig";
		Signal.DrawStyle = DRAWSTYLE_LINE;
		Signal.DrawZeros = true;
		Signal.PrimaryColor = RGB(255,0,0);
		Signal.LineWidth = 2;		

		Histogram.Name = "Hist";
		Histogram.DrawStyle = DRAWSTYLE_FILLTOZERO_TRANSPARENT;
//		Histogram.DrawStyle = DRAWSTYLE_FILLTOZERO;		
		Histogram.DrawZeros = true;	
		Histogram.LineStyle = LINESTYLE_SOLID;	
		Histogram.PrimaryColor = RGB(0,128,0);
		Histogram.SecondaryColor = RGB(220,0,0);	
		Histogram.SecondaryColorUsed = 1;
		Histogram.AutoColoring = AUTOCOLOR_POSNEG;
		Histogram.LineWidth = 2;	
		
		ZeroLine.Name = "ZeroLine";
		ZeroLine.DrawStyle = DRAWSTYLE_LINE;
		ZeroLine.LineStyle = LINESTYLE_DASH;			
		ZeroLine.DrawZeros = true;
		ZeroLine.PrimaryColor = RGB(128,128,0);
		ZeroLine.LineWidth = 0;
		ZeroLine.DisplayNameValueInWindowsFlags = 0;	
		ZeroLine.DisplayNameValueInDataLine = 0;
		
	
		unsigned short DisplayOrder = 1;
	
		InputData.Name = "Input Data";
		InputData.SetInputDataIndex(SC_LAST);
		InputData.DisplayOrder = DisplayOrder++;

		FastLength.Name = "Fast Moving Average Length";
		FastLength.SetInt(12);  
		FastLength.SetIntLimits(1,MAX_STUDY_LENGTH);
		FastLength.DisplayOrder = DisplayOrder++;

		SlowLength.Name = "Slow Moving Average Length";
		SlowLength.SetInt(26);  
		SlowLength.SetIntLimits(1,MAX_STUDY_LENGTH);
		SlowLength.DisplayOrder = DisplayOrder++;

		SignalLength.Name = "Signal Moving Average Length";
		SignalLength.SetInt(9);   
		SignalLength.SetIntLimits(1,MAX_STUDY_LENGTH);
		SignalLength.DisplayOrder = DisplayOrder++;
		
	
		FastMAType.Name = "Fast Moving Average Type";
		FastMAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL);
		FastMAType.DisplayOrder = DisplayOrder++;
		
		SlowMAType.Name = "Slow Moving Average Type";
		SlowMAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL);		
		SlowMAType.DisplayOrder = DisplayOrder++;
		
		SignalMAType.Name = "Signal Moving Average Type";
		SignalMAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL);		
		SignalMAType.DisplayOrder = DisplayOrder++;		
			
			
		InvertMACD.Name ="Invert MACD";
		InvertMACD.SetCustomInputStrings("No;Yes");
		InvertMACD.SetCustomInputIndex(0);	
		InvertMACD.DisplayOrder = DisplayOrder++;
		
		InvertSig.Name ="Invert Signal";
		InvertSig.SetCustomInputStrings("No;Yes");
		InvertSig.SetCustomInputIndex(0);	
		InvertSig.DisplayOrder = DisplayOrder++;
		
		InvertHist.Name ="Invert Histogram";
		InvertHist.SetCustomInputStrings("No;Yes");
		InvertHist.SetCustomInputIndex(0);	
		InvertHist.DisplayOrder = DisplayOrder++;

		InvertStudy.Name ="Invert Study";
		InvertStudy.SetYesNo(0);
		InvertStudy.DisplayOrder = DisplayOrder++;

		
		sc.FreeDLL = 0; 
	
		return;
	}

	if (sc.HideStudy)
		return;

	
	int FastL = FastLength.GetInt();
	int SlowL = SlowLength.GetInt();
	int SigL = SignalLength.GetInt();	

	int FastTypeMA = FastMAType.GetInt();
	int SlowTypeMA = SlowMAType.GetInt();
	int SigTypeMA = SignalMAType.GetInt();	
	

	Flex_MACD(sc, sc.BaseDataIn[InputData.GetInputDataIndex()], MACDTemp.Arrays[0], MACDTemp.Arrays[1], 
			MACDTemp, MACDTemp.Arrays[2], MACDTemp.Arrays[3], 
			sc.Index, FastL, SlowL, SigL, 	
			FastTypeMA, SlowTypeMA, SigTypeMA
		); 
	
	
	sc.DataStartIndex = min(FastLength.GetInt(), SlowLength.GetInt()) + 1;
	
	
	if(sc.Index < sc.DataStartIndex)
	{	
		MACD[sc.Index]		= 0;
		Signal[sc.Index]	= 0;
		Histogram[sc.Index]	= 0;	
		
		return;
	}
	
	
	
	MACD[sc.Index]		= MACDTemp[sc.Index];
	Signal[sc.Index]	= MACDTemp.Arrays[2][sc.Index];
	Histogram[sc.Index]	= MACDTemp.Arrays[3][sc.Index];


	
	if(InvertMACD.GetIndex() == 1)
		MACD[sc.Index]		= -MACDTemp[sc.Index];

	
	if(InvertSig.GetIndex() == 1)
		Signal[sc.Index]	= -MACDTemp.Arrays[2][sc.Index];

	
	if(InvertHist.GetIndex() == 1)
		Histogram[sc.Index]	= -MACDTemp.Arrays[3][sc.Index];

	
		
	if(InvertStudy.GetYesNo())
	{
	MACD[sc.Index]		= -MACD[sc.Index];
	Signal[sc.Index]	= -Signal[sc.Index];
	Histogram[sc.Index]	= -Histogram[sc.Index];
	}
	
	ZeroLine[sc.Index]	= 0;	
	
}
/************************************************************/