Strategy · Pine Script v5 · Own pane

Ruckard Fiery RSI A008

by ruckard

This strategy uses a 100-period RSI to generate long and short signals with 5% pre-entry buffers.

View on GitHub

GitHub stars13on the repository
Pine versionv5runs as is
Lines of code905
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update1 year ago2 Mar 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

905 lines of Pine Script v5 from scripts/ruckard_fiery_rsi/ruckard_fiery_rsi.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

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

//@version=5

// Current version: v20220102 ( A008 )
// Tradingview Public description - BEGIN
// 
// This strategy serves as a beginner's guide to connect TradingView signals to Zignaly Crypto Trading Platform.
// This specific strategy also includes Risk Management.
// 
// It was originally tested at BTCUSDT pair and 15m timeframe.
//
// Before using this documentation it's recommended that you:
// [LIST]
// [*] Use default TradingView strategy script or another script and setup its associated alert manually. Just make the alert pop-up in the screen.
// [*] Create a 'Copy-Trader provider' (or Signal Provider) in Zignaly and send signals to it either thanks to your browser or with some basic programming.
// [/LIST]

// [B]SETTINGS[/B]
// [B]__ SETTINGS - Capital[/B]
// [LIST]
// [*] (CAPITAL) Capital quote invested per order in USDT units {100.0}. This setting is only used when '(ZIG) Provider type' is set to 'Signal Provider'.
// [*] (CAPITAL) Capital percentage invested per order (%) {25.0}. This setting is only used when '(ZIG) Provider type' is set to 'Copy Trader Provider'.
// [/LIST]
// [B]__ SETTINGS - Misc[/B]
// [LIST]
// [*] (ZIG) Enable Alert message {True}: Whether to enable alert message or not.
// [*] (DEBUG) Enable debug on order comments {False}: Whether to show alerts on order comments or not.
// [*] Number of decimal digits for Prices {2}.
// [*] (DECIMAL) Maximum number of decimal for contracts {3}.
// [/LIST]
// [B]__ SETTINGS - Zignaly[/B]
// [LIST]
// [*] (ZIG) Integration type {TradingView only}: [b]Hybrid[/b]: Both TradingView and Zignaly handle take profit, trailing stops and stop losses. Useful if you are scared about TradingView not firing an alert. It might arise problems if TradingView and Zignaly get out of sync. [b]TradingView only[/b]: TradingView sends entry and exit orders to Zignaly so that Zignaly only buys or sells. Zignaly won't handle stop loss or other settings on its own.
// [*] (ZIG) Zignaly Alert Type {WebHook}: 'Email' or 'WebHook'.
// [*] (ZIG) Provider type {Profit Sharing Provider}: 'Profit Sharing Provider', 'Copy Trader Provider', or 'Signal Provider'. 'Copy Trader Provider' or 'Profit Sharing Provider' sends a percentage to manage. 'Signal Provider' sends a quote to manage.
// [*] (ZIG) Exchange {Zignaly}: 'Zignaly', 'Binance' or 'Kucoin'.
// [*] (ZIG) Exchange Type {Futures}: 'Spot' or 'Futures'.
// [*] (ZIG) Leverage {1}. Set it to '1' when '(ZIG) Exchange Type' is set to 'Spot'.
// [/LIST]
// [B]__ SETTINGS - Strategy[/B]
// [LIST]
// [*] (STRAT) Strategy Type: 'Long and Short', 'Long Only' or 'Short Only'.
// [*] (STRAT) Strategy Start Time {2021-01-01 00:00:00}: When to start the strategy if '(STRAT) Strategy Start Time forced?' setting is set to true.
// [*] (STRAT) Strategy Stop Time {2021-12-31 00:00:00}: When to stop the strategy if '(STRAT) Strategy Stop Time forced?' setting is set to true.
// [*] (STRAT) Strategy Start Time forced? {True}: Whether to start the strategy from a given point in time.
// [*] (STRAT) Strategy Stop Time forced? {False}: Whether to stop the strategy after a given point in time.
// [*] (STOPTAKE) Take Profit? {false}: Whether to enable Take Profit.
// [*] (STOPTAKE) Stop Loss? {True}: Whether to enable Stop Loss.
// [*] (TRAILING) Enable Trailing Take Profit (%) {True}: Whether to enable Trailing Take Profit.
// [*] (STOPTAKE) Take Profit % {3.0}: Take profit percentage. This setting is only used when '(STOPTAKE) Take Profit?' setting is set to true.
// [*] (STOPTAKE) Stop Loss % {2.0}: Stop loss percentage. This setting is only used when '(STOPTAKE) Stop Loss?' setting is set to true.
// [*] (TRAILING) Trailing Take Profit Trigger (%) {2.5}: Trailing Stop Trigger Percentage. This setting is only used when '(TRAILING) Enable Trailing Take Profit (%)' setting is set to true.
// [*] (TRAILING) Trailing Take Profit as a percentage of Trailing Take Profit Trigger (%) {25.0}: Trailing Stop Distance Percentage. This setting is only used when '(TRAILING) Enable Trailing Take Profit (%)' setting is set to true.
// [*] (RECENT) Number of minutes to wait to open a new order after the previous one has been opened {6}.
// [/LIST]
// [B]____ SETTINGS - Risk Management [/B]
// [list]
// [*] (RISKM) Risk Management Type: 'Safe', 'Somewhat safe compound' or 'Unsafe compound'. '[b]Safe[/b]': Calculations are always done with the initial capital (1000) in mind. The maximum losses per trade/day/week/month are taken into account. '[b]Somewhat safe compound[/b]': Calculations are done with initial capital (1000) or a higher capital if it increases. The maximum losses per trade/day/week/month are taken into account. '[b]Unsafe compound[/b]': In each order all the current capital is gambled and only the default stop loss per order is taken into account. That means that the maximum losses per trade/day/week/month are not taken into account. [b]Default[/b]: 'Somewhat safe compound'.
// [*] (RISKM) Maximum loss per trade % {1.0}.
// [*] (RISKM) Maximum loss per day % {6.0}.
// [*] (RISKM) Maximum loss per week % {8.0}.
// [*] (RISKM) Maximum loss per month % {10.0}.
// [/list]

// [B]DEFAULT SETTINGS[/B]

// By default this strategy has been setup with these beginner settings:
// [LIST]
// [*] '(ZIG) Integration type' : TradingView only
// [*] '(ZIG) Provider type'    : 'Copy Trader Provider'
// [*] '(ZIG) Exchange'         : 'Binance'
// [*] '(ZIG) Exchange Type'    : 'Spot'
// [*] '(STRAT) Strategy Type'  : 'Long Only'
// [*] '(ZIG) Leverage'         : '1' (Or no leverage)
// [/LIST]
// but you can change those settings if needed.


// [B]FIRST STEP[/B]
// [LIST]
// [*] For both future or spot markets you should make sure to change '(ZIG) Zignaly Alert Type' to match either WebHook or Email. If you have a non paid account in TradingView as in October 2020 you would have to use Email which it's free to use.
// [/LIST]

// [B]RECOMMENDED SETTINGS[/B]
// [B]__ RECOMMENDED SETTINGS - Spot markets[/B]
// [LIST]
// [*] '(ZIG) Exchange Type'   setting should be set to 'Spot'
// [*] '(STRAT) Strategy Type' setting should be set to 'Long Only'
// [*] '(ZIG) Leverage'        setting should be set to '1'
// [/LIST]
// [B]__ RECOMMENDED SETTINGS - Future markets[/B]
// [LIST]
// [*] '(ZIG) Exchange Type'   setting should be set to 'Futures'
// [*] '(STRAT) Strategy Type' setting should be set to 'Long and Short'
// [*] '(ZIG) Leverage'        setting might be changed if desired.
// [/LIST]
// [B]__ RECOMMENDED SETTINGS - Signal Providers[/B]
// [LIST]
// [*] '(ZIG) Provider type'   setting should be set to 'Signal Provider'
// [*] '(CAPITAL) Capital quote invested per order in USDT units' setting might be changed if desired.
// [/LIST]
// [B]__ RECOMMENDED SETTINGS - Copy Trader Providers[/B]
// [LIST]
// [*] '(ZIG) Provider type'   setting should be set to 'Copy Trader Provider'
// [*] '(CAPITAL) Capital percentage invested per order (%)' setting might be changed if desired.
// [*] Strategy Properties setting: 'Initial Capital' might be changed if desired.
// [/LIST]

