PTpExits ProfitTrailing ExitsOrderOptions to flip or reduce, hide
alphaDescription
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!