AGbayLIB
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © agbay

//@version=5

// @description Changes the timeframe period to the given period and returns the data matrix[cyear, cmonth, cday, chour, cminute_, csecond, cfulltime, copen, cclose, chigh, clow, cvolume] and sets the timeframe to the active time period
library(title = "AGbayLIB") 

export type agSetting
    string symbol = na
    string period = na
    int iperiod = na
    int max_bar_count = 100
    int min_trend_count = 0
    int tenkansen_count = 9
    int kijunsen_count = 26
    int order_block_period = 7
    float threshold=0.0

//@type Contains candle values
//@field timestamp Time value of the candle
//@field year Extracted year value from time
//@field month Extracted month value from time
//@field day Extracted day value from time
//@field hour Extracted hour value from time
//@field minute Extracted minute value from time
//@field second Extracted second value from time
//@field open Open value of candle
//@field close Close value of candle
//@field high High value of candle
//@field low Low value of candle
//@field volume Volume value of candle
//@field trend Calculated trend value of candle
//@field trend_count Calculated trending candle count of active candle
export type agCandle
    int timestamp = 0
    int year = 0
    int month = 0
    int day = 0
    int dayofweek = 0
    int hour = 0
    int minute = 0
    int second = 0
    string fulltime = ""
    int barindex = -1
    float open = 0.0
    float close = 0.0
    float high = 10.0
    float low = 0.0
    float volume  = 0.0
    bool resistantance = false
    bool supply = false
    int trend = 0 
    int trend_count = 0
    bool is_order = false
    bool is_white = false
    bool is_bullish = false

export type agZigZagNode
    agCandle candle=na
    int candle_index=-1
    int trend=0
    agCandle pinnedCandle=na
    int pinned_candle_index=-1


export type agSymbolCandles
    agSetting setting = na
    int count=0
    array<agCandle> candles=na
    array<agZigZagNode> zigzag_nodes=na

// @function: Creates an data_set typed object, copies open,close,high,low,volume,time data into records and also calculates trends of records
// @param symbol Symbol 
// @param period Target time period for returning data
// @param max_bars The historical bar count to be get
// @param opens The historical bars of open data
// @param closes The historical bars of open data
// @param highs The historical bars of open data
// @param lows The historical bars of open data
// @param volumes The historical bars of open data
// @param times The historical bars of open data
// @returns An agSymbolCandles object which contains array of agCandles type which includes [timestamp, year, month, day, hour, minute, second, fulltime, open, close, high, clow, volume, trend] 
export getTimeFrameValues(agSetting setting=na, series float opens, series float closes, series float highs, series float lows, series float volumes, series int times, series int bar_indexes)=>
    max_bars=setting.max_bar_count
    time_period = setting.period
    symbol = setting.symbol
    period = setting.period
    var data = agSymbolCandles.new(setting =  setting, count=max_bars, candles = array.new<agCandle>(max_bars), zigzag_nodes = array.new<agZigZagNode>()) 
    
    int max_bar_count = max_bars
    //data.candles := array.new<data_row>(max_bar_count)
    int max1 = max_bar_count-1
    int max2 = max1-1

    trend = 0
    counter = 0
    float prev_o    = na
    float prev_c    = na
    float prev_h    = na
    float prev_l    = na

    float prev_min    = na
    float prev_max    = na

    bool prev_white = na

    for bi=max1 to 0
        if na(opens[bi])
            continue
        if na(prev_o)
            prev_o := opens[bi]
            prev_c := closes[bi]
            prev_h := highs[bi]
            prev_l :=lows[bi]

            prev_white := prev_o < prev_c ? true : false
            
            prev_min    := prev_o < prev_c ? prev_o : prev_c
            prev_max    := prev_o > prev_c ? prev_o : prev_c


        if bi<0
            continue
        //----- Get Current Candle Values 
        o = opens[bi]
        h = highs[bi]
        l = lows[bi]
        c = closes[bi]
        v = volumes[bi]
        t = times[bi]
        b_index = bar_indexes[bi]
        white = o < c ? true : false
        //------------  { Trend sequential calculation starts here        

        min = o < c ? o : c
        max = o > c ? o : c

        if o==c and prev_o==prev_c
            trend := 0
            counter := 0
        else if prev_min < c and c < prev_h and o!=c
            trend := 0
            counter := 0
        else if prev_c < c and o!=c
            if trend > 0 
                trend := trend + 1
                counter := counter + 1
            else 
                trend := 1
                prev_c := c
                counter := 0
        else if prev_c > c and o!=c
            if trend > 0
                trend := -1
                prev_c := c
                counter := 0
            else  
                trend := trend - 1 
                counter := counter + 1
        prev_o := o
        prev_c := c
        prev_l := o
        prev_h := c
        
        prev_min := min
        prev_max := max
        //------------ } Trend sequential calculation ends here --------         
        // initialize current candle
        ty = year(t)
        tm = month(t)
        td = dayofmonth(t)
        tdw = dayofweek(t)
        th= hour(t)
        tmin = minute(t)
        ts = second(t)
        agCandle ci = agCandle.new()
        ci.timestamp := 0
        ci.year := ty
        ci.month := tm
        ci.day := td
        ci.dayofweek := tdw
        ci.hour := th
        ci.minute := tmin
        ci.second := ts
        ci.fulltime := str.format("{0}-{1}-{2} {3}:{4}:{5}",ty,tm,td,th,tmin,ts)
        ci.barindex := b_index
        ci.open := o
        ci.close := c
        ci.high := h
        ci.low := l
        ci.volume  := v
        ci.trend := trend
        ci.trend_count := counter
        ci.resistantance := false
        ci.supply := false, 
        ci.barindex := b_index
        ci.is_white := white        
        //---- Add candle to the array
        //data.candles.unshift(ci) 
        data.candles.set(bi,ci)
    for bi = data.candles.size()-2 to 0
        if bi<0 
            break
        if not na(data.candles.get(bi)) and not na(data.candles.get(bi+1)) 
            ci = data.candles.get(bi)
            ci2 = data.candles.get(bi+1)
            if ci.trend>0 and ci2.trend<0
                ci.resistantance :=  true
            else    
                ci.resistantance :=  false    
            if not ci2.is_white and ci.is_white and ci.close>ci2.close
                ci.is_order := true
            if ci2.is_white and not ci.is_white
                if ci.high>ci2.high and ci.open<=ci.close and ci.open>=ci2.open and ci.low>ci2.low
                    ci.is_bullish := true
            data.candles.set(bi,ci)   
    [data]