// [B]INTEGRATION TYPE EXPLANATION[/B]
// [LIST]
// [*] 'Hybrid': Both TradingView and Zignaly handle take profit, trailing stops and stop losses. Useful if you are scared about TradingView not firing an alert. It might arise problems if TradingView and Zignaly get out of sync.
// [*] 'TradingView only': TradingView sends entry and exit orders to Zignaly so that Zignaly only buys or sells. Zignaly won't handle stop loss or other settings on its own.
// [/LIST]

// [B]HOW TO USE THIS STRATEGY[/B]
// [LIST]
// [*] Beginner: Copy and paste the strategy and change it to your needs. Turn off '(DEBUG) Enable debug on order comments' setting.
// [*] Medium: Reuse functions and inputs from this strategy into your own as if it was a library.
// [*] Advanced: Check Strategy Tester. List of trades. Copy and paste the different suggested 'alert_message' variable contents to your script and change them to your needs.
// [*] Expert: You needed a way to pass data from TradingView script to the alert. Now you know it's the 'alert_message' variable. You can find several examples in the source code using the variable. You also have seen 'ALERTS SETUP' explanation below. An additional quick look at 'Strategy Tester', 'List of Trades' and you are ready to go.
// [/LIST]


// [B] ALERTS SETUP[/B]
// This is the important piece of information that allows you to connect TradingView to Zignaly in a semi-automatic manner.
// [B] __ ALERTS SETUP - WebHook[/B]
// [LIST]
// [*] Webhook URL: https : // zignaly . com / api / signals.php?key=MYSECRETKEY
// [*] Message: { {{strategy.order.alert_message}} , "key" : "MYSECRETKEY" }
// [/LIST]
// [B] __ ALERTS SETUP - Email[/B]
// [LIST]
// [*] Setup a new Hotmail account
// [*] Add it as an 'SMS email' in TradingView Profile settings page.
// [*] Confirm your own the email address
// [*] Create a rule in your Hotmail account that 'Redirects' (not forwards) emails to 'signals @ zignaly . email' when (1): 'Subject' includes 'Alert', (2): 'Email body' contains string 'MYZIGNALYREDIRECTTRIGGER' and (3): 'From' contains 'noreply @ tradingview . com'.
// [*] In 'More Actions' check: Send Email-to-SMS
// [*] Message: ||{{strategy.order.alert_message}}||key=MYSECRETKEY||
// MYZIGNALYREDIRECTTRIGGER
// [/LIST]


// '(DEBUG) Enable debug on order comments' is turned on by default so that you can see in the Strategy Tester. List of Trades. The different orders alert_message that would have been sent to your alert. You might want to turn it off it some many letters in the screen is problem.

// [B]STRATEGY ADVICE[/B]
// [LIST]
// [*] If you turn on 'Take Profit' then turn off 'Trailing Take Profit'.
// [/LIST]
//
// [B]ZIGNALY SIDE ADVICE[/B]
// [LIST]
// [*] If you are a 'Signal Provider' make sure that 'Allow reusing the same signalId if there isn't any open position using it?' setting in the profile tab is set to true.
// [*] You can find your 'MYSECRETKEY' in your 'Copy Trader/Signal' provider Edit tab at 'Signal URL'.
// [/LIST]
//
// [B]ADDITIONAL ZIGNALY DOCUMENTATION[/B]
// This beginner's guide is quite basic and meant to be an introduction. Please read additional documentation to learn what you actually can do with Zignaly.
// [LIST]
// [*] docs . zignaly . com / signals / how-to -- How to send signals to Zignaly
// [*] help . zignaly . com / hc/en-us/categories/360002703720-Sending-Signals -- Sending zignals
// [/LIST]
//
// [B]FINAL REMARKS[/B]
// [LIST]
// [*] This strategy tries to match the Pine Script Coding Conventions as best as possible.
// [*] You can check my 'Ruckard TradingLatino' strategy for a more complex strategy that it's also integrated with Zignaly. Unfortunatley it does not use Pine Script Coding Conventions as much.
// [/LIST]

// Tradingview Public description - END

strategy('Ruckard Fiery RSI A008', shorttitle='A008RFRSI', overlay=false, max_bars_back=5000, calc_on_order_fills=false, calc_on_every_tick=false, pyramiding=0, initial_capital=1000, slippage=1, commission_type=strategy.commission.percent, commission_value=0.04)

// INPUTS - BEGIN

// Strategy - Inputs
i_enableZignalyAlert = input(true, '(ZIG) Enable Alert message {True}')

