This strategy uses a Kalman filter to track prices and dynamically adjusts the stop loss point with a stop loss line to achieve a sliding stop loss.
This strategy uses a Kalman filter to track prices in real time. The Kalman filter contains two equations:
Prediction equation:
smooth = kf[1] + dk * sqrt(gain / 10000 * 2)
Update equation:
kf = smooth + velo
where dk is the prediction error, gain is the Kalman gain that determines tracking sensitivity.
In addition, the strategy uses a sliding stop loss line to lock in profits. The initial stop loss distance is the stop loss percentage setting, such as 2%.
When long, if the price rises, the stop loss line also moves up gradually approaching the Kalman line, with a step size of downStep, such as 0.5%. If the price falls to the stop loss, reopen the position and set the initial stop loss distance.
Short is similar.
Thus, the strategy can gradually lock in profits according to the trend, with good risk management.
Use Kalman filter to track prices in real time with fast response.
Lock in profits with sliding stop loss line, achieving good risk management. Customizable stop loss distance.
Flexibly choose long/short or only long/short.
Actively or conservatively stop loss based on trend.
Flexibly set take profit and stop loss as needed.
Improper parameter settings of Kalman filter may lead to unstable tracking.
Slippage may trigger stop loss point prematurely. Widen stop loss distance appropriately.
Sliding stop loss is not suitable for strong trending markets, should follow trend.
Stop loss may trigger frequently in ranging markets. Widen stop loss distance or don’t use sliding stop loss.
Incorporate more indicators to optimize entry timing.
Adjust stop loss line movement step based on market volatility.
Use machine learning to train optimal stop loss parameters.
Incorporate more risk indicators to dynamically adjust position sizing.
The loft stop strategy uses a Kalman filter to track price changes and lock in profits with a sliding stop loss line, ensuring profitability while controlling risks. It is a reliable and easily optimized strategy. Combining it with trend judgment and dynamic position sizing can achieve even better strategy performance.
/*backtest start: 2023-09-06 00:00:00 end: 2023-10-06 00:00:00 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © BigCoinHunter //@version=5 // strategy(title='Loft Strategy V1', overlay=true, // pyramiding=0, default_qty_type=strategy.fixed, // default_qty_value=100, initial_capital=100000, // currency=currency.USD, commission_value=0.05, // commission_type=strategy.commission.percent, // process_orders_on_close=true) //-------------- fetch user inputs ------------------ gain = input.float(title="Kalman Gain:", defval=1.0, minval=1.0, maxval=5000.0, step=100.0) src = input(defval=close, title='Source:') stopPercentMax = input.float(title='Beginning Approach(%):', defval=2.0, minval=0.1, maxval=30.0, step=0.1) stopPercentMin = input.float(title='Final Approach(%): ', defval=0.5, minval=0.1, maxval=30.0, step=0.1) downStep = input.float(title='Approach Decrease Step:', defval=0.005, minval=0.0, maxval = 5, step=0.005) tp = input.float(title="Take Profit:", defval=1.5, minval=0.0, maxval=100.0, step=0.1) * 0.01 sl = input.float(title="Stop Loss: ", defval=0.0, minval=0.0, maxval=100.0, step=0.1) * 0.01 longEntry = input.bool(defval=true, title= 'Long Entry', inline="11") shortEntry = input.bool(defval=true, title='Short Entry', inline="11") //---------- backtest range setup ------------ fromDay = input.int(defval = 1, title = "From Day", minval = 1, maxval = 31) fromMonth = input.int(defval = 1, title = "From Month", minval = 1, maxval = 12) fromYear = input.int(defval = 2021, title = "From Year", minval = 2010) toDay = input.int(defval = 30, title = "To Day", minval = 1, maxval = 31) toMonth = input.int(defval = 12, title = "To Month", minval = 1, maxval = 12) toYear = input.int(defval = 2022, title = "To Year", minval = 2010) //------------ time interval setup ----------- start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window finish = timestamp(toYear, toMonth, toDay, 23, 59) // backtest finish window window() => true // create function "within window of time" //------- define the global variables ------ enterLongComment = "ENTER LONG" exitLongComment = "EXIT LONG" enterShortComment = "ENTER SHORT" exitShortComment = "EXIT SHORT" longTPSL = "Long TP/SL" longTP = "Long TP" longSL = "Long SL" shortTPSL = "Short TP/SL" shortTP = "Short TP" shortSL = "Short SL" var bool long = true var bool stoppedOutLong = false var bool stoppedOutShort = false var float kf = 0.0 var float velo = 0.0 //------ kalman filter calculation -------- dk = src - nz(kf[1], src) smooth = nz(kf[1], src) + dk * math.sqrt(gain / 10000 * 2) velo := nz(velo[1], 0) + gain / 10000 * dk kf := smooth + velo //--------- calculate the loft stopLoss line --------- var stopPercent = stopPercentMax var stopLoss = kf - kf * (stopPercent /100) if long == true stopLoss := kf - (kf * (stopPercent / 100)) if long[1] == true and stopLoss <= stopLoss[1] stopLoss := stopLoss[1] else if (long[1] == true) stopPercent := stopPercent - downStep if(stopPercent < stopPercentMin) stopPercent := stopPercentMin if(kf < stopLoss) long := false stopPercent := stopPercentMax stopLoss := kf + (kf * (stopPercent / 100)) else stopLoss := kf + (kf * (stopPercent / 100)) if long[1] == false and stopLoss >= stopLoss[1] stopLoss := stopLoss[1] else if(long[1] == false) stopPercent := stopPercent - downStep if(stopPercent < stopPercentMin) stopPercent := stopPercentMin if(kf > stopLoss) long := true stopPercent := stopPercentMax stopLoss := kf - (kf * (stopPercent / 100)) //--------- calculate the input/output points ----------- longProfitPrice = strategy.position_avg_price * (1 + tp) // tp -> take profit percentage longStopPrice = strategy.position_avg_price * (1 - sl) // sl -> stop loss percentage shortProfitPrice = strategy.position_avg_price * (1 - tp) shortStopPrice = strategy.position_avg_price * (1 + sl) //------------------- determine buy and sell points --------------------- buySignall = window() and long and (not stoppedOutLong) sellSignall = window() and (not long) and (not stoppedOutShort) //---------- execute the strategy ----------------- if(longEntry and shortEntry) if long strategy.entry("LONG", strategy.long, when = buySignall, comment = enterLongComment) stoppedOutLong := true stoppedOutShort := false else strategy.entry("SHORT", strategy.short, when = sellSignall, comment = enterShortComment) stoppedOutLong := false stoppedOutShort := true else if(longEntry) strategy.entry("LONG", strategy.long, when = buySignall, comment = enterLongComment) strategy.close("LONG", when = sellSignall, comment = exitLongComment) if long stoppedOutLong := true else stoppedOutLong := false else if(shortEntry) strategy.entry("SHORT", strategy.short, when = sellSignall, comment = enterShortComment) strategy.close("SHORT", when = buySignall, comment = exitShortComment) if not long stoppedOutShort := true else stoppedOutShort := false //----------------- take profit and stop loss ----------------- if(tp>0.0 and sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, stop=longStopPrice, comment = longTPSL) else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, stop=shortStopPrice, comment = shortTPSL) else if(tp>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, comment = longTP) else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, comment = shortTP) else if(sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", stop=longStopPrice, comment = longSL) else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", stop=shortStopPrice, comment = shortSL) //------------- plot charts --------------------- lineColor1 = long ? color.green : color.red lineColor2 = long ? color.aqua : color.fuchsia kalmanLine = plot(kf, color=lineColor1, linewidth=3, title = "Kalman Filter") stopLine = plot(stopLoss, color=lineColor2, linewidth=2, title = "Stop Loss Line")