[pshaiBot] Simple Market Maker (SPOT MODE)

3 287 Views No Comments 2 months ago
  • Simple Market Maker
    by pshai @ 2020

    Introduction:
    This simple market maker makes the market!
    It doesn’t stop, it has no limits (other than max. pos. size)
    and it’s amazing. Get familiar with the bot before using it!
    I strongly suggest doing backtests and especially running it
    using a simulated account until you are confident that you know that
    this bot knows what it is doing! Also remember that backtests cannot
    represent the results you would see with a live bot; the difference
    is very…different.

    –== !NEW! Spot Version ==–
    This version is for spot not leverage!

    *THINGS TO NOTE:*
    – This bot will not work well on:
    –> Bybit; bot is too intense for their API, dont trade there…
    –> Bitmex; API Incompatibilities

    ~~ May the profits be with you ~~
    ~pshai

    Consider donating to support my work!
    BTC: 3FRx1EkG4T4izrkaS34xeZHJFK4kQefHKf

    HaasScript Code
    -- Simple Market Maker
    -- by pshai @ 2020
    --
    -- Introduction:
    -- This simple market maker makes the market!
    -- It doesn't stop, it has no limits (other than max. pos. size)
    -- and it's amazing. Get familiar with the bot before using it!
    -- I strongly suggest doing backtests and especially running it
    -- using a simulated account until you are confident that you know that
    -- this bot knows what it is doing! Also remember that backtests cannot
    -- represent the results you would see with a live bot; the difference
    -- is very...different.
    --
    -- --== !NEW! Spot Version ==--
    -- This version is for spot not leverage!
    --
    -- *THINGS TO NOTE:*
    --  - This bot will not work well on:
    --    --> Bybit; bot is too intense for their API, dont trade there...
    --    --> Bitmex; API Incompatibilities
    --  - BE VERY CAREFUL with fixed high leverage!
    --
    --
    -- ~~ May the profits be with you ~~
    -- ~pshai
    --
    --
    -- Consider donating to support my work!
    -- BTC: 3FRx1EkG4T4izrkaS34xeZHJFK4kQefHKf
    -- --------------------------------------------------------------------------
    
    EnableHighSpeedUpdates(true)
    HideOrderSettings()
    HideTradeAmountSettings()
    
    -- inputs
    local slotCount = Input('01. Slot Count', 5, 'How many orders are constantly kept open on both long and short side')
    local slotSize = Input('02. Slot Size', 0.01, 'Trade amount per slot')
    local slotSpread = Input('03. Slot Spread %', 0.1, 'Percentage based spread value between each slot')
    local slotCancel = Input('04. Cancel Distance %', 0.1, 'How much price can move to the opposite direction before orders are cancelled and replaced')
    local minSpread = Input('05. Minimum Spread %', 0.1, 'Minimum spread percentage between the first long and short entries. This setting only works when bot has no position.')
    local maxSize = Input('06. Max. Size', 120, 'Maximum open contracts at any given time. After exceeding this value, the bot will dump a portion of position at a loss')
    local reduceSize = Input('07. Size Reduction %', 25, 'How big of a portion the bot will dump once Max. Open Contracts is exceeded')
    local reduceOrderType = InputOrderType('08. Reduction Order Type', MarketOrderType, 'The order type for size reduction dump')
    local takeProfit = Input('09. Take-Profit %', 0.2, 'Fixed take-profit value, based on price change')
    local tpOrderType = InputOrderType('10. TP Order Type', MakerOrCancelOrderType, 'The order type for take-profit')
    
    --
    minSpread = minSpread / 2.0
    
    -- price and data
    local cp = CurrentPrice()
    local aep = GetPositionEnterPrice()
    local pamt = GetPositionAmount()
    local proi = GetPositionROI()
    
    Log('position ROI: '..Round(proi, 4)..'%')
    
    -- not using spread if we have a position
    if pamt > 0 then
      minSpread = 0
    end
    
    -- slot function
    local slot = function(index, amount, spread, cancelDist)
      local prefix = 'L'
      local name = prefix .. index
      local priceBase = cp.bid
      local spr = minSpread + spread * index
    
      -- if we have average entry price
      if aep > 0 then
        priceBase = Min(aep, priceBase)
      end
    
      -- get price
      local price = SubPerc(priceBase, spr)
    
      local oid = Load(name..'oid', '') -- order id
    
      if oid != '' then
        local order = OrderContainer(oid)
    
        if order.isOpen then
          local delta = Delta(AddPerc(order.price, spr), priceBase)
    
          if delta >= cancelDist then
            CancelOrder(oid)
            oid = '' -- reset id immediately, otherwise need 2 updates to get new order
            LogWarning('Delta cancelled '..name)
          end
        else
          oid = ''
        end
      else
          SetFee(Abs(MakersFee())*-1)
          oid = PlaceBuyOrder(price, amount, {type = MakerOrCancelOrderType, note = name, timeout = 3600})
      end
    
      Save(name..'oid', oid)
    end
    
    -- update take-profit
    local updateTakeProfit = function(currentSize, entryPrice, targetRoi, cancelDist)
      local name = 'Take-Profit'
      local oid = Load('tp_oid', '')
      local price = cp.ask
      local timer = Load('tp_timer', Time())
      local tp_delta = Delta(entryPrice, cp.bid)
    
      if oid != '' then
        local order = OrderContainer(oid)
    
        if order.isOpen then
          local delta = Delta(order.price, cp.close)
    
          if delta >= cancelDist then
            CancelOrder(oid)
            LogWarning('Delta cancelled '..name)
          end
        else
          oid = ''
        end
      else
        if tp_delta >= targetRoi and Time() >= timer then
          SetFee(tpOrderType == MarketOrderType and TakersFee() or Abs(MakersFee())*-1)
          oid = PlaceSellOrder(price, currentSize, {type = tpOrderType, note = name, timeout = 3600})
          timer = Time() + 60 -- 1min
        end
      end
    
      Save('tp_oid', oid)
      Save('tp_timer', timer)
    end
    
    
    -- update position size
    local updatePositionManagement = function(currentSize, sizeLimit, cancelDist)
      local name = 'Size Reduction'
      local oid = Load('pos_oid', '')
      local amount = SubPerc(currentSize, 100 - reduceSize) -- take X% of position
      local price = cp.ask
      local timer = Load('pos_timer', Time())
    
      if oid != '' then
        local order = OrderContainer(oid)
    
        if order.isOpen then
          local delta = Delta(order.price, cp.close)
    
          if delta >= cancelDist then
            CancelOrder(oid)
            LogWarning('Delta cancelled '..name)
          end
        else
          oid = ''
        end
      else
        if currentSize > sizeLimit and Time() >= timer then
          SetFee(reduceOrderType == MarketOrderType and TakersFee() or Abs(MakersFee())*-1)
          oid = PlaceSellOrder(price, amount, {type = reduceOrderType, note = name, timeout = 6000})
          timer = Time() + 60 -- 1min
        end
      end
    
      Save('pos_oid', oid)
      Save('pos_timer', timer)
    end
    
    
    -- da logica
    
    -- take profit
    updateTakeProfit(pamt, aep, takeProfit, slotCancel)
    
    -- risk management
    updatePositionManagement(pamt, maxSize, slotCancel)
    
    
    -- update slots
    for i = 1, slotCount do
      slot(i, slotSize, slotSpread, slotCancel) -- long slot
    end
    
    if aep > 0 then
      local posId = PositionContainer().positionId
      Plot(0, 'AvgEP', aep, {c=Purple, id=posId, w=2})
    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