_ZIGHYBRIDINTEGRATION_ = 'Hybrid', _ZIGTVONLYINTEGRATION_ = 'TradingView only'
i_zignalyIntegrationType = input.string(_ZIGHYBRIDINTEGRATION_, '(ZIG) Integration type', options=[_ZIGTVONLYINTEGRATION_, _ZIGHYBRIDINTEGRATION_])
_ZIGSIGNALPROVIDER_ = 'Signal Provider', _ZIGCOPYTRADERPROVIDER_ = 'Profit Sharing/Copy Trader Provider'
i_zignalyProviderType = input.string(_ZIGCOPYTRADERPROVIDER_, '(ZIG) Provider type', options=[_ZIGSIGNALPROVIDER_, _ZIGCOPYTRADERPROVIDER_])
L_S = 'Long and Short', _L_ = 'Long Only', _S_ = 'Short Only'
i_strategyType = input.string(L_S, '(STRAT) Strategy Type', options=[L_S, _L_, _S_])
i_strategyStartTime = input.time(timestamp('01 Jan 2021'), '(STRAT) Strategy Start Time {2021-01-01 00:00:00}')
i_strategyStopTime = input.time(timestamp('31 Dec 2021'), '(STRAT) Strategy Stop Time {2021-12-31 00:00:00}')
i_strategyStartTimeOn = input.bool(true, '(STRAT) Strategy Start Time forced? {True}')
i_strategyStopTimeOn = input.bool(false, '(STRAT) Strategy Stop Time forced? {False}')
i_rsiLength = input.int(100, '(STRAT) RSI length {100}', minval=1, step=1)
i_rsiUseEmergency = input.bool(false, "RSI . Use Emergency Exit?")
i_rsiLongEntry = input.float(45, "RSI Long Entry {45}", minval=0.01, step=0.01, maxval=100.00)
i_rsiUseLongPreEntry = input.bool(true, "RSI . Use Long Pre Entry? {True}")
i_rsiLongPreEntryPercentage = input.float(5, "RSI Long Pre Entry % {5}", minval=0.01, step=0.01, maxval=100.00) * 0.01
i_rsiLongExit = input.float(55, "RSI Long Exit {55}", minval=0.01, step=0.01, maxval=100.00)
i_rsiLongEmergencyExit = input.float(10, "RSI Long Emergency Exit {10}", minval=0.01, step=0.01, maxval=100.00)
i_rsiShortEntry = input.float(55, "RSI Short Entry {55}", minval=0.01, step=0.01, maxval=100.00)
i_rsiUseShortPreEntry = input.bool(true, "RSI . Use Short Pre Entry? {True}")
i_rsiShortPreEntryPercentage = input.float(5, "RSI Short Pre Entry % {5}", minval=0.01, step=0.01, maxval=100.00) * 0.01
i_rsiShortExit = input.float(47, "RSI Short Exit {47}", minval=0.01, step=0.01, maxval=100.00)
// i_rsiShortEmergencyExit = input.float(10, "RSI Short Emergency Exit {85}", minval=0.01, step=0.01, maxval=100.00)
i_HigherTFMultiplier = input.int(15, '(STRAT) Higher Time Frame Multiplier {15}', minval=1, step=1)
i_HigherTFFastEma = input.int(10, '(STRAT) Higher Time Frame Fast EMA {10}', minval=1, step=1)
i_HigherTFSlowEma = input.int(55, '(STRAT) Higher Time Frame Slow EMA {55}', minval=1, step=1)
i_HigherTFChangeMinimumPeriod = input.int(2, '(STRAT) Higher Time Frame Minimum periods in a row for change{2}', minval=1, step=1)
// Order comments based debug
i_enableOrderCommentDebug = input.bool(false, title='(DEBUG) Enable debug on order comments {False}')
i_enableTakeProfit = input.bool(false, '(STOPTAKE) Take Profit? {false}')
i_enableStopLoss = input.bool(true, '(STOPTAKE) Stop Loss? {True}')
i_enableTrailingTakeProfit = input.bool(false, title='(TRAILING) Enable Trailing Take Profit (%) {False}')
i_takeProfit = input.float(1.1, title='(STOPTAKE) Take Profit % {3.0}') / 100
i_stopLoss = input.float(1.5, title='(STOPTAKE) Stop Loss % {1.5}', minval=0.01) / 100
// Trailing Take Profit - Inputs
i_trailingTakeProfitPercentageTrigger = input.float(1.2, '(TRAILING) Trailing Take Profit Trigger (%) {2.5}', minval=0, step=0.01) * 0.01
i_trailingTakeProfitPercentageOffset = input.float(25.0, '(TRAILING) Trailing Take Profit as a percentage of Trailing Take Profit Trigger (%) {25.0}', minval=0, step=0.01) * 0.01
// Zignaly - Email (zignalye)
_ZIGNALYE_ = 'Email', _ZIGNALYW_ = 'WebHook'
i_zignalyAlertType = input.string(_ZIGNALYW_, '(ZIG) Zignaly Alert Type {WebHook}', options=[_ZIGNALYW_, _ZIGNALYE_])
_ZIGEXZIGNALY_ = 'Zignaly', _ZIGEXBINANCE_ = 'Binance', _ZIGEXKUCOIN_ = 'Kucoin'
i_zignalyExchange = input.string(_ZIGEXZIGNALY_, '(ZIG) Exchange {Zignaly}', options=[_ZIGEXZIGNALY_, _ZIGEXBINANCE_, _ZIGEXKUCOIN_])
_ZIGEXTYPESPOT_ = 'spot', _ZIGEXFUTURES_ = 'futures'
i_zignalyExchangeType = input.string(_ZIGEXFUTURES_, '(ZIG) Exchange Type {Futures}', options=[_ZIGEXFUTURES_, _ZIGEXTYPESPOT_])
i_zignalyLeverage = input.int(1, '(ZIG) Leverage {1}', minval=1, step=1, maxval=125)
var i_zignalyLeverage_str = str.tostring(i_zignalyLeverage)  // It needs to run only once
i_priceDecimalDigits = input.int(2, 'Number of decimal digits for Prices {2}', minval=0, maxval=10, step=1)
// Decimal - Inputs
i_contractMaximumDecimalNumber = input.int(3, title='(DECIMAL) Maximum number of decimal for contracts {3}', minval=0)
i_tooRecentMinutesNumber = input.int(6, '(RECENT) Number of minutes to wait to open a new order after the previous one has been opened {6}', minval=1, maxval=100, step=1)
i_CapitalQuote = input.float(100.0, title='(CAPITAL) Capital quote invested per order in USDT units {100.0}')
i_CapitalPercentage = input.float(25.0, title='(CAPITAL) Capital percentage invested per order (%) {25.0}', minval=0, step=0.01) * 0.01
// Risk Management - Inputs
_SAFE_ = 'Safe', _SCOMPOUND_ = 'Somewhat safe compound', _UCOMPOUND_ = 'Unsafe compound'
i_riskManagementType = input.string(_SCOMPOUND_, '(RISKM) Risk Management Type', options=[_SAFE_, _SCOMPOUND_, _UCOMPOUND_])
i_riskManagementMaximumLossPerTrade = input.float(1.0, title='(RISKM) Maximum loss per trade % {1.0}') / 100
i_riskManagementMaximumLossPerDay = input.float(6.0, title='(RISKM) Maximum loss per day % {6.0}') / 100
i_riskManagementMaximumLossPerWeek = input.float(8.0, title='(RISKM) Maximum loss per week % {8.0}') / 100
i_riskManagementMaximumLossPerMonth = input.float(10.0, title='(RISKM) Maximum loss per month % {10.0}') / 100

// INPUTS - END



// Strategy - INIT - BEGIN

onStartTimeInterval = (not i_strategyStartTimeOn) or (time >= i_strategyStartTime)
offStopTimeInterval = (i_strategyStopTimeOn) and (time > i_strategyStopTime)

// order Stop Loss
float orderStopLoss = na

// Dynamic Trailing Take Profit - Variables

var int buyOrderOpenBarIndex = na
var int sellOrderOpenBarIndex = na

// Handle to avoid two long and short orders being too next to each other
var bool _oldInsideABuyOrder = false
var bool oldInsideASellOrder = false
var bool insideABuyOrder = false
var bool insideASellOrder = false

_oldInsideABuyOrder := insideABuyOrder
oldInsideASellOrder := insideASellOrder

var int lastOrderOpenBarTime = na

// Handle recalculate after Stop Loss / Take Profit order
if (strategy.position_size == 0.0)
    insideABuyOrder := false
    insideASellOrder := false
else
    lastOrderOpenBarTime := time_close

// Zignaly
exchangeTickerID = syminfo.basecurrency + syminfo.currency
var string zignalySeparator = ','
var string zignalyQuote = '"'
var string zignalyEquals = '='
if i_zignalyAlertType == _ZIGNALYE_
    zignalySeparator := '||'
    zignalyQuote := ''
    zignalyEquals := '='
    zignalyEquals
else
    zignalySeparator := ','
    zignalyQuote := '"'
    zignalyEquals := ':'
    zignalyEquals

zignalyCommonAlertMessage = zignalyQuote + 'exchange' + zignalyQuote + zignalyEquals + zignalyQuote + i_zignalyExchange + zignalyQuote + zignalySeparator + zignalyQuote + 'exchangeAccountType' + zignalyQuote + zignalyEquals + zignalyQuote + i_zignalyExchangeType + zignalyQuote + zignalySeparator + zignalyQuote + 'pair' + zignalyQuote + zignalyEquals + zignalyQuote + '' + exchangeTickerID + zignalyQuote + zignalySeparator + zignalyQuote + 'leverage' + zignalyQuote + zignalyEquals + zignalyQuote + i_zignalyLeverage_str + zignalyQuote

var string tmpOrderComment = na
var string tmpOrderAlertMessage = na

var int i_tooRecentMinutesNumber_ms = i_tooRecentMinutesNumber * 60 * 1000 // Convert minutes into milliseconds only once

// Strategy - INIT - END

// FUNCTIONS - BEGIN

// Decimals - Functions
f_getContractMultiplier(_contractMaximumDecimalNumber) =>
    _contractMultiplier = 1
    if (_contractMaximumDecimalNumber == 0)
        _contractMultiplier // Return 1
    else
        for _counter = 1 to _contractMaximumDecimalNumber
            _contractMultiplier:= _contractMultiplier * 10
        _contractMultiplier

f_priceDecimalDigitsZeroString () =>
    // Dependencies: i_priceDecimalDigits (initialized in inputs).
    _zeroString = ''
    if not(i_priceDecimalDigits == 0)
        for _digit = 1 to i_priceDecimalDigits by 1
            _zeroString += '0'
            _zeroString

