// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ //@version=5 strategy("nehroranay OCC TDFI Strategy",overlay = true,process_orders_on_close = true) gr_str="Strategy Settings" slDist=input.float(0.5,"Distance SL points",0,group = gr_str) tpRR=input.float(3.0,"TakeProfit RR",0,group = gr_str) islong=input(true,"Long Entry",group=gr_str) isshort=input(true,"Short Entry",group=gr_str) gr_bp='Backtest Period' i_startTime = input.time(defval = timestamp("01 Jan 2021 00:00 +0000"), title = "Backtest Start Time",group=gr_bp,inline='bs') i_endTime = input.time(defval = timestamp("01 Dec 2023 00:00 +0000"), title = "Backtest End Time",group=gr_bp,inline='be') time_cond = (time >= i_startTime) and (time <= i_endTime) //OCC{ // === INPUTS === gr_occ1="OCC1" useRes = input(defval=true, title='Use Alternate Resolution?',group = gr_occ1) intRes = input(defval=3, title='Multiplier for Alernate Resolution',group = gr_occ1) stratRes = timeframe.ismonthly ? str.tostring(timeframe.multiplier * intRes, '###M') : timeframe.isweekly ? str.tostring(timeframe.multiplier * intRes, '###W') : timeframe.isdaily ? str.tostring(timeframe.multiplier * intRes, '###D') : timeframe.isintraday ? str.tostring(timeframe.multiplier * intRes, '####') : '60' // basisType = input.string(defval='SMMA', title='MA Type: ', options=['SMA', 'EMA', 'DEMA', 'TEMA', 'WMA', 'VWMA', 'SMMA', 'HullMA', 'LSMA', 'ALMA', 'SSMA', 'TMA'],group = gr_occ1) basisLen = input.int(defval=8, title='MA Period', minval=1,group = gr_occ1) offsetSigma = input.int(defval=6, title='Offset for LSMA / Sigma for ALMA', minval=0,group = gr_occ1) offsetALMA = input.float(defval=0.85, title='Offset for ALMA', minval=0, step=0.01,group = gr_occ1) delayOffset = input.int(defval=0, title='Delay Open/Close MA (Forces Non-Repainting)', minval=0, step=1,group = gr_occ1) // // // uDiv = input(false, 'Show Divergence Channel') // multi = input.float(0.5, minval=0.0, maxval=3.0, title='Divergence Channel Width Factor (Stddev)') // uHid = input(false, title='Show Hidden Divergence') // uReg = input(false, title='Show Regular Divergence') // uDiv := uReg or uHid ? uDiv : false // === /INPUTS === // - variant(type, src, len) // Returns MA input selection variant, default to SMA if blank or typo. // Returns MA input selection variant, default to SMA if blank or typo. variant(type, src, len, offSig, offALMA) => v1 = ta.sma(src, len) // Simple v2 = ta.ema(src, len) // Exponential v3 = 2 * v2 - ta.ema(v2, len) // Double Exponential v4 = 3 * (v2 - ta.ema(v2, len)) + ta.ema(ta.ema(v2, len), len) // Triple Exponential v5 = ta.wma(src, len) // Weighted v6 = ta.vwma(src, len) // Volume Weighted v7 = 0.0 sma_1 = ta.sma(src, len) // Smoothed v7 := na(v7[1]) ? sma_1 : (v7[1] * (len - 1) + src) / len v8 = ta.wma(2 * ta.wma(src, len / 2) - ta.wma(src, len), math.round(math.sqrt(len))) // Hull v9 = ta.linreg(src, len, offSig) // Least Squares v10 = ta.alma(src, len, offALMA, offSig) // Arnaud Legoux v11 = ta.sma(v1, len) // Triangular (extreme smooth) // SuperSmoother filter // © 2013 John F. Ehlers a1 = math.exp(-1.414 * 3.14159 / len) b1 = 2 * a1 * math.cos(1.414 * 3.14159 / len) c2 = b1 c3 = -a1 * a1 c1 = 1 - c2 - c3 v12 = 0.0 v12 := c1 * (src + nz(src[1])) / 2 + c2 * nz(v12[1]) + c3 * nz(v12[2]) type == 'EMA' ? v2 : type == 'DEMA' ? v3 : type == 'TEMA' ? v4 : type == 'WMA' ? v5 : type == 'VWMA' ? v6 : type == 'SMMA' ? v7 : type == 'HullMA' ? v8 : type == 'LSMA' ? v9 : type == 'ALMA' ? v10 : type == 'TMA' ? v11 : type == 'SSMA' ? v12 : v1 // security wrapper for repeat calls reso(exp, use, res) => security_1 = request.security(syminfo.tickerid, res, exp, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on) use ? security_1 : exp // === SERIES SETUP === closeSeries = variant(basisType, close[delayOffset], basisLen, offsetSigma, offsetALMA) openSeries = variant(basisType, open[delayOffset], basisLen, offsetSigma, offsetALMA) closeOpenAvg = (closeSeries + openSeries) / 2 // === /SERIES === // Get Alternate Open/Close Series MAs, if selected. closeSeriesAlt = reso(closeSeries, useRes, stratRes) openSeriesAlt = reso(openSeries, useRes, stratRes) // // xlong = ta.crossover(closeSeriesAlt, openSeriesAlt) // xshort = ta.crossunder(closeSeriesAlt, openSeriesAlt) // longCond = xlong // alternative: longCond[1]? false : (xlong or xlong[1]) and close>closeSeriesAlt and close>=open // shortCond = xshort // alternative: shortCond[1]? false : (xshort or xshort[1]) and close openSeriesAlt ? color.green : color.red // hline(0, color=color.gray, linestyle=hline.style_dashed) // plot(pcd, title='OCC Difference Factor', color=trendColour, linewidth=1, style=plot.style_area, transp=80) // plot(pcd, title='OCC Difference Factor', color=trendColour, linewidth=2, style=plot.style_line, transp=20) // plotshape(alert, title='OCC Alert Plot', color=trendColour, style=shape.circle, location=location.bottom, size=size.auto, transp=0) // // || Functions: // f_top_fractal(_src) => // _src[4] < _src[2] and _src[3] < _src[2] and _src[2] > _src[1] and _src[2] > _src[0] // f_bot_fractal(_src) => // _src[4] > _src[2] and _src[3] > _src[2] and _src[2] < _src[1] and _src[2] < _src[0] // f_fractalize(_src) => // f_bot_fractal__1 = f_bot_fractal(_src) // f_top_fractal(_src) ? 1 : f_bot_fractal__1 ? -1 : 0 // // === /BASE FUNCTIONS === // rsi_high = pcd // rsi_low = pcd // offset_ = multi * ta.stdev(pcd, 20) // fractal_top_rsi = f_fractalize(rsi_high) > 0 ? rsi_high[2] : na // fractal_bot_rsi = f_fractalize(rsi_low) < 0 ? rsi_low[2] : na // rsi_high_prev = ta.valuewhen(fractal_top_rsi, rsi_high[2], 1) // rsi_high_price = ta.valuewhen(fractal_top_rsi, high[2], 1) // rsi_low_prev = ta.valuewhen(fractal_bot_rsi, rsi_low[2], 1) // rsi_low_price = ta.valuewhen(fractal_bot_rsi, low[2], 1) // regular_bearish_div = fractal_top_rsi and high[2] > rsi_high_price and rsi_high[2] < rsi_high_prev and rsi_high > 0 // hidden_bearish_div = fractal_top_rsi and high[2] < rsi_high_price and rsi_high[2] > rsi_high_prev and rsi_high > 0 // regular_bullish_div = fractal_bot_rsi and low[2] < rsi_low_price and rsi_low[2] > rsi_low_prev and rsi_low < 0 // hidden_bullish_div = fractal_bot_rsi and low[2] > rsi_low_price and rsi_low[2] < rsi_low_prev and rsi_low < 0 // // plot(title='RSI High', series=uDiv ? rsi_high : na, color=color.new(color.gray, 0)) // // plot(title='RSI Low', series=uDiv ? rsi_low : na, color=color.new(color.gray, 0)) // // plot(title='RSI H F', series=uDiv ? fractal_top_rsi + offset_ : na, color=color.new(color.red, 0), offset=-2) // // plot(title='RSI L F', series=uDiv ? fractal_bot_rsi - offset_ : na, color=color.new(color.green, 0), offset=-2) // // plot(title='RSI H D', series=uDiv ? fractal_top_rsi + offset_ : na, style=plot.style_circles, color=regular_bearish_div and uReg or hidden_bearish_div and uHid ? color.maroon : color.gray, linewidth=3, offset=-2) // // plot(title='RSI L D', series=uDiv ? fractal_bot_rsi - offset_ : na, style=plot.style_circles, color=regular_bullish_div and uReg or hidden_bullish_div and uHid ? color.green : color.gray, linewidth=3, offset=-2) // // plotshape(title='+RBD', series=regular_bearish_div and uReg ? rsi_high[2] + offset_ : na, text='Regular', style=shape.labeldown, location=location.absolute, color=color.new(color.maroon, 0), textcolor=color.new(color.white, 0), offset=-2) // // plotshape(title='+HBD', series=hidden_bearish_div and uHid ? rsi_high[2] + offset_ : na, text='hidden', style=shape.labeldown, location=location.absolute, color=color.new(color.maroon, 0), textcolor=color.new(color.white, 0), offset=-2) // // plotshape(title='-RBD', series=regular_bullish_div and uReg ? rsi_low[2] - offset_ : na, text='Regular', style=shape.labelup, location=location.absolute, color=color.new(color.green, 0), textcolor=color.new(color.white, 0), offset=-2) // // plotshape(title='-HBD', series=hidden_bullish_div and uHid ? rsi_low[2] - offset_ : na, text='hidden', style=shape.labelup, location=location.absolute, color=color.new(color.green, 0), textcolor=color.new(color.white, 0), offset=-2) // // // === ALARM ALERTS for TradingView ALARM sub-system (server based) === // // alertcondition(alert, message='OCC BothCond', title='OCC BothCond') // // alertcondition(longCond, message='OCC LongCond', title='OCC LongCond') // // alertcondition(shortCond, message='OCC ShortCond', title='OCC ShortCond') //OCC} //OCC2{ gr_occ2="OCC2" useRes2 = input(defval=true, title='Use Alternate Resolution?',group = gr_occ2) intRes2 = input(defval=3, title='Multiplier for Alernate Resolution',group = gr_occ2) stratRes2 = timeframe.ismonthly ? str.tostring(timeframe.multiplier * intRes2, '###M') : timeframe.isweekly ? str.tostring(timeframe.multiplier * intRes2, '###W') : timeframe.isdaily ? str.tostring(timeframe.multiplier * intRes2, '###D') : timeframe.isintraday ? str.tostring(timeframe.multiplier * intRes2, '####') : '60' // basisType2 = input.string(defval='SMMA', title='MA Type: ', options=['SMA', 'EMA', 'DEMA', 'TEMA', 'WMA', 'VWMA', 'SMMA', 'HullMA', 'LSMA', 'ALMA', 'SSMA', 'TMA'],group = gr_occ2) basisLen2 = input.int(defval=8, title='MA Period', minval=1,group = gr_occ2) offsetSigma2 = input.int(defval=6, title='Offset for LSMA / Sigma for ALMA', minval=0,group = gr_occ2) offsetALMA2 = input.float(defval=0.85, title='Offset for ALMA', minval=0, step=0.01,group = gr_occ2) delayOffset2 = input.int(defval=0, title='Delay Open/Close MA (Forces Non-Repainting)', minval=0, step=1,group = gr_occ2) closeSeries2 = variant(basisType2, close[delayOffset2], basisLen2, offsetSigma2, offsetALMA2) openSeries2 = variant(basisType2, open[delayOffset2], basisLen2, offsetSigma2, offsetALMA2) closeOpenAvg2 = (closeSeries2 + openSeries2) / 2 closeSeriesAlt2 = reso(closeSeries2, useRes2, stratRes2) openSeriesAlt2 = reso(openSeries2, useRes2, stratRes2) diff2 = closeSeriesAlt2 - openSeriesAlt2 pcd2 = 50000.0 * diff2 / closeOpenAvg2 // plot(pcd2) //OCC2} //TDFI{ lookback = input(13, title='Lookback',group = "TDFI") filterHigh = input(0.05, title='Filter High',group = "TDFI") filterLow = input(-0.05, title='Filter Low',group = "TDFI") price = input(close, 'Period',group = "TDFI") mma = ta.ema(price * 1000, lookback) smma = ta.ema(mma, lookback) impetmma = mma - mma[1] impetsmma = smma - smma[1] divma = math.abs(mma - smma) averimpet = (impetmma + impetsmma) / 2 number = averimpet pow = 3 result = float(na) for i = 1 to pow - 1 by 1 if i == 1 result := number result result *= number result tdf = divma * result ntdf = tdf / ta.highest(math.abs(tdf), lookback * 3) c = ntdf > filterHigh ? color.green : ntdf < filterLow ? color.red : color.gray // plot(ntdf, linewidth=2, color=c) // hline(filterHigh, color=color.black) // hline(filterLow, color=color.black) //TDFI} //ATR{ // Inputs atrPeriod = input.int(title='ATR Period', defval=3, minval=1, group="ATR Bands") // While it seemed like a nice idea at the time, having separately-configurable upper and lower bands just doesn't really seem that useful as 90% of the time the settings for both are the same. // Therefore, We're going to simplify the config to make these settings unified for both bands, as it would otherwise just add even more confusion with the addition of take-profit bands as well... // // atrMultiplierUpper = input.float(title='ATR Upper Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Upper Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " + // "This will usually be between 1 and 3.") // srcUpper = input.source(title='ATR Upper Offset Source', defval=close, group="ATR Upper Band Settings", tooltip="This setting determines the offset point for ATR bands. " + // "For this band, 'high' and 'close' (default) are generally the most appropriate values.") // atrMultiplier = input.float(title='ATR Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Bands") // On second thought, I'm going to nix this setting and force it to be the "close" source. Having the ability to offset based on the wicks was a nice idea, but doesn't really seem to have any notable practical application. atrSourceRef = "close" //atrSourceRef = input.string(title='ATR Upper Offset Source', defval="close", options=["close","wicks"], group="ATR Bands Standard Settings", tooltip="This setting determines the offset point for ATR bands. " + // "The default value 'close' should be your go-to, but 'wicks' might provide a bit more breathing room in securities that tend to have large wicks.") // // See above - these are deprecated and no longer used... // // atrMultiplierLower = input.float(title='ATR Lower Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Lower Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " + // "This will usually be between 1 and 3.") // srcLower = input.source(title='ATR Lower Offset Source', defval=close, group="ATR Lower Band Settings", tooltip="This setting determines the offset point for ATR bands. " + // "For this band, 'low' and 'close' (default) are generally the most appropriate values.") // // // // // Take-Profit band settings // showTPBands = input.bool(title="Show opposite bands for take-profit zones", defval=false, tooltip="If enalbled, the existing ATR bands will be treated as 'stop-loss' bands, and 'take-profit' bands will be plotted " + // "to depict potential take-profit targets that are scaled based on the 'stop-loss' band and an additional reward/risk scaling factor (see below).\n\nDefault: Unchecked", group="Take-Profit Settings") // tpScaleFactor = input.float(title="Take-Profit Scale Factor", defval=1.5, minval=1, step=0.1, tooltip="This is a secondary scaling factor used based on the 'stop-loss' ATR bands to calculate and plot a potential take-profit target.\n\n" + // "The easiest way to think of this is as a desired reward/risk ratio, where the primary ATR Bands represent the risk/stop-loss.\n\nDefault: 1.5") // // // // // // As an added bonus, give the option to plot a table containing exact figures for all of the bands... // // Functional settings // showTable = input.bool(title="Show Table for Stops and Targets", defval=false, group="Table Settings", tooltip="If enabled, a table will be placed on-chart showing exact values for both stop bands, as well as optional take-profit bands/targets.\n\n" + // "Note: Take-profit values are based on the 'Take-Profit Scale Factor' setting above.\n\nDefault: Unchecked") // allowTableRepainting = input.bool(title="Allow Table Repainting", defval=false, group="Table Settings", tooltip="If enabled, table data will show real-time values, which will inherently repaint. This may be desirable for people preparing to enter prior " + // "to candle close, but should be used with extreme caution.\n\nDefault: Unchecked") // showTPinTable = input.bool(title="Include additional rows/columns to display take-profit values.", defval=false, group="Table Settings", tooltip="If enabled, additional table rows/columns will be drawn and populated with take-profit band/target values.\n\n" + // "Note: Take-profit values are based on the 'Take-Profit Scale Factor' setting above.\n\nDefault: Unchecked") // // // Display settings // alignTableVertically = input.bool(title="Align Table Vertically", defval=true, group="Table Settings", tooltip="If enabled, the table will be re-aligned to display vertically (headers to the left) instead of horizontally (headers on top).\n\nDefault: Checked") // tablePosition = input.string(title="Table Location", defval="Bottom Right", options=["Top Right","Top Left","Top Center","Middle Right","Middle Left","Middle Center","Bottom Right","Bottom Left","Bottom Center"], group="Table Settings", // tooltip='This setting controls the position on the chart where the table will be located.\n\nDefault: Bottom Right') // tableColor = input.color(title="Table Color: ", defval=color.rgb(0, 175, 200, 20), group="Table Settings", inline="A") // tableTextHeaderColor = input.color(title="Table Header Color: ", defval=color.rgb(255, 255, 0, 0), group="Table Settings", tooltip="These settings determine the colors used for the table cell borders/outlines, and the text inside the table cells used as data headers.", inline="A") // tableTextColor = input.color(title="Table Text Color: ", defval=color.rgb(255, 255, 255, 0), group="Table Settings", tooltip="This setting determines the color used for the text inside the table cells.", inline="B") // // tableTooltipColor = input.color(title="Table Tooltip Color: ", defval=color.rgb(255, 75, 255, 0), group="Table Display Settings", tooltip="This setting determines the color used for any cell tooltips.") // Not used // tableLongBGColor = input.color(title="Table Background Color - Long: ", defval=color.rgb(0, 255, 0, 90), group="Table Settings", inline="C") // tableShortBGColor = input.color(title="Short: ", defval=color.rgb(255, 0, 0, 80), group="Table Settings", tooltip="These settings determine the background fill colors used for long/short position info.", inline="C") // Functions // // Function to convert the input "source" to a proper "source" getBandOffsetSource(srcIn, isUpperBand) => // Initialize the return to our fail-safe 'close', which is also the default input, then update thru the switch statement ret = close switch srcIn "close" => ret := close "wicks" => ret := isUpperBand ? high : low => ret := close ret // // Function to convert table position input to a an appropriate argument getTablePosition(posIn) => posOut = position.bottom_right switch (posIn) "Top Right" => posOut := position.top_right "Top Left" => posOut := position.top_left "Top Center" => posOut := position.top_center "Middle Right" => posOut := position.middle_right "Middle Left" => posOut := position.middle_left "Middle Center" => posOut := position.middle_center "Bottom Right" => posOut := position.bottom_right "Bottom Left" => posOut := position.bottom_left "Bottom Center" => posOut := position.bottom_center => posOut := position.bottom_right posOut // ATR atr = ta.atr(atrPeriod) scaledATR = atr * atrMultiplier upperATRBand = getBandOffsetSource(atrSourceRef, true) + scaledATR lowerATRBand = getBandOffsetSource(atrSourceRef, false) - scaledATR // // Since we can calcualte ATR bands based on either close or wicks, we need to be sure to normalize the true distance // from the close to the "stop band" before we can then apply our take-profit scaler and calculate the TP bands... // scaledTPLong = close + ((close - lowerATRBand) * tpScaleFactor) // scaledTPShort = close - ((upperATRBand - close) * tpScaleFactor) // OG ATR Band Plotting plot(upperATRBand, title="Upper ATR Band", color=color.rgb(0, 255, 0, 50), linewidth=2) plot(lowerATRBand, title="Lower ATR Band", color=color.rgb(255, 0, 0, 50), linewidth=2) // // TP band plots // plot(showTPBands ? scaledTPLong : na, title="Upper Take-Profit Band", color=color.rgb(255, 255, 255, 80), linewidth=1) // plot(showTPBands ? scaledTPShort : na, title="Lower Take-Profit Band", color=color.rgb(255, 255, 0, 80), linewidth=1) //ATR} //Function{ var buypsnsize = 0 var sellpsnsize = 0 var lstlngprice = 0.0 var lstshtprice = 0.0 var lsttplprice = 0.0 var lsttpsprice = 0.0 var lstsllprice = 0.0 var lstslsprice = 0.0 var buybarindex = 0 var sellbarIndex = 0 stoplosscacl(isbuy)=> pce = 0.0 if isbuy pce := lowerATRBand - slDist else pce := upperATRBand + slDist pce takeprofitcalc(isbuy) => pce = 0.0 if isbuy pce := close + ((close - stoplosscacl(true)) * tpRR) else pce := close - ((stoplosscacl(false) - close) * tpRR) pce //Function} occ1green = closeSeriesAlt > openSeriesAlt occ1red = closeSeriesAlt < openSeriesAlt occ2green = closeSeriesAlt2 > openSeriesAlt2 occ2red = closeSeriesAlt2 < openSeriesAlt2 tdfigreen = ntdf > filterHigh tdfired=ntdf < filterLow combinedbuy=occ1green and occ2green and tdfigreen combinedsell=occ1red and occ2red and tdfired buycdn = combinedbuy and not combinedbuy[1] and barstate.isconfirmed and time_cond and islong sellcdn = combinedsell and not combinedsell[1] and barstate.isconfirmed and time_cond and isshort // bgcolor(occ2green? color.new(color.green,50):na) if buycdn and strategy.opentrades == 0 strategy.entry("long",strategy.long) lstlngprice := close lsttplprice := takeprofitcalc(true) lstsllprice := stoplosscacl(true) strategy.exit("exit_TP/SL","long",limit=lsttplprice,stop=lstsllprice) if sellcdn and strategy.opentrades == 0 strategy.entry("short",strategy.short) lstshtprice := close lsttpsprice := takeprofitcalc(false) lstslsprice := stoplosscacl(false) strategy.exit("exit_TP/SL","short",limit=lsttpsprice,stop=lstslsprice) plot(strategy.position_size > 0? lstlngprice : na,color=color.yellow,style=plot.style_linebr,title="Entry Price Long") plot(strategy.position_size < 0? lstshtprice : na,color=color.yellow,style=plot.style_linebr,title="Entry Price Short") plot(strategy.position_size > 0? lsttplprice : na,color=color.green,style=plot.style_linebr,title="TP Price Long") plot(strategy.position_size > 0? lstsllprice : na,color=color.red,style=plot.style_linebr,title="SL Price Long") plot(strategy.position_size < 0? lsttpsprice : na,color=color.green,style=plot.style_linebr,title="TP Price Short") plot(strategy.position_size < 0? lstslsprice : na,color=color.red,style=plot.style_linebr,title="SL Price Short")