[pshaiBot] MadHatter Bot v2 – The original Haasonline MadHatter Bot in steroids

0 299 Views No Comments 3 months ago
  • 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 Code
    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('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)
    safeties = SafetyContainer(StopLoss(stopLoss), TakeProfit(takeProfit))
    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 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
    InputGroupHeader('Settings')
    
    bbandResult = CC_MadHatterBBands(0, '')
    
    InputGroupHeader('MadHatter MACD')
    macdResult = CC_MadHatterMACD(1, '')
    
    InputGroupHeader('MadHatter RSI')
    rsiResult = CC_MadHatterRSI(2, '')
    
    indicatorContainer = IndicatorContainer( 
        bbandResult,
        macdResult,
        rsiResult
    )
    
    indicatorSignal = indicatorContainer[1]
    if consensus then
        indicatorSignal = indicatorContainer[2]
    end
    
    -- Insurances
    insurances = InsuranceContainer(OvercomeFeeCosts())
    
    
    -- useful data
        local cp = CurrentPrice()
        local botPos = GetPositionDirection()
        local botRoi = GetPositionROI()
        local entryCount = Load('ec', 0)
    
    -- entry logic function
        local updateEntryLogic = function(isLong)
            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 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
        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
                updateEntryLogic(true)
            
            elseif indicatorSignal == SignalSell
            and botPos != PositionLong
            and botRoi <= 0 then
                updateEntryLogic(false)
            end
        end
    
    -- 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)
Login or Register to Comment

Unlock your crypto trading potential

Create a free account and enjoy everything we have to offer.

Join for Free