[DMcL] Kernel Trading Machine
betaDescription
"the trend is your friend"
Rather than a mean-reverting strategy, I wanted something that goes all-in once (instead of doubling down on losing entry) and then captures profits in layers.
It doesnt trade often when using good settings - maybe once every week or two - but can lock in those profits to keep gains consistent.
HaasScript
-- Author: DMcL
-- original indicator by jdehorty
-- https://www.tradingview.com/script/AWNvbPRM-Nadaraya-Watson-Rational-Quadratic-Kernel-Non-Repainting/
EnableHighSpeedUpdates(true)
HideOrderSettings()
HideTradeAmountSettings()
SetFee(-0.025) -- for backtesting
OptimizedForInterval(60,
function()
local trade_margin = Input('Trade Margin', 100, 'Total margin used of quote currency (e.g. USDT)', 'Bet Size')
local h = Input('Lookback Window', 6, 'The number of bars used for the estimation. This is a sliding value that represents the most recent historical bars. Recommended range: 3-50', 'Kernel Settings')
local r = Input('Relative Weighting', 25, 'Relative weighting of time frames. As this value approaches zero, the longer time frames will exert more influence on the estimation. As this value approaches infinity, the behavior of the Rational Quadratic Kernel will become identical to the Gaussian kernel. Recommended range: 0.25-25', 'Kernel Settings')
local x_0 = Input("Start Regression at Bar", 17, 'Bar index on which to start regression. The first bars of a chart are often highly volatile, and omission of these initial bars often leads to a better overall fit. Recommended range: 5-25', 'Kernel Settings')
local close = ClosePrices()
local high = HighPrices()
local low = LowPrices()
local ohlc = OHLCPrices()
-- inputs
local emaFilter = Input('Use EMA Filter', true, 'If true, will only take long trades when price is above ema, and short when below', 'EMA settings')
local emaLength = Input('EMA Length', 150, '', 'EMA settings')
local oppSig = Input('Opposite signal acts as Stop Loss', true, 'If true, change of signal will exit', 'EMA settings')
local layers = Input('Take Profit Layers', 6, 'How many exit orders to create. Must be greater than 1', 'Take Profit & Stop Loss')
local atrPeriod = 20
local atrpMult = Input('Take Profit gaps ATR multiplier', 0.1, 'Recommended range: 0-0.5. The ATR as a percentage, multiplied by this number, will be added to each take profit layer. Use to make take profit layers size dynamic. 0 will disable', 'Take Profit & Stop Loss')
local natr = (ATR(high, low, close, atrPeriod)/close)*100
local natrScaled = natr*atrpMult
local tpGaps = Input('Take Profit gaps %', 0.9, 'Recommended range: 0.5-3. This exact value, as a percentage, will be added to each take profit layer. 0 will disable', 'Take Profit & Stop Loss')
local follow = Input('Trailing Stop Loss Follows Take Profit Reached',0, 'MUST be integer. If set to 0, the stop loss will move to break even when take profit 1 is filled, move to take profit 1 when take profit 2 is filled and so on. If set to 1, stop loss will move to break even once take profit 2 is reached, move to take profit 1 once take profit 3 is reached and so on.', 'Take Profit & Stop Loss')
local stoploss = Input("Stop Loss %", 20, 'Percent where stop loss is set at beginning of position ', 'Take Profit & Stop Loss')
local stopTrailLimit = Input("Limit Trailing Stop-loss to break-even", true, 'If true, trailing stop loss will stop trailing at break even level.', 'Take Profit & Stop Loss')
local forceExitPos = Input("Force Exit Position", false, 'manually exit position', 'Take Profit & Stop Loss')
-- data
local ema = EMA(close, emaLength)
local cp = CurrentPrice()
local ob = GetOrderbook()
local cv = ContractValue()
local profit = GetBotProfit()
local tradeAmount = trade_margin/cv * Leverage()
-- position
local posId = Load('posId', NewGuid())
local position = PositionContainer(posId)
-- useful values
local entryPrice = position.enterPrice
local posAmount = position.amount
local tpAmount = (posAmount/layers)
local shutdownTypes = {
stoploss = 1,
fliplong = 2,
flipshort = 3
}
-- new array function
function newArray(size, def_val)
local arr = {}
for i = 1, size do
arr[i] = def_val
end
return arr
end
-- memory
local leid = Load('leid', '')
local seid = Load('seid', '')
local lxeid = Load('lxeid', '')
local sxeid = Load('sxeid', '')
local xeid = Load('xeid', '')
local changeLong = Load('changeLong', false)
local changeShort = Load('changeShort', false)
local stopOrder = Load('stopOrder', false)
local index = Load('index', 0)
local TPidL = Load('TPidL', newArray(layers, ''))
-- new position function
function newPosition()
leid = ''
seid = ''
lxeid = ''
sxeid = ''
xeid = ''
changeLong = false
changeShort = false
stopOrder = false
index = 0
TPidL = newArray(layers, '')
posId = NewGuid()
end
-- stop-loss function
function execStopLossExit(type)
if IsAnyOrderOpen(posId) then
CancelAllOrders(posId)
LogWarning('cancelling tp orders...')
stopOrder = true
end
if type == shutdownTypes.fliplong then
LogWarning('--- flip direction long')
elseif type == shutdownTypes.flipshort then
LogWarning('--- flip direction short')
elseif type == shutdownTypes.stoploss then
LogWarning('--- stop loss cutoff')
elseif type == shutdownTypes.force then
LogWarning('--- manual exit')
end
end
-- stop-loss order function
if stopOrder then
if not IsAnyOrderOpen(posId) then
Log('All Take Profits cancelled...')
PlaceExitPositionOrder(posId, {type = MarketOrderType, note = 'Stoploss Exit position order exec..'})
newPosition()
end
end
-- set the stop loss price
function updateOrders(isLong)
slPrice = isLong
and SubPerc(entryPrice, stoploss)
or AddPerc(entryPrice, stoploss)
brEven = isLong
and AddPerc(entryPrice, 0.00)
or SubPerc(entryPrice, 0.00)
-- loop for updating take profit filled index for trailing stop loss
for z=1, (layers - 1) do
if TPidL[z] != '' and IsOrderFilled(TPidL[z]) then
index = (z - follow)
end
-- stop loss price
if index <= 0 then
SL = slPrice
elseif index == 1 then
SL = brEven
elseif index > 1 and stopTrailLimit == false then
SL = OrderContainer(TPidL[(index - 1)]).price
end
end
-- plot stop loss in red
if isLong then
Plot(0, 'SL', SL, {c=Red, id=leid})
else
Plot(0, 'SL', SL, {c=Red, id=seid})
end
-- checking if stop loss triggered
if (position.isLong and cp.bid < SL)
or (position.isShort and cp.ask > SL)
then
execStopLossExit(shutdownTypes.stoploss)
end
end
-- take profit orders
-- loop to create desired (layers) amount of take profit orders
for z = 1, layers do
-- setting take profits
if (leid != '' and (TPidL[z] == '' or not TPidL[z])) then
TPidL[z] = PlaceExitLongOrder(AddPerc(OrderContainer(leid).price, ((tpGaps+natrScaled) * z)), tpAmount,{type=LimitOrderType, note='Take Profit L'..z, timeout=-1, positionId=posId})
end
if (seid != '' and (TPidL[z] == '' or not TPidL[z])) then
TPidL[z] = PlaceExitShortOrder(SubPerc(OrderContainer(seid).price, ((tpGaps+natrScaled) * z)), tpAmount,{type=LimitOrderType, note='Take Profit S'..z, timeout=-1, positionId=posId})
end
-- plotting
if TPidL[z] != '' and IsOrderOpen(TPidL[z]) then
Plot(0, 'TPidL'..z, OrderContainer(TPidL[z]).price, {c=Yellow, id = TPidL[z]})
end
end
-- checking if last take profit hit
if TPidL[layers] != '' and IsOrderFilled(TPidL[layers]) then
Log('All Take Profits Hit')
PlaceExitPositionOrder(posId, {type = MarketOrderType, note = 'Exit position in full..'})
newPosition()
end
-- entry functions
function goLong()
if (leid == '' or not leid)then
leid = PlaceGoLongOrder(cp, tradeAmount,{type=MarketOrderType, note='Long Entry', timeout=-1, positionId = posId})
end
end
function goShort()
if (seid == '' or not seid)then
seid = PlaceGoShortOrder(cp, tradeAmount,{type=MarketOrderType, note='Short Entry', timeout=-1, positionId = posId})
end
end
-- ema trend
local emaUptrend = close > ema
local emaDowntrend = close < ema
local emaAllowLong = (emaUptrend and emaFilter) or not emaFilter
local emaAllowShort = (emaDowntrend and emaFilter) or not emaFilter
local signal = CC_Nadaraya_Watson_Kernel(2, h, r, x_0)
-- trading
if TradeOncePerBar() and not forceExitPos then
if signal == SignalLong then
Log("SIGNAL LONG")
if emaAllowLong then
if (position.isShort and not position.isLong) and IsAnyOrderOpen(posId) then
LogWarning("flipping long...")
CancelAllOrders(posId)
changeLong = true
elseif not (position.isLong or position.isShort) then
goLong()
end
elseif (position.isShort and not position.isLong) and oppSig then
execStopLossExit(shutdownTypes.stoploss)
end
end
end
if TradeOncePerBar() and not forceExitPos then
if signal == SignalShort then
Log("SIGNAL SHORT")
if emaAllowShort then
if (position.isLong and not position.isShort) and IsAnyOrderOpen(posId) then
LogWarning("flipping short...")
CancelAllOrders(posId)
changeShort = true
elseif not (position.isLong or position.isShort) then
goShort()
end
elseif (position.isLong and not position.isShort) and oppSig then
execStopLossExit(shutdownTypes.stoploss)
end
end
end
-- flipping position
if changeLong and not IsAnyOrderOpen(posId) then
Log('all tps cancelled')
sxeid = PlaceExitPositionOrder(posId, {type = MarketOrderType, note = 'Change to Long...'})
changeLong = false
end
if sxeid != '' and IsOrderFilled(sxeid) then
Log('Short exit filled')
newPosition()
goLong()
end
if changeShort and not IsAnyOrderOpen(posId) then
Log('all tps cancelled')
lxeid = PlaceExitPositionOrder(posId, {type = MarketOrderType, note = 'Change to Short...'})
changeShort = false
end
if lxeid != '' and IsOrderFilled(lxeid) then
Log('Long exit filled')
newPosition()
goShort()
end
if position.isLong then
updateOrders(true)
elseif position.isShort then
updateOrders(false)
end
if forceExitPos == true then
execStopLossExit(shutdownTypes.force)
end
-- plot
Plot(0, "EMA", ema, Yellow(10))
prof_plot = Plot(2, "PnL", profit, Green(40))
PlotDoubleColor(prof_plot, 0, Red)
Plot(2, "", 0, White)
-- saving order ids
Save('posId', posId)
Save('leid', leid)
Save('lxeid', lxeid)
Save('seid', seid)
Save('sxeid', sxeid)
Save('xeid', xeid)
Save('changeLong', changeLong)
Save('changeShort', changeShort)
Save('stopOrder', stopOrder)
Save('index', index)
Save('TPidL', TPidL)
end)
local roi = GetBotROI()
local pfac = (GetTradingReport().profitFactor)
local winPrc = GetTradingReport().winPercentage
local factor = Load('factor', pfac)
if pfac == 1 then
factor = 99
else
factor = pfac
end
Save('factor', factor)
Finalize(function()
CustomReport('win %', winPrc, '', true)
end)
0 Comments
Sign in to leave a comment.
No comments yet. Be the first!