この戦略は,単純な移動平均値のゴールデンクロスとデッドクロスによってトレンド方向を特定し,トレンドの開始時に完全なポジションサイズでロングまたはショートで走り,リスクを制御するためにストップ・ロストとテイク・プロフィートオーダーを設定します.ポジションに入ると,移動平均値を使用してトレンドを追跡し,トレンド逆転があるときに時間をかけて損失を削減します.この戦略には,ストップ・ロスト,テイク・プロフィート,ポジションサイジングの構成可能なモジュールもあり,異なる製品のためのパラメータの柔軟な調整を可能にします.
この戦略の核心は,単純な移動平均値の金十字と死十字を使用してトレンド開始と終止を決定することです.まず,高速SMA (例えば21期) と遅いSMA (例えば49期) の関係に基づいてトレンド方向を特定します.高速SMAが遅いSMAを超えると,上昇傾向を示し,戦略は長くなります.高速SMAが遅いSMAを下回ると,ダウントレンドを示し,戦略は短くなります.
ポジションに入ると,戦略はリアルタイムでSMAとの関係価格をモニターし続けます.価格がSMAを上から破るとロングポジションを閉じて,価格がSMAを下から破るとショートポジションを閉じて,トレンド逆転信号となります.
リスクを制御するために,戦略は,ポジションを開く時に同時にストップ・ロストとプロフィート・オーダーを設定する.ストップ・ロスト距離はATRに基づいているが,プロフィート・ロスト距離はパーセントまたはATR倍数として設定できる.ポジションを開いた後,ストップ・ロスはトレンドをたどる価格を追跡し続けます.プロフィート・ロストが触れたとき,完全に閉じるまで残りを追跡し続けながら,最初に部分的なポジションを閉じます.
この戦略には,各取引に使用される資金を制限し,取引リスクの露出を制御するためのポジションサイジングモジュールもあります. さらに,最大引き上げ制限は,全体的な戦略リスクを制限するのに役立ちます.
概要すると,これは初心者にとって非常に適したスタート戦略であり,シンプルな論理と理解が容易である.また,大きな損失を減らすために適切なリスク管理能力を持っています.パラメータチューニングによって良い結果が得られます.しかし,その内在的な弱点は,高精度で動作することができないことを決定します.初心者が練習することをお勧めしますが,高効率と勝利率を追求する高度なトレーダーには合致しない可能性があります.より良い取引パフォーマンスを獲得するには,より強力な予測力を持つ戦略を探すべきです.
/*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') // ==================================================================================================================