Firetron HedgedDCADipper - Blazing mod with Grid mode

stable
By AVWcTL in Trading Bots Published July 2021 👁 1,325 views 💬 0 comments

Description

A mod of FireTron's DCADipper script. Added a minimum price delta option, so the bot will only buy if the price has moved more than the minimum delta. Also added a Grid Mode option, which is a shortcut to setting the interval to 1 minute, and the profit trigger to match the minimum price delta. Grid mode loosely resembles a hedged grid strategy.
HaasScript
--  ============================================================================
--    Firetron's Hedged DCA - Blazing mod with Grid mode
--
--    Runs a long and a short each doing dollar cost averaging strategy.
--    Expands positions on an interval and exits whenever there is a profit.
--
--    Custom Command Dependencies:
--    Firetron's CurrentVsEntry
--    Firetron's FormatRoundedPercent
--    Firetron's FormatRoundedQuoteCurrency
--    Firetron's ReportMaxRiskPoint
--    Firetron's ReportOpenPositions
--    Firetron's TrueOnInterval
--
--    Discord:  @FiretronP75
--  ============================================================================
 
--  ========================================================
--    Configuration
--  ========================================================
 
EnableHighSpeedUpdates()
HideOrderSettings()
HideTradeAmountSettings()
 
--  ========================================================
--    Variables
--  ========================================================
 
local logHRule = '------------------------------------------------------------';
 
--  ------------------------------------
--    Enumerations
--  ------------------------------------
 
local booleanOption = {
  no  = 'No',
  yes = 'Yes',
}
 
local ProfitType = {
  marketChange = 'Market Change',
  positionROI  = 'Position ROI',
}
 
--  ------------------------------------
--    Positions
--  ------------------------------------
 
local longPositionId  = Load('longPositionId',  '')
local shortPositionId = Load('shortPositionId', '')
 
--  ========================================================
--    Inputs
--  ========================================================
 
local group   = ''
local label   = ''
local tooltip = ''
 
--  ------------------------------------
--    Testing
--  ------------------------------------
 
local fee               = Fee()
local isVerbose         = booleanOption.no
local verbosityInterval = 60
 
group = ' Testing'
 
label   = 'Fee Percentage'
tooltip = 'For backtests and simulated trading.'
fee     = Input(label, fee, tooltip, group)
 
label     = 'Verbose Logging'
tooltip   = 'Log extra details. Will run slower.'
isVerbose = InputOptions(label, isVerbose, booleanOption, tooltip, group)
 
label             = 'Verbose Logging Interval'
tooltip           = 'Time between verbose logging.'
verbosityInterval = InputInterval(label, verbosityInterval, tooltip, group)
 
--  ------------------------------------
--    Main
--  ------------------------------------
 
local expandBy      = MinimumTradeAmount()
local interval      = 1440
local profitTrigger = 10
local profitType    = ProfitType.positionROI
local minPriceDelta = 0
local gridMode      = false
 
group = 'Main'
 
label    = '1. Expand By'
tooltip  = 'Number of contracts to expand by each interval.'
expandBy = Input(label, expandBy, tooltip, group)
 
label    = '2. Minimum Price Delta (%)'
tooltip  = 'Minimum price difference to allow an expansion. 0 to disable'
minPriceDelta = Input(label, minPriceDelta, tooltip, group)

label    = '3. Grid Mode'
tooltip  = 'Min Price Delta must be set (> 0). Profit Trigger will be automatically set to MinPriceDelta. Interval is ignored'
gridMode = Input(label, gridMode, tooltip, group)
 
label    = '4. Interval'
tooltip  = 'Time between position expansions.'
interval = InputInterval(label, interval, tooltip, group)

label         = '5. Profit Trigger'
tooltip       = 'Percent profit that will trigger an exit.'
profitTrigger = Input(label, profitTrigger, tooltip, group)
 
label      = '6. Profit Type'
tooltip    = 'Calculate profit using either position ROI or simple change in market price. In other words, you are specifying whether or not your profit trigger is taking leverage into account or not.'
profitType = InputOptions(label, profitType, ProfitType, tooltip, group)
 
 if gridMode then
    if minPriceDelta <= 0 then
      LogError('Minimum Price Delta needs to be greater than 0 for Grid Mode')
      return
    end
    profitTrigger = minPriceDelta
    profitType    = ProfitType.marketChange
    interval      = 1
  end

--  ========================================================
--    Functions
--  ========================================================
 
--  ------------------------------------
--    Debug
--  ------------------------------------
 
