Candles HTF on Heikin Ashi Chart
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © allanster

//@version=5
indicator(title = "Candles HTF on Heikin Ashi Chart", overlay = false)

// This script enables calling and/or plotting of traditional Candles sources while loaded on Heikin Ashi charts. 
// Thanks to @PineCoders for rounding method: https://www.pinecoders.com/faq_and_code/#how-can-i-round-to-ticks
// Thanks to @BeeHolder for method to regex normalize syminfo.tickerid.

// NOTICE: While this script is meant to be utilized on Heikin Ashi charts it does NOT enable ability to backtest! 
// NOTICE: For more info on why non standard charts cannot be reliably backtested please see:
// https://www.tradingview.com/script/q9laJNG9-Backtesting-on-Non-Standard-Charts-Caution-PineCoders-FAQ/


// === INPUTS ===
resHTF     = input.timeframe(defval = '',                   title = "HTF Resolution",
 tooltip   =     "Only use with timeframes >= current period.")
rpmHTF     = input.string   (defval = '🔮 Live (Repaints)', title = "HTF Uses Mode", options = ['🔮 Live (Repaints)', '✅ Safe (Lag1Look)'], 
 tooltip   =    "IMPORTANT: When using Higher Timeframe with alerts or strategies do NOT choose '🔮 Live (Repaints)' else script behavior will not be reliable!")


// === CANDLES ===
src(_src)  => 
    Close  = close, Open = open, High = high, Low = low, HL2 = hl2, HLC3 = hlc3, HLCC4 = hlcc4, OHLC4 = ohlc4
    Price  =
     _src == 'close' ? Close : _src == 'open' ? Open : _src == 'high'  ? High : _src == 'low' ? Low :
     _src == 'hl2'   ? HL2   : _src == 'hlc3' ? HLC3 : _src == 'hlcc4' ? HLC3 : OHLC4  
    Source = math.round(Price / syminfo.mintick) * syminfo.mintick  // PineCoders method for aligning Pine prices with chart instrument prices


// === HTF ===
tickerID = str.match(syminfo.tickerid, "\\w+:\\w+") // BeeHolder method to normalize "blah syminfo.tickerid blah" -> "syminfo.tickerid"

htf(_i) => [src('open')[_i], src('high')[_i], src('low')[_i], src('close')[_i]]                        // function create tuples 
[OrpY,HrpY,LrpY,CrpY] = request.security(tickerID, resHTF, htf(0))                                     // declare called htf 'Live (Repaints)' tuples  
[OrpN,HrpN,LrpN,CrpN] = request.security(tickerID, resHTF, htf(1), lookahead = barmerge.lookahead_on)  // declare called htf 'Safe (Lag1Look)' tuples
//    NOTICE: For HTF with alerts or strategies ONLY use i = 1 ^ & lookahead = barmerge.lookahead_on else script behavior will not be reliable!


// === PLOTTING ===
preEvalO   = rpmHTF == '🔮 Live (Repaints)' ? OrpY : OrpN  // pre-Evaluate!
preEvalH   = rpmHTF == '🔮 Live (Repaints)' ? HrpY : HrpN  // pre-Evaluate!
preEvalL   = rpmHTF == '🔮 Live (Repaints)' ? LrpY : LrpN  // pre-Evaluate!
preEvalC   = rpmHTF == '🔮 Live (Repaints)' ? CrpY : CrpN  // pre-Evaluate!
barColor   = preEvalC > preEvalO ? #26a69a : #ef5350       // series color
plotcandle(preEvalO, preEvalH, preEvalL, preEvalC, title = "", color = barColor, wickcolor = barColor, bordercolor = barColor) // plot candles