//+------------------------------------------------------------------+
//|                                     Chaikin Money Flow+ Jurik MA |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Transmuted in 2024 by Cagliostro"
#property link      "www.forex-station.com"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 Lime
#property indicator_color3 Blue

// Input parameters
extern int CMF_Period = 20;
extern bool Jurik_visible = false;
extern int Jurik_Length = 5;
extern int Jurik_Phase = 0;

// Indicator buffers
double CMF[];
double CMF_Above[];
double Jurik_MA[];

// Jurik Moving Average function
double JurikMA(double price, double length, double phase, int i)
{
    static double wrk[][10];
    if (ArrayRange(wrk, 0) != Bars) ArrayResize(wrk, Bars);

    int r = Bars - i - 1;
    if (r == 0) {
        for (int k = 0; k < 7; k++) wrk[0][k] = price;
        for (; k < 10; k++) wrk[0][k] = 0;
        return price;
    }

    double len1 = MathMax(MathLog(MathSqrt(0.5 * (length - 1))) / MathLog(2.0) + 2.0, 0);
    double pow1 = MathMax(len1 - 2.0, 0.5);
    double del1 = price - wrk[r - 1][5];
    double del2 = price - wrk[r - 1][6];
    double div = 1.0 / (10.0 + 10.0 * (MathMin(MathMax(length - 10, 0), 100)) / 100);
    int forBar = MathMin(r, 10);

    wrk[r][7] = 0;
    if (MathAbs(del1) > MathAbs(del2)) wrk[r][7] = MathAbs(del1);
    if (MathAbs(del1) < MathAbs(del2)) wrk[r][7] = MathAbs(del2);
    wrk[r][8] = wrk[r - 1][8] + (wrk[r][7] - wrk[r - forBar][7]) * div;

    wrk[r][9] = wrk[r - 1][9] + (2.0 / (MathMax(4.0 * length, 30) + 1.0)) * (wrk[r][8] - wrk[r - 1][9]);
    double dVolty = wrk[r][9] > 0 ? wrk[r][7] / wrk[r][9] : 0;
    dVolty = MathMin(MathMax(dVolty, MathPow(len1, 1.0 / pow1)), 1.0);

    double pow2 = MathPow(dVolty, pow1);
    double len2 = MathSqrt(0.5 * (length - 1)) * len1;
    double Kv = MathPow(len2 / (len2 + 1), MathSqrt(pow2));

    wrk[r][5] = del1 > 0 ? price : price - Kv * del1;
    wrk[r][6] = del2 < 0 ? price : price - Kv * del2;

    double R = MathMax(MathMin(phase, 100), -100) / 100.0 + 1.5;
    double beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2);
    double alpha = MathPow(beta, pow2);

    wrk[r][0] = price + alpha * (wrk[r - 1][0] - price);
    wrk[r][1] = (price - wrk[r][0]) * (1 - beta) + beta * wrk[r - 1][1];
    wrk[r][2] = wrk[r][0] + R * wrk[r][1];
    wrk[r][3] = (wrk[r][2] - wrk[r - 1][4]) * MathPow((1 - alpha), 2) + MathPow(alpha, 2) * wrk[r - 1][3];
    wrk[r][4] = wrk[r - 1][4] + wrk[r][3];

    return wrk[r][4];
}

int init()
{
    IndicatorBuffers(3);
    SetIndexBuffer(0, CMF);
    SetIndexBuffer(1, CMF_Above);
    SetIndexBuffer(2, Jurik_MA);
    SetIndexStyle(0, DRAW_LINE); 
    SetIndexStyle(1, DRAW_LINE); 
    SetIndexStyle(2, Jurik_visible ? DRAW_LINE : DRAW_NONE); 
    IndicatorShortName("CMF + Jurik");

    SetIndexDrawBegin(0, CMF_Period);
    SetIndexDrawBegin(1, CMF_Period);
    SetIndexDrawBegin(2, CMF_Period);

    return (0);
}

int deinit()
{
    return (0);
}

int start()
{
    int shift, limit, counted_bars = IndicatorCounted();

    if (Bars <= CMF_Period) return (0);

    // Initial zero
    if (counted_bars < 1)
    {
        for (int i = 1; i <= CMF_Period; i++) {
            CMF[Bars - i] = 0.0;
            CMF_Above[Bars - i] = EMPTY_VALUE;
            Jurik_MA[Bars - i] = 0.0;
        }
    }

    if (counted_bars > 0) limit = Bars - counted_bars;
    if (counted_bars == 0) limit = Bars - CMF_Period - 1;

    for (shift = limit; shift >= 0; shift--)
    {
        double dN_Sum = 0.0;
        double Volume_Sum = 0.0;
        for (int j = 0; j < CMF_Period - 1; j++)
        {
            Volume_Sum += Volume[shift + j];
            if ((High[shift + j] - Low[shift + j]) > 0)
                dN_Sum += Volume[shift + j] * (Close[shift + j] - Open[shift + j]) / (High[shift + j] - Low[shift + j]);
        }
        double cmf_value = dN_Sum / Volume_Sum;

        CMF[shift] = cmf_value;
        Jurik_MA[shift] = Jurik_visible ? JurikMA(cmf_value, Jurik_Length, Jurik_Phase, shift) : cmf_value;

        // Overlay green color only where CMF is above zero
        if (CMF[shift] > 0) {
            CMF_Above[shift] = CMF[shift];
            if (shift < Bars - 1 && CMF[shift + 1] <= 0) {
                CMF[shift + 1] = 0;  // Ensure smooth transition
                CMF_Above[shift + 1] = 0;  // Start green segment at zero
            }
        } else {
            if (shift < Bars - 1 && CMF[shift + 1] > 0) {
                CMF_Above[shift] = 0;  // Ensure smooth transition
                CMF[shift] = 0;  // End green segment at zero
            } else {
                CMF_Above[shift] = EMPTY_VALUE;
            }
        }
    }

    return (0);
}