function GetDebugInfo ()
 
  if isVerbose == booleanOption.no then
    return {
      isVerbose = false,
    }
  end
 
  if not CC_TrueOnInterval(verbosityInterval) then
    return {
      isVerbose = false,
    }
  end
 
  local currentPrice = CurrentPrice()
 
  return {
    baseCurrency = BaseCurrency(),
    currentAsk   = CC_FormatRoundedQuoteCurrency(currentPrice.ask),
    currentBid   = CC_FormatRoundedQuoteCurrency(currentPrice.bid),
    isVerbose    = true,
  }
 
end

--  ------------------------------------
--    Exiting
--  ------------------------------------
 
function Exit ()
 
  local debugInfo = GetDebugInfo()
 
  ExitCheckLong( debugInfo)
  ExitCheckShort(debugInfo)
 
end
 
--  ----------------
 
function ExitCheckLong (debugInfo)
 
  local longProfit
 
  if longPositionId != '' then
    longProfit = profitType == ProfitType.positionROI and GetPositionROI(longPositionId) or CC_CurrentVsEntry(longPositionId)
  end
 
  if longPositionId == '' then
    if debugInfo.isVerbose then
      Log(logHRule)
      Log('No long position.')
    end
  elseif longProfit >= profitTrigger then
    ExitLong()
  elseif debugInfo.isVerbose then
    Log(logHRule)
    Log('Long profit is '..CC_FormatRoundedPercent(longProfit))
    Log(debugInfo.baseCurrency..' bid is @ '..debugInfo.currentBid)
  end
 
end
 
--  ----------------
 
function ExitCheckShort (debugInfo)
 
  local shortProfit
 
  if shortPositionId != '' then
    shortProfit = profitType == ProfitType.positionROI and GetPositionROI(shortPositionId) or CC_CurrentVsEntry(shortPositionId)
  end
 
  if shortPositionId == '' then
    if debugInfo.isVerbose then
      Log(logHRule)
      Log('No short position.')
    end
  elseif shortProfit >= profitTrigger then
    ExitShort()
  elseif debugInfo.isVerbose then
    Log(logHRule)
    Log('Short profit is '..CC_FormatRoundedPercent(shortProfit))
    Log(debugInfo.baseCurrency..' ask is @ '..debugInfo.currentAsk)
  end
 
end
 
--  ----------------
 
function ExitLong ()
 
  local parameters = {
    positionId = longPositionId,
    type = MarketOrderType,
  }
 
  Log(logHRule)
  LogWarning('Taking profit on long.')
  PlaceExitPositionOrder(parameters);
  longPositionId = ''
  Save('longPositionId', '')
 
end
 
--  ----------------
 
function ExitShort ()
 
  local parameters = {
    positionId = shortPositionId,
    type = MarketOrderType,
  }
 
  Log(logHRule)
  LogWarning('Taking profit on short.')
  PlaceExitPositionOrder(parameters);
  shortPositionId = ''
  Save('shortPositionId', '')
 
end
 
 function notEnoughPriceDelta(isVerbose)
    local cp = CurrentPrice().close
    local lastPrice = Load('LastPrice', 0)
    local priceDelta = Abs(Delta(lastPrice, cp))
    if lastPrice != 0 and minPriceDelta > 0 and  priceDelta < minPriceDelta then
        if isVerbose == booleanOption.yes then
          Log('Skipping expansion. Last Price: '..lastPrice
          ..', Current Price: '..cp..', delta: '..CC_FormatRoundedPercent(priceDelta,2,'%'))
        end
        return true
      end
      Save('LastPrice', cp)
  return false
end

--  ------------------------------------
--    Going
--  ------------------------------------
 
function Go ()
 
  if notEnoughPriceDelta(isVerbose) then
    return
  end

  if longPositionId == '' then
 
    longPositionId = NewGuid()
    Save('longPositionId', longPositionId)
 
  end

  Log(logHRule)
  GoLong()
 
  if shortPositionId == '' then
 
    shortPositionId = NewGuid()
    Save('shortPositionId', shortPositionId)
 
  end
 
  GoShort()
 
end
 
--  ----------------
 
function GoLong ()
 
  local parameters = {
    type = MarketOrderType,
    positionId = longPositionId,
  }
  PlaceGoLongOrder(CurrentPrice().bid, expandBy, parameters)
 
end
 
--  ----------------
 
function GoShort ()
 
  local parameters = {
    type = MarketOrderType,
    positionId = shortPositionId,
  }
 
  PlaceGoShortOrder(CurrentPrice().ask, expandBy, parameters)
 
end
 
--  ========================================================
--    Execution
--  ========================================================
 
SetFee(fee)
 
CC_ReportOpenPositions()
CC_ReportMaxRiskPoint()
 
Exit()
if gridMode or interval == 1 then
  Go()
else
  OptimizedForInterval(interval, Go)
end

0 Comments

Sign in to leave a comment.

No comments yet. Be the first!