Swing Trading Safely with Super Trend Signal v1

stable
By deemzie in Trading Bots Published March 2021 👁 4,133 views 💬 15 comments

Description

Hey! Pleasure to present to you the first version of my palindromic script I called: Swing Trading Safely with Super Trend Signal (STSwSTS) This script is a simple improvement of the MassEve script by our King pshai and is quite relevant in this bull market. Thanks mate, you're the best :) It uses the required command: CC_SuperTrendExt The script uses two supertrends, one closer to the price (the TP ST) and one further (the main ST). The script enters a long if both ST are below the price and when the price dips a bit on LTF. Then it takes a safety TP once the price pumped a bit. The long is kept until the TP ST flips, at which point the script takes some profit. When the main ST flips bearish it exits the long. A SL is included when a candle closes below some price defined relatve to the entry though it may not be useful on HTF because of the ST flip safety. This script is mainly designed for HTF, though it may work on LTF for some pairs. Many parameters to adjust to your needs! You may experience some issues in Equity mode. The maximum nb of contracts which can be longed is not accurate in HBS, you may divide your equities by 4 in order to make it work fine. Let me know if you run into some issues! v2, v3 and v4 are planned and I may publish them in due time. Short version for bear market is straightforward, spot version also, I may publish them later. Safe trading! ~deemzie
HaasScript
-- Swing Trading Safely with Super Trend Signal (STSwSTS)
-- Author: deemzie
-- Thanks to pshai for the MassEve script which inspired the present and for the SuperTrend command
-- Consider donating to support our work!
-- deemzie: ETH/BSC: 0xFcFD51f3eD7BCcb3652631E7118C2c5913A3aa14
-- phsai BTC: 3FRx1EkG4T4izrkaS34xeZHJFK4kQefHKf

HideTradeAmountSettings()

local src_types = {
    'Close',
    'Open',
    'HL',
    'HLC',
    'OHLC'
}
 
InputGroupHeader('Timeframe Settings')
local tf_update = InputInterval('1. Update Timeframe', 60, 'Update timeframe, how frequently does the bot logic update.')
local tf_price = InputInterval('2. Prices Timeframe', 240, 'Prices timeframe to use.')

InputGroupHeader('Position Settings')
local type = InputOptions('1. Position order type', 'Amount', {'Amount', 'Equity'}, 'Initial position defined either by the number of contract or a percentage of the wallet balance.')
local amount = Input('2. Position amount', 100, 'Trade amount to use')
local prop = Input('3. Equity', 20, 'Equity of the available wallet balance to use')

InputGroupHeader('Entry and Exit Settings')
local ent_trlg = Input('1. Entry Trailing %', 1, 'Price move down before going Long after the SuperTrend Buy signal')
local sec_tp = Input('2. Safety TP price %', 5, 'Price move up after going Long to secure profit')
local sec_tp_prct = Input('3. Safety TP amount %', 50, 'Portion of the Long to close when the Safety TP is reached')
local tp_prct = Input('4. Partial TP amount %', 15, 'Portion of the Long to close after the SuperTrend TP Sell signal')
local sl = Input('5. Stop Loss %', 20, 'Maximum price movement from entry before triggering the Stop Loss')
local sl_lim = Input('6. Stop Loss limit %', 0.2, 'Limit order below the trigger for the Stop Loss')
local sl_type = InputOptions('7. Stop Loss type', 'Fixed Market', {'Fixed Market', 'Fixed Limit', 'Close'}, 'Fixed: SL triggered if the price drops below trigger, Close: if the candle closes below')

