Supertrend Rule Design == ## Description Supertrend is a basic yet powerful indicator that can decide whether we are in a bull trend or bear trend. "Super trend 2" strategy on TradingView has a 155% net profit on "BTC-PERP" symbol during the past two months (backtest), only using supertrend indicators. Personally, I've been running a trading bot I developed using supertrend: https://github.com/CheshireCatNick/crypto-flash With the quant zone, we can now enjoy supertrend without deploying a trading bot. In this ruleset, we implement supertrend indicator and demonstrate how to use it to enter a long or short position in the quant zone. 1. Recent supertrend indicator on TradingView: ![](https://i.imgur.com/ubPlhQl.png) 2. Performane of supertrend 2 strategy: ![](https://i.imgur.com/Kax0g3h.png) Note that on TradingView, the strategy uses two supertrend for better performance. Here we only implement one supertrend for simplicity. One can easily implement another supertrend and combine them. ## Observations 1. Setting variables takes effect in the next cycle 2. Rules can be triggered in any order in one cycle 3. Actions in one rule is executed in order. However, it does not matter since they can't communicate with each other by variables. (see observation 1) ## Rules ### UpdateTrade15m 1. Purpose: collect data for 15m candle 2. Trigger: `get_variable("update15m") == 0 or get_variable("update15m") == 1` 3. Actions: 1. update `tmpOpen15m`, `tmpHigh15m`, `tmpLow15m` and `tmpClose15m` 2. set `update15m` to 2 if `time > wakeUpTime15m`. This will trigger GetCandle15m in the next cycle. 4. Code: ``` tmpOpen15m: get_variable("tmpOpen15m") tmpHigh15m: max(get_variable("tmpHigh15m"), last_trade_price("BTC-PERP")) tmpLow15m: min(get_variable("tmpLow15m"), last_trade_price("BTC-PERP")) tmpClose15m: last_trade_price("BTC-PERP") update15m: 2 if floor(time) > get_variable("wakeUpTime15m") else 1 timeDiff: floor(time) - get_variable("lastTime") lastTime: floor(time) ``` ### GetCandle15m 1. Purpose: create 15m candle 2. Trigger: `get_variable("update15m") == 2` 3. Actions: 1. set `update15m` to 3. This will trigger CalculateTrend in the next cycle. 2. set `wakeUpTime15m` to `floor(time) - floor(time) % (15 * 60) + 15 * 60` 3. set `up` 4. set `down` 4. Code: ``` update15m: 3 lastTimeGetCandle: minute wakeUpTime15m: floor(time) - floor(time) % (15 * 60) + 15 * 60 # supertrend source code: trueRange = max(max(tmpHigh15m - tmpLow15m, abs(tmpHigh15m - prevClose15m)), abs(tmpLow15m - prevClose15m)) atr = (2 * prevAtr + trueRange) / 3 up = (tmpHigh15m + tmpLow15m) / 2 - atr down = (tmpHigh15m + tmpLow15m) / 2 + atr trendUp = max(up, prevTrendUp) if prevClose15m > prevTrendUp else up trendDown = min(down, prevTrendDown) if prevClose15m < prevTrendDown else down trend = 1 if tmpClose15m > prevTrendDown else (-1 if tmpClose15m < prevTrendUp else prevTrend) # replace all variables to tmp* and prev*: trueRange: max(max(get_variable("tmpHigh15m") - get_variable("tmpLow15m"), abs(get_variable("tmpHigh15m") - get_variable("prevClose15m"))), abs(get_variable("tmpLow15m") - get_variable("prevClose15m"))) up: (get_variable("tmpHigh15m") + get_variable("tmpLow15m")) / 2 - (2 * get_variable("prevAtr") + max(max(get_variable("tmpHigh15m") - get_variable("tmpLow15m"), abs(get_variable("tmpHigh15m") - get_variable("prevClose15m"))), abs(get_variable("tmpLow15m") - get_variable("prevClose15m")))) / 3 down: (get_variable("tmpHigh15m") + get_variable("tmpLow15m")) / 2 + (2 * get_variable("prevAtr") + max(max(get_variable("tmpHigh15m") - get_variable("tmpLow15m"), abs(get_variable("tmpHigh15m") - get_variable("prevClose15m"))), abs(get_variable("tmpLow15m") - get_variable("prevClose15m")))) / 3 ``` ### CalcTrend15m 1. Purpose: since "expression is too long", we use this rule to calculate trend in the next cycle after GetCandle15m 2. Trigger: `get_variable("update15m") == 3` 3. Actions: 1. set `update15m` to 1. This will trigger UpdateTrade15m in the next cycle. 2. set `prevAtr` 3. set `prevTrendUp` 4. set `prevTrendDown` 5. set `trend` to -1, 0 or 1. This will trigger Long and Short rules in the next cycle. 6. update `prevClose15m` 7. reset `tmpOpen15m`, `tmpHigh15m`, `tmpLow15m` and `tmpClose15m` 4. Code: ``` update15m: 1 prevAtr: (2 * get_variable("prevAtr") + max(max(get_variable("tmpHigh15m") - get_variable("tmpLow15m"), abs(get_variable("tmpHigh15m") - get_variable("prevClose15m"))), abs(get_variable("tmpLow15m") - get_variable("prevClose15m")))) / 3 prevTrendUp: max(get_variable("up"), get_variable("prevTrendUp")) if get_variable("prevClose15m") > get_variable("prevTrendUp") else get_variable("up") prevTrendDown: min(get_variable("down"), get_variable("prevTrendDown")) if get_variable("prevClose15m") < get_variable("prevTrendDown") else get_variable("down") trend: 1 if get_variable("tmpClose15m") > get_variable("prevTrendDown") else -1 if get_variable("tmpClose15m") < get_variable("prevTrendUp") else get_variable("trend") prevClose: get_variable("tmpClose15m") tmpOpen15m: last_trade_price("BTC-PERP") tmpHigh15m: last_trade_price("BTC-PERP") tmpLow15m: last_trade_price("BTC-PERP") tmpClose15m: last_trade_price("BTC-PERP") ``` ### Long 1. Purpose: check if should long according to `trend` 2. Trigger: `trend == 1 and position("BTC-PERP", "buy") == 0` 3. Actions: 1. close short position if any 2. open long position 3. set take profit and stop loss 4. Code: ![](https://i.imgur.com/rYdot85.png) ### Short 1. Purpose: check if should short according to `trend` 2. Trigger: `trend == -1 and position("BTC-PERP", "sell") == 0` 3. Actions: 1. close long position if any 2. open short position 3. set take profit and stop loss 4. Code: ![](https://i.imgur.com/8zEGEev.png) ## Known Issues 1. Trade collection is not accurate. It can be solved if there is candle functions. 2. Rule does not run every 15s. What's worse, it can differ from 15 to 90 seconds. During the time UpdateTrade15m is not running, we lost trade data. - Update: this seems to be solved 4. Since setting variables in one cycle only takes effect in the next cycle, we can't use variable to do calculations in the same cycle. We have two solutions: 1. Use one-line expression. The expression is hard to read and cause "expression too long" error. 2. Use variables and do the calculation in the next cycle. This obviously makes our calculation slow since it is separated into several cycles instead of one. For now we use the second solution since the first one is not feasible. ## Todo 1. Add another 4h supertrend as the main trend. 2. Make candle resolution a parameter.