    #include "sierrachart.h"

    SCSFExport scsf_StochasticCrossover(SCStudyInterfaceRef sc)
    {
        SCSubgraphRef Subgraph_Buy = sc.Subgraph[0];
        SCSubgraphRef Subgraph_Sell = sc.Subgraph[1];
        SCSubgraphRef Subgraph_FastD = sc.Subgraph[2];
        SCFloatArrayRef Subgraph_SlowK = Subgraph_FastD.Arrays[0];
        SCFloatArrayRef Subgraph_SlowD = Subgraph_FastD.Arrays[1];

        SCInputRef Input_FastK = sc.Input[0];
        SCInputRef Input_FastD = sc.Input[1];
        SCInputRef Input_SlowD = sc.Input[2];
        SCInputRef Input_Line1 = sc.Input[3];
        SCInputRef Input_Line2 = sc.Input[4];
        SCInputRef Input_UseBuySell = sc.Input[5];
        SCInputRef Input_ArrowOffsetPercentage = sc.Input[6];

        if (sc.SetDefaults)
        {
            // Set the configuration and defaults

            sc.GraphName = "Stochastic Crossover System";
            sc.StudyDescription = "This is an example of a Stochastic Crossover Study System.";

            Subgraph_Buy.Name = "Buy";
            Subgraph_Buy.PrimaryColor = RGB_COLOR(0, 255, 0);   // green
            Subgraph_Buy.DrawStyle = DRAWSTYLE_ARROW_UP;
            Subgraph_Buy.LineWidth = 2; //Width of arrow

            Subgraph_Sell.Name = "Sell";
            Subgraph_Sell.DrawStyle = DRAWSTYLE_ARROW_DOWN;
            Subgraph_Sell.PrimaryColor = RGB_COLOR(255, 0, 0);  // red
            Subgraph_Sell.LineWidth = 2; //Width of arrow

            Input_FastK.Name = "Fast %K Length";
            Input_FastK.SetInt(10);

            Input_FastD.Name = "Fast %D Length";
            Input_FastD.SetInt(3);

            Input_SlowD.Name = "Slow %D Length";
            Input_SlowD.SetInt(3);

            Input_Line1.Name = "Line 1 Value";
            Input_Line1.SetFloat(70);

            Input_Line2.Name = "Line 2 Value";
            Input_Line2.SetFloat(30);

            Input_UseBuySell.Name = "Use Buy/Sell Lines";
            Input_UseBuySell.SetYesNo(true);

            Input_ArrowOffsetPercentage.Name = "Arrow Offset Percentage";
            Input_ArrowOffsetPercentage.SetInt(3);

            sc.GraphRegion = 0; //Main chart region
            sc.DrawZeros= 0;

            sc.AutoLoop = 1;

            return;
        }

        // Do data processing

        // The following line calculates the stochastic.
        // The 3 stochastic lines are placed in sc.Subgraph[2].Data, sc.Subgraph[2].Arrays[0] and sc.Subgraph[2].Arrays[1].
        sc.Stochastic(sc.BaseDataIn, Subgraph_FastD, Input_FastK.GetInt(), Input_FastD.GetInt(), Input_SlowD.GetInt(), MOVAVGTYPE_SIMPLE);

        int Index=sc.Index; //Sets the variable Index to the current Bar index.

        /* This is used further down to position a buy or sell arrow below or above a price bar so it does not touch exactly the low or high.  This is not necessary.  It is only for appearance purposes.*/
            float Offset=(sc.High[Index] -sc.Low[Index] )*(Input_ArrowOffsetPercentage.GetInt() * 0.01f);

        /*This code is not currently used:

        //Calculate crossing point
        float CrossY = 0.0f;
        float p1x, p2x, p3x, p4x;
        float p1y, p2y, p3y, p4y;

        p1x = p3x = (float)(Index - 1);
        p2x = p4x = (float)(Index);

        if(SlowK[Index] > SlowD[Index])
        {
            p1y = SlowD[Index - 1];
            p2y = SlowD[Index];
            p3y = SlowK[Index - 1];
            p4y = SlowK[Index];
        }
        else
        {
            p1y = SlowK[Index - 1];
            p2y = SlowK[Index];
            p3y = SlowD[Index - 1];
            p4y = SlowD[Index];
        }

        float t
            = ((p4x - p3x) * (p1y - p3y) - (p4y - p3y) * (p1x - p3x)) /
            (float)((p4y - p3y) * (p2x - p1x) - (p4x - p3x) * (p2y - p1y));

        CrossY = p1y + (t * (p2y - p1y));

        */

        /*If Slow %k crosses Slow %d from the bottom AND %k is below 30*/
        if (sc.CrossOver( Subgraph_SlowK,  Subgraph_SlowD, Index) == CROSS_FROM_BOTTOM &&
            (!Input_UseBuySell.GetYesNo() || Subgraph_SlowK[Index] < Input_Line2.GetFloat()))
        {

            //Place an Up arrow below the low of the current bar.
            Subgraph_Buy[Index] = sc.Low[Index] - Offset;

            /*Make sure we have no down arrow from a prior calculation.  It is important to set this to zero since we perform calculations on the same bar many times while the bar is being updated and we may have had a prior sell signal when we now have a buy signal or no signal.*/
            Subgraph_Sell[Index] = 0;
        }

        /*If Slow %k crosses Slow %d from the top AND %k is over 70*/
        else if  (sc.CrossOver(Subgraph_SlowK, Subgraph_SlowD, Index) == CROSS_FROM_TOP &&
            (!Input_UseBuySell.GetYesNo() || Subgraph_SlowK[Index] > Input_Line1.GetFloat()))
        {
            Subgraph_Sell[Index] = sc.High[Index] + Offset;
            Subgraph_Buy[Index] = 0;
        }
        else
        {
            Subgraph_Buy[Index] = 0;
            Subgraph_Sell[Index] = 0;
        }
    }

    /************************************************************************/
    SCSFExport scsf_MACDCrossoverSystem(SCStudyInterfaceRef sc)
    {
        SCSubgraphRef Subgraph_Buy = sc.Subgraph[0];
        SCSubgraphRef Subgraph_Sell = sc.Subgraph[1];
        SCSubgraphRef Subgraph_MACDData = sc.Subgraph[2];

        SCInputRef Input_InputData  = sc.Input[0];
        SCInputRef Input_FastLength     = sc.Input[1];
        SCInputRef Input_SlowLength     = sc.Input[2];
        SCInputRef Input_MACDLength     = sc.Input[3];
        SCInputRef Input_MAType     = sc.Input[4];
        SCInputRef Input_OffsetPercentInput = sc.Input[5];

        if (sc.SetDefaults)
        {
            // Set the configuration and defaults

            sc.GraphName = "MACD Crossover System";

            sc.GraphRegion = 0; //Main chart region

            sc.AutoLoop = 1;

            Subgraph_Buy.Name = "Buy";
            Subgraph_Buy.PrimaryColor = RGB_COLOR(0, 255, 0);   // green
            Subgraph_Buy.DrawStyle = DRAWSTYLE_ARROW_UP;
            Subgraph_Buy.LineWidth = 2; //Width of arrow
            Subgraph_Buy.DrawZeros = 0;

            Subgraph_Sell.Name = "Sell";
            Subgraph_Sell.DrawStyle = DRAWSTYLE_ARROW_DOWN;
            Subgraph_Sell.PrimaryColor = RGB_COLOR(255, 0, 0);  // red
            Subgraph_Sell.LineWidth = 2; //Width of arrow
            Subgraph_Sell.DrawZeros = 0;

            Input_InputData.Name = "Input Data";
            Input_InputData.SetInputDataIndex(SC_LAST);

            Input_FastLength.Name ="Fast Moving Average Length";
            Input_FastLength.SetInt(12);
            Input_FastLength.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_SlowLength.Name = "Slow Moving Average Length";
            Input_SlowLength.SetInt(26);
            Input_SlowLength.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_MACDLength.Name = "MACD Moving Average Length";
            Input_MACDLength.SetInt(9);
            Input_MACDLength.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_MAType.Name = "Moving Average Type";
            Input_MAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL);

            Input_OffsetPercentInput.Name = "Arrow Offset Percentage";
            Input_OffsetPercentInput.SetFloat(8);

            return;
        }

        // Do data processing
        sc.DataStartIndex = max(Input_FastLength.GetInt(), Input_SlowLength.GetInt()) + Input_MACDLength.GetInt() - 1;

        sc.MACD(sc.BaseDataIn[Input_InputData.GetInputDataIndex()], Subgraph_MACDData, sc.Index, Input_FastLength.GetInt(), Input_SlowLength.GetInt(), Input_MACDLength.GetInt(), Input_MAType.GetInt());

        if (sc.Index < sc.DataStartIndex)
            return;

        float Range = (sc.High[sc.Index] - sc.Low[sc.Index]);

        float OffsetPercent = Input_OffsetPercentInput.GetFloat() * 0.01f;

        SCFloatArrayRef MACDLine = Subgraph_MACDData.Data;
        SCFloatArrayRef MACDMovingAverageLine = Subgraph_MACDData.Arrays[2];

        if (sc.CrossOver( MACDLine, MACDMovingAverageLine) == CROSS_FROM_BOTTOM)
        {

            Subgraph_Buy[sc.Index] = sc.Low[sc.Index] - OffsetPercent * Range;

            Subgraph_Sell[sc.Index] = 0;
        }
        else if  (sc.CrossOver(Subgraph_MACDData, Subgraph_MACDData.Arrays[2]) == CROSS_FROM_TOP)
        {
            Subgraph_Sell[sc.Index] = sc.High[sc.Index] + OffsetPercent * Range;
            Subgraph_Buy[sc.Index] = 0;
        }
        else
        {
            Subgraph_Buy[sc.Index] = 0;
            Subgraph_Sell[sc.Index] = 0;
        }
    }

    /************************************************************************/

    SCSFExport scsf_MACDZeroCrossOverSystem(SCStudyInterfaceRef sc)
    {
        SCSubgraphRef Subgraph_Buy = sc.Subgraph[0];
        SCSubgraphRef Subgraph_Sell = sc.Subgraph[1];
        SCSubgraphRef Subgraph_MACDData = sc.Subgraph[2];

        SCInputRef Input_InputData  = sc.Input[0];
        SCInputRef Input_FastLen        = sc.Input[1];
        SCInputRef Input_SlowLen        = sc.Input[2];
        SCInputRef Input_MACDLen        = sc.Input[3];
        SCInputRef Input_MAType     = sc.Input[4];
        SCInputRef Input_OffsetPercentInput = sc.Input[5];

        if (sc.SetDefaults)
        {
            // Set the configuration and defaults

            sc.GraphName = "MACD Zero Cross Over System";

            sc.GraphRegion = 0; //Main chart region

            sc.AutoLoop = 1;

            Subgraph_Buy.Name = "Buy";
            Subgraph_Buy.PrimaryColor = RGB_COLOR(0, 255, 0);   // green
            Subgraph_Buy.DrawStyle = DRAWSTYLE_ARROW_UP;
            Subgraph_Buy.LineWidth = 2; //Width of arrow
            Subgraph_Buy.DrawZeros = 0;

            Subgraph_Sell.Name = "Sell";
            Subgraph_Sell.DrawStyle = DRAWSTYLE_ARROW_DOWN;
            Subgraph_Sell.PrimaryColor = RGB_COLOR(255, 0, 0);  // red
            Subgraph_Sell.LineWidth = 2; //Width of arrow
            Subgraph_Sell.DrawZeros = 0;

            Input_InputData.Name = "Input Data";
            Input_InputData.SetInputDataIndex(SC_LAST);

            Input_FastLen.Name ="Fast Moving Average Length";
            Input_FastLen.SetInt(12);
            Input_FastLen.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_SlowLen.Name = "Slow Moving Average Length";
            Input_SlowLen.SetInt(26);
            Input_SlowLen.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_MACDLen.Name = "MACD Moving Average Length";
            Input_MACDLen.SetInt(9);
            Input_MACDLen.SetIntLimits(1,MAX_STUDY_LENGTH);

            Input_MAType.Name = "Moving Average Type";
            Input_MAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL);

            Input_OffsetPercentInput.Name = "Arrow Offset Percentage";
            Input_OffsetPercentInput.SetFloat(8);

            return;
        }

        // Do data processing
        sc.MACD(sc.BaseDataIn[Input_InputData.GetInputDataIndex()], Subgraph_MACDData, sc.Index, Input_FastLen.GetInt(), Input_SlowLen.GetInt(), Input_MACDLen.GetInt(), Input_MAType.GetInt());

        float Range = (sc.High[sc.Index] - sc.Low[sc.Index]);

        float OffsetPercent = Input_OffsetPercentInput.GetFloat() * 0.01f;

        if (sc.CrossOver( Subgraph_MACDData.Arrays[8],  Subgraph_MACDData.Arrays[2]) == CROSS_FROM_TOP)
        {

            Subgraph_Buy[sc.Index] = sc.Low[sc.Index] - OffsetPercent * Range;

            Subgraph_Sell[sc.Index] = 0;
        }
        else if  (sc.CrossOver( Subgraph_MACDData.Arrays[8], Subgraph_MACDData.Arrays[2]) == CROSS_FROM_BOTTOM)
        {
            Subgraph_Sell[sc.Index] = sc.High[sc.Index] + OffsetPercent * Range;
            Subgraph_Buy[sc.Index] = 0;
        }
        else
        {
            Subgraph_Buy[sc.Index] = 0;
            Subgraph_Sell[sc.Index] = 0;
        }
    }

    /************************************************************************/