Firetron's Hedged DCA
stableDescription
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
HaasScript
-- ============================================================================
-- 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)
10 Comments
Sign in to leave a comment.
MAN! You got some elegant code going on with this one. Beautiful! Great work!
Additional Dependencies Required
Firetron's ReportMaxRiskPoint
Firetron's ReportOpenPositions
Thanks Rusty I will add that to the description.
Hi Firetron, any suggested setting for this?
Hi Firetron and others in the comments. I’m new here, can I use this script with any membership subscription? Am I able to simply copy and paste and tune settings to test this out when signed up?
I’m looking through the getting started guide and browsing the documentation but I haven’t found any specific answers so far. Open to input and suggestions. Can also refer to support as needed or suggested. Thank you. Have a nice day.
Join us on Discord to get some help.
Okay. I will join you all on discord to get some help in a few minutes. Thanks.
I cant seem to get this profit target working. When I out put logging there appear to be no market to market values
Hi Firetron, how can I join the discord group ? Thanks
https://discord.gg/DYhV4bK