InputGroupHeader('SuperTrend Settings')
local st_atr_len = Input('1. ATR Length Open', 10, 'SuperTrend ATR period lenth.')
local st_atr_mul = Input('2. ATR Mult Open', 3, 'SuperTrend ATR multiplier.')
local st_atr_len_tp = Input('1. ATR Length TP', 10, 'SuperTrend ATR period lenth.')
local st_atr_mul_tp = Input('2. ATR Mult TP', 2, 'SuperTrend ATR multiplier.')
local st_src_type = InputOptions('3. Price Source Type', src_types[4], src_types, 'Price source used for SuperTrend.')
local st_use_smooth = Input('4. Use Smoothing', false, 'Whether or not use MA smoothing on SuperTrend price source.')
local st_smooth_type = InputMaTypes('5. Smooth Type', SmaType, 'MA type for smoothing, if enabled.')
local st_smooth_len = Input('6. Smooth Length', 10, 'MA length for smoothing, if enabled.')

if type == 'Equity' then
    amount = MaxLongAmount(AccountGuid()) * prop / 100 
end

function init_id (name)
    local id = Load(name)
    if id == nil then
        id = NewGuid()
    end
    return id
end
 
-- all trading logic etc happens inside this command's callback.
OptimizedForInterval(
    tf_update, -- update interval
 
    -- the callback function
    function()
        -- get candle prices
        local o = OpenPrices(tf_price)
        local h = HighPrices(tf_price)
        local l = LowPrices(tf_price)
        local c = ClosePrices(tf_price)
 
        local op = OpenPrices(tf_update)
        local hp = HighPrices(tf_update)
        local lp = LowPrices(tf_update)
        local cp = ClosePrices(tf_update)
 
        -- get source prices
        local st_src
        local src
 
        if st_src_type == src_types[1] then
            st_src = c
            src = cp
        elseif st_src_type == src_types[2] then
            st_src = o
            src = op
        elseif st_src_type == src_types[3] then
            st_src = (h+l)/2
            src = (hp+lp)/2
        elseif st_src_type == src_types[4] then
            st_src = (h+l+c)/3
            src = (hp+lp+cp)/3
        elseif st_src_type == src_types[5] then
            st_src = (o+h+l+c)/4
            src = (op+hp+lp+cp)/4
        end
 
        -- apply smoothing if used
        if st_use_smooth then
            st_src = MA(st_src, st_smooth_len, st_smooth_type)
        end
 
        -- super trend
        local st = CC_SuperTrendExt(h, l, st_src, st_atr_len, st_atr_mul)
        local st_tp = CC_SuperTrendExt(h, l, st_src, st_atr_len_tp, st_atr_mul_tp)
        Plot(0, 'st', st)
        Plot(0, 'st tp', st_tp) 
 
        -- go long orders
        local enter_id = init_id('enter_id')
        local enter = OrderContainer(enter_id)

        -- exit long orders
        local sec_id = init_id('sec_id')
        local sec = OrderContainer(sec_id)

        local tp_id = init_id('tp_id')
        local tp = OrderContainer(tp_id)
        
        local stop_id = init_id('stop_id')
        local stop = OrderContainer(stop_id)

        -- position
        local long_id = init_id('long_id')
        local long = PositionContainer(long_id)
 
        local entry = GetPositionEnterPrice(long_id)
        local pos_amount = GetPositionAmount(long_id)

        -- entry logic
        if st_src > st_tp and st_src > st and not long.isLong and not stop.isFilled then 
            if (enter.isOpen and enter.price < lp * (1 - ent_trlg / 100)) or not enter.isOpen then
                CancelAllOrders(long_id)
                long_id = NewGuid()
                enter_id = PlaceGoLongOrder(lp * (1 - ent_trlg / 100), amount, {timeout = 999999, positionId = long_id})
                sec_id = NewGuid()
                tp_id = NewGuid()
                stop_id = NewGuid()
            end
        end

        -- SL logic
         if sl_type == 'Fixed Market' then 
            if long.isLong and not stop.isOpen and not stop.isFilled then
                stop_id = PlaceExitLongOrder(entry * (1 - sl / 100), pos_amount, {triggerPrice = entry * (1 - sl / 100), type = StopMarketOrderType, timeout = 999999, positionId = long_id})
            end
            if long.isLong and stop.isOpen and not stop.isFilled and stop.executedAmount != pos_amount then
                CancelOrder(stop_id)
                stop_id = PlaceExitLongOrder(entry * (1 - sl / 100), pos_amount, {triggerPrice = entry * (1 - sl / 100), type = StopMarketOrderType, timeout = 999999, positionId = long_id})
            end
        elseif sl_type == 'Fixed Limit' then 
            if long.isLong and not stop.isOpen and not stop.isFilled then
                stop_id = PlaceExitLongOrder(entry * (1 - sl / 100) * (1 - sl_lim / 100), pos_amount, {triggerPrice = entry * (1 - sl / 100), type = StopLimitOrderType, timeout = 999999, positionId = long_id})
            end
            if long.isLong and stop.isOpen and not stop.isFilled and stop.executedAmount != pos_amount then
                CancelOrder(stop_id)
                stop_id = PlaceExitLongOrder(entry * (1 - sl / 100) * (1 - sl_lim / 100), pos_amount, {triggerPrice = entry * (1 - sl / 100), type = StopLimitOrderType, timeout = 999999, positionId = long_id})
            end
        else
            if long.isLong and c < entry * (1 - sl / 100) then
                CancelAllOrders(long_id)
                stop_id = PlaceExitPositionOrder(long_id, {type = MarketOrderType, timeout = 999999})
                long_id = NewGuid()
                long = PositionContainer(long_id)
                Log('Stop!')
            end
        end


         -- Exit logic
        if long.isLong and st_src < st then
            CancelAllOrders(long_id)
            PlaceExitPositionOrder(long_id, {type = MarketOrderType, timeout = 999999})
            long_id = NewGuid()
            long = PositionContainer(long_id)
            Log('Exit!')
        end

        -- Secure TP logic
        if long.isLong and not sec.isOpen and not sec.isFilled and not stop.isFilled then
            sec_id = PlaceExitLongOrder(entry * (1 + sec_tp / 100), pos_amount * sec_tp_prct / 100, {timeout = 999999, positionId = long_id})
        end

         -- TP logic
        if long.isLong and st_src < st_tp and not tp.isOpen and not tp.isFilled and not stop.isFilled then
            tp_id = PlaceExitLongOrder(hp, pos_amount * tp_prct / 100, {timeout = 999999, positionId = long_id})
        end

        -- reset TP
        if long.isLong and st_src > st_tp and tp.isFilled then
            tp_id = NewGuid()
        end
 
        -- reset SL: if SL has been triggered, wait for ST to flip bullish again
        if stop.isFilled then
            CancelAllOrders(long_id)
            long_id = NewGuid()
        end
        if st_src < st and stop.isFilled then
            stop_id = NewGuid()
        end

        Save('long_id', long_id)
        Save('enter_id', enter_id)
        Save('sec_id', sec_id)
        Save('tp_id', tp_id)
        Save('stop_id', stop_id)
    end
)

