PTpExits ProfitTrailing ExitsOrderOptions to flip or reduce, hide

alpha
By Kobalt in Safeties Published July 2022 👁 1,387 views 💬 0 comments

Description

early test will further look into Firetron's OrderOptions this needs to be cleaner.. But Trailing, logging, plotting and fwd compatibillity should be better with the reduceOnly addition, to only use PlaceSellOrder, PlaceBuyOrder on Spot and on Leverage use PlaceShortOrder, PlaceLongOrder with isReduceOnly enabled to close, giving the added non reducing (opposite Entry on Exit) to Flip vs flatten dependency in VE Unmanaged Template plus bot
HaasScript
-- Author: Kobalt
DefineCommand("PTpExits", "last step to including Interim managed order placement--only add the result trigger, order specs..check inputOrderOptions integration A price-based ProfitTrailer implementation by Pshai TEST InterimManaged handle order placements inside--Loging--verbose logging")
local ptqname = DefineParameter(StringType, "name", "Name to distinguish it from others if used multiples in one script.", false, "long", "Text: direction-order-prefix" ) 
local idirection = DefineParameter(StringType, "direction", "sell or up to (spot PlaceSellOrder) PlaceGoShortOrder_reduceOnly [PlaceExitLongOrder], buy or down to (spot PlaceBuyOrder) PlaceGoShortOrder_reduceOnly [PlaceExitLongOrder], default = exit PlaceExitPositionOrder/DoExit or unspecified]'", false, "exit", "Text: direction-order-prefix or tradeActionRouteKey" )
local trailStartPrc = DefineParameter(NumberType, "trailStartPrc", "Price change level (as percentage) where the trailing starts.", false, 1, "Input")
local trailDistPrc = DefineParameter(NumberType, "trailDistPrc", "Trailing distance (as percentage) from the highest recorded price change.", false, 0.5, "Input")
local trailMode = DefineParameter(StringType, "trailMode", "Trailing mode. Use one of the following: 'default', 'grow', or 'shrink'.", false, "default", "Input")
local maxRebounds = DefineParameter(NumberType, "maxRebounds", "Maximum rebounds allowed. If not set, then rebound is not used. Default is 0 (disabled).", false, 0, "Input")
local isReduceOnly = DefineParameter(BooleanType, "reduceOnly or Opposite", "PlaceGoShortOrder_reduceOnly or (potentially non reducing) Opposite PlaceExitLongOrder (ignored on spot)", false, true, "pre-tradeActionRouteKey" )
local positionId = DefineParameter(StringType, "positionId", "Unique position ID.", false, "", "Load" )
local interimInside = DefineParameter(BooleanType, "Interim Managed OrderExecution", "Do everything here.", false, false, 'true, false' )
local isLogging = DefineParameter(BooleanType, "logging", "Turn logging on or off.", false, false, "" )
local isVerbose = DefineParameter(BooleanType, "verbose", "Log extra detail.", false, false, "" )
local isPlotting = DefineParameter(BooleanType, "plotting", "Log extra detail.", false, false, "" )


-- Input fields 
InputGroupHeader( ' ' ..ptqname..' pTIm Settings')
local idirection = InputOptions('direction', 'exit', {'exit', 'sell', 'up', 'buy' , 'down'}, 'sell or up to (spot PlaceSellOrder) PlaceGoShortOrder_reduceOnly [PlaceExitLongOrder], buy or down to (spot PlaceBuyOrder) PlaceGoShortOrder_reduceOnly [PlaceExitLongOrder], default = exit PlaceExitPositionOrder/DoExit if unspecified]')
local trailStartPrc = Input("   Trailing Start %", 1.5, "Profit level (as percentage) where the trailing starts.", "")
local trailDistPrc = Input("  Trailing Distance %", 0.5, "Trailing distance (as percentage) from the highest recorded profit.", "")
local trailMode = Input(" Trailing Mode", 'default', "Trailing mode. Use one of the following: 'default', 'grow', or 'shrink'.","")
local maxRebounds = Input(" Max. Rebounds", 0, "Maximum rebounds allowed. If not set, then rebound is not used. Default is 0 (disabled).","")
local isLogging = Input("Logging", false, "","")
local isVerbose = Input("Verbose Logging", false, "", "")
local isPlotting = Input("Plotting", true, "","")

local position = PositionContainer(positionId)
if positionId == "" then positionId = position[1] end --override empty position id
 
local cp = CurrentPrice()
local market = position[2]
local isLong = position[3]
local direction = GetPositionDirection(positionId)
local ep = GetPositionEnterPrice(positionId)
local start_l = AddPerc(ep, trailStartPrc)
local start_s = SubPerc(ep, trailStartPrc)
 
local isTrailing = Load('isTrailing'..positionId, false)
local highestRoi = Load('highestRoi'..positionId, 0)
local rebounds = Load('rebounds'..positionId, 0)
local reboundLevel = Load('reboundlevel'..positionId, 0)
 
maxRebounds = Abs(maxRebounds)
 
local result = false
 
if direction != NoPosition then
 
    local roi = 0
    if direction == PositionLong then
        roi = (cp.close - ep) / cp.close * 100
    else
        roi = (ep - cp.close) / ep * 100
    end
     if isVerbose then
    Log(market..': Current profit: '..roi..' %')
    Log(market..': Position: '..IfElse(isLong, 'Long', 'Short'))
    end
    -- Check if we need to start trailing
    if not isTrailing then
        if trailStartPrc < roi then
            isTrailing = true
            if isLogging then
                LogWarning(market..': Started trailing.')
            end
        end
    end
 
    -- plot the start-line
    local exitTriggerPlotColor
    if true then
        local start_line = 0
        if direction == PositionLong then
            start_line = AddPerc(ep, trailStartPrc)
        else
            start_line = SubPerc(ep, trailStartPrc)
        end
                if direction == PositionLong then
            exitTriggerPlotColor = Red
        else
            exitTriggerPlotColor = Green 
        end
 if isPlotting then
        Plot(0, 'PT-Start', start_line, {c = exitTriggerPlotColor(33), id = positionId})
    end
 end
    
    -- Update trailing
    if isTrailing then 
        highestRoi = Max(roi, highestRoi)
        local trailStop = 0
 
        -- Check if we need to stop trailing
        --[[
        if roi < trailStartPrc then
            isTrailing = false
            rebounds = 0
            highestRoi = 0
            reboundLevel = 0
 
            LogWarning(market..': Profits have dropped below start value. Trailing is stopped, better luck next time.')
        end
        ]]
 
        -- Default mode
        if trailMode == "default" then
            trailStop = highestRoi - trailDistPrc
        
        -- Grow mode: trail distance grows as profit grows
        elseif trailMode == "grow" then
            local multiplier = trailDistPrc / trailStartPrc
            local newDist = multiplier * highestRoi
            trailStop = highestRoi - newDist
 
        -- Shrink mode: trail distance shrinks as profit grows
        elseif trailMode == "shrink" then
            local multiplier = trailDistPrc * trailStartPrc
            local newDist = multiplier / highestRoi
            trailStop = highestRoi - newDist
        end
 
        -- Update rebound count if used
        if maxRebounds > 0 and reboundLevel > 0 and roi > reboundLevel then
            rebounds = rebounds + 1
            if isLogging then   
                LogWarning(market..': Rebound of '..rebounds..'/'..maxRebounds..'.')
            end
            reboundLevel = 0
        end
     -- plot the start-line
    local exitTriggerPlotColor
    if true then
        local start_line = 0
        if direction == PositionLong then
            start_line = AddPerc(ep, trailStartPrc)
        else
            start_line = SubPerc(ep, trailStartPrc)
        end
                if direction == PositionLong then
            exitTriggerPlotColor = Red
        else
            exitTriggerPlotColor = Green 
        end
 if isPlotting then
        Plot(0, 'PT-Start', start_line, {c = exitTriggerPlotColor(33), id = positionId})
    end
 end
        
        -- Check if we need or can exit...
        if trailStop > roi then
 
            -- Prepare for a rebound if used
            if maxRebounds > 0 and rebounds < maxRebounds and roi >= 0 and reboundLevel <= 0 then
                reboundLevel = roi
                highestRoi = roi
                if isLogging then
                    LogWarning(market..': Rebound target of '..reboundLevel..' % is set.')
                end
            end
            -- Signal for exit
            if rebounds >= maxRebounds then
                result = true
                if isLogging then
                    LogWarning(market..': Signaling exit.') --insert PlaxeEXITS
                end
            end
        end
        
    end
-- Set order placement calls.
-- If we start long we use PlaceBuyOrder or PlaceGoLongOrder
local trigger
local reduce
local enterV
local exitCall = false
                if direction == PositionLong and isReduceOnly then
            trigger = reduce
        else
            trigger = enterV 
        end

local exitCall = IfElse(enterV, PlaceGoLongOrder, PlaceGoShortOrder)

-- If we start short we use PlaceSellOrder or PlaceGoShortOrder -- this is mixed up
local exitCall = IfElse(reduce, PlaceExitLongOrder, PlaceExitShortOrder)
if exitCall and result then
Log(trigger, Yellow)
end
if direction == PositionLong and interimInside then
            exitTriggerPlotColor = Red
        else
            exitTriggerPlotColor = Green 
        end
end

 --DO THE EXITS INSIDE?
-- Store values for next update
Save('isTrailing'..positionId, isTrailing)
Save('highestRoi'..positionId, highestRoi)
Save('rebounds'..positionId, rebounds)
Save('reboundlevel'..positionId, reboundLevel)


-- Define output signal. 
--interim managed inside log exit orderId change to text or dynamic
DefineOutput(BooleanType, result, "True if safety has triggered, otherwise false", "SafetyContainer, And, Or, IfElse, IfElseIf")

0 Comments

Sign in to leave a comment.

No comments yet. Be the first!