// @function: Searches bearish and bullish order blocks
// @param setting  setting parameters for calculation
// @param oclh  Given [open, close, low, high] series tuple
// @returns  [bullishOB, bearishOB, OB_bull, OB_bull_chigh, OB_bull_clow, OB_bull_avg,  OB_bear, OB_bear_chigh, OB_bear_clow,OB_bear_avg] Tuple
export isBearishBullish(agSetting setting, series float copen, series float cclose, series float clow, series float chigh )=>
    periods=setting.order_block_period  
    threshold = setting.threshold
    ob_period = periods + 1                                                     // Identify location of relevant Order Block candle
    absmove   = ((math.abs(cclose[ob_period] - cclose[1]))/cclose[ob_period]) * 100  // Calculate absolute percent move from potential OB to last candle of subsequent candles
    relmove   = absmove >= threshold    
    // Bullish Order Block Identification
    bullishOB = cclose[ob_period] < copen[ob_period]                              // Determine potential Bullish OB candle (red candle)
    int upcandles  = 0
    for i = 1 to periods
        upcandles := upcandles + (cclose[i] > copen[i]? 1 : 0)                    // Determine color of subsequent candles (must all be green to identify a valid Bearish OB)
    OB_bull      = bullishOB and (upcandles == (periods)) and relmove             // Identification logic (red OB candle & subsequent green candles)
    OB_bull_chigh = OB_bull? chigh[ob_period] : na                                // Determine OB upper limit (Open or High depending on input)
    OB_bull_clow  = OB_bull? clow[ob_period]  : na                                // Determine OB clower limit (Low)
    OB_bull_avg  = (OB_bull_chigh + OB_bull_clow)/2                               // Determine OB middle line
    // Bearish Order Block Identification
    bearishOB = cclose[ob_period] > copen[ob_period]                              // Determine potential Bearish OB candle (green candle)

    int downcandles  = 0
    for i = 1 to periods
        downcandles := downcandles + (cclose[i] < copen[i]? 1 : 0)                // Determine color of subsequent candles (must all be red to identify a valid Bearish OB)

    OB_bear      = bearishOB and (downcandles == (periods)) and relmove           // Identification logic (green OB candle & subsequent green candles)
    OB_bear_chigh = OB_bear? chigh[ob_period] : na                                // Determine OB upper limit (High)
    OB_bear_clow  = OB_bear? clow[ob_period] : na                                 // Determine OB clower limit (Open or Low depending on input)
    OB_bear_avg  = (OB_bear_clow + OB_bear_chigh)/2                               // Determine OB middle line

    [bullishOB, bearishOB, ob_period, OB_bull, OB_bull_chigh, OB_bull_clow, OB_bull_avg,  OB_bear, OB_bear_chigh, OB_bear_clow,OB_bear_avg]






