[pshaiBot] MadHatter Bot v2 - The original Haasonline MadHatter Bot in steroids
stableDescription
This bot is the same as the original, but now you are able to do multiple entries!
Hope this script also brings some educational value to those who want to learn HaasScript! :) <3
HaasScript
EnableHighSpeedUpdates(true)
-- market compatibility
local isSpot = MarketType() == SpotTrading
local buy_cmd = isSpot and PlaceBuyOrder or PlaceGoLongOrder
local sell_cmd = isSpot and PlaceSellOrder or PlaceGoShortOrder
-- Safeties
InputGroupHeader('General Settings')
maxEntries = Input('1. Max. Entries', 10, 'The maximum amount of entries allowed per position')
stopLoss = Input('2. Stop Loss (%)', 1)
takeProfit = Input('3. Take Profit (%)', 1)
consensus = Input('4. Indicator Consensus', true)
entryOrderType = InputOrderType('5. Entry Order Type', MakerOrCancelOrderType)
entryTimeout = Input('6. Entry Order Timeout', 10, 'Entry order timeout in minutes')
entryTimeLimit = Input('7. Entry Cooldown', 10, 'Entry cooldown in minutes. Use this to ensure bot doesn\'t consume all entries on consecutive signals (unless that is a wanted behavior). Set this to zero to ignore')
exitOrderType = InputOrderType('8. Exit Order Type', MakerOrCancelOrderType)
exitTimeout = Input('9. Exit Order Timeout', 10, 'Exit order timeout in minutes')
-- Indicators
bbInterval = InputInterval('BBands Interval', 5, 'Sets the data and update interval for BBANDS', 'MadHatter BBands ')
macdInterval = InputInterval('MACD Interval', 5, 'Sets the data and update interval for MACD', 'MadHatter MACD ')
rsiInterval = InputInterval('RSI Interval', 5, 'Sets the data and update interval for RSI', 'MadHatter RSI ')
bbandResult = CC_MadHatterBBands(0, '', bbInterval)
macdResult = CC_MadHatterMACD(1, '', macdInterval)
rsiResult = CC_MadHatterRSI(2, '', rsiInterval)
indicatorContainer = IndicatorContainer(
bbandResult,
macdResult,
rsiResult
)
indicatorSignal = indicatorContainer[1]
if consensus then
indicatorSignal = indicatorContainer[2]
end
-- Insurances
insurances = InsuranceContainer(OvercomeFeeCosts())
-- Safeties
safeties = SafetyContainer(StopLoss(stopLoss), TakeProfit(takeProfit))
-- useful data
local cp = CurrentPrice()
local botPos = GetPositionDirection()
local botRoi = GetPositionROI()
local entryCount = Load('ec', 0)
-- entry logic function
local updateEntryLogic = function(isLong, can_entry)
local orderId = Load('en_oid', '')
local remaining = 0
local cmd = isLong and buy_cmd or sell_cmd
if orderId != '' then
local order = OrderContainer(orderId)
if order.isOpen then
return -- nothing to do
else
remaining = order.executedAmount - order.filledAmount
if order.isFilled and remaining == 0 then
-- increment entryCount
entryCount = entryCount + 1
end
orderId = ''
end
end
if can_entry and entryCount < maxEntries then
local price = isLong and SubPerc(cp.bid, 0.001) or AddPerc(cp.ask, 0.001)
local amount = remaining == 0 and TradeAmount() or remaining
local note = (isLong and 'L' or 'S') .. (entryCount + 1)
if IsTradeAmountEnough(PriceMarket(), price, amount, true) then
-- place order
orderId = cmd(price, amount, {type = entryOrderType, note = note, timeout = entryTimeout})
end
end
Save('en_oid', orderId)
end
-- exit logic function
local updateExitLogic = function(isProfit)
local orderId = Load('ex_oid', '')
local remaining = 0
if orderId != '' then
local order = OrderContainer(orderId)
if order.isOpen then
return -- nothing to do
else
remaining = order.executedAmount - order.filledAmount
if order.isFilled and remaining == 0 then
-- reset entryCount since we exited successfully
entryCount = 0
end
orderId = ''
end
end
local note = isProfit and 'Take-Profit' or 'Stop-Loss'
-- place order
orderId = PlaceExitPositionOrder({type = exitOrderType, note = note, timeout = exitTimeout})
Save('ex_oid', orderId)
end
-- the new logic
local entry_long = false
local entry_short = false
if insurances and (entryTimeLimit == 0 or TradeOncePerBar(entryTimeLimit)) then
-- having botRoi in the rules will make sure we don't
-- increase position size in the profitable direction.
-- we only want to add to the position when we are on
-- the losing side, to ensure our DCA/AvgEP moves only
-- outwards - not inwards!
if indicatorSignal == SignalBuy
and botPos != PositionShort
and botRoi <= 0 then
entry_long = true
elseif indicatorSignal == SignalSell
and botPos != PositionLong
and botRoi <= 0 then
entry_short = true
end
end
-- we call these on every update,
-- just so we get our order IDs updated
updateEntryLogic(true, entry_long) -- long
updateEntryLogic(false, entry_short) -- short
-- safeties
if safeties and botPos != NoPosition then
updateExitLogic(botRoi > 0)
end
-- Save memory
Save('ec', entryCount)
-- Reports
Finalize(function()
CustomReport('BBands Signal', bbandResult)
CustomReport('MACD Signal', macdResult)
CustomReport('RSI Signal', rsiResult)
CustomReport('Entry Count', entryCount)
end)
1 Comment
Sign in to leave a comment.
Could you kindly assist on what code I need to add to mad hatter for a second RSI check.
I'm trading on the 5 or 15 min interval with buy at 25 RSI
I'd like to also add another settings section for an additional RSI indicator, example: buy on 4 hour RSI < 40.