Firetron’s Hedged DCA

4 456 Views 3 Comments 5 months ago
  • 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

    • This topic was modified 5 months, 2 weeks ago by Firetron. Reason: Changed default settings
    • This topic was modified 5 months, 1 week ago by Firetron. Reason: Added more commands to the dependency list
    • This topic was modified 5 months, 1 week ago by Firetron. Reason: Broke up Exit function into smaller functions. Added Verbose Interval input to control frequency of verbose logging
    • This topic was modified 5 months, 1 week ago by Firetron. Reason: Added hyperlinks to commands
    • This topic was modified 3 months ago by Firetron. Reason: Added option for ROI based profit trigger
    • This topic was modified 1 week, 3 days ago by Firetron. Reason: Removed tip addresses
    HaasScript Code
    --  ============================================================================
    --    Firetron's Hedged DCA
    --
    --    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
    
    group = 'Main'
    
    label    = 'Expand By'
    tooltip  = 'Number of contracts to expand by each interval.'
    expandBy = Input(label, expandBy, tooltip, group)
    
    label    = 'Interval'
    tooltip  = 'Time between position expansions.'
    interval = InputInterval(label, interval, tooltip, group)
    
    label         = 'Profit Trigger'
    tooltip       = 'Percent profit that will trigger an exit.'
    profitTrigger = Input(label, profitTrigger, tooltip, group)
    
    label      = '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)
    
    --  ========================================================
    --    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);
      Save('longPositionId', '')
    
    end
    
    --  ----------------
    
    function ExitShort ()
    
      local parameters = {
        positionId = shortPositionId,
        type = MarketOrderType,
      }
    
      Log(logHRule)
      LogWarning('Taking profit on short.')
      PlaceExitPositionOrder(parameters);
      Save('shortPositionId', '')
    
    end
    
    --  ------------------------------------
    --    Going
    --  ------------------------------------
    
    function Go ()
    
      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(0, expandBy, parameters)
    
    end
    
    --  ----------------
    
    function GoShort ()
    
      local parameters = {
        type = MarketOrderType,
        positionId = shortPositionId,
      }
    
      PlaceGoShortOrder(0, expandBy, parameters)
    
    end
    
    --  ========================================================
    --    Execution
    --  ========================================================
    
    SetFee(fee)
    
    CC_ReportOpenPositions()
    CC_ReportMaxRiskPoint()
    
    Exit()
    OptimizedForInterval(interval, Go)
    • #1133
      pshai
      Admin
      Up
      1
      Down

      MAN! You got some elegant code going on with this one. Beautiful! Great work!

    • #1134
      Up
      1
      Down

      Additional Dependencies Required
      Firetron’s ReportMaxRiskPoint
      Firetron’s ReportOpenPositions

    • #1135
      Firetron
      Basic
      Up
      1
      Down

      Thanks Rusty I will add that to the description.

Login or Register to Comment

Unlock your crypto trading potential

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

Join for Free