// "Mystery Strategy" / "Holy Grail for ETH" // // Preconfigured for ETH 30m on Bitget // Works on: ETH since 2022-12, AVAX since 2023-3 // // (c) Stefan Reich //@version=5 strategy(shorttitle="Stefan Reich's Mystery Strategy v230", title="Stefan Reich's Mystery Strategy", overlay=true, commission_type=strategy.commission.percent, commission_value=0.07, initial_capital = 100, default_qty_type=strategy.cash, default_qty_value=1000, calc_on_every_tick = true, max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500) // commission_value is an approximately correct estimate for fees+spread on ETH on typical exchanges (Bitget, Bybit) // This strategy opens few positions though, so fees+spread are not a big deal anyway. shrouded = input.bool(false) startingDate = input.time(timestamp("8 Dec 2022")) doLongs=input.bool(true, "Do longs") doShorts=input.bool(false, "Do shorts") minMoveLong = input.float(1.6, step=0.1) minMoveShort = input.float(1.6, step=0.1) arrowOffset = input.float(10) initialOffset = input.float(10) equityOffset = input.float(10) topOffset = input.float(1, step=0.25) filesSlanted = input.bool(true) ieBoxColor = input.color(color.black) ieTextColor = input.color(color.blue) positionSize = input.float(1000, "Position size in $", tooltip="After leverage") // UTILITY FUNCTIONS drift() => sumDrift = 0.0 for tradeNo = 0 to strategy.opentrades - 1 sumDrift += strategy.opentrades.size(tradeNo) result = sumDrift // macro logFloat(value, title) { plotchar(value, title, "", location.top) } // MACD inputs fast_length = input(title="Fast Length", defval=25) slow_length = input(title="Slow Length", defval=100) macd_src = input(title="Source", defval=close) signal_length = input.int(title="Signal Smoothing", minval = 1, defval = 9) sma_source = input.string(title="Oscillator MA Type", defval="EMA", options=["SMA", "EMA"]) sma_signal = input.string(title="Signal Line MA Type", defval="EMA", options=["SMA", "EMA"]) intraCandleOperation = input.bool(false, tooltip="Open or close trades within a candle") switchOnLongsAbove = input.float(-100, step=0.1, tooltip="Allow longs only if MACD is above this level") switchOnShortsBelow = input.float(100, step=0.1, tooltip="Allow shorts only if MACD is below this level") equityXOffset = input.int(10, tooltip="Move equity box to the right using this value") exitThresholdLong = input.float(999, step=0.1, tooltip="MACD histogram value to exit a long at. To use -MinMoveShort, enter 999") exitThresholdShort = input.float(999, step=0.1, tooltip="MACD histogram value to exit a short at. To use MinMoveLong, enter 999") hotSwitchOkay = input.bool(true, tooltip="Can we kill a long by opening a short and vice versa?") equityShort = input.bool(true, tooltip="Show only the new equity, no text") useEndDate = input.bool(false, tooltip="Activate the end date below") endDate = input.time(timestamp("31 Dec 2023"), tooltip="When to end the backtest or execution (if checkbox above is set)") useRelativeMACD = input.bool(false, tooltip="Use relative MACD (normalized to asset price)") // Add more inputs down here to not mess up configurations of older versions // MACD calculation fast_ma = sma_source == "SMA" ? ta.sma(macd_src, fast_length) : ta.ema(macd_src, fast_length) slow_ma = sma_source == "SMA" ? ta.sma(macd_src, slow_length) : ta.ema(macd_src, slow_length) macd = fast_ma - slow_ma signal = sma_signal == "SMA" ? ta.sma(macd, signal_length) : ta.ema(macd, signal_length) hist = macd - signal // Plot MACD plot(fast_ma, title="MACD Fast MA", color=color.yellow) plot(slow_ma, title="MACD Slow MA", color=color.blue) plotchar(macd, "MACD", "", location.top) // Relative MACD values (in preparation for Mark II strategy) factor = 1000 / slow_ma relMACD = macd * factor relSignal = signal * factor relHist = (macd - signal) * factor plotchar(relMACD, "Relative MACD", "", location.top) // logFloat plotchar(hist, "MACD Histogram", "", location.top) // logFloat plotchar(relHist, "Relative MACD Histogram", "", location.top) // logFloat actualExitLong = exitThresholdLong == 999 ? -minMoveShort : exitThresholdLong actualExitShort = exitThresholdShort == 999 ? minMoveLong : exitThresholdShort macdToUse = useRelativeMACD ? relMACD : macd histToUse = useRelativeMACD ? relHist : hist if time >= startingDate and (not useEndDate or time <= endDate) and (intraCandleOperation or barstate.isconfirmed) qty = positionSize/close if drift() < 0.0 and histToUse >= actualExitShort strategy.close_all(shrouded ? "Exit" : "MACD Green") else if drift() > 0.0 and histToUse <= actualExitLong strategy.close_all(shrouded ? "Exit" : "MACD Red") if hotSwitchOkay or drift() == 0.0 if doLongs and histToUse >= minMoveLong and macdToUse >= switchOnLongsAbove strategy.entry("Long", strategy.long, qty=qty) else if doShorts and histToUse <= -minMoveShort and macdToUse <= switchOnShortsBelow strategy.entry("Short", strategy.short, qty=qty) // PAINT TRADES & INITIAL EQUITY plusMinusFix(s) => currency = " $" str.startswith(s, "-") ? "-" + currency + str.substring(s, 1) : "+" + currency + s formatProfit(profit) => plusMinusFix(str.tostring(profit, "#,##0.00")) var int tradesPainted = 0 var label initialEquityLabel = na if na(initialEquityLabel) and time >= startingDate ieText = "⬆\nWe invest\n$" + str.tostring(strategy.initial_capital, "#,##0") + "\nand start\nthe strategy!" ieTime = startingDate-2*24*60*60*1000 // 2 days back //ieY = close*(1-arrowOffset/100) // for style_label_center //style=label.style_label_center ieY = close*(1-initialOffset/100) // for style_label_up //boxColor = color.black //textColor = color.white style = label.style_label_up //style = label.style_triangleup initialEquityLabel := label.new(ieTime, ieY, ieText, xloc=xloc.bar_time, color=ieBoxColor, textcolor=ieTextColor, tooltip="Initial equity", size=size.huge, style=style) type PaintedTrade array lines array