이 전략은 단순한 이동 평균의 황금 십자 및 죽은 십자에 의해 트렌드 방향을 식별하고, 트렌드의 시작에서 전체 포지션 크기로 길거나 짧게 이동하고, 위험을 제어하기 위해 스톱 로스를 설정하고 수익을 취하십시오. 포지션에 진입한 후, 트렌드를 이동 평균을 사용하여 추적하고 트렌드 반전이있을 때 손실을 절감합니다. 이 전략에는 또한 다른 제품에 대한 매개 변수를 유연하게 조정 할 수있는 스톱 로스, 수익을 취하고 포지션 크기를 구성 할 수있는 모듈이 있습니다.
이 전략의 핵심은 단순한 이동 평균의 황금 십자와 죽은 십자 를 사용하여 트렌드 시작과 끝을 결정하는 것입니다. 먼저 빠른 SMA (예를 들어 21 기간) 와 느린 SMA (예를 들어 49 기간) 사이의 관계를 기반으로 트렌드 방향을 식별합니다. 빠른 SMA가 느린 SMA 위에 넘을 때 상승 추세를 신호하며 전략은 길게 갈 것입니다. 빠른 SMA가 느린 SMA 아래에 넘을 때 하락 추세를 신호하며 전략은 짧게 갈 것입니다.
포지션에 입력 한 후 전략은 실시간으로 SMA에 대한 가격을 모니터링합니다. 가격이 SMA를 상에서 깨면 긴 포지션을 닫고 가격이 SMA를 아래에서 깨면 짧은 포지션을 닫습니다. 트렌드 역전 신호로.
위험 통제를 위해 전략은 포지션을 오픈할 때 simultaneously stop loss and take profit orders를 설정한다. Stop loss 거리는 ATR를 기반으로 하고, take profit 거리는 ATR의 배수 또는 비율로 구성될 수 있다. 포지션을 오픈한 후, stop loss는 트렌드를 추적하기 위해 가격을 추적한다. take profit가 닿으면 부분적인 포지션을 먼저 닫고 나머지는 완전히 닫기 전까지 추적을 계속한다.
이 전략은 또한 각 거래에 사용 된 자금을 제한하고 거래 리스크 노출을 제어하는 위치 사이징 모듈을 가지고 있습니다. 또한 최대 인출 제한은 전체 전략 위험을 제한하는 데 도움이됩니다.
요약하자면, 이것은 간단한 논리와 이해하기 쉬운 초보자에게 매우 적합한 시작 전략입니다. 또한 큰 손실을 줄이기 위해 적절한 위험 통제 기능을 가지고 있습니다. 매개 변수 조정으로 좋은 결과를 얻을 수 있습니다. 그러나 그것의 본질적인 약점 또한 높은 정확도로 작동 할 수 없다는 것을 결정합니다. 초보자가 연습하는 것이 권장되지만 높은 효율성과 승률을 추구하는 고급 거래자에게 적합하지 않을 수 있습니다. 더 나은 거래 성능을 얻기 위해 더 강력한 예측 능력을 가진 전략을 추구해야합니다.
/*backtest start: 2023-01-01 00:00:00 end: 2023-11-02 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // ----------------------------------------------------------------------------- // Copyright 2022 Iason Nikolas | jason5480 // Template Strategy script may be freely distributed under the MIT license. // // Permission is hereby granted, free of charge, // to any person obtaining a copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // ----------------------------------------------------------------------------- // // Authors: @jason5480 // Revision: v0.0.1 // Date: 26-Feb-2022 // // Description // ============================================================================= // This script is designed to be used as a template for building new strategies. // The framework provide you with a configurable implementation of the entry, exit, // stop loss and take profit trailing logic. The user of this script has to copy // it and replace the openLongPosition, openShortPosition, closeLongPosition and // closeShortPosition variables in the STRATEGY module according to his needs! // // ----------------------------------------------------------------------------- // Disclaimer: // 1. I am not licensed financial advisors or broker dealer. I do not tell you // when or what to buy or sell. I developed this software which enables you // execute manual or automated trades using TradingView. The // software allows you to set the criteria you want for entering and exiting // trades. // 2. Do not trade with money you cannot afford to lose. // 3. I do not guarantee consistent profits or that anyone can make money with no // effort. And I am not selling the holy grail. // 4. Every system can have winning and losing streaks. // 5. Money management plays a large role in the results of your trading. For // example: lot size, account size, broker leverage, and broker margin call // rules all have an effect on results. Also, your Take Profit and Stop Loss // settings for individual pair trades and for overall account equity have a // major impact on results. If you are new to trading and do not understand // these items, then I recommend you seek education materials to further your // knowledge. // // YOU NEED TO FIND AND USE THE TRADING SYSTEM THAT WORKS BEST FOR YOU AND YOUR // TRADING TOLERANCE. // // I HAVE PROVIDED NOTHING MORE THAN A TOOL WITH OPTIONS FOR YOU TO TRADE WITH THIS PROGRAM ON TRADINGVIEW. // // I accept suggestions to improve the script. // If you encounter any problems I will be happy to share with me. // ----------------------------------------------------------------------------- // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // SETUP ============================================================================================================ strategy(title = 'Template Trailing Strategy', shorttitle = 'TTS', overlay = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, initial_capital = 100000) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // FILTERS ========================================================================================================== // INPUT ============================================================================================================ usefromDate = input.bool(defval = true, title = 'From', inline = "From Date", group = "Filters") fromDate = input(defval = timestamp('01 Jan 2021 00:00 UTC'), title = '', inline = "From Date", group = 'Filters') usetoDate = input.bool(defval = false, title = 'To ', inline = "To Date", group = "Filters") toDate = input(defval = timestamp('31 Dec 2121 23:59 UTC'), title = '', inline = "To Date", group = 'Filters') longTradesEnabled = input.bool(defval = true, title = 'Long Trades', inline = 'Trades', group = 'Filters') shortTradesEnabled = input.bool(defval = true, title = 'Short Trades', tooltip = 'Enable long/short trades.', inline = 'Trades', group = 'Filters') emaFilterEnabled = input.bool(defval = true, title = 'EMA Filter', tooltip = 'Enable long/short trades based on EMA.', group = 'Filters') emaResolution = input.timeframe(defval = 'D', title = 'EMA Res/Len/Src', inline = 'EMA Filter', group = 'Filters') emaLength = input.int(defval = 200, title = '', inline = 'EMA Filter', group = 'Filters') emaSrc = input.source(defval = close, title = '', tooltip = 'The timeframe, period and source for the EMA calculation.', inline = 'EMA Filter', group = 'Filters') emaAtrBandEnabled = input.bool(defval = true, title = 'EMA ATR Band', tooltip = 'Enable ATR band for EMA filter.', group = 'Filters') filterAtrLength = input.int(defval = 5, title = 'EMA ATR Len/Mul', minval = 1, inline = 'EMA ATR', group = 'Filters') filterAtrMul = input.float(defval = 1.0, title = '', tooltip = 'ATR length and multiplier to be used for the ATR calculation that will be added on top of the EMA filter.', minval = 0.1, step = 0.1, inline = 'EMA ATR', group = 'Filters') // LOGIC ============================================================================================================ isWithinPeriod() => true emaLine = request.security(syminfo.tickerid, emaResolution, ta.ema(emaSrc, emaLength)) emaAtr = ta.atr(filterAtrLength) emaUpperBand = emaLine + filterAtrMul * emaAtr emaLowerBand = emaLine - filterAtrMul * emaAtr bool emaLongApproval = emaFilterEnabled ? close > (emaAtrBandEnabled ? emaUpperBand : emaLine) and open > (emaAtrBandEnabled ? emaUpperBand : emaLine) : true bool emaShortApproval = emaFilterEnabled ? close < (emaAtrBandEnabled ? emaLowerBand : emaLine) and open < (emaAtrBandEnabled ? emaLowerBand : emaLine) : true bool longFiltersApproval = longTradesEnabled and emaLongApproval and isWithinPeriod() bool shortFiltersApproval = shortTradesEnabled and emaShortApproval and isWithinPeriod() // PLOT ============================================================================================================= bgcolor(color = isWithinPeriod() ? color.new(color.gray, 90) : na, title = 'Period') showEma = input.bool(defval = true, title = 'Show EMA Line', inline = 'EMA Show', group = 'Plot') showEmaBand = input.bool(defval = false, title = 'Show EMA Band', tooltip = 'Show the EMA Line/Band.', inline = 'EMA Show', group = 'Plot') emaLineColor = emaLongApproval ? color.teal : emaShortApproval ? color.maroon : color.gray plot(series = emaFilterEnabled and showEma ? emaLine : na, color = emaLineColor, style = plot.style_line, linewidth = 2, title = 'EMA Line') emaUpperBandPlot = plot(series = emaUpperBand, color = na, style = plot.style_line, linewidth = 1, title = 'EMA Upper Band') emaLowerBandPlot = plot(series = emaLowerBand, color = na, style = plot.style_line, linewidth = 1, title = 'EMA Lower Band') emaBandFillColor = emaFilterEnabled and emaAtrBandEnabled and showEmaBand ? color.new(emaLineColor, 95) : na fill(plot1 = emaUpperBandPlot, plot2 = emaLowerBandPlot, color = emaBandFillColor, title = 'EMA Band') // INPUT ============================================================================================================ // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // STRATEGY ========================================================================================================= // INPUT ============================================================================================================ fastMALen = input.int(defval = 21, title = 'Fast/Slow SMA Length', inline = 'MA Length', group = 'Strategy') slowMALen = input.int(defval = 49, title = '', tooltip = 'How many candles back to calculte the fast/slow SMA.', inline = 'MA Length', group = 'Strategy') // LOGIC ============================================================================================================ fastMA = ta.sma(close, fastMALen) slowMA = ta.sma(close, slowMALen) bool openLongPosition = longFiltersApproval and ta.crossover(fastMA, slowMA) bool openShortPosition = shortFiltersApproval and ta.crossunder(fastMA, slowMA) bool closeLongPosition = longTradesEnabled and ta.crossunder(fastMA, slowMA) bool closeShortPosition = shortTradesEnabled and ta.crossover(fastMA, slowMA) // PLOT ============================================================================================================= var fastColor = color.new(#0056BD, 0) plot(series = fastMA, title = 'Fast SMA', color = fastColor, linewidth = 1, style = plot.style_line) var slowColor = color.new(#FF6A00, 0) plot(series = slowMA, title = 'Slow SMA', color = slowColor, linewidth = 1, style = plot.style_line) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // SHARED VARIABLES ================================================================================================= // INPUT ============================================================================================================ atrLength = input.int(defval = 14, title = 'ATR Length', minval = 1, tooltip = 'How many previous candles to use for the ATR calculation.', group = 'General') // LOGIC ============================================================================================================ // the open signals when not already into a position bool validOpenLongPosition = openLongPosition and not (strategy.position_size > 0) bool validOpenShortPosition = openShortPosition and not (strategy.position_size < 0) bool validCloseLongPosition = closeLongPosition and strategy.position_size > 0 bool validCloseShortPosition = closeShortPosition and strategy.position_size < 0 // count how far are the last valid open and regular close signals int barsSinceValidOpenLong = nz(ta.barssince(validOpenLongPosition), 999999) int barsSinceValidOpenShort = nz(ta.barssince(validOpenShortPosition), 999999) int barsSinceCloseLong = nz(ta.barssince(closeLongPosition), 999999) int barsSinceCloseShort = nz(ta.barssince(closeShortPosition), 999999) // take profit has to communicate its execution with the stop loss logic when 'TP' mode is selected var bool longTrailingTakeProfitExecuted = false var bool shortTrailingTakeProfitExecuted = false // close price when the valid open signal was triggered float openPrice = ta.valuewhen(validOpenLongPosition or validOpenShortPosition, close, 0) float openAtr = ta.valuewhen(validOpenLongPosition or validOpenShortPosition, ta.atr(atrLength), 0) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // ENTRY ============================================================================================================ // INPUT ============================================================================================================ enableEntryTrailing = input.bool(defval = false, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for entry position.', group = 'Entry') devEntryMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Entry.', group = 'Entry') devEntryPerc = input.float(defval = 1.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The step to follow the price when the open position condition is met.', group = 'Entry') / 100 devEntryAtrMul = input.float(defval = 0.5, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the entry target is reached.', group = 'Entry') ctrLongEntrySrc = input.source(defval = high, title = 'Long/Short Entry Control', inline = 'Control', group = 'Entry') ctrShortEntrySrc = input.source(defval = low, title = '', tooltip = 'The price source to check with the entry target to trigger the entry order for Long/Short position.', inline = 'Control', group = 'Entry') // LOGIC ============================================================================================================ var bool enterLongPosition = false int barsSinceEnterLong = nz(ta.barssince(enterLongPosition), 999999) bool openLongIsActive = barsSinceCloseLong >= barsSinceValidOpenLong bool enterLongIsPending = barsSinceEnterLong >= barsSinceValidOpenLong bool tryEnterLongPosition = longFiltersApproval and openLongIsActive and enterLongIsPending getLongEntryPrice(baseSrc) => switch devEntryMethod 'PERC' => baseSrc * (1 + devEntryPerc) 'ATR' => baseSrc + devEntryAtrMul * openAtr => na float longEntryPrice = na longEntryPrice := if validOpenLongPosition getLongEntryPrice(close) else if tryEnterLongPosition math.min(getLongEntryPrice(low), nz(longEntryPrice[1], 999999)) else na enterLongPosition := enableEntryTrailing ? longFiltersApproval and ta.crossover(openLongPosition ? close : ctrLongEntrySrc, longEntryPrice) : openLongPosition bool validEnterLongPosition = enterLongPosition and not (strategy.position_size > 0) var bool enterShortPosition = false int barsSinceEnterShort = nz(ta.barssince(enterShortPosition), 999999) bool openShortIsActive = barsSinceCloseShort >= barsSinceValidOpenShort bool enterShortIsPending = barsSinceEnterShort >= barsSinceValidOpenShort bool tryEnterShortPosition = shortFiltersApproval and openShortIsActive and enterShortIsPending getShortEntryPrice(baseSrc) => switch devEntryMethod 'PERC' => baseSrc * (1 - devEntryPerc) 'ATR' => baseSrc - devEntryAtrMul * openAtr => na float shortEntryPrice = na shortEntryPrice := if validOpenShortPosition getShortEntryPrice(close) else if tryEnterShortPosition math.max(getShortEntryPrice(high), nz(shortEntryPrice[1])) else na enterShortPosition := enableEntryTrailing ? shortFiltersApproval and ta.crossunder(openShortPosition ? close : ctrShortEntrySrc, shortEntryPrice) : openShortPosition bool validEnterShortPosition = enterShortPosition and not (strategy.position_size < 0) // PLOT ============================================================================================================= var buyColor = color.new(color.green, 0) plot(series = enableEntryTrailing ? longEntryPrice : na, title = 'Long Buy Price', color = buyColor, linewidth = 1, style = plot.style_linebr) plot(series = enableEntryTrailing ? shortEntryPrice : na, title = 'Short Sell Price', color = buyColor, linewidth = 1, style = plot.style_linebr) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // EXIT ============================================================================================================ // INPUT ============================================================================================================ enableExitTrailing = input.bool(defval = false, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for exit position.', group = 'Exit') devExitMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Exit.', group = 'Exit') devExitPerc = input.float(defval = 3.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The step to follow the price when the close position condition is met.', group = 'Exit') / 100 devExitAtrMul = input.float(defval = 0.5, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the exit target is reached.', group = 'Exit') ctrLongExitSrc = input.source(defval = low, title = 'Long/Short Exit Control', inline = 'Control', group = 'Exit') ctrShortExitSrc = input.source(defval = high, title = '', tooltip = 'The price source to check with the entry target to trigger the entry order for Long/Short position.', inline = 'Control', group = 'Exit') // LOGIC ============================================================================================================ var bool exitLongPosition = false int barsSinceExitLong = nz(ta.barssince(exitLongPosition), 999999) bool closeLongIsActive = barsSinceValidOpenLong >= barsSinceCloseLong bool exitLongIsPending = barsSinceExitLong >= barsSinceCloseLong bool tryExitLongPosition = isWithinPeriod() and closeLongIsActive and exitLongIsPending getLongExitPrice(baseSrc) => switch devExitMethod 'PERC' => baseSrc * (1 - devExitPerc) 'ATR' => baseSrc - devExitAtrMul * openAtr => na float longExitPrice = na longExitPrice := if validCloseLongPosition getLongExitPrice(close) else if tryExitLongPosition math.max(getLongExitPrice(high), nz(longExitPrice[1], 999999)) else na exitLongPosition := enableExitTrailing ? isWithinPeriod() and ta.crossunder(closeLongPosition ? close : ctrLongExitSrc, longExitPrice) : closeLongPosition bool longIsActive = enterLongPosition or strategy.position_size > 0 and not exitLongPosition var bool exitShortPosition = false int barsSinceExitShort = nz(ta.barssince(exitShortPosition), 999999) bool closeShortIsActive = barsSinceValidOpenShort >= barsSinceCloseShort bool exitShortIsPending = barsSinceExitShort >= barsSinceCloseShort bool tryExitShortPosition = isWithinPeriod() and closeShortIsActive and exitShortIsPending getShortExitPrice(baseSrc) => switch devExitMethod 'PERC' => baseSrc * (1 + devExitPerc) 'ATR' => baseSrc + devExitAtrMul * openAtr => na float shortExitPrice = na shortExitPrice := if validCloseShortPosition getShortExitPrice(close) else if tryExitShortPosition math.min(getShortExitPrice(low), nz(shortExitPrice[1], 999999)) else na exitShortPosition := enableExitTrailing ? isWithinPeriod() and ta.crossunder(closeShortPosition ? close : ctrShortExitSrc, shortExitPrice) : closeShortPosition bool shortIsActive = enterShortPosition or strategy.position_size < 0 and not exitShortPosition // PLOT ============================================================================================================= var sellColor = color.new(color.red, 0) plot(series = enableExitTrailing ? longExitPrice : na, title = 'Long Sell Price', color = sellColor, linewidth = 1, style = plot.style_linebr) plot(series = enableExitTrailing ? shortExitPrice : na, title = 'Short Sell Price', color = sellColor, linewidth = 1, style = plot.style_linebr) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // STOP LOSS ======================================================================================================== // INPUT ============================================================================================================ stopLossMethod = input.string(defval = 'PERC', title = 'Stop Loss Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Stop Loss (percentagewise, based on initial ATR or based on ATR changing over time).', group = 'Stop Loss - Target') longTrailingStopLossPerc = input.float(defval = 7.5, title = 'Long/Short Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, inline = 'Trailing Stop Loss Perc', group = 'Stop Loss - Target') / 100 shortTrailingStopLossPerc = input.float(defval = 7.5, title = '', minval = 0.05, maxval = 100, step = 0.05, tooltip = 'The percentage of the price decrease/increase to set the Stop Loss price target for long/short positions.', inline = 'Trailing Stop Loss Perc', group = 'Stop Loss - Target') / 100 longStopLossAtrMul = input.float(defval = 3.0, title = 'ATR Long/Short Mul ', minval = 0.1, step = 0.1, inline = 'Trailing Stop Loss ATR Multiplier', group = 'Stop Loss - Target') shortStopLossAtrMul = input.float(defval = 3.0, title = '', minval = 0.1, step = 0.1, tooltip = 'ATR multiplier to be used for the long/short Stop Loss.', inline = 'Trailing Stop Loss ATR Multiplier', group = 'Stop Loss - Target') enableStopLossTrailing = input.string(defval = 'TP', title = 'Enable Trailing', options = ['TP', 'ON', 'OFF'], tooltip = 'Enable the trailing for Stop Loss when Take Profit order is executed (TP) or from the start of the entry order (ON) or not at all (OFF).', group = 'Stop Loss - Trailing') breakEvenEnabled = input.bool(defval = false, title = 'Break Even', tooltip = 'When Take Profit price target is hit, move the Stop Loss to the entry price (or to a more strict price defined by the Stop Loss %/ATR Multiplier).', group = 'Stop Loss - Trailing') // LOGIC ============================================================================================================ getLongStopLossPrice(baseSrc) => switch stopLossMethod 'PERC' => baseSrc * (1 - longTrailingStopLossPerc) 'ATR' => baseSrc - longStopLossAtrMul * openAtr => na getLongStopLossPerc(baseSrc) => (baseSrc - getLongStopLossPrice(baseSrc)) / baseSrc // trailing starts when the take profit price is reached if 'TP' mode is set or from the very begining if 'ON' mode is selected bool enableLongTakeProfitTrailing = enableStopLossTrailing == 'ON' or enableStopLossTrailing == 'TP' and longTrailingTakeProfitExecuted // calculate trailing stop loss price when enter long position and peserve its value until the position closes float longTrailingStopLossPrice = na longTrailingStopLossPrice := if longIsActive if validEnterLongPosition getLongStopLossPrice(openPrice) else stopPrice = getLongStopLossPrice(enableLongTakeProfitTrailing ? high : openPrice) stopPrice := breakEvenEnabled and longTrailingTakeProfitExecuted ? math.max(stopPrice, openPrice) : stopPrice math.max(stopPrice, nz(longTrailingStopLossPrice[1])) else na getShortStopLossPrice(baseSrc) => switch stopLossMethod 'PERC' => baseSrc * (1 + shortTrailingStopLossPerc) 'ATR' => baseSrc + shortStopLossAtrMul * openAtr => na getShortStopLossPerc(baseSrc) => (getShortStopLossPrice(baseSrc) - baseSrc) / baseSrc // trailing starts when the take profit price is reached if 'TP' mode is set or from the very begining if 'ON' mode is selected bool enableShortTakeProfitTrailing = enableStopLossTrailing == 'ON' or enableStopLossTrailing == 'TP' and shortTrailingTakeProfitExecuted // calculate trailing stop loss price when enter short position and peserve its value until the position closes float shortTrailingStopLossPrice = na shortTrailingStopLossPrice := if shortIsActive if validEnterShortPosition getShortStopLossPrice(openPrice) else stopPrice = getShortStopLossPrice(enableShortTakeProfitTrailing ? low : openPrice) stopPrice := breakEvenEnabled and shortTrailingTakeProfitExecuted ? math.min(stopPrice, openPrice) : stopPrice math.min(stopPrice, nz(shortTrailingStopLossPrice[1], 999999.9)) else na // PLOT ============================================================================================================= var stopLossColor = color.new(#e25141, 0) plot(series = longTrailingStopLossPrice, title = 'Long Trail Stop', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 1) plot(series = shortTrailingStopLossPrice, title = 'Short Trail Stop', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 1) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // TAKE PROFIT ====================================================================================================== // INPUT ============================================================================================================ takeProfitMethod = input.string(defval = 'PERC', title = 'Take Profit Method', options = ['PERC', 'ATR', 'RR'], tooltip = 'The method to calculate the Take Profit price.', group = 'Take Profit - Target') longTakeProfitPerc = input.float(defval = 10.0, title = 'Long/Short Take Profit %', minval = 0.05, step = 0.05, inline = 'Take Profit Perc', group = 'Take Profit - Target') / 100 shortTakeProfitPerc = input.float(defval = 10.0, title = '', minval = 0.05, step = 0.05, tooltip = 'The percentage of the price increase/decrease to set the take profit price target for long/short positions.', inline = 'Take Profit Perc', group = 'Take Profit - Target') / 100 longTakeProfitAtrMul = input.float(defval = 9.0, title = 'ATR Long/Short Mul ', minval = 0.1, step = 0.1, inline = 'Take Profit ATR Multiplier', group = 'Take Profit - Target') shortTakeProfitAtrMul = input.float(defval = 9.0, title = '', minval = 0.1, step = 0.1, tooltip = 'ATR multiplier to be used for the long/short Take Profit.', inline = 'Take Profit ATR Multiplier', group = 'Take Profit - Target') longRiskRewardRatio = input.float(defval = 1.5, title = 'Long/Short RR Ratio ', minval = 0.1, step = 0.1, inline = 'Risk Reward Ratio', group = 'Take Profit - Target') shortRiskRewardRatio = input.float(defval = 1.5, title = '', minval = 0.1, step = 0.1, tooltip = 'The Risk/Reward Ratio to be used for the long/short Take Profit based on the Stop Loss Price.', inline = 'Risk Reward Ratio', group = 'Take Profit - Target') enableTakeProfitTrailing = input.bool(defval = true, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for take profit.', group = 'Take Profit - Trailing') devTakeProfitMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Take Profit.', group = 'Take Profit - Trailing') devTakeProfitPerc = input.float(defval = 1.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The percentage wise step to be used for following the price, when the take profit target is reached.', group = 'Take Profit - Trailing') / 100 devTakeProfitAtrMul = input.float(defval = 1.0, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the take profit target is reached.', group = 'Take Profit - Trailing') // LOGIC ============================================================================================================ getLongTakeProfitPrice(baseSrc) => switch takeProfitMethod 'PERC' => baseSrc * (1 + longTakeProfitPerc) 'ATR' => baseSrc + longTakeProfitAtrMul * openAtr 'RR' => baseSrc + longRiskRewardRatio * (baseSrc - getLongStopLossPrice(baseSrc)) => na getLongTakeProfitPerc(baseSrc) => (baseSrc - getLongTakeProfitPrice(baseSrc)) / baseSrc // calculate take profit price when enter long position and peserve its value until the position closes float longTakeProfitPrice = na longTakeProfitPrice := if longIsActive and not longTrailingTakeProfitExecuted if validEnterLongPosition getLongTakeProfitPrice(openPrice) else nz(longTakeProfitPrice[1], getLongTakeProfitPrice(close)) else na longTrailingTakeProfitExecuted := strategy.position_size > 0 and (longTrailingTakeProfitExecuted[1] or strategy.position_size < strategy.position_size[1] or strategy.position_size[1] == 0 and high >= longTakeProfitPrice) longTrailingTakeProfitStepTicks = switch devTakeProfitMethod 'PERC' => longTakeProfitPrice * devTakeProfitPerc / syminfo.mintick 'ATR' => devTakeProfitAtrMul * openAtr / syminfo.mintick => na getShortTakeProfitPrice(baseSrc) => switch takeProfitMethod 'PERC' => baseSrc * (1 - shortTakeProfitPerc) 'ATR' => baseSrc - shortTakeProfitAtrMul * openAtr 'RR' => baseSrc - shortRiskRewardRatio * (getShortStopLossPrice(baseSrc) - baseSrc) => na getShortTakeProfitPerc(baseSrc) => (getShortTakeProfitPrice(baseSrc) - baseSrc) / baseSrc // calculate take profit price when enter short position and peserve its value until the position closes float shortTakeProfitPrice = na shortTakeProfitPrice := if shortIsActive and not shortTrailingTakeProfitExecuted if validEnterShortPosition getShortTakeProfitPrice(openPrice) else nz(shortTakeProfitPrice[1], getShortTakeProfitPrice(close)) else na shortTrailingTakeProfitExecuted := strategy.position_size < 0 and (shortTrailingTakeProfitExecuted[1] or strategy.position_size > strategy.position_size[1] or strategy.position_size[1] == 0 and low <= shortTakeProfitPrice) shortTrailingTakeProfitStepTicks = switch devTakeProfitMethod 'PERC' => shortTakeProfitPrice * devTakeProfitPerc / syminfo.mintick 'ATR' => devTakeProfitAtrMul * openAtr / syminfo.mintick => na // PLOT ============================================================================================================= var takeProfitColor = color.new(#419388, 0) plot(series = longTakeProfitPrice, title = 'Long Take Profit', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 1) plot(series = shortTakeProfitPrice, title = 'Short Take Profit', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 1) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // QUANTITY MANAGEMENT ============================================================================================== // INPUT ============================================================================================================ takeProfitQuantityPerc = input.float(defval = 50, title = 'Take Profit Quantity %', minval = 0.0, maxval = 100, step = 1.0, tooltip = 'The percentage of the position that will be withdrawn when the take profit price target is reached.', group = 'Quantity/Risk Management') riskPerc = input.float(defval = 2, title = 'Capital at Risk %', minval = 1, tooltip = 'The maximum percentage of the equity to risk in every trade when no leverage is used.', group = "Quantity/Risk Management") / 100 minTrade = input.int(defval = 10, title = 'Minimum Trade Price', minval = 1, tooltip = 'The minimum trade price in Quote currency that is allowed in the exchange for a valid new position.', group = "Quantity/Risk Management") longLeverage = input.int(defval = 1, title = 'Leverage Long/Short ', minval = 1, inline = 'Leverage', group = "Quantity/Risk Management") shortLeverage = input.int(defval = 1, title = '', minval = 1, tooltip = 'Leverage factor used to multiply the initial risk quantity of each trade (by borrowing the remaining amount). Thus, the profits and losses are multiplied respectivelly.', inline = 'Leverage', group = "Quantity/Risk Management") // LOGIC ============================================================================================================ var int quoteDecimalDigits = math.max(math.ceil(-1 * math.log10(syminfo.mintick * syminfo.pointvalue)), 0) floor(number, precision) => fact = math.pow(10, precision) num = number * fact math.floor(num) / fact ceil(number, precision) => fact = math.pow(10, precision) num = number * fact math.ceil(num) / fact clamp(number, lower, highest, precision) => ceil(math.max(floor(math.min(number, highest), precision), lower), precision) getLongRiskQuoteQuantity() => clamp(strategy.equity * riskPerc * longLeverage / getLongStopLossPerc(close), minTrade, strategy.equity * longLeverage, quoteDecimalDigits) getLongRiskQuoteQuantityPerc() => getLongRiskQuoteQuantity() / strategy.equity getLongRiskBaseQuantity() => getLongRiskQuoteQuantity() / close float longEntryBaseQuantity = na longEntryBaseQuantity := if longIsActive if validOpenLongPosition getLongRiskBaseQuantity() else nz(longEntryBaseQuantity[1], getLongRiskBaseQuantity()) else na getShortRiskQuoteQuantity() => clamp(strategy.equity * riskPerc * shortLeverage / getShortStopLossPerc(close), minTrade, strategy.equity * shortLeverage, quoteDecimalDigits) getShortRiskQuoteQuantityPerc() => getShortRiskQuoteQuantity() / strategy.equity getShortRiskBaseQuantity() => getShortRiskQuoteQuantity() / close float shortEntryBaseQuantity = na shortEntryBaseQuantity := if shortIsActive if validOpenShortPosition getShortRiskBaseQuantity() else nz(shortEntryBaseQuantity[1], getShortRiskBaseQuantity()) else na // PLOT ============================================================================================================= label.new(x = validOpenLongPosition ? bar_index : na, y = na, text = 'Buy\n' + str.tostring(100 * getLongRiskQuoteQuantityPerc(), '#.##') + '%', yloc = yloc.belowbar, color = buyColor, style = label.style_label_up, textcolor = color.new(color.white, 0)) label.new(x = validOpenShortPosition ? bar_index : na, y = na, text = 'Sell\n' + str.tostring(100 * getShortRiskQuoteQuantityPerc(), '#.##') + '%', yloc = yloc.abovebar, color = sellColor, style = label.style_label_down, textcolor = color.new(color.white, 0)) label.new(x = validCloseShortPosition ? bar_index : na, y = na, text = 'Buy', yloc = yloc.belowbar, color = buyColor, style = label.style_label_up, textcolor = color.new(color.white, 0)) label.new(x = validCloseLongPosition ? bar_index : na, y = na, text = 'Sell', yloc = yloc.abovebar, color = sellColor, style = label.style_label_down, textcolor = color.new(color.white, 0)) // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // ALERT MESSAGES =================================================================================================== // INPUT ============================================================================================================ msgOpenLong = input.string(defval = 'Long: Started', title = 'Open Long/Short', inline = 'Open Message', group = 'Alert Messages') msgOpenShort = input.string(defval = 'Short: Started', title = '', tooltip = 'Alert messages emited when open long/short position.', inline = 'Open Message', group = 'Alert Messages') msgCloseLong = input.string(defval = 'Long: Closed at market price', title = 'Close Long/Short', inline = 'Close Message', group = 'Alert Messages') msgCloseShort = input.string(defval = 'Short: Closed at market price', title = '', tooltip = 'Alert messages emited when close long/short position.', inline = 'Close Message', group = 'Alert Messages') msgTPSLLong = input.string(defval = 'Long: Take Profit or Stop Loss executed', title = 'TP/SL Long/Short', inline = 'TP/SL Message', group = 'Alert Messages') msgTPSLShort = input.string(defval = 'Short: Take Profit or Stop Loss executed', title = '', tooltip = 'Alert message emited when the first quantity target (take profit or stop loss) for long/short position is hit.', inline = 'TP/SL Message', group = 'Alert Messages') msgSLLong = input.string(defval = 'Long: Stop Loss executed', title = 'SL Long/Short ', inline = 'SL Message', group = 'Alert Messages') msgSLShort = input.string(defval = 'Short: Stop Loss executed', title = '', tooltip = 'Alert message emited when the second quantity stop loss target for long/short position is hit.', inline = 'SL Message', group = 'Alert Messages') msgMaxDrawdown= input.string(defval = 'Death is the new beginning', title = 'Max Drawdown', tooltip = 'Alert message emited when the max drawdown limit is hit.', group = 'Alert Messages') // // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ // POSITION ORDERS ================================================================================================== // INPUT ============================================================================================================ maxDrawdown = input.int(defval = 25, title = 'Max Drawdown %', minval = 1, maxval = 100, tooltip = 'The maximum drawdown to stop trading.', group = "Quantity/Risk Management") highlighting = input.bool(defval = false, title = 'Show Position Highlighter', tooltip = 'Highlight winning/lossing position.', group = 'Plot') // LOGIC ============================================================================================================ // close on trend reversal strategy.close(id = 'Long Entry', when = exitLongPosition, comment = 'Close Long', alert_message = msgCloseLong) // close on trend reversal strategy.close(id = 'Short Entry', when = exitShortPosition, comment = 'Close Short', alert_message = msgCloseShort) // getting into LONG position strategy.entry(id = 'Long Entry', direction = strategy.long, qty = longEntryBaseQuantity, when = enterLongPosition, alert_message = msgOpenLong) // submit exit order for trailing take profit price also set the stop loss for the take profit percentage in case that stop loss it reached first strategy.exit(id = 'Long Take Profit / Stop Loss', from_entry = 'Long Entry', qty_percent = takeProfitQuantityPerc, limit = enableTakeProfitTrailing ? na : longTakeProfitPrice, stop = longTrailingStopLossPrice, trail_price = enableTakeProfitTrailing ? longTakeProfitPrice : na, trail_offset = enableTakeProfitTrailing ? longTrailingTakeProfitStepTicks : na, when = longIsActive, alert_message = msgTPSLLong) // submit exit order for trailing stop loss price for the remaining percent of the quantity not reserved by the take profit order strategy.exit(id = 'Long Stop Loss', from_entry = 'Long Entry', stop = longTrailingStopLossPrice, when = longIsActive, alert_message = msgSLLong) // getting into SHORT position strategy.entry(id = 'Short Entry', direction = strategy.short, qty = shortEntryBaseQuantity, when = enterShortPosition, alert_message = msgOpenShort) // submit exit order for trailing take profit price also set the stop loss for the take profit percentage in case that stop loss it reached first strategy.exit(id = 'Short Take Profit / Stop Loss', from_entry = 'Short Entry', qty_percent = takeProfitQuantityPerc, limit = enableTakeProfitTrailing ? na : shortTakeProfitPrice, stop = shortTrailingStopLossPrice, trail_price = enableTakeProfitTrailing ? shortTakeProfitPrice : na, trail_offset = enableTakeProfitTrailing ? shortTrailingTakeProfitStepTicks : na, when = shortIsActive, alert_message = msgTPSLShort) // submit exit order for trailing stop loss price for the remaining percent of the quantity not reserved by the take profit order strategy.exit(id = 'Short Stop Loss', from_entry = 'Short Entry', stop = shortTrailingStopLossPrice, when = shortIsActive, alert_message = msgSLShort) // limit the maximum drawdown // strategy.risk.max_drawdown(value = maxDrawdown, type = strategy.percent_of_equity, alert_message = msgMaxDrawdown) // PLOT ============================================================================================================= lowHighPrice = high > strategy.position_avg_price and low < strategy.position_avg_price ? longIsActive ? high : shortIsActive ? low : na : high > strategy.position_avg_price ? high : low < strategy.position_avg_price ? low : na pricePlot = plot(series = lowHighPrice, title = 'Price', color = na, linewidth = 1, style = plot.style_linebr) var posColor = color.new(color.white, 0) posPlot = plot(series = strategy.position_avg_price, title = 'Position', color = posColor, linewidth = 1, style = plot.style_linebr) highlightColor = lowHighPrice > strategy.position_avg_price and longIsActive or lowHighPrice < strategy.position_avg_price and shortIsActive ? takeProfitColor : lowHighPrice < strategy.position_avg_price and longIsActive or lowHighPrice > strategy.position_avg_price and shortIsActive ? stopLossColor : na fill(plot1 = posPlot, plot2 = pricePlot, color = highlighting ? color.new(highlightColor, 90) : na, title = 'Highlight trades') // ==================================================================================================================