[Fedra Algotrading Strategy Trailing Stop].pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fbarberis
// User Version
//@version=5
strategy('[Fedra Algotrading Strategy Trailing Stop]', '[FASTS] 4.5', calc_on_every_tick=true, overlay=true, process_orders_on_close=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=1000, precision=4, pyramiding=0, commission_type=strategy.commission.percent, commission_value=0.1)
disclaimer = input.bool (defval = false, title = '🔥🔥Default parameters of this strategy are intended to work on 30 or 15 minute charts but his values still need to be optimized. It uses real-time price information calculated on each tick to close trades. Read the tooltips (!) to understand the function of each parameter.🔥🔥', tooltip = "Remember when backtesting that past performance is no guarantee of future results")
i_startTime = input.time(defval=timestamp('01 Jan 2016 00:00 +0000'), title='Start Time', group='Backtest Period')
i_endTime = input.time(defval=timestamp('30 Sep 2030 00:30 +0000'), title='End Time', group='Backtest Period')
backtestmode = true //input.bool(title='Disable trailing to prevent repainting in Backtest (Uncheck to set the alarms)', defval=false, group='Backtest Period')
lastdays = input.bool (defval = false, title = 'Only last days', group = 'Backtest Period')
btDays = input.int(defval = 180, step=30, title = 'How many days?', group = 'Backtest Period', tooltip="Limits the backtest to the last selected days.")
days_millis = btDays * 86400000
newdate=timenow-days_millis
showLRplot = input.bool(title='Show LR line', defval=false, group='LR Settings')
i_length = 20//input.int(defval=20, title='Length', group='LR Settings')
source = input.source(open, group='LR Settings')
length = input.int(title='Lenght: 10-100', defval= 10, step = 10, minval=1, group='LR Settings', tooltip="Number of candles used to calculate the Linear Regression. Recommended values are between 10 and 100, but generally optimizing this parameter tends to result in overfit, so its default value is recommended.")
offset = 0//input.int(0, minval=0, group='LR Settings')
dev = input.float(title='Deviation: -3/0/3', defval= 2.0, step = 0.5, group='LR Settings', tooltip="Linear regression deviation to establish the range. Recommended values are between -3 and 3, but generally optimizing this parameter tends to result in overfit, so its default value is recommended.")
smoothing = 1//input.int(1, minval=1, group='LR Settings')
mtf_val = input.timeframe('', 'Resolution', group='LR Settings')
line_thick = 1//input.int(1, 'S&R Thickness', minval=1, maxval=4, group='LR Settings')
//signals = input("All", "Signals Display", options=["Recent", "All"])
p = 'Lime'//input.string('Lime', 'Up Color', options=['Red', 'Lime', 'Orange', 'Teal', 'Yellow', 'White', 'Black'], group='LR Settings')
q = 'Red'//input.string('Red', 'Down Color', options=['Red', 'Lime', 'Orange', 'Teal', 'Yellow', 'White', 'Black'], group='LR Settings')
goto = 0//input.int(0, 'End At Bar Index', group='LR Settings')
//longProfitPerc = input(title="Long Take Profit (%)", minval=0.0, step=0.1, defval=3) / 100
//rsiSource = input(title="RSI Source", type=input.source, defval=close)
//rsiLength = input(title="RSI Length", type=input.integer, defval=14)
emaLength = input.int(title='Fast MA Length', defval=20, group='MA Settings to determine downtrend', tooltip="Yellow line: Suggested optimization values, between 10 and 50")
showSTfilter = input.bool(title='Apply Supertrend Filter?', defval=false, group='SuperTrend Settings', tooltip="Be aware that the optimization of the super trend parameters often results in overfitting.")
showSLEMAfilter = true //input.bool(title='Apply SL Filter?', defval=true, group='Fine Tunning Settings')
string i_maType = input.string("SMA", "Fast MA type", options = ["SMA","EMA", "RMA", "WMA","HMA", "CHANGE","CMO","COG","DEV","HIGHEST","LOWEST","MEDIAN","MOM","RANGE","STDEV","VARIANCE"], group='MA Settings to determine downtrend')
float ma = switch i_maType
"SMA" => ta.sma(source, emaLength)
"EMA" => ta.ema(source, emaLength)
"RMA" => ta.rma(source, emaLength)
"HMA" => ta.hma(source, emaLength)
"CHANGE" => ta.change(source, emaLength)
"CMO" => ta.cmo(source, emaLength)
"COG" => ta.cog(source, emaLength)
"DEV" => ta.dev(source, emaLength)
"HIGHEST" => ta.highest(source, emaLength)
"LOWEST" => ta.lowest(source, emaLength)
"MEDIAN" => ta.median(source, emaLength)
"MOM" => ta.mom(source, emaLength)
"RANGE" => ta.range(source, emaLength)
"STDEV" => ta.stdev(source, emaLength)
"VARIANCE" => ta.variance(source, emaLength)
// Default used when the three first cases do not match.
=> ta.wma(source, emaLength)
emaLength2 = input.int(title='Slow MA Length', defval=100, step=10, group='MA Settings to determine downtrend', tooltip="Blue line: Suggested optimization values, between 50 and 400")
string i_maType2 = input.string("SMA", "Slow MA type", options = ["SMA","EMA","RMA", "WMA","HMA", "CHANGE", "CMO","COG","DEV","HIGHEST","LOWEST","MEDIAN", "MOM","RANGE","STDEV","VARIANCE"], group='MA Settings to determine downtrend')
float ma2 = switch i_maType2
"SMA" => ta.sma(source, emaLength2)
"EMA" => ta.ema(source, emaLength2)
"RMA" => ta.rma(source, emaLength2)
"HMA" => ta.hma(source, emaLength2)
"CHANGE" => ta.change(source, emaLength2)
"CMO" => ta.cmo(source, emaLength2)
"COG" => ta.cog(source, emaLength2)
"DEV" => ta.dev(source, emaLength2)
"HIGHEST" => ta.highest(source, emaLength2)
"LOWEST" => ta.lowest(source, emaLength2)
"MEDIAN" => ta.median(source, emaLength2)
"MOM" => ta.mom(source, emaLength2)
"RANGE" => ta.range(source, emaLength2)
"STDEV" => ta.stdev(source, emaLength2)
"VARIANCE" => ta.variance(source, emaLength2)
// Default used when the three first cases do not match.
=> ta.wma(source, emaLength2)
showMA = true//input.bool(title='Show SMA', defval=true, group='Appearance')
showBGcolor = true//input.bool(title='Show BG Color', defval=true, group='Appearance')
showBGcolorSL = true//input.bool(title='Show SL Active Color', defval=true, group='Appearance')
EMAfilter = ma > ma2
enableBuy2 = input.bool(title='Enable Entry on MA cross?', defval=false, group='Fine Tunning Settings (SELL)', tooltip="Open a trade when a new candle opens above the slow MA (blue line) and the fast MA (yellow line) is below the slow MA (blue line).")
line1 = plot(showMA ? ma : na, linewidth=2, color=color.new(color.yellow, 0))
line2 = plot(showMA ? ma2 : na, linewidth=2, color=color.new(color.blue, 0))
fill(line1, line2, color = ma > ma2 ? color.green : color.red, transp=85)
//Opcional//plotshape(buy2, title= "Buy2", location=location.abovebar, color=color.blue, transp=0, style=shape.labelup)
price = input.source(close, title= "Price source. Select 'close' for real time calculations", group='Fine Tunning Settings (SELL)')
uptrend = price > ma
downtrend = price < ma
//Opcional//plotshape(buy2, title= "Buy2", location=location.abovebar, color=color.blue, transp=0, style=shape.labelup)
cc(x) =>
x == 'Red' ? color.red : x == 'Lime' ? color.lime : x == 'Orange' ? color.orange : x == 'Teal' ? color.teal : x == 'Yellow' ? color.yellow : x == 'Black' ? color.black : color.white
data(x) =>
ta.sma(request.security(syminfo.tickerid, mtf_val != '' ? mtf_val : timeframe.period, x), smoothing)
//Opcional//rsiOverbought = input(title="RSI Overbought Level", type=input.integer, defval=70)
//Opcional//rsiOversold = input(title="RSI Oversold Level", type=input.integer, defval=40)
//Opcional//isRsiOB = rsiValue >= rsiOverbought
//Opcional//isRsiOS = rsiValue <= rsiOversold
//plotshape(isRsiOB, title= "Overbought", location=location.abovebar, color=color.red, transp=0, style=shape.triangledown, text="OB")
//Opcional//plotshape(isRsiOS, title= "Oversold", location=location.belowbar, color=color.green, transp=0, style=shape.labelup)
linreg = data(ta.linreg(source, length, offset))
linreg_p = data(ta.linreg(source, length, offset + 1))
plot(showLRplot ? linreg : na, "Regression Line", cc(linreg>linreg[1]?p:q), editable=false)
x = bar_index
slope = linreg - linreg_p
intercept = linreg - x * slope
deviationSum = 0.0
for i = 0 to length - 1 by 1
deviationSum := deviationSum + math.pow(source[i] - (slope * (x - i) + intercept), 2)
deviationSum
deviation = math.sqrt(deviationSum / length)
x1 = x - length
x2 = x
y1 = slope * (x - length) + intercept
y2 = linreg
updating = goto <= 0 or x < goto
if updating
line b = line.new(x1, y1, x2, y2, xloc.bar_index, extend.right, color.aqua, width=line_thick)
line.delete(b[1])
line dp = line.new(x1, deviation * dev + y1, x2, deviation * dev + y2, xloc.bar_index, extend.right, cc(q), width=line_thick)
line.delete(dp[1])
line dm = line.new(x1, -deviation * dev + y1, x2, -deviation * dev + y2, xloc.bar_index, extend.right, cc(p), width=line_thick)
line.delete(dm[1])
dm_current = -deviation * dev + y2
dp_current = deviation * dev + y2
//Plot TP
//longExitPrice = strategy.position_size * (1 + longProfitPerc)
//shortStopPrice = strategy.position_avg_price * (1 + shortProfitPerc)
sellup = ta.crossover(close, dp_current) //and rsiValue > 30
plot(x, 'Bar Index', color.new(color.aqua, 0), line_thick, plot.style_cross, display=display.none)
// The Fixed Percent Stop Loss Code
// User Options to Change Inputs (%)
enableTP = false//input.bool(title='Enable TP %', defval=false, group='Fine Tunning Settings', tooltip="This option will close a trade at the configured percentage")
takePer = 3.0//input.float(3.0, title='TP %', group='Fine Tunning Settings') / 100
stopPer = 3.0//input.float(3.0, title='Stop Loss switch. Level %', group='Fine Tunning Settings') / 100
velasSL = 0//input.int(title='Bars from entry for SL level activation', defval=0, step=24, group='Fine Tunning Settings')
breakEven = 1.5//input.float(1.5, title='Break Even % (<TP)', step= 0.5, group='Fine Tunning Settings') / 100
// Determine where you've entered and in what direction
longStop = strategy.position_avg_price * (1 - stopPer)
shortStop = strategy.position_avg_price * (1 + stopPer)
shortTake = strategy.position_avg_price * (1 - takePer)
longTake = strategy.position_avg_price * (1 + takePer)
longBreakeven = strategy.position_avg_price * (1 + breakEven)
longTrailPerc = input.float(3.0, title='Trailing SL %', group='Fine Tunning Settings') / 100
longStopPrice = 0.0
longStopPrice := if strategy.position_size > 0
stopValue = price * (1 - longTrailPerc)
math.max(stopValue, longStopPrice)
else
0
// Submit exit orders
start = timestamp(2021, 9, 21, 11, 0)
end = timestamp(2030, 9, 19, 0, 0)
/////////////Trailing Take Profit
//trailpoints = 0.01 //input.float(title='Trail Points', defval=0.01, minval=0.0, maxval=2.0, step=0.01, group='Fine Tunning Settings')
trailoffset = 0.01//input.float(title='Trail Offset', defval=0.01, minval=0.0, maxval=2.0, step=0.01, group='Fine Tunning Settings')
//trailloss = 0.01//input.float(title='Trail loss', defval=0.01, minval=0.0, maxval=2.0, step=0.01, group='Fine Tunning Settings')
tradenumber = 1
//a = strategy.closedtrades.exit_bar_index(tradenumber)
var int nPastDays = 0
opened_order = strategy.position_size[0] != strategy.position_size[1] and strategy.position_size[0] != 1
bars = ta.barssince(opened_order)
a = ta.barssince(ta.change(strategy.position_size))
lastTradeResult = ta.change(strategy.netprofit)
barsSinceLastLoss = ta.barssince(lastTradeResult < 0)
//if a == na
// a:= 1
//label.new(bar_index, high, text=tostring(a))
// Check if there's a new losing trade that increased the streak
newLoss = (strategy.losstrades > strategy.losstrades[1]) and
(strategy.wintrades == strategy.wintrades[1]) and
(strategy.eventrades == strategy.eventrades[1])
streakLen = 0
streakLen := if (newLoss)
nz(streakLen[1]) + 1
else
if (strategy.wintrades > strategy.wintrades[1]) or
(strategy.eventrades > strategy.eventrades[1])
0
else
nz(streakLen[1])
// See if losing streak is under max allowed
//plot (velasSL)
risk = input.float(title='% of $ Allocation for Drawdown', defval=100.00, minval=0.0, maxval=100.0, step=0.10, group='Risk Management', tooltip="Kill switch: The script will close the current trade and stop trading once the set percentage of capital has been lost. To use this function it is important to set the current date and time for the start of the backtest to not include past trades in the calculations.")
strategy.risk.max_drawdown(value=risk, type=strategy.percent_of_equity)
maxLosingStreak = input.int(title="Max Losing Streak Length", defval=15, minval=1, group='Risk Management', tooltip="Kill switch: The script will close the current trade and stop trading once the set number of consecutive negative trades has been reached. To use this function it is important to set the current date and time for the start of the backtest in order not to include past trades in the calculations.")
okToTrade = streakLen < maxLosingStreak
//strategy.risk.max_intraday_loss(value=20, type=strategy.percent_of_equity)
//BTC_15 = request.security("BTC.D", "360", close)
//smaBTC = request.security("BTC.D", "360", ta.ema(close,100))
//plot (showMA ? smaBTC : na, linewidth=2, color=color.new(color.green, 0))
//STfilter = BTC_15 < smaBTC
//////////////////////////////SUPERTREND
Periods = input.int(title="ATR Period", defval=10, group='SuperTrend Settings')
src2 = input(hl2, title="Source", group='SuperTrend Settings')
Multiplier = input.float(title="ATR Multiplier", step=0.1, defval=3.0, group='SuperTrend Settings')
changeATR= false//input.bool(title="Change ATR Calculation Method ?", defval=false, group='SuperTrend Settings')
//showsignals = input.bool(title="Show Buy/Sell Signals ?", defval=true)
//highlighting = input.bool(title="Highlighter On/Off ?", defval=true, group='SuperTrend Settings')
atr2 = ta.sma(ta.tr, Periods)
atr= changeATR ? ta.atr(Periods) : atr2
up=src2-(Multiplier*atr)
up1 = nz(up[1],up)
up := close[1] > up1 ? math.max(up,up1) : up
dn=src2+(Multiplier*atr)
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
upPlot = plot(showSTfilter and trend == 1 ? up : na, title="Up Trend", style=plot.style_linebr, linewidth=1, color=color.aqua)
buySignal = trend == 1 and trend[1] == -1
//plotshape(buySignal ? up : na, title="UpTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.green, transp=0)
//plotshape(buySignal and showsignals ? up : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0)
dnPlot = plot(showSTfilter and trend != 1 ? dn : na, title="Down Trend", style=plot.style_linebr, linewidth=1, color=color.maroon)
sellSignal = trend == 1 and trend[1] == 1
//plotshape(sellSignal ? dn : na, title="DownTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.red, transp=0)
//plotshape(sellSignal and showsignals ? dn : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0)
isup = trend == 1 ? up : na
isdn = trend == 1 ? dn : na
//////////////////////////////
mapositive = ma-ma2 > ma[1]-ma2[1]
buy = ((EMAfilter == false and ta.crossunder(price, dm_current) and isup) and mapositive)
buy2 = open > ma2 and ma < ma2
buycondition = a >= 1 or na(a)
if showSTfilter == true
buy := ta.crossunder(price, dm_current) and isup and mapositive
else
buy := ta.crossunder(price, dm_current) and mapositive
//STfilter_int = STfilter ? 0 : 1
//plot(BTCfilter_int)highl
//showSignals = input.bool(title='Show Signals', defval=false, group='Appearance')
SLEMAfilter = strategy.position_size > 0 and EMAfilter// == false
if showSLEMAfilter == true
SLEMAfilter:= strategy.position_size > 0 and EMAfilter //== false
else
SLEMAfilter:= strategy.position_size > 0
//bgcolor(STfilter_int and showSTfilter ? color.red : na, transp=95)
enterLong = input(title = 'Enter Long Command', defval="", group='Optional bot Command Settings {{strategy.order.comment}}', tooltip="Enter here the command provided by your preferred bot platform to enter long.")
exitLong = input(title= 'Exit Long Command', defval="", group='Optional bot Command Settings {{strategy.order.comment}}', tooltip="Enter here the command provided by your preferred bot platform to exit long.")
var tradecloseprice = 0.0
entry_price = ta.valuewhen((strategy.position_size == 0 and buy and EMAfilter and buycondition) or (strategy.position_size == 0 and enableBuy2 and buy2 and buycondition), close, 0)
// Determine trail stop loss prices
longStopP = 0.0
longStopP := if (strategy.position_size > 0)
stopValue = close * (1 - longTrailPerc)
math.max(stopValue, longStopP[1])
else
0
showLabels= input.bool(title="Show PnL labels?", defval=false, group='SuperTrend Settings')
closecondition = ta.crossunder(close, longStopP)
if close > 0 and strategy.position_size > 0
tplabel = label.new(x=bar_index[0], y=high[0]+high[0]*0.03, color=color.gray, textcolor=color.white, style=label.style_label_down, text='Unr.PnL: ' + str.tostring(((close-tradecloseprice)/tradecloseprice)*100)+'%')
tplabel
label.delete(tplabel[1])
if showLabels and closecondition and ((((close-tradecloseprice)/tradecloseprice)*100) > 0)
tplabel = label.new(x=bar_index[0], y=high[0]+high[0]*0.06, color=color.green, textcolor=color.white, style=label.style_label_down, text='PnL: ' + str.tostring(((close-tradecloseprice)/tradecloseprice)*100)+'%')
tplabel
if showLabels and closecondition and ((((close-tradecloseprice)/tradecloseprice)*100) < 0)
tplabel = label.new(x=bar_index[0], y=low[0]-low[0]*0.02, color=color.red, textcolor=color.white, style=label.style_label_up, text='PnL: ' + str.tostring(((close-tradecloseprice)/tradecloseprice)*100)+'%')
tplabel
//longStopP := if (strategy.position_size > 0)
//stopValue = close[1] * (1 - longTrailPerc)
//math.max(stopValue, longStopP[1])
//else
//stopValue = 1
// a = ta.barssince(ta.change(strategy.position_size))
plotshape(buy, title='buy', location=location.belowbar, color=color.new(color.yellow, 0), style=shape.triangleup)
var timeperiod = i_startTime
if lastdays
timeperiod := newdate
else
timeperiod := i_startTime
if time >= timeperiod and time <= i_endTime and okToTrade and (a >= 0 or na(a))
if strategy.position_size == 0 and buy and EMAfilter and buycondition
strategy.entry(id='BUY', direction=strategy.long, comment=enterLong)
tradecloseprice := close
//a:= ta.barssince(ta.change(strategy.position_size))
if strategy.position_size == 0 and enableBuy2 and buy2 and buycondition
strategy.entry(id='BUY', direction=strategy.long, comment=enterLong)
tradecloseprice := close
//a:= ta.barssince(ta.change(strategy.position_size))
if strategy.position_size > 0
a:= 0//ta.barssince(ta.change(strategy.position_size))
strategy.close_all(when = closecondition, comment=exitLong)
//longStopP:= 0
//a:= 0//ta.barssince(ta.change(strategy.position_size))
//if strategy.position_size > 0
// strategy.close_all(when= ta.crossunder (ma, ma2), comment=exitLong)
if strategy.position_size == 0
nPastDays := 0
nPastDays
plot(strategy.position_size > 0 and enableTP ? longTake : na, style=plot.style_linebr, color=color.new(color.green, 0), linewidth=1, title='Long Take Profit')
//plot(strategy.position_size > 0 ? longStop : na, style=plot.style_linebr, color=color.new(color.white, 70), linewidth=1, title='Stop Loss level')
plot(strategy.position_size > 0 ? longStopP : na, style=plot.style_linebr, color=color.new(color.silver, 0), linewidth=3, title='Stop Loss level')
//plot(a, style=plot.style_linebr, color=color.new(color.white, 0), linewidth=3, title='Stop Loss level')
Show all 375 lines