Advanced PineConnector Template
This lesson breaks down the source code to my Advanced PineConnector script template which includes the majority of PineConnector functionality inbuilt right into the Pine code.
Check out my other free lessons!Source Code
Change Notes:
2nd December 2023
- Fixed ATR multiplier not overriding fixed pip SL/TP when Use Pip-Based SL & TP setting was selected
- Fixed Exit Reasons still sending TP to PineConnector when selected
8th December 2023:
- Fixed ATR multiplier not sending the correct pips to PineConnector
- Fixed ATR trailing stop still using TP
- Added swing high/low input setting
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © ZenAndTheArtOfTrading / www.PineScriptMastery.com // @version=5 strategy("PineConnector Template Code", overlay=true, initial_capital=10000, currency=currency.USD, default_qty_type=strategy.fixed, default_qty_value=100000) // Strategy Settings var const string GROUP_STRATEGY = "Your Strategy Settings" STRATEGY_SL_DISTANCE = input.float(title="Stop Loss Distance", defval=5, minval=0, group=GROUP_STRATEGY, tooltip="Distance in pips or ATR multiplier to place your SL", display=display.none) STRATEGY_SL_ANCHOR = input.string(title="SL Anchor Price", defval="Close", options=["Close","High/Low"], group=GROUP_STRATEGY, tooltip="Which price to calculate SL distance from", display=display.none) STRATEGY_SL_LOOKBACK = input.int(title="SL High/low Lookback", defval=1, group=GROUP_STRATEGY, tooltip="How many bars to look back for high/low anchor price", display=display.none) STRATEGY_ATR_MULTIPLIER = input.float(title="ATR Multiplier", defval=0, minval=0, group=GROUP_STRATEGY, tooltip="14-period ATR multiplier for stop loss distance - set to 0 to use fixed pips instead", display=display.none) STRATEGY_RISK_REWARD = input.float(title="Profit Risk:Reward", defval=1, minval=0, group=GROUP_STRATEGY, tooltip="Your risk:reward profile for taking profit", display=display.none) STRATEGY_BREAK_EVEN = input.float(title="Break-Even Risk:Reward", defval=0, minval=0, group=GROUP_STRATEGY, tooltip="Your risk:reward profile for triggering your Stop Loss to move to break-even (set to 0 to disable)", display=display.none) STRATEGY_TRAIL_STOP = input.float(title="Trailing Stop Distance", defval=0, minval=0, group=GROUP_STRATEGY, tooltip="Your risk:reward profile for triggering your Trailing Stop (set to 0 to disable)", display=display.none) STRATEGY_EXIT_HCLC = input.bool(title="Exit on Higher-Close/Lower-Close", defval=false, group=GROUP_STRATEGY, tooltip="If enabled, the script will exit on a higher/lower close after take-profit price is hit", display=display.none) STRATEGY_EXIT_EXHAUST = input.bool(title="Exit on Opposite Color Bar", defval=false, group=GROUP_STRATEGY, tooltip="If enabled, the script will exit on a bullish/bearish bar in the opposite direction of trade after price is hit", display=display.none) // PineConnector Settings var const string GROUP_PC = "PineConnector Settings" PC_ENABLED = input.bool(title="Use PineConnector", defval=true, group=GROUP_PC, tooltip="If accepted, when you set alert() function call then PineConnector commands will be automatically triggered by the script. Use this experimental feature at your own risk and don't use it with money you can't afford to lose", display=display.none) PC_ID = input.string(title="License ID", defval="ID", group=GROUP_PC, tooltip="This is your PineConnector license ID", display=display.none) PC_RISK = input.float(title="Risk Per Trade", defval=1, step=0.5, group=GROUP_PC, tooltip="This is how much to risk per trade (% of account balance OR lots - which one is used depends on your PineConnector settings)", display=display.none) PC_ENTRY_PIPS = input.float(title="Entry Pips", defval=0.1, minval=0, group=GROUP_PC, tooltip="Enter your pip offset for limit orders (ie. entry buy-limit/entry sell-limit)", display=display.none) PC_SPREAD_FILTER = input.float(title="Spread Filter", defval=0, group=GROUP_PC, tooltip="Optional Spread filter - will only execute trades if the current market Spread is below this pip amount. Zero to disable", display=display.none) PC_BREAK_EVEN_OFFSET = input.float(title="Break Even Offset", defval=0, group=GROUP_PC, tooltip="", display=display.none) PC_USE_LIMIT = input.bool(title="Use Entry Limit Order", defval=true, group=GROUP_PC, tooltip="If true a limit order will be used, if false a market order will be used", display=display.none) PC_USE_PIP_ENTRY = input.bool(title="Use Pip-Based Entry", defval=false, group=GROUP_PC, tooltip="If turned on and you're using a buylimit/selllimit order to enter, then pips will be sent to PineConnector - otherwise a Price value will be sent", display=display.none) PC_USE_PIP_TARGET = input.bool(title="Use Pip-Based SL & TP", defval=false, group=GROUP_PC, tooltip="Turn this on if you want to use a pip-based TP & SL, turn it off if you want to use a TradingView price-based TP & SL. Watch Update v3.05 course video for more info", display=display.none) PC_OVERRIDE = input.string(title="MetaTrader Symbol Override", defval="", group=GROUP_PC + " Optional", tooltip="Don't touch unless you really need to. This overrides the symbol sent from TradingView. Eg. if the TV symbol you're using is BTCUSDT.P and your MT broker's symbol is BTCUSDT, put BTCUSDT in here to override TV's symbol. This also overrides the prefix and suffix settings below.", display=display.none) PC_PREFIX = input.string(title="MetaTrader Prefix", defval="", group=GROUP_PC + " Optional", tooltip="OPTIONAL: This is your broker's MetaTrader symbol prefix", display=display.none) PC_SUFFIX = input.string(title="MetaTrader Suffix", defval="", group=GROUP_PC + " Optional", tooltip="OPTIONAL: This is your broker's MetaTrader symbol suffix", display=display.none) PC_STRATEGY = input.string(title="Strategy ID", defval="", group=GROUP_PC + " Optional", tooltip="OPTIONAL: This allows for multi-strategy setups by adding this string as a 'comment' parameter to any orders sent to PC. Useful for running multiple strategies on the same market across different timeframes or with different parameters.") PC_DEBUG = input.bool(title="Debug Automation Alerts", defval=true, group=GROUP_PC + " Optional", tooltip="Turns on/off label that displays what your alert message will look like if it gets sent to AutoView or PineConnector (useful for debugging errors or issues)", display=display.none) // Prepare PineConnector Variables var PC_VAR_SYMBOL = PC_OVERRIDE == "" ? (PC_PREFIX + syminfo.ticker + PC_SUFFIX) : PC_OVERRIDE var PC_VAR_USE_LIMIT = PC_USE_LIMIT ? "limit" : "" var PC_VAR_SPREAD_FILTER = PC_SPREAD_FILTER != 0 ? (",spread=" + str.tostring(PC_SPREAD_FILTER)) : "" var PC_VAR_STRATEGY = PC_STRATEGY == "" ? "" : ",comment=\"" + PC_STRATEGY + "\"" var label PC_DEBUG_LABEL = na var label PC_DEBUG_LABEL_TS = na // Generate PineConnector entry alert string PC_Entry_Alert(_direction, _entryprice, _sl, _tp, _be, _truncate=true) => _format = _truncate ? "#.#####" : "#.##########" _price = PC_USE_LIMIT ? "price=" + str.tostring(_entryprice, _format) + "," : "" _tpText = _tp == 0 ? "" : "tp=" + str.tostring(_tp, _format) + "," _beText = _be == 0 ? "" : "betrigger=" + str.tostring(_be, _format) + ",beoffset=" + str.tostring(PC_BREAK_EVEN_OFFSET, _format) + "," PC_ID + "," + _direction + PC_VAR_USE_LIMIT + "," + PC_VAR_SYMBOL + "," + _price + "sl=" + str.tostring(_sl, _format) + "," + _tpText + _beText + "risk=" + str.tostring(PC_RISK) + PC_VAR_SPREAD_FILTER + PC_VAR_STRATEGY // Get market point -> pip value GetPipSize() => syminfo.mintick * (syminfo.type == "forex" ? 10 : 1) // Stops & Targets var float StopDistanceFixedPips = STRATEGY_SL_DISTANCE * GetPipSize() var float TradeEntryPrice = na var float TradeStopPrice = na var float TradeProfitPrice = na var float TradeBreakEvenPrice = na var float TrailStopActivatePrice = na var bool TrailStopActivated = false var bool SearchingForExit = false // Get indicator values ATR_Value = nz(ta.atr(14)) //! SIMPLE EXAMPLE STRATEGY ENTRY CODE (REPLACE WITH YOUR OWN!) bool LongTrade = ta.rsi(close, 14) < 30 and close > open and strategy.position_size == 0 bool ShortTrade = ta.rsi(close, 14) > 70 and close < open and strategy.position_size == 0 bool UseExitReason = STRATEGY_EXIT_HCLC or STRATEGY_EXIT_EXHAUST // Generate PineConnector Alert String with all required parameters GenerateEntryAlertString() => pcStopPips = math.abs(close - TradeStopPrice) pcTargetPips = math.abs(close - TradeProfitPrice) pcBreakEvenPips = math.abs(close - TradeBreakEvenPrice) pcEntry = PC_USE_PIP_ENTRY ? PC_ENTRY_PIPS : TradeEntryPrice pcStop = PC_USE_PIP_TARGET ? pcStopPips / GetPipSize() : TradeStopPrice pcTarget = UseExitReason ? 0 : PC_USE_PIP_TARGET ? pcTargetPips / GetPipSize() : TradeProfitPrice pcBreakEven = na(TradeBreakEvenPrice) ? 0 : pcBreakEvenPips PC_Entry_Alert(LongTrade ? "buy" : "sell", pcEntry, pcStop, pcTarget, pcBreakEven, true) // Get Long Stop Loss swingHigh = ta.highest(high, STRATEGY_SL_LOOKBACK) swingLow = ta.lowest(low, STRATEGY_SL_LOOKBACK) GetStopPrice(bool strategy_direction) => AnchorPriceSL = STRATEGY_SL_ANCHOR == "Close" ? close : (strategy_direction ? swingLow : swingHigh) if strategy_direction returnValue = AnchorPriceSL - (STRATEGY_ATR_MULTIPLIER > 0 ? (ATR_Value * STRATEGY_ATR_MULTIPLIER) : StopDistanceFixedPips) else returnValue = AnchorPriceSL + (STRATEGY_ATR_MULTIPLIER > 0 ? (ATR_Value * STRATEGY_ATR_MULTIPLIER) : StopDistanceFixedPips) // Long Entry Code if LongTrade and barstate.isconfirmed TradeStopPrice := GetStopPrice(true) StopDistancePips = close - TradeStopPrice TradeProfitPrice := close + (StopDistancePips * STRATEGY_RISK_REWARD) TradeEntryPrice := close SearchingForExit := false if STRATEGY_BREAK_EVEN > 0 TradeBreakEvenPrice := close + (StopDistancePips * STRATEGY_BREAK_EVEN) if STRATEGY_TRAIL_STOP > 0 TrailStopActivated := false TrailStopActivatePrice := close + (StopDistancePips * STRATEGY_TRAIL_STOP) if PC_USE_LIMIT strategy.cancel_all() strategy.entry("Buy", strategy.long, limit=PC_USE_LIMIT ? close - (PC_ENTRY_PIPS * GetPipSize()) : na) if PC_ENABLED alert(GenerateEntryAlertString(), alert.freq_once_per_bar_close) // Short Entry Code if ShortTrade and barstate.isconfirmed TradeStopPrice := GetStopPrice(false) StopDistancePips = TradeStopPrice - close TradeProfitPrice := close - (StopDistancePips * STRATEGY_RISK_REWARD) TradeEntryPrice := close SearchingForExit := false if STRATEGY_BREAK_EVEN > 0 TradeBreakEvenPrice := close - (StopDistancePips * STRATEGY_BREAK_EVEN) if STRATEGY_TRAIL_STOP > 0 TrailStopActivated := false TrailStopActivatePrice := close - (StopDistancePips * STRATEGY_TRAIL_STOP) if PC_USE_LIMIT strategy.cancel_all() strategy.entry("Sell", strategy.short, limit=PC_USE_LIMIT ? close + (PC_ENTRY_PIPS * GetPipSize()) : na) if PC_ENABLED alert(GenerateEntryAlertString(), alert.freq_once_per_bar_close) // Update trade entry price to match TradingView strategy tester if strategy.position_size != 0 if TradeEntryPrice != strategy.position_avg_price TradeEntryPrice := strategy.position_avg_price // Long Strategy Management Code if strategy.position_size > 0 // Long Break-Even Code (break-even order is handled directly by PC so no need for alert) if not na(TradeBreakEvenPrice) and high >= TradeBreakEvenPrice and TradeStopPrice < TradeEntryPrice TradeStopPrice := TradeEntryPrice + (PC_BREAK_EVEN_OFFSET * GetPipSize()) TradeBreakEvenPrice := na // Long Trailing Stop Activation Code if STRATEGY_TRAIL_STOP > 0 and high >= TrailStopActivatePrice TrailStopActivated := true // Long Exit Reason Activation Code if high >= TradeProfitPrice if UseExitReason SearchingForExit := true if PC_USE_LIMIT // Ensure pending entry limit order is cancelled if target is hit in case entry order was not filled strategy.cancel("Buy") if PC_ENABLED alert(PC_ID + ",cancellong," + PC_VAR_SYMBOL + PC_STRATEGY, alert.freq_once_per_bar) // Confirmed Bar Code if barstate.isconfirmed //! SIMPLE EXAMPLE EXIT DETECTION CODE (REPLACE WITH YOUR OWN!) bool ExitTrade = false if SearchingForExit if STRATEGY_EXIT_HCLC and close < low[1] ExitTrade := true if STRATEGY_EXIT_EXHAUST and close < open ExitTrade := true // Long Exit Alert if ExitTrade strategy.close("Buy") if PC_ENABLED alert(PC_ID + ",closelong," + PC_VAR_SYMBOL + PC_VAR_STRATEGY, alert.freq_once_per_bar) // Long Trailing Stop Code LongStopLoss = GetStopPrice(true) if TrailStopActivated and LongStopLoss > TradeStopPrice TradeStopPrice := LongStopLoss NEW_SL = PC_USE_PIP_TARGET ? math.abs(TradeStopPrice - close) / GetPipSize() : TradeStopPrice string alertMessage = PC_ID + ",newsltplong," + PC_VAR_SYMBOL + ",sl=" + str.tostring(NEW_SL) + PC_VAR_STRATEGY if PC_ENABLED alert(alertMessage, alert.freq_once_per_bar_close) // Debug alert message label PC_DEBUG_LABEL_TS := label.new(bar_index, high + (GetPipSize() * 10), alertMessage, color=color.white) label.delete(PC_DEBUG_LABEL_TS[1]) // Short Strategy Management Code if strategy.position_size < 0 // Short Break-Even Code (break-even order is handled directly by PC so no need for alert) if not na(TradeBreakEvenPrice) and low <= TradeBreakEvenPrice and TradeStopPrice > TradeEntryPrice TradeStopPrice := TradeEntryPrice - (PC_BREAK_EVEN_OFFSET * GetPipSize()) TradeBreakEvenPrice := na // Short Trailing Stop Activation Code if STRATEGY_TRAIL_STOP > 0 and low <= TrailStopActivatePrice TrailStopActivated := true // Short Exit Reason Activation Code if low <= TradeProfitPrice if UseExitReason SearchingForExit := true if PC_USE_LIMIT // Ensure pending entry limit order is cancelled if target is hit in case entry order was not filled strategy.cancel("Buy") if PC_ENABLED alert(PC_ID + ",cancelshort," + PC_VAR_SYMBOL + PC_STRATEGY, alert.freq_once_per_bar) // Confirmed Bar Code if barstate.isconfirmed //! SIMPLE EXAMPLE EXIT DETECTION CODE (REPLACE WITH YOUR OWN!) bool ExitTrade = false if SearchingForExit if STRATEGY_EXIT_HCLC and close > high[1] ExitTrade := true if STRATEGY_EXIT_EXHAUST and close > open ExitTrade := true // Long Exit Alert if ExitTrade strategy.close("Sell") if PC_ENABLED alert(PC_ID + ",closeshort," + PC_VAR_SYMBOL + PC_VAR_STRATEGY, alert.freq_once_per_bar) // Short Trailing Stop Code ShortStopLoss = GetStopPrice(false) if TrailStopActivated and ShortStopLoss < TradeStopPrice TradeStopPrice := ShortStopLoss NEW_SL = PC_USE_PIP_TARGET ? math.abs(TradeStopPrice - close) / GetPipSize() : TradeStopPrice string alertMessage = PC_ID + ",newsltpshort," + PC_VAR_SYMBOL + ",sl=" + str.tostring(NEW_SL) + PC_VAR_STRATEGY if PC_ENABLED alert(alertMessage, alert.freq_once_per_bar_close) // Debug alert message label PC_DEBUG_LABEL_TS := label.new(bar_index, high + (GetPipSize() * 10), alertMessage, color=color.white) label.delete(PC_DEBUG_LABEL_TS[1]) // Trigger SL/TP Orders strategy.exit("Long Exit", "Buy", stop=TradeStopPrice, limit=UseExitReason ? na : TradeProfitPrice) strategy.exit("Short Exit", "Sell", stop=TradeStopPrice, limit=UseExitReason ? na : TradeProfitPrice) // Display automation alert string on last valid trade - for debugging purposes if PC_DEBUG and ((LongTrade and barstate.isconfirmed) or (ShortTrade and barstate.isconfirmed)) debugString = "Automation is not enabled!" if PC_ENABLED debugString := GenerateEntryAlertString() PC_DEBUG_LABEL := label.new(bar_index, high + (GetPipSize() * 10), debugString, color=color.white) label.delete(PC_DEBUG_LABEL[1]) // Draw trade info to chart plot(strategy.position_size != 0 ? TradeStopPrice : na, "SL", color=color.red, linewidth=1, style=plot.style_linebr) plot(strategy.position_size != 0 and not SearchingForExit ? TradeProfitPrice : na, "TP", color=color.green, linewidth=1, style=plot.style_linebr) plot(strategy.position_size != 0 and STRATEGY_BREAK_EVEN != 0 ? TradeBreakEvenPrice : na, "BE", color=color.blue, linewidth=1, style=plot.style_linebr) plot(strategy.position_size != 0 and not TrailStopActivated ? TrailStopActivatePrice : na, "TS", color=color.orange, linewidth=1, style=plot.style_linebr)