Zone Recovery Bot Hedge SMOD
stableDescription
My modification for Haasonline's original Zone Recovery Bot for HEDGE trading mode.
The bot use balance ratio as stop loss and not position size like the original bot.
"Closing all positions when working balance (total used margin - total unrealized profit) / bot balance (starting balance + realized profit) > value."
The TP % is minimum. The end % is dynamic calculated using formula i steal from Pshai's SMM 2.0. Hedging TP (when bot has both direction open) is the % of used margin.
Have fun with it and may the profits be with you!
More questions ? Find me in Haasonline Discord.
If you would like to buy me a cup of coffee or diamond:
ENS: smokyho.eth
HaasScript
--If you would like to buy me a cup of coffee or diamond:
--ENS: smokyho.eth
EnableHighSpeedUpdates()
HideTradeAmountSettings()
-- Inputfields
InputGroupHeader('Bot Settings')
local startingBalance = Input('Starting Balance '..ProfitLabel(), 0)
local startingAmount = Input('Starting exposure '..AmountLabel(), 1)
local amountFactor = Input('Trade amount factor', 2)
local zoneFactor = Input('Zone factor', 1)
InputGroupHeader('Backtest Settings')
local wtfBalRatio = Input('Stop at Bal. Ratio Limit', false, 'Stop backtest when balance ratio limit below reached.')
InputGroupHeader('Safety Settings')
local balRatioLimit = Input("Balance Ratio Limit", 0.25, "Closing all positions when working balance (total used margin - total unrealized profit) / bot balance (starting balance + realized profit) > value.")
InputGroupHeader('Profit Settings')
local minProfit = Input('Min. Percentage profits', 0.5)
local market = PriceMarket()
local leverage = GetLeverage()
local mainInterval = CurrentInterval()
local cp = CurrentPrice()
local report = GetTradingReport()
local tpTrigger = minProfit
local h, l, c, basePrice, tpTrigger = OptimizedForInterval(0, function()
local h = HighPrices()
local l = LowPrices()
local c = ClosePrices()
local basePrice = HLCPrices()
local tr = TRANGE(h, l, c)
local diff = Max(tr, DEMA(tr, 7), SMA(tr, 7), TRIMA(tr, 7)) / c * 100
local rsi = RSI(c, 14)
local skew = Max(Abs(50 - rsi) / 50, DEMA(Abs(50 - rsi) / 50, 20))
local tpTrigger = Max(minProfit, diff) + skew
return h, l, c, basePrice, tpTrigger
end)
---------------------
-- PERSISTENT STORAGE
if not inited then
bot = Load('bot', {})
if Count(bot) == 0 then
-- positions
bot.longPosId = NewGuid()
bot.shortPosId = NewGuid()
-- stats
bot.reset = true
bot.basePrice = basePrice
bot.targetSide = SignalExitPosition
bot.startingAmount = startingAmount
bot.targetAmount = startingAmount
bot.highestBalRatio = 0
end
inited = true
end
---------------------
-- DATA
local pamt_l = GetPositionAmount(bot.longPosId)
local pamt_s = GetPositionAmount(bot.shortPosId)
local aep_l = AverageEnterPrice(bot.longPosId)
local aep_s = AverageEnterPrice(bot.shortPosId)
local usedLong = aep_l > 0 and UsedMargin(market, aep_l, pamt_l, leverage) or 0
local usedShort = aep_s > 0 and UsedMargin(market, aep_s, pamt_s, leverage) or 0
local usedTotal = usedLong + usedShort
local profitLong = aep_l > 0 and GetPositionProfit(bot.longPosId) or 0
local profitShort = aep_s > 0 and GetPositionProfit(bot.shortPosId) or 0
local profitTotal = profitLong + profitShort
local botProfit = GetBotProfit(market)
local netBotProfit = GetBotProfit(market, true)
local unrealizedBotProfit = netBotProfit - botProfit
local botBalance = startingBalance + botProfit
local workingBalance = usedTotal - profitTotal
local balRatio = workingBalance / botBalance
local highestBal = startingBalance + report.highestPointInProfit
local lowestBal = startingBalance + report.lowestPointInProfit
-- Side Check
if bot.targetSide == SignalLong then
PlotSignalEnum(-2, SignalLong)
elseif bot.targetSide == SignalShort then
PlotSignalEnum(-2, SignalShort)
elseif bot.targetSide == SignalExitPosition then
PlotSignalEnum(-2, SignalExitPosition)
end
---------------------
-- CALCULATE ENTRY PRICE
if IsAnyOrderOpen() == false and bot.targetSide == SignalExitPosition then
-- We dont have open orders.
-- Reset base price if we dont have a position and are resetting.
if pamt_l + pamt_s == 0 and bot.reset then
zoneTrigger = tpTrigger
bot.reset = false
bot.basePrice = basePrice
bot.longPosId = NewGuid()
bot.shortPosId = NewGuid()
end
end
local zoneSize = (bot.basePrice / 100) * zoneTrigger / zoneFactor
local goLongPrice = bot.basePrice + zoneSize
local goShortPrice = bot.basePrice - zoneSize
---------------------
-- EXECUTION
if IsAnyOrderOpen() == false then
if pamt_l > 0 and pamt_s > 0
and profitTotal > usedTotal * tpTrigger / 100 then
--and profitTotal > (usedLong * TakersFee() * 2) + (usedShort * TakersFee() * 2) then
PlotSignalBar(-2, White)
PlaceExitShortOrder(cp.bid, pamt_s, {positionId = bot.shortPosId, type = MarketOrderType, note = 'Hedge Exit'})
PlaceExitLongOrder(cp.ask, pamt_l, {positionId = bot.longPosId, type = MarketOrderType, note = 'Hedge Exit'})
bot.targetSide = SignalExitPosition
bot.reset = true
elseif bot.targetSide == SignalExitPosition and pamt_l + pamt_s == 0 and MinutesTillCandleClose(mainInterval) == 0 then
-- Do we want to go long?
if cp.close > goLongPrice then
bot.targetSide = SignalLong
bot.targetAmount = bot.startingAmount
PlaceGoLongOrder(cp.bid, bot.startingAmount, {positionId = bot.longPosId, timeout = mainInterval * 60, note = "1st Order"})
-- Or do we want to go short?
elseif cp.close < goShortPrice then
bot.targetSide = SignalShort
bot.targetAmount = bot.startingAmount
PlaceGoShortOrder(cp.ask, bot.startingAmount, {positionId = bot.shortPosId, timeout = mainInterval * 60, note = "1st Order"})
end
elseif bot.targetSide == SignalLong then
-- Are we fully in the long and out the short?
if pamt_l < bot.targetAmount then
local theNote = pamt_s == 0 and "1st Side Order" or "Hedge Order"
PlaceGoLongOrder(cp.bid, bot.targetAmount - pamt_l, {positionId = bot.longPosId, note = theNote})
-- Go short price reached?
elseif cp.close < goShortPrice then
bot.targetSide = SignalExitPosition
-- Maximum amount check
amount = pamt_l * amountFactor
-- Checking working balance
if balRatio < balRatioLimit then
-- Open short with a higher amount
bot.targetSide = SignalShort
bot.targetAmount = amount
PlaceGoShortOrder(cp.ask, amount, {positionId = bot.shortPosId, note = "Hedge Order"})
end
--Take profit price reached?
elseif pamt_s == 0 and cp.close > AddPerc(aep_l, tpTrigger) then
PlaceExitLongOrder(cp.ask, pamt_l, {type = MarketOrderType, positionId = bot.longPosId, note = 'Long TP'})
bot.targetSide = SignalExitPosition
bot.reset = true--]]
end
elseif bot.targetSide == SignalShort then
-- Are we in the short and out the long?
if pamt_s < bot.targetAmount then--or pamt_l > 0 then
local theNote = pamt_l == 0 and "1st Side Order" or "Hedge Order"
PlaceGoShortOrder(cp.ask, bot.targetAmount - pamt_s, {positionId = bot.shortPosId, note = theNote})
-- Go long price reached?
elseif cp.close > goLongPrice then
bot.targetSide = SignalExitPosition
-- Maximum amount check
amount = pamt_s * amountFactor
-- Checking working balance
if balRatio < balRatioLimit then
-- Open long with a higher amount
bot.targetSide = SignalLong
bot.targetAmount = amount
PlaceGoLongOrder(cp.bid, amount, {positionId = bot.longPosId, note = "Hedge Order"})
end
--Take profit price reached?
elseif pamt_l == 0 and cp.close < SubPerc(aep_s, tpTrigger) then
PlaceExitShortOrder(cp.bid, pamt_s, {type = MarketOrderType, positionId = bot.shortPosId, note = 'Short TP'})
bot.targetSide = SignalExitPosition
bot.reset = true
end
end
end
---------------------
-- BALANCE RATIO CHECKING
if balRatio > balRatioLimit then
LogWarning('Maximum Balance Ratio reached. Closing all position and restarting')
PlotSignalBar(-2, Orange)
if wtfBalRatio then
DeactivateBot('Maximum Balance Ratio Reached', true)
end
PlaceExitShortOrder(cp.bid, pamt_s, {positionId = bot.shortPosId, type = MarketOrderType, note = 'Hedge SL'})
PlaceExitLongOrder(cp.ask, pamt_l, {positionId = bot.longPosId, type = MarketOrderType, note = 'Hedge SL'})
bot.reset = true
end
if balRatio > bot.highestBalRatio then
bot.highestBalRatio = balRatio
end
---------------------
-- Lets draw the target prices
Plot(0, 'Go long', goLongPrice, DarkGreen)
Plot(0, 'Go Short', goShortPrice, Red)
Plot(0, "Base", bot.basePrice, DarkGray)
---------------------
-- CHARTS
ChartSetOptions(2, 'Exposure')
Plot(2, 'Long', pamt_l, {c=Green, s=Step})
Plot(2, 'Short', pamt_s, {c=Red, s=Step})
Plot(2, 'Starting Amount', bot.startingAmount, {c=DarkGray, s=Step})
ChartSetOptions(8, 'Balance Monitor')
--Plot(8, 'Net Balance', netBalance, {c=Orange, s=Step})
Plot(8, 'Working Balance', workingBalance, {c=White, s=Step})
Plot(8, 'Unrealized Bot Profit', unrealizedBotProfit, {c=Red, s=Step})
Plot(8, 'Realized Bot Profit', botProfit, {c=DarkGreen, s=Step})
Plot(8, 'Bot Balance', botBalance, {c=Yellow, s=Step})
Plot(8, 'Highest Balance', highestBal, {c=Green, s=Step})
Plot(8, 'Lowest Balance', lowestBal, {c=Fuchsia, s=Step})
Save('bot', bot)
---------------------
-- REPORT
Finalize(function()
local profitPerc = botProfit / startingBalance * 100
local runProfitPerc = netBotProfit / startingBalance * 100
CustomReport('Running Profit %', runProfitPerc..' %')
CustomReport('Realized Profit %', profitPerc..' %')
CustomReport('Highest Bal Ratio', Round(bot.highestBalRatio, 2))
end)
0 Comments
Sign in to leave a comment.
No comments yet. Be the first!