Reputation: 1
//@version=4
strategy(title="test_rukia", shorttitle="test_rukia")
atrLookback = 12
atrMultiplier = 1.3
atrTrailMode = 'Trailing'
atrFlipInput = "Close"
dummy2 = false
atrBodyPercent = 100
atrWickPercent = 100
atrSmoothingMode = "RMA"
// ============================== CALCULATE ATR ==================================
f_ma(_source, _length, _atrSmoothingMode) => rma(_source, _length)
atrBodyTrueRange = max(abs(open - close), abs(open - close[1]), abs(close - close[1]))
atrWickTrueRange = (high - max(open,close)) + (min(open,close))-low
atrPercentAdjustedTrueRange = (atrBodyTrueRange*(atrBodyPercent/100))+(atrWickTrueRange*(atrWickPercent/100))
atrValue = f_ma(atrPercentAdjustedTrueRange,atrLookback,atrSmoothingMode)
atrMultiplied = atrValue * atrMultiplier
// Plot the price plus or minus the ATR
atrLow = low - atrMultiplied
atrHigh = high + atrMultiplied
// ============================== CALCULATE TRAILING ATR ==================================
f_trail(_source, _trail, _direction) =>
// This function trails the source series up or down
_direction == "down" and _source >= _trail ? _trail : _direction == "up" and _source <= _trail ? _trail : _source
// Need to declare these variables here, in the global scope, so we can use them in other functions later
var float trailAtrLong = atrLow
var float trailAtrShort = atrHigh
// Trail the high (short) stop down and the low (long) stop up
trailAtrLong := f_trail(atrLow, trailAtrLong, "up")
trailAtrShort := f_trail(atrHigh, trailAtrShort, "down")
// ============================== FLIP WHEN PRICE CROSSES ==================================
f_flip(_flipInput, _longTrail, _shortTrail, _longReset, _shortReset) =>
// These variables say whether we are flipping long or short this very bar. Usually they are both false. Only one of them can be true at once.
var bool _flipLongNow = false
var bool _flipShortNow = false
// These variables say what state we're in: long or short. One or both are always true.
// In the beginning, we haven't hit any trails yet, so we start off both long and short, to display both lines.
var bool _isLong = true
var bool _isShort = true
// Get the source, depending whether it's on close or on touch
float _flipLongSource = _flipInput == "Close" ? close : _flipInput == "Wick" ? high : na
float _flipShortSource = _flipInput == "Close" ? close : _flipInput == "Wick" ? low : na
// Are we flipping long or short this bar?
_flipLongNow := _isShort[1] and _flipLongSource > _shortTrail ? true : false
_flipShortNow := _isLong[1] and _flipShortSource < _longTrail ? true : false
// In the edge case where we manage to flip both long and short, we need to reset that based on the close. The close is definitive for history and intra-candle it will take the current value.
_flipLongNow := _flipShortNow and _flipLongNow and close > _longTrail ? true : _flipShortNow and _flipLongNow and close <= _longTrail ? false : _flipLongNow
_flipShortNow := _flipLongNow and _flipShortNow and close < _shortTrail ? true : _flipShortNow and _flipLongNow and close >= _shortTrail ? false : _flipShortNow
// Set the long and short state variables. Set if we flip (simple), initialise to true if this is the first time (needed), otherwise persist.
_isLong := _flipLongNow ? true : _flipShortNow ? false : na(_isLong[1]) ? true : _isLong[1]
_isShort := _flipShortNow ? true : _flipLongNow ? false : na(_isShort[1]) ? true : _isShort[1]
// Update the trailing price. If we flip this bar, reset to the nearest fractal - which goes against the trail direction, which is why we need to use another series.
_longTrailOutput = _longTrail
_shortTrailOutput = _shortTrail
_longTrailOutput := _isLong and not _isLong[1] ? _longReset : _longTrailOutput
_shortTrailOutput := _isShort and not _isShort[1] ? _shortReset : _shortTrailOutput
// Hide the trailing long stop if we are short, and hide the trailing short stop if we are long. Show both if we are both long and short.
float _longTrailPlot = _isLong ? _longTrailOutput : _isLong and _isShort ? _longTrailOutput : na
float _shortTrailPlot = _isShort ? _shortTrailOutput : _isLong and _isShort ? _shortTrailOutput: na
[_longTrailOutput, _shortTrailOutput, _longTrailPlot, _shortTrailPlot]
// Get the plots for the trails, to show only long stop when long and short stop when short.
[trailAtrLongTemp, trailAtrShortTemp, trailAtrLongPlot, trailAtrShortPlot] =
f_flip(atrFlipInput, trailAtrLong, trailAtrShort, atrLow, atrHigh)
// Put these variables back in the global scope so we can persist them and use them as inputs to the function next bar.
trailAtrLong := trailAtrLongTemp
trailAtrShort := trailAtrShortTemp
test=security(syminfo.tickerid, '1', trailAtrLongPlot)
plot(test)
Regarding the content of the test, the error prompts me 'Cannot use a mutable variable as an argument of the security function'. I know it is because the variable is used in the security function, but I have checked a lot of information and still will not modify it.
For a moment, my appeal is to get the trailAtrLongPlot data at the minute level. It seems that only the security function can be implemented, but now the code cannot run.
Upvotes: 0
Views: 122
Reputation: 1699
Mutable variables are variables that get rewritten via the :=
operator. They cannot be used in the security()
function. In your case, you pass two of those, and
, to the f_flip
function, which causes the issue. The quick fix is to create and reassign this variables inside the function itself (I've converted the code to v5 for personal convenience while checking, the fix is similar in v4):
//@version=5
strategy(title="test_rukia", shorttitle="test_rukia")
atrLookback = 12
atrMultiplier = 1.3
atrTrailMode = 'Trailing'
atrFlipInput = "Close"
dummy2 = false
atrBodyPercent = 100
atrWickPercent = 100
atrSmoothingMode = "RMA"
// ============================== CALCULATE ATR ==================================
f_ma(_source, _length, _atrSmoothingMode) => ta.rma(_source, _length)
atrBodyTrueRange = math.max(math.abs(open - close), math.abs(open - close[1]), math.abs(close - close[1]))
atrWickTrueRange = (high - math.max(open,close)) + (math.min(open,close))-low
atrPercentAdjustedTrueRange = (atrBodyTrueRange*(atrBodyPercent/100))+(atrWickTrueRange*(atrWickPercent/100))
atrValue = f_ma(atrPercentAdjustedTrueRange,atrLookback,atrSmoothingMode)
atrMultiplied = atrValue * atrMultiplier
// Plot the price plus or minus the ATR
atrLow = low - atrMultiplied
atrHigh = high + atrMultiplied
// ============================== CALCULATE TRAILING ATR ==================================
f_trail(_source, _trail, _direction) =>
// This function trails the source series up or down
_direction == "down" and _source >= _trail ? _trail : _direction == "up" and _source <= _trail ? _trail : _source
// ============================== FLIP WHEN PRICE CROSSES ==================================
f_flip(_flipInput, _longReset, _shortReset) =>
// Need to declare these variables here, in the global scope, so we can use them in other functions later
var float trailAtrLong = atrLow
var float trailAtrShort = atrHigh
// Trail the high (short) stop down and the low (long) stop up
trailAtrLong := f_trail(atrLow, trailAtrLong, "up")
trailAtrShort := f_trail(atrHigh, trailAtrShort, "down")
// These variables say whether we are flipping long or short this very bar. Usually they are both false. Only one of them can be true at once.
var bool _flipLongNow = false
var bool _flipShortNow = false
// These variables say what state we're in: long or short. One or both are always true.
// In the beginning, we haven't hit any trails yet, so we start off both long and short, to display both lines.
var bool _isLong = true
var bool _isShort = true
// Get the source, depending whether it's on close or on touch
float _flipLongSource = _flipInput == "Close" ? close : _flipInput == "Wick" ? high : na
float _flipShortSource = _flipInput == "Close" ? close : _flipInput == "Wick" ? low : na
// Are we flipping long or short this bar?
_flipLongNow := _isShort[1] and _flipLongSource > trailAtrShort ? true : false
_flipShortNow := _isLong[1] and _flipShortSource < trailAtrLong ? true : false
// In the edge case where we manage to flip both long and short, we need to reset that based on the close. The close is definitive for history and intra-candle it will take the current value.
_flipLongNow := _flipShortNow and _flipLongNow and close > trailAtrLong ? true : _flipShortNow and _flipLongNow and close <= trailAtrLong ? false : _flipLongNow
_flipShortNow := _flipLongNow and _flipShortNow and close < trailAtrShort ? true : _flipShortNow and _flipLongNow and close >= trailAtrShort ? false : _flipShortNow
// Set the long and short state variables. Set if we flip (simple), initialise to true if this is the first time (needed), otherwise persist.
_isLong := _flipLongNow ? true : _flipShortNow ? false : na(_isLong[1]) ? true : _isLong[1]
_isShort := _flipShortNow ? true : _flipLongNow ? false : na(_isShort[1]) ? true : _isShort[1]
// Update the trailing price. If we flip this bar, reset to the nearest fractal - which goes against the trail direction, which is why we need to use another series.
_longTrailOutput = trailAtrLong
_shortTrailOutput = trailAtrShort
_longTrailOutput := _isLong and not _isLong[1] ? _longReset : _longTrailOutput
_shortTrailOutput := _isShort and not _isShort[1] ? _shortReset : _shortTrailOutput
// Hide the trailing long stop if we are short, and hide the trailing short stop if we are long. Show both if we are both long and short.
float _longTrailPlot = _isLong ? _longTrailOutput : _isLong and _isShort ? _longTrailOutput : na
float _shortTrailPlot = _isShort ? _shortTrailOutput : _isLong and _isShort ? _shortTrailOutput: na
[_longTrailOutput, _shortTrailOutput, _longTrailPlot, _shortTrailPlot]
// Get the plots for the trails, to show only long stop when long and short stop when short.
// Put these variables back in the global scope so we can persist them and use them as inputs to the function next bar.
// trailAtrLong := trailAtrLongTemp
// trailAtrShort := trailAtrShortTemp
[trailAtrLongTemp, trailAtrShortTemp, trailAtrLongPlot, trailAtrShortPlot] = request.security(syminfo.tickerid, '1', f_flip(atrFlipInput, atrLow, atrHigh))
plot(trailAtrLongPlot)
Upvotes: 1