// —————————— PineCoders MTF Selection Framework functions
// ————— Converts current "timeframe.multiplier" plus the TF into minutes of type float.
f_resInMinutes() =>
    _resInMinutes = timeframe.multiplier * (
      timeframe.isseconds ? 1. / 60. :
      timeframe.isminutes ? 1.       :
      timeframe.isdaily   ? 1440.    :
      timeframe.isweekly  ? 10080.   :
      timeframe.ismonthly ? 43800.   : na)

var currentResInMinutes = f_resInMinutes() // We need to calculate it only once

f_getResolutionBarMinutes(resolution) =>
    minutes = resolution == '1' ? (1 * 1) :
     resolution == '3' ? (3 * 1) :
     resolution == '5' ? (5 * 1) :
     resolution == '15' ? (15 * 1) :
     resolution == '30' ? (30 * 1) :
     resolution == '45' ? (45 * 1) :
     resolution == '60' ? (60 * 1) :
     resolution == '120' ? (2 * 60) :
     resolution == '180' ? (3 * 60) :
     resolution == '240' ? (4 * 60) :
     resolution == '1D' ? (24 * 60) :
     resolution == '1W' ? (7 * 24 * 60) :
     resolution == '1M' ? (4 * 7 * 24 * 60) :
     currentResInMinutes // Equal to current symbol
    minutes

// Zignalye - Functions - BEGIN
f_getZignalyLongAlertMessage(_entryQuantityContractsUSDT, _currentCapital) =>
    // Dependencies: zignalyQuote
    // Dependencies: zignalyEquals
    // Dependencies: zignalySeparator
    // Dependencies: zignalyCommonAlertMessage

    // Dependencies: i_enableStopLoss (initialized in inputs).
    // Dependencies: i_enableTakeProfit (initialized in inputs).
    // Dependencies: i_takeProfit (initialized in inputs).
    // Dependencies: i_enableTrailingTakeProfit (initialized in inputs).
    // Dependencies: i_trailingTakeProfitPercentageOffset (initialized in inputs).
    // Dependencies: i_trailingTakeProfitPercentageTrigger (initialized in inputs).
    // Dependencies: i_zignalyIntegrationType (initialized in inputs).
    
    // Function Dependencies: f_priceDecimalDigitsZeroString()

    var string _zignaleStopLossCombo = ''
    var string _zignaleTakeProfitCombo = ''
    var string _zignaleTrailingTakeProfitCombo = ''
    _zignalyLongCommonAlertMessage = zignalyQuote + 'type' + zignalyQuote + zignalyEquals + zignalyQuote + 'entry' + zignalyQuote + zignalySeparator + zignalyQuote + 'side' + zignalyQuote + zignalyEquals + zignalyQuote + 'long' + zignalyQuote + zignalySeparator + zignalyQuote + 'orderType' + zignalyQuote + zignalyEquals + zignalyQuote + 'market' + zignalyQuote + zignalySeparator + zignalyQuote + 'signalId' + zignalyQuote + zignalyEquals + zignalyQuote + 'LONG-' + exchangeTickerID + zignalyQuote
    float _floatEntryQuantityContractsUSDT = _entryQuantityContractsUSDT
    _entryQuantityContractsUSDTStr = str.tostring(_entryQuantityContractsUSDT, '0.' + f_priceDecimalDigitsZeroString())
    float _floatCurrentCapital = _currentCapital
    float _entryQuantityContractsPercent = _floatEntryQuantityContractsUSDT / _floatCurrentCapital * 100.00
    _entryQuantityContractsPercentStr = str.tostring(_entryQuantityContractsPercent, '0.' + f_priceDecimalDigitsZeroString())

    if i_enableStopLoss and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleStopLossCombo := zignalySeparator + zignalyQuote + 'stopLossPercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '-' + str.tostring(nz(orderStopLoss) * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleStopLossCombo := ''
    if i_enableTakeProfit and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleTakeProfitCombo := zignalySeparator + zignalyQuote + 'takeProfitPercentage1' + zignalyQuote + zignalyEquals + zignalyQuote + '' + str.tostring(i_takeProfit * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleTakeProfitCombo := ''
    if i_enableTrailingTakeProfit and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleTrailingTakeProfitCombo := zignalySeparator + zignalyQuote + 'trailingStopDistancePercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '-' + str.tostring(i_trailingTakeProfitPercentageOffset * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote + zignalySeparator + zignalyQuote + 'trailingStopTriggerPercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '' + str.tostring(i_trailingTakeProfitPercentageTrigger * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleTrailingTakeProfitCombo := ''



    var string _message = ''
    if (i_zignalyProviderType == _ZIGCOPYTRADERPROVIDER_)
        _message := 
             zignalyCommonAlertMessage + 
             zignalySeparator + 
             _zignalyLongCommonAlertMessage + 
             zignalySeparator + 
             zignalyQuote + 'positionSizePercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '' +  _entryQuantityContractsPercentStr + zignalyQuote +
             _zignaleStopLossCombo +
             _zignaleTakeProfitCombo +
             _zignaleTrailingTakeProfitCombo
    else // _ZIGSIGNALPROVIDER_
        _message := 
             zignalyCommonAlertMessage + 
             zignalySeparator + 
             _zignalyLongCommonAlertMessage + 
             zignalySeparator + 
             zignalyQuote + 'positionSizeQuote' + zignalyQuote + zignalyEquals + zignalyQuote + '' +  _entryQuantityContractsUSDTStr + zignalyQuote +
             _zignaleStopLossCombo +
             _zignaleTakeProfitCombo +
             _zignaleTrailingTakeProfitCombo

    _message

f_getZignalyLongCloseAlertMessage() =>
    // Dependencies: zignalyQuote
    // Dependencies: zignalyEquals
    // Dependencies: zignalySeparator
    // Dependencies: zignalyCommonAlertMessage

    _zignalyLongCloseCommonAlertMessage = zignalyQuote + 'type' + zignalyQuote + zignalyEquals + zignalyQuote + 'exit' + zignalyQuote + zignalySeparator + zignalyQuote + 'side' + zignalyQuote + zignalyEquals + zignalyQuote + 'long' + zignalyQuote + zignalySeparator + zignalyQuote + 'orderType' + zignalyQuote + zignalyEquals + zignalyQuote + 'market' + zignalyQuote + zignalySeparator + zignalyQuote + 'signalId' + zignalyQuote + zignalyEquals + zignalyQuote + 'LONG-' + exchangeTickerID + zignalyQuote

    var string _message = ''
    _message := zignalyCommonAlertMessage + zignalySeparator + _zignalyLongCloseCommonAlertMessage
    _message

f_getZignalyShortAlertMessage(_entryQuantityContractsUSDT, _currentCapital) =>
    // Dependencies: zignalyQuote
    // Dependencies: zignalyEquals
    // Dependencies: zignalySeparator
    // Dependencies: zignalyCommonAlertMessage

    // Dependencies: i_enableStopLoss (initialized in inputs).
    // Dependencies: i_enableTakeProfit (initialized in inputs).
    // Dependencies: i_takeProfit (initialized in inputs).
    // Dependencies: i_enableTrailingTakeProfit (initialized in inputs).
    // Dependencies: i_trailingTakeProfitPercentageOffset (initialized in inputs).
    // Dependencies: i_trailingTakeProfitPercentageTrigger (initialized in inputs).
    // Dependencies: i_zignalyIntegrationType (initialized in inputs).
    
    // Function Dependencies: f_priceDecimalDigitsZeroString()

    var string _zignaleStopLossCombo = ''
    var string _zignaleTakeProfitCombo = ''
    var string _zignaleTrailingTakeProfitCombo = ''
    _zignalyLongCloseCommonAlertMessage = zignalyQuote + 'type' + zignalyQuote + zignalyEquals + zignalyQuote + 'entry' + zignalyQuote + zignalySeparator + zignalyQuote + 'side' + zignalyQuote + zignalyEquals + zignalyQuote + 'short' + zignalyQuote + zignalySeparator + zignalyQuote + 'orderType' + zignalyQuote + zignalyEquals + zignalyQuote + 'market' + zignalyQuote + zignalySeparator + zignalyQuote + 'signalId' + zignalyQuote + zignalyEquals + zignalyQuote + 'SHORT-' + exchangeTickerID + zignalyQuote
    float _floatEntryQuantityContractsUSDT = _entryQuantityContractsUSDT
    _entryQuantityContractsUSDTStr = str.tostring(_entryQuantityContractsUSDT, '0.' + f_priceDecimalDigitsZeroString())
    float _floatCurrentCapital = _currentCapital
    float _entryQuantityContractsPercent = _floatEntryQuantityContractsUSDT / _floatCurrentCapital * 100.00
    _entryQuantityContractsPercentStr = str.tostring(_entryQuantityContractsPercent, '0.' + f_priceDecimalDigitsZeroString())

    if i_enableStopLoss and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleStopLossCombo := zignalySeparator + zignalyQuote + 'stopLossPercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '' + str.tostring(nz(orderStopLoss) * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleStopLossCombo := ''
    if i_enableTakeProfit and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleTakeProfitCombo := zignalySeparator + zignalyQuote + 'takeProfitPercentage1' + zignalyQuote + zignalyEquals + zignalyQuote + '-' + str.tostring(i_takeProfit * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleTakeProfitCombo := ''
    if i_enableTrailingTakeProfit and i_zignalyIntegrationType == _ZIGHYBRIDINTEGRATION_
        _zignaleTrailingTakeProfitCombo := zignalySeparator + zignalyQuote + 'trailingStopDistancePercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '' + str.tostring(i_trailingTakeProfitPercentageOffset * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote + zignalySeparator + zignalyQuote + 'trailingStopTriggerPercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '-' + str.tostring(i_trailingTakeProfitPercentageTrigger * 100, '0.' + f_priceDecimalDigitsZeroString()) + zignalyQuote
    else
        _zignaleTrailingTakeProfitCombo := ''



    var string _message = ''
    if (i_zignalyProviderType == _ZIGCOPYTRADERPROVIDER_)
        _message := 
             zignalyCommonAlertMessage + 
             zignalySeparator + 
             _zignalyLongCloseCommonAlertMessage + 
             zignalySeparator + 
             zignalyQuote + 'positionSizePercentage' + zignalyQuote + zignalyEquals + zignalyQuote + '' +  _entryQuantityContractsPercentStr + zignalyQuote +
             _zignaleStopLossCombo +
             _zignaleTakeProfitCombo +
             _zignaleTrailingTakeProfitCombo
    else // _ZIGSIGNALPROVIDER_
        _message := 
             zignalyCommonAlertMessage + 
             zignalySeparator + 
             _zignalyLongCloseCommonAlertMessage + 
             zignalySeparator + 
             zignalyQuote + 'positionSizeQuote' + zignalyQuote + zignalyEquals + zignalyQuote + '' +  _entryQuantityContractsUSDTStr + zignalyQuote +
             _zignaleStopLossCombo +
             _zignaleTakeProfitCombo +
             _zignaleTrailingTakeProfitCombo

    _message

f_getZignalyShortCloseAlertMessage() =>
    // Dependencies: zignalyQuote
    // Dependencies: zignalyEquals
    // Dependencies: zignalySeparator
    // Dependencies: zignalyCommonAlertMessage

    zignalyShortCloseCommonAlertMessage = zignalyQuote + 'type' + zignalyQuote + zignalyEquals + zignalyQuote + 'exit' + zignalyQuote + zignalySeparator + zignalyQuote + 'side' + zignalyQuote + zignalyEquals + zignalyQuote + 'short' + zignalyQuote + zignalySeparator + zignalyQuote + 'orderType' + zignalyQuote + zignalyEquals + zignalyQuote + 'market' + zignalyQuote + zignalySeparator + zignalyQuote + 'signalId' + zignalyQuote + zignalyEquals + zignalyQuote + 'SHORT-' + exchangeTickerID + zignalyQuote

    var string _message = ''
    _message := zignalyCommonAlertMessage + zignalySeparator + zignalyShortCloseCommonAlertMessage
    _message

// Zignalye - Functions - END

// Order comment - Functions - BEGIN

f_getOrderComment(_typeOrder, _side, _alertMessage) =>
    // Dependencies: i_enableOrderCommentDebug (initialized in inputs).

    // TODO: Add descriptive comments
    // _typeOrder="entry" or _typeOrder="close"
    // _side: true means long ; false means short ; We can use strategy.long or strategy.short as true and false aliases
    // _alertMessage
    var string _orderComment = ""
    
    if (i_enableOrderCommentDebug)
        _orderComment := _alertMessage
    else
        // TODO: Use human explanations instead of default order comment value (na)
        _orderComment := na
        
    _orderComment

// Order comment - Functions - END

// Too recent orders functions

f_getTooRecentOrderNotOpenAdvice () =>
    // Dependencies: i_tooRecentMinutesNumber_ms
    // Dependencies: lastOrderOpenBarTime

    // Condition 1: The order was open
    // Condition 2: The order was long or short
    // Condition 3: Time since order was last open is smaller than minimum between orders
    // Returns boolean
    bool _isTooRecent =  ((time_close) <= (lastOrderOpenBarTime + i_tooRecentMinutesNumber_ms))

    bool _tooRecentOrderBuyNotOpenAdvice = na
    if (na(lastOrderOpenBarTime))
        _tooRecentOrderBuyNotOpenAdvice := false
    else
        _tooRecentOrderBuyNotOpenAdvice := _isTooRecent
    _tooRecentOrderBuyNotOpenAdvice

// FUNCTIONS - END


// Strategy Body - BEGIN

hTFFastEmaPeriod = i_HigherTFFastEma * i_HigherTFMultiplier
hTFFastEma = ta.ema(close, hTFFastEmaPeriod)
hTFSlowEmaPeriod = i_HigherTFSlowEma * i_HigherTFMultiplier
hTFSlowEma = ta.ema(close, hTFSlowEmaPeriod)

lowEmaPeriodElapsed = bar_index > hTFSlowEmaPeriod

changeMinimumPeriod = i_HigherTFChangeMinimumPeriod * i_HigherTFMultiplier
var longCondition = true
var shortCondition = false
// Simple Logic to go LONG/LONG or go SHORT/SHORT - BEGIN
if (hTFFastEma > hTFSlowEma) and (hTFFastEma[changeMinimumPeriod] > hTFSlowEma[changeMinimumPeriod])
    longCondition := true
    shortCondition := false
if (hTFFastEma < hTFSlowEma) and (hTFFastEma[changeMinimumPeriod] < hTFSlowEma[changeMinimumPeriod])
    longCondition := false
    shortCondition := true
// Simple Logic to go LONG/LONG or go SHORT/SHORT - END

rsi = ta.rsi(close, i_rsiLength)
float i_rsiLongPreEntry = i_rsiLongEntry - (i_rsiLongEntry * i_rsiLongPreEntryPercentage)
var rsiLongPreEntered = false
if (ta.crossover(rsi, i_rsiLongPreEntry))
    rsiLongPreEntered := true

float i_rsiShortPreEntry = i_rsiShortEntry + (i_rsiShortEntry * i_rsiShortPreEntryPercentage)
var rsiShortPreEntered = false
if (ta.crossunder(rsi, i_rsiShortPreEntry))
    rsiShortPreEntered := true

plot(rsi, color=(not lowEmaPeriodElapsed) ? color.navy : longCondition ? color.white : color.gray, linewidth=2)
plot(longCondition ? i_rsiLongEntry : i_rsiShortEntry, color=color.green)
plot(longCondition ? i_rsiLongExit : i_rsiShortExit, color=color.red)

// Position price calculation - BEGIN
float positionPrice = na
if (insideASellOrder or insideABuyOrder)
    positionPrice := strategy.position_avg_price
else
    positionPrice := close
    
// Position price calculation - END

tooRecentOrderNotOpenAdvice = f_getTooRecentOrderNotOpenAdvice ()

// Decide if we are going to LONG/Go LONG - BEGIN
PRE_LONG = false
if (i_rsiUseLongPreEntry)
    PRE_LONG := onStartTimeInterval and longCondition and (not tooRecentOrderNotOpenAdvice) and ta.crossover(rsi, i_rsiLongEntry) and rsiLongPreEntered and lowEmaPeriodElapsed
else
    PRE_LONG := onStartTimeInterval and longCondition and (not tooRecentOrderNotOpenAdvice) and ta.crossover(rsi, i_rsiLongEntry) and lowEmaPeriodElapsed

if (ta.crossover(rsi, i_rsiLongEntry))
    rsiLongPreEntered := false

// LONG = PRE_LONG[1] and PRE_LONG // Wait for confirmation
LONG = PRE_LONG // Do not wait for confirmation

// Decide if we are going to LONG/Go LONG - END

// Decide if we are going to SHORT/Go SHORT - BEGIN
PRE_SHORT = false
if (i_rsiUseShortPreEntry)
    PRE_SHORT := onStartTimeInterval and shortCondition and (not tooRecentOrderNotOpenAdvice) and ta.crossunder(rsi, i_rsiShortEntry) and rsiShortPreEntered and lowEmaPeriodElapsed
else
    PRE_SHORT := onStartTimeInterval and shortCondition and (not tooRecentOrderNotOpenAdvice) and ta.crossunder(rsi, i_rsiShortEntry) and lowEmaPeriodElapsed

if (ta.crossunder(rsi, i_rsiShortEntry))
    rsiShortPreEntered := false

// SHORT = PRE_SHORT[1] and PRE_SHORT // Wait for confirmation
SHORT = PRE_SHORT // Do not wait for confirmation

// Decide if we are going to SHORT/Go SHORT - END

// Decide if a LONG/LONG entry should be closed - BEGIN
LONG_CLOSE = true
if (i_rsiUseEmergency)
    LONG_CLOSE := offStopTimeInterval or (not (longCondition)) or ta.crossunder(rsi, i_rsiLongExit) or ta.crossunder(rsi, i_rsiLongEmergencyExit)
else
    LONG_CLOSE := offStopTimeInterval or (not (longCondition)) or ta.crossunder(rsi, i_rsiLongExit)

// Let's make sure LONG does not trigger if LONG_CLOSE would tell us to close the LONG
if LONG_CLOSE
    LONG := false
// Decide if a LONG/LONG entry should be closed - END

// Decide if a SHORT/SHORT entry should be closed - BEGIN
SHORT_CLOSE = true
SHORT_CLOSE := offStopTimeInterval or (not (shortCondition)) or ta.crossover(rsi, i_rsiShortExit)

// Let's make sure SHORT does not trigger if SHORT_CLOSE would tell us to close the SHORT
if SHORT_CLOSE
    SHORT := false
// Decide if a SHORT/SHORT entry should be closed - END

// orderStopLoss is just here just in case
// we implement i_longStopLoss and i_shortStopLoss
// in the future
if LONG
    orderStopLoss := i_stopLoss
else
    orderStopLoss := i_stopLoss


// How much to LONG/GO LONG/SHORT/GO SHORT - BEGIN

// Custom take profit and stop loss
LongTakeProfit = positionPrice * (1 + i_takeProfit)
ShortTakeProfit = positionPrice * (1 - i_takeProfit)

float LongStopLoss = na
float ShortStopLoss = na

LongStopLoss := positionPrice * (1 - orderStopLoss)
ShortStopLoss := positionPrice * (1 + orderStopLoss)

float entryQuantity = na
float currentCapital = strategy.initial_capital + strategy.netprofit

if (i_zignalyProviderType == _ZIGCOPYTRADERPROVIDER_)
    entryQuantity := i_CapitalPercentage * currentCapital
else // _ZIGSIGNALPROVIDER_
    entryQuantity := i_CapitalQuote

if (i_zignalyProviderType == _ZIGCOPYTRADERPROVIDER_) // Risk management is only implemented for CopyTrader Providers
    // i_riskManagementMaximumLossPerDay
    var float currentDayEntryQuantity = na
    currentDayEntryQuantity := na
    var currentDayLoss = 0.0
    var currentDayCapital = 0.0
    var currentDay = 0
    var dayMinutes = f_getResolutionBarMinutes('1D')
    var barMinutes = f_getResolutionBarMinutes(timeframe.period)
    barMinutesToNow = bar_index * barMinutes
    currentDay := math.floor(barMinutesToNow / dayMinutes)

    // i_riskManagementMaximumLossPerWeek
    var float currentWeekEntryQuantity = na
    currentWeekEntryQuantity := na
    var currentWeekLoss = 0.0
    var currentWeekCapital = 0.0
    var currentWeek = 0
    var weekMinutes = f_getResolutionBarMinutes('1W')
    currentWeek := math.floor(barMinutesToNow / weekMinutes)

    // riskManagementMaximumLossPerMonth
    var float currentMonthEntryQuantity = na
    currentMonthEntryQuantity := na
    var currentMonthLoss = 0.0
    var currentMonthCapital = 0.0
    var currentMonth = 0
    var monthMinutes = f_getResolutionBarMinutes('1M')
    currentMonth := math.floor(barMinutesToNow / monthMinutes)

    float tmpEntryQuantity = na

    if (i_riskManagementType == _SAFE_)
        // Safe means we stick to the original initial capital
        // to enforce our risk management policy
        tmpEntryQuantity := (strategy.initial_capital * i_riskManagementMaximumLossPerTrade) / orderStopLoss

    else if (i_riskManagementType == _SCOMPOUND_)
        // Safe compound means that we are gambling everything we have
        // but we try to follow risk management rules
        tmpEntryQuantity:= (currentCapital * i_riskManagementMaximumLossPerTrade) / orderStopLoss

    else if (i_riskManagementType == _UCOMPOUND_)
        // Unsafe compound means that we are gambling always everything we have
        tmpEntryQuantity := currentCapital

    if (tmpEntryQuantity > currentCapital)
        // Avoid being stuck when numbers don't match
        entryQuantity := currentCapital
    else
        entryQuantity := tmpEntryQuantity

    // DAY
    if (currentDay[1] != currentDay)
        currentDayLoss := 0.0
        currentDayCapital := currentCapital
    else
        if (currentCapital < currentDayCapital)
            currentDayLoss := currentDayCapital - currentCapital
        else
            currentDayLoss := 0.0
        tmpCurrentDayLossPerOne = currentDayLoss / currentDayCapital
        if (tmpCurrentDayLossPerOne >= i_riskManagementMaximumLossPerDay)
            currentDayEntryQuantity:= 0.0 // Avoid entering a position

    // WEEK
    if (currentWeek[1] != currentWeek)
        currentWeekLoss := 0.0
        currentWeekCapital := currentCapital
    else
        if (currentCapital < currentWeekCapital)
            currentWeekLoss := currentWeekCapital - currentCapital
        else
            currentWeekLoss := 0.0
        tmpCurrentWeekLossPerOne = currentWeekLoss / currentWeekCapital
        if (tmpCurrentWeekLossPerOne >= i_riskManagementMaximumLossPerWeek)
            currentWeekEntryQuantity:= 0.0 // Avoid entering a position

    // MONTH
    if (currentMonth[1] != currentMonth)
        currentMonthLoss := 0.0
        currentMonthCapital := currentCapital
    else
        if (currentCapital < currentMonthCapital)
            currentMonthLoss := currentMonthCapital - currentCapital
        else
            currentMonthLoss := 0.0
        tmpCurrentMonthLossPerOne = currentMonthLoss / currentMonthCapital
        if (tmpCurrentMonthLossPerOne >= i_riskManagementMaximumLossPerMonth)
            currentMonthEntryQuantity:= 0.0 // Avoid entering a position

    // Avoid to enter a position overall logic
    if ( (not na(currentDayEntryQuantity)) or (not na(currentWeekEntryQuantity)) or (not na(currentMonthEntryQuantity)) )
        entryQuantity:= 0.0

float entryQuantityContractsReducer = 0.99

contractMultiplier = f_getContractMultiplier(i_contractMaximumDecimalNumber)

// We assume the current price is current bar close

entryQuantityContracts = (math.floor(((entryQuantity / close) * entryQuantityContractsReducer) * contractMultiplier) / contractMultiplier)
entryQuantityContractsUSDT = entryQuantityContracts * (close)

// How much to LONG/GO LONG/SHORT/GO SHORT - END


// GO LONG only logic - BEGIN

var float tmpPositionBeforeOpeningOrder = na

if (i_strategyType == _L_)
    if LONG
        tmpPositionBeforeOpeningOrder := strategy.position_avg_price
        tmpOrderAlertMessage := f_getZignalyLongAlertMessage(entryQuantityContractsUSDT, currentCapital)
        tmpOrderComment := f_getOrderComment("entry", strategy.long, tmpOrderAlertMessage)
        strategy.entry("[L]", strategy.long, qty=entryQuantityContracts, alert_message=i_enableZignalyAlert ? tmpOrderAlertMessage : na, comment=tmpOrderComment)
        if (na(tmpPositionBeforeOpeningOrder)) // bar_index should only be saved when there is no order opened
            buyOrderOpenBarIndex := bar_index + 1
        insideABuyOrder := true
        0 // Workaround for making every if branch to return the same type of value
    else if LONG_CLOSE
        tmpOrderComment := f_getOrderComment("close", strategy.long, f_getZignalyLongCloseAlertMessage())
        strategy.close("[L]", alert_message=i_enableZignalyAlert ? f_getZignalyLongCloseAlertMessage() : na, comment=tmpOrderComment)
        insideABuyOrder := false
        0 // Workaround for making every if branch to return the same type of value
// GO LONG only logic - END

// GO SHORT only logic - BEGIN
if (i_strategyType == _S_)
    if SHORT
        tmpPositionBeforeOpeningOrder := strategy.position_avg_price
        tmpOrderAlertMessage := f_getZignalyShortAlertMessage(entryQuantityContractsUSDT, currentCapital)
        tmpOrderComment := f_getOrderComment("entry", strategy.short, tmpOrderAlertMessage)
        strategy.entry("[S]", strategy.short, qty=entryQuantityContracts, alert_message=i_enableZignalyAlert ? tmpOrderAlertMessage : na, comment=tmpOrderComment)
        if (na(tmpPositionBeforeOpeningOrder)) // bar_index should only be saved when there is no order opened
            sellOrderOpenBarIndex := bar_index + 1
        insideASellOrder := true
        0 // Workaround for making every if branch to return the same type of value
    else if SHORT_CLOSE
        tmpOrderComment := f_getOrderComment("close", strategy.short, f_getZignalyShortCloseAlertMessage())
        strategy.close("[S]", alert_message=i_enableZignalyAlert ? f_getZignalyShortCloseAlertMessage() : na, comment=tmpOrderComment)
        insideASellOrder := false
        0 // Workaround for making every if branch to return the same type of value
// GO SHORT only logic - END

// GO LONG and SHORT logic - BEGIN
if (i_strategyType == L_S)
// Asumption: Above we have:
// if LONG_CLOSE
//    LONG := false
// if SHORT_CLOSE
//    SHORT := false

    // LONG and SHORT cannot be true at the same time
    // Anyways we will take it into account
    if (LONG == true) and (SHORT == true)
        LONG := true
        SHORT := false
        SHORT_CLOSE := true

    if LONG
        tmpPositionBeforeOpeningOrder := strategy.position_avg_price
        tmpOrderAlertMessage := f_getZignalyLongAlertMessage(entryQuantityContractsUSDT, currentCapital)
        tmpOrderComment := f_getOrderComment("entry", strategy.long, tmpOrderAlertMessage)
        strategy.entry("[L]", strategy.long, qty=entryQuantityContracts, alert_message=i_enableZignalyAlert ? tmpOrderAlertMessage : na, comment=tmpOrderComment)
        if (na(tmpPositionBeforeOpeningOrder)) // bar_index should only be saved when there is no order opened
            buyOrderOpenBarIndex := bar_index + 1
        insideABuyOrder := true
    if LONG_CLOSE
        tmpOrderComment := f_getOrderComment("close", strategy.long, f_getZignalyLongCloseAlertMessage())
        strategy.close("[L]", alert_message=i_enableZignalyAlert ? f_getZignalyLongCloseAlertMessage() : na, comment=tmpOrderComment)
        insideABuyOrder := false
    if SHORT
        tmpPositionBeforeOpeningOrder := strategy.position_avg_price
        tmpOrderAlertMessage := f_getZignalyShortAlertMessage(entryQuantityContractsUSDT, currentCapital)
        tmpOrderComment := f_getOrderComment("entry", strategy.short, tmpOrderAlertMessage)
        strategy.entry("[S]", strategy.short, qty=entryQuantityContracts, alert_message=i_enableZignalyAlert ? tmpOrderAlertMessage : na, comment=tmpOrderComment)
        if (na(tmpPositionBeforeOpeningOrder)) // bar_index should only be saved when there is no order opened
            sellOrderOpenBarIndex := bar_index + 1
        insideASellOrder := true
    if SHORT_CLOSE
        tmpOrderComment := f_getOrderComment("close", strategy.short, f_getZignalyShortCloseAlertMessage())
        strategy.close("[S]", alert_message=i_enableZignalyAlert ? f_getZignalyShortCloseAlertMessage() : na, comment=tmpOrderComment)
        insideASellOrder := false
// GO LONG and SHORT logic - END

// Handle STOP LOSS (and similar) order exits - BEGIN

// Quick Paste - BEGIN
float longTrailingTakeProfitPrice = na
float longTrailingTakeProfitPoints = na
float longTrailingTakeProfitOffset = na
float shortTrailingTakeProfitPrice = na
float shortTrailingTakeProfitPoints = na
float shortTrailingTakeProfitOffset = na

// Calculate trailing_take_profit_offset based on tick units
longTmpTtpBaseValue = positionPrice * (1 + i_trailingTakeProfitPercentageTrigger)
longTmpTtpTop_value = longTmpTtpBaseValue * (1 + i_trailingTakeProfitPercentageOffset)
longTrailingTakeProfitOffsetFloat = longTmpTtpTop_value - longTmpTtpBaseValue
float longTrailingTakeProfitOffsetTick = math.floor (longTrailingTakeProfitOffsetFloat / syminfo.mintick)

shortTmpTtpBaseValue = positionPrice * (1 - i_trailingTakeProfitPercentageTrigger)
shortTmpTtpBottomValue = shortTmpTtpBaseValue * (1 - i_trailingTakeProfitPercentageOffset)
shortTrailingTakeProfitOffsetFloat = shortTmpTtpBaseValue - shortTmpTtpBottomValue
float shortTrailingTakeProfitOffsetTick = math.floor (shortTrailingTakeProfitOffsetFloat / syminfo.mintick)

if i_enableTrailingTakeProfit
    longTrailingTakeProfitPrice := positionPrice * (1 + i_trailingTakeProfitPercentageTrigger)
    longTrailingTakeProfitOffset := longTrailingTakeProfitOffsetTick
    shortTrailingTakeProfitPrice := positionPrice * (1 - i_trailingTakeProfitPercentageTrigger)
    shortTrailingTakeProfitOffset := shortTrailingTakeProfitOffsetTick
else
    longTrailingTakeProfitPrice := na
    longTrailingTakeProfitOffset := na
    shortTrailingTakeProfitPrice := na
    shortTrailingTakeProfitOffset := na
// Quick Paste - END

// This might trigger additional close orders than needed in zignaly
// Better close an existing order twice than regreting zignaly not having closed it.

tmpOrderComment := f_getOrderComment("close", strategy.long, f_getZignalyLongCloseAlertMessage())
strategy.exit("[SL/TP]", "[L]", stop= i_enableStopLoss ? LongStopLoss : na, limit= i_enableTakeProfit ? LongTakeProfit : na, trail_price= i_enableTrailingTakeProfit ? longTrailingTakeProfitPrice : na, trail_offset = i_enableTrailingTakeProfit ? longTrailingTakeProfitOffset : na, alert_message= i_enableZignalyAlert ? f_getZignalyLongCloseAlertMessage() : na, comment=tmpOrderComment)
tmpOrderComment := f_getOrderComment("close", strategy.short, f_getZignalyShortCloseAlertMessage())
strategy.exit("[SL/TP]", "[S]", stop= i_enableStopLoss ? ShortStopLoss : na, limit= i_enableTakeProfit ? ShortTakeProfit : na, trail_price= i_enableTrailingTakeProfit ? shortTrailingTakeProfitPrice : na, trail_offset = i_enableTrailingTakeProfit ? shortTrailingTakeProfitOffset : na, alert_message= i_enableZignalyAlert ? f_getZignalyShortCloseAlertMessage() : na, comment=tmpOrderComment)

// Handle STOP LOSS (and similar) order exits - END

// Strategy Body - END

Overview

Long entries trigger at RSI 45 and shorts at RSI 55. Exits occur at RSI 55 for longs and 47 for shorts, with emergency stops at RSI 10. Higher-timeframe EMA confirmation (fast 10, slow 55, minimum 2 periods) filters signals on the 15-minute BTCUSDT chart. The strategy supports strategy type selection, start and stop times, stop loss at 1.5% by default, optional take profit, and trailing stops. Signals plot in a separate pane and integrate with Zignaly for crypto trading.

Details

Published by

ruckard on GitHub

Type

Strategy, Pine Script v5

Draws

Separate pane below the chart

Category

Oscillators & momentum, Moving averages

Markets

Crypto

Timeframes

M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
(ZIG) Enable Alert message {True}booltruei_enableZignalyAlert
(ZIG) Integration typestring_ZIGHYBRIDINTEGRATION_i_zignalyIntegrationType
(ZIG) Provider typestring_ZIGCOPYTRADERPROVIDER_i_zignalyProviderType
(STRAT) Strategy TypestringL_Si_strategyType
(STRAT) Strategy Start Time {2021-01-01 00:00:00}timetimestamp('01 Jan 2021')i_strategyStartTime
(STRAT) Strategy Stop Time {2021-12-31 00:00:00}timetimestamp('31 Dec 2021')i_strategyStopTime
(STRAT) Strategy Start Time forced? {True}booltruei_strategyStartTimeOn
(STRAT) Strategy Stop Time forced? {False}boolfalsei_strategyStopTimeOn
(STRAT) RSI length {100}int100i_rsiLength
RSI . Use Emergency Exit?boolfalsei_rsiUseEmergency
RSI Long Entry {45}float45i_rsiLongEntry
RSI . Use Long Pre Entry? {True}booltruei_rsiUseLongPreEntry
Show all 40 settings
SettingTypeDefaultVariable
RSI Long Pre Entry % {5}float5i_rsiLongPreEntryPercentage
RSI Long Exit {55}float55i_rsiLongExit
RSI Long Emergency Exit {10}float10i_rsiLongEmergencyExit
RSI Short Entry {55}float55i_rsiShortEntry
RSI . Use Short Pre Entry? {True}booltruei_rsiUseShortPreEntry
RSI Short Pre Entry % {5}float5i_rsiShortPreEntryPercentage
RSI Short Exit {47}float47i_rsiShortExit
(STRAT) Higher Time Frame Multiplier {15}int15i_HigherTFMultiplier
(STRAT) Higher Time Frame Fast EMA {10}int10i_HigherTFFastEma
(STRAT) Higher Time Frame Slow EMA {55}int55i_HigherTFSlowEma
(STRAT) Higher Time Frame Minimum periods in a row for change{2}int2i_HigherTFChangeMinimumPeriod
(DEBUG) Enable debug on order comments {False}boolfalsei_enableOrderCommentDebug
(STOPTAKE) Take Profit? {false}boolfalsei_enableTakeProfit
(STOPTAKE) Stop Loss? {True}booltruei_enableStopLoss
(TRAILING) Enable Trailing Take Profit (%) {False}boolfalsei_enableTrailingTakeProfit
(STOPTAKE) Take Profit % {3.0}float1.1i_takeProfit
(STOPTAKE) Stop Loss % {1.5}float1.5i_stopLoss
(TRAILING) Trailing Take Profit Trigger (%) {2.5}float1.2i_trailingTakeProfitPercentageTrigger
(TRAILING) Trailing Take Profit as a percentage of Trailing Take Profit Trigger (%) {25.0}float25.0i_trailingTakeProfitPercentageOffset
(ZIG) Zignaly Alert Type {WebHook}string_ZIGNALYW_i_zignalyAlertType
(ZIG) Exchange {Zignaly}string_ZIGEXZIGNALY_i_zignalyExchange
(ZIG) Exchange Type {Futures}string_ZIGEXFUTURES_i_zignalyExchangeType
(ZIG) Leverage {1}int1i_zignalyLeverage
Number of decimal digits for Prices {2}int2i_priceDecimalDigits
(DECIMAL) Maximum number of decimal for contracts {3}int3i_contractMaximumDecimalNumber
(RECENT) Number of minutes to wait to open a new order after the previous one has been opened {6}int6i_tooRecentMinutesNumber
(CAPITAL) Capital quote invested per order in USDT units {100.0}float100.0i_CapitalQuote
(CAPITAL) Capital percentage invested per order (%) {25.0}float25.0i_CapitalPercentage
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

330 stars

MACD + Divergences [Alorse] is a momentum strategy that calculates the MACD oscillator and identifies regular and hidden divergences using pivot high and low points. It filters trade signals with dual Exponential Moving Averages (EMA 150 and 600) to ensure tra

Strategy v4 Oscillators & momentumDivergence Repaints
Updated 2 months ago · None stated GitHub repository of MACD + Divergences [Alorse]

MACD Crossover (tutorial)

by pineforge-4pass
193 stars

This strategy calculates the Moving Average Convergence Divergence indicator and plots the MACD line, signal line, and histogram in a separate pane. It enters long positions when the MACD line crosses above the signal line and enters short positions when it cr

Strategy v6 Oscillators & momentumMoving averages
Updated today · Apache-2.0 GitHub repository of MACD Crossover (tutorial)

8D Run

by hasnocool
106 stars

8D Run is a Pine Script momentum strategy inspired by Linda Bradford Raschke. It tracks consecutive price closes relative to a 5-period Simple Moving Average (SMA). When price remains above the SMA for 8 or more bars and then dips below it, the strategy enters

Strategy v5 Oscillators & momentumMoving averages
Updated 2 years ago · GPL-3.0 GitHub repository of 8D Run

BTC Futures MACD

by iamrichardD
57 stars

This strategy plots a MACD oscillator in a separate pane and trades Bitcoin futures from zero-line and signal-line crosses. Optional early momentum signals, a volume filter, and a trend moving-average filter can confirm entries. It sizes positions as fixed con

Strategy v6 Oscillators & momentumMoving averages Repaints
Updated 1 year ago · Apache-2.0 GitHub repository of BTC Futures MACD
25 stars

This Pine Script strategy calculates Bayesian probabilities of price breaking up or down relative to Bollinger Bands and a Simple Moving Average. It plots these breakout and breakdown probability lines as oscillators in a separate pane. Long entries trigger wh

Strategy v4 Oscillators & momentumVolatility & bands
Updated 6 years ago · None stated GitHub repository of Bayesian BBSMA Oscillator Strategy

Greeffer BB Strategy

by SammyEnigma
18 stars

This strategy combines Bollinger Bands, Bollinger Band Width, and the Relative Strength Index (RSI) for mean-reversion trades. It enters long when price crosses below the lower band with oversold RSI, or when band width contracts under low volatility. Short en

Strategy v4 Mean reversionOscillators & momentum
Updated 6 years ago · None stated GitHub repository of Greeffer BB Strategy

More strategys

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers