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)
Copy to Clipboard