15 Comments

Sign in to leave a comment.

P
Patjekadetje about 5 years ago

Hmm I am getting this warning in the log

WARNING: IsOrderFilled(): orderId can not be empty

And it looks like it cant close its position, so did I make a mistake or is there something else I missed?
I am running it in equity mode (5%), would that be the problem?

D
deemzie about 5 years ago

Fixed. Try the new script, it should work properly now.

P
Patjekadetje about 5 years ago

thanks, nice work. Will set up tests and give feedback when I have some interesting data

I
IQGobal about 5 years ago

I am interested in the spot version of this script. Could you possibly publish that?

D
deemzie about 5 years ago

Yes! The spot version is planned... I am a bit busy rn, I will publish it by this weekend

F
firestone777 about 5 years ago

Nice script and amazing backtesting performance on the BTC / USDT pair in futures trading ... 1,123.97% ... in 4 Weeks ... !!! Will give it a try the next two weeks! Thanks for sharing!

F
firestone777 about 5 years ago

With which settings and which pairs do you have good success with your bot?

D
deemzie about 5 years ago

I updated the script, there was an issue with the stop loss and the take profits. Make sure you have the new one or the bot may take a short after exiting the long...

This bots works well with essentially any pair that displays regular patterns of the type: pump -> dump -> fairly flat accumulation -> pump...
It catches the pump and exits when it starts to dump to enter again lower.
Works great on like BTC, DOT, BNB, THETA...
It may work less on like RUNE, SUSHI or SNX which have more volatile PA, thought some settings may be found to work ok.

Update 1h - Prices 4h is the most reliable setting imo. It may work with 1h prices but you may want to set the ATH Length to 3 and 4.
It depends on the pair but you may want to set an entry trailling to like 4-5% for volatile pairs, while 1% may be good for BTC or idk
For alts, a sec TP may be set to as much as 6-10% because of increased volatility, while you may want it lower for majors 4-5%
Safety TP also depends on volatility, 40-50% may be used for alts and maybe 20-30% for less volatile pairs. This needs to be adjusted depending on the nb of bots you run at the same time on your account. Idem for partial TP, 10-20% is fine in general.

Feel free to do some BT and share your results and the settings you chose. I have few time do try it myself rn as I am working on v2 and other stuff...

D
deemzie about 5 years ago

Script updated to allow for a Fixed Stop Loss.

B
Bozza about 5 years ago

Just been doing backtesting and it doesn't look like there is liquidation detection built-in? is that correct?

K
kr3nk1 over 4 years ago

Hello I´m new here but the script give this error:

4. 04 Nov 2021 20:06:34 ERROR: Unknown references: CC_SuperTrendExt3. 04 Nov 2021 20:06:34 ERROR: Unknown references: CC_SuperTrendExt2. 04 Nov 2021 20:06:34 This script is compatible with margin and leverage trading.1. 04 Nov 2021 20:06:34 Doing compile test..

I found the solutions, you must create a command script for SuperTrend Extended but save as CC_SuperTrendExt otherwise the principal scrip won´t find the command

K
Katerin almost 4 years ago

Here is my errors:/ what am i doing wrong? Any idea?
Using the updated version of script and try to save it with both "CC_SuperTrendExt" and "SuperTrendExt" names as command script
455. 19 Jul 2022 12:19:00 ERROR: OptimizedForInterval(): Execution error occurred.
454. 19 Jul 2022 12:19:00 ERROR: Index out of range exception.
453. 19 Jul 2022 12:19:00 ERROR: Plot(): Attempting to call with 'null' value for value.
452. 19 Jul 2022 12:19:00 ERROR: CC_SuperTrendExt(): Invalid input count of 5 (requires 6 inputs).
451. 19 Jul 2022 12:19:00 ERROR: CC_SuperTrendExt(): Invalid input count of 5 (requires 6 inputs)

Solved. Thank you @Tilanthi (Discord) for your guide
Depending on which version of SuperTrendExt you are using, try adding the ClosePrices() into the supertrend call in your main script as the third callable parameter, which gives you the six inputs that it is looking for - so for example
local c = ClosePrices(tf_price)
local st = CC_SuperTrendExt(h, l, c, st_src, st_atr_len, st_atr_mul)
and hopefully it should work for you - it did when I just tried it !

J
JeffVernon almost 4 years ago

Great trading bot scrpt!

I
iddqd over 2 years ago

Hi

Share please Swing Trading Safely with Super Trend Signal v1 exmaple where I need to put it ?

Becase I have the same error

8
8qevdn over 2 years ago

I fixed this error - ERROR: CC_SuperTrendExt(): Invalid input count of 5 (requires 6 inputs).

But now I'm experiencing another error:

ERROR: Unknown references:
ERROR: - st_tp