Skip to main content

Mirrorpip Supertrend Martingale Strategy: Recovering Trend-Following Losses with Intelligent Position Sizing

Introduction

The Mirrorpip Supertrend Martingale Strategy is an advanced trend-following system designed to solve one of the biggest challenges faced by traditional Supertrend traders: consecutive false signals during sideways market conditions. Instead of blindly taking every Supertrend reversal, this strategy intelligently waits for a predefined number of failed Supertrend trades before entering the market. Once an entry is triggered, the strategy uses a configurable Martingale position-sizing model to recover previous losses and capture profits during the next successful trend. The strategy is fully automated and can be deployed on Mirrorpip using TradingView alerts and webhooks.

What Is the Supertrend Indicator?

Supertrend is one of the most popular trend-following indicators available in TradingView. The indicator generates:
  • Buy signals when trend changes from bearish to bullish
  • Sell signals when trend changes from bullish to bearish
  • Dynamic support and resistance levels
  • Clear trend direction
Supertrend performs exceptionally well during trending markets but can generate multiple losing trades during ranging or choppy conditions. The Mirrorpip Supertrend Martingale Strategy is specifically designed to exploit this weakness.

Here is the source code of the strategy \
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Mirrorpip

//@version=6
strategy("MirrorPip SuperTrend Martingale v1.0", shorttitle="MirrorPip ST Martingale", overlay=true, default_qty_value=1, process_orders_on_close=false, calc_on_every_tick=true, calc_on_order_fills=false)

////======================================================
paraTradeMode = input.string(title='Trade Mode', defval='Both', options=['Both', 'LongOnly', 'ShortOnly'], group = "Trade Settings")
paraSystemMode = input.session(defval="Positional", title="System Mode", options=["Intraday", "Positional"], group = "Trade Settings")
s = input.session(title='Intraday Start Session:', defval='0915-1445', group='Trade Settings')
e = input.session(title='Intraday End Session:', defval='1500-1515', group='Trade Settings')

paraSTMultiplier = input.float(3, title="ST Multiplier", minval=0.1, group='SuperTrend Settings', inline = "ST")
paraSTPeriod = input.int(10, title="ST Period", minval = 1, group='SuperTrend Settings', inline = "ST")
paraMinSTLossTrades = input.int(2, title="Min. ST Loss Trades", minval = 0, group='SuperTrend Settings', inline = "ST1")

//paraQty = input.float(title='Quantity ', defval=1, minval=1, group='Trade')
paraMartingaleMode = input.string(title="Martingale Mode", defval='+',options=['Off', '+', '*'], group='Trade')
paraMartingaleQty = input.int(title='Martingale Qty.', defval=1, minval=0, group='Trade')

paraTGTMode = input.string(defval="Off", title="Target : ", options=["Off", "%", "Pts"], inline = "TGT", group = "Target Settings")
paraTGT = input.float(20, "Value : ", minval = 0.1, inline = "TGT", group = "Target Settings")

paraSLMode = input.string(defval="Off", title="Stoploss : ", options=["Off", "%", "Pts"], inline = "SL", group = "Stoploss Settings")
paraSL = input.float(10, "Value : ", minval = 0.1, inline = "SL", group = "Stoploss Settings")

paraTSLMode = input.string(defval="Off", title="Trail SL : ", options=["Off", "%", "Pts"], inline = "TSL", group = "TSL Settings")
paraTSL = input.float(10, "Value : ", minval = 0.1, inline = "TSL", group = "TSL Settings")

paraShowDashboard = input.bool(true, "Show Strategy Dashboard")
////======================================================

////======================================================
grpAlgo = "Algo Setup"
paraExchange = input.string(title='Exchange', defval='delta', group=grpAlgo)
paraCode = input.string(title='Code', defval='XXXXXX', group=grpAlgo)
paraSTAG = input.string(title='Strategy Tag', defval='PRO1', group=grpAlgo)
paraPriceType = input.string(title="Price Type", defval='market',options=['market','limit'], group=grpAlgo)
paraQtyType = input.string(title="Quantity Type", defval='Fixed',options=['Fixed','$'], group=grpAlgo)
paraQtyEn = input.float(title='Qty. Value', defval=1, minval=0, group=grpAlgo, tooltip='Qty in Lots for Futures', inline = "Qty")
paraQtyEx = paraQtyEn //input.float(title='Exit Qty. ', defval=1, minval=0, group=grpAlgo, tooltip='Qty in Lots for Futures', inline = "Qty")
paraOptMode = input.bool(true, "Options Mode?", group=grpAlgo, inline = "AlgoOpt")
paraOptUnderlying = input.string('BTC', 'Underlying Scrip', group=grpAlgo, inline = "AlgoOpt")
paraOptExpiry = input.string("200925", "Expiry", group=grpAlgo, inline = "AlgoOpt")
paraOptSteps = input.int(1000, 'Strike: Steps (ATM)', group=grpAlgo, tooltip='Options Strikes Steps for ATM', inline = "AlgoOpt1")
paraOptMulti = input.int(0, 'Offset', group=grpAlgo, tooltip='Options Strikes Offset: 0: ATM / <0: ITM / >0: OTM', inline = "AlgoOpt1")
paraOptBuySellMode = input.string("Buyer", "Options Trade Mode", options=['Buyer','Seller'], group=grpAlgo)
////======================================================

////======================================================
varip bool QtyResetF = false
var int STPnLCtr = na
var bool STTradeF = false
var float LastPNL = na

FC = session.isfirstbar
LC = session.islastbar
BSFC = ta.barssince(FC) + 1

st = paraSystemMode=="Positional" ? true : not na(time(timeframe.period, s)) 
et = paraSystemMode=="Intraday" and not na(time(timeframe.period, e))
IsIntraday = paraSystemMode=="Intraday"

if (FC and IsIntraday)
    QtyResetF := true
// else
//     QtyResetF := false

[SuperTrend, STTrend] = ta.supertrend(paraSTMultiplier, paraSTPeriod)

eBuy1 = STTrend==-1 and barstate.isconfirmed
eShort1 = STTrend==1 and barstate.isconfirmed

eSignal = 0
eBuy = eBuy1 and st
eShort = eShort1 and st
eSell = eShort1 or et
eCover = eBuy1 or et
eSignal := eBuy ? 1 : eShort ? -1 : eSell and eSignal[1] > 0 ? 0 : eCover and eSignal[1] < 0 ? 0 : eSignal[1]

STBuy = STTrend == -1 and STTrend[1] != -1 and barstate.isconfirmed
STShort = STTrend == 1 and STTrend[1] != 1 and barstate.isconfirmed

STBuyPrice = ta.valuewhen(STBuy, close, 0)
STShortPrice = ta.valuewhen(STShort, close, 0)
STPNL = STShortPrice - STBuyPrice

if (STBuy or STShort) 
    if STPNL < 0
        STPnLCtr += 1
    else if STPNL > 0
        STPnLCtr := 0
        STTradeF := false
        QtyResetF := true

if STPnLCtr >= paraMinSTLossTrades
    STTradeF := true

// if (strategy.position_size <= 0 and strategy.position_size[1] > 0)
//     LastPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)
// else if (strategy.position_size >= 0 and strategy.position_size[1] < 0)
//     LastPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)

MainSignal = 0
BuySignal = paraTradeMode!="ShortOnly" and STTradeF and st and eSignal > 0 and eSignal[1] <= 0 and barstate.isconfirmed and (nz(MainSignal[1]) <= 0)
ShortSignal = paraTradeMode!="LongOnly" and STTradeF and st and eSignal < 0 and eSignal[1] >= 0 and barstate.isconfirmed and (nz(MainSignal[1]) >= 0)
SellSignal = (((ShortSignal or eSignal <= 0) and barstate.isconfirmed) or et) and (nz(MainSignal[1]) == 1)
CoverSignal = (((BuySignal or eSignal >= 0) and barstate.isconfirmed) or et) and (nz(MainSignal[1]) == -1)
MainSignal := BuySignal ? 1 : ShortSignal ? -1 : SellSignal and MainSignal[1] > 0 ? 0 : CoverSignal and MainSignal[1] < 0 ? 0 : MainSignal[1]
////======================================================

////======================================================
symbol = syminfo.ticker

eBuyPrice = ta.valuewhen(BuySignal, close, 0)
eShortPrice = ta.valuewhen(ShortSignal, close, 0)

BATM = math.round(eBuyPrice/paraOptSteps)*paraOptSteps
SATM = math.round(eShortPrice/paraOptSteps)*paraOptSteps
LEStrike = BATM + (paraOptMulti * paraOptSteps)
SEStrike = SATM - (paraOptMulti * paraOptSteps)

LESym = str.tostring(syminfo.ticker) 
LXSym = str.tostring(syminfo.ticker) 
SESym = str.tostring(syminfo.ticker) 
SXSym = str.tostring(syminfo.ticker) 

var float BuyTradeQty = na
var float ShortTradeQty = na
var float SellTradeQty = na
var float CoverTradeQty = na
var float BuyRisk = na
var float ShortRisk = na
var float eBuySL = na
var float eShortSL = na
var float eBuyTGT = na
var float eShortTGT = na
var string QtySuffix = ""

// BuyTradeQty := paraQtyEn
// SellTradeQty := paraQtyEx
// ShortTradeQty := paraQtyEn
// CoverTradeQty := paraQtyEx

// if (paraQtyType=="Exposure")
//     BuyTradeQty := paraQtyEn / eBuyPrice
//     BuyTradeQty := math.round(BuyTradeQty / syminfo.pointvalue) 
//     ShortTradeQty := paraQtyEn / eShortPrice
//     ShortTradeQty := math.round(ShortTradeQty / syminfo.pointvalue) 

//     if (BuyTradeQty < 0)
//         BuyTradeQty := 1
//     if (ShortTradeQty < 0)
//         ShortTradeQty := 1

//     SellTradeQty := BuyTradeQty
//     CoverTradeQty := ShortTradeQty

if (paraQtyType=="$")
    QtySuffix := "$"

buyData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(BuyTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
sellData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(SellTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
shortData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(ShortTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
coverData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(CoverTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'

if (paraOptMode)
    if (paraOptBuySellMode == "Seller")
        LESym := "P-" + paraOptUnderlying + "-" + str.tostring(LEStrike) + "-" + paraOptExpiry
        LXSym := "P-" + paraOptUnderlying + "-" + str.tostring(LEStrike[1]) + "-" + paraOptExpiry
        SESym := "C-" + paraOptUnderlying + "-" + str.tostring(SEStrike) + "-" + paraOptExpiry
        SXSym := "C-" + paraOptUnderlying + "-" + str.tostring(SEStrike[1]) + "-" + paraOptExpiry

        buyData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(BuyTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        sellData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(SellTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        shortData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(ShortTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        coverData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(CoverTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    else
        LESym := "C-" + paraOptUnderlying + "-" + str.tostring(LEStrike) + "-" + paraOptExpiry
        LXSym := "C-" + paraOptUnderlying + "-" + str.tostring(LEStrike[1]) + "-" + paraOptExpiry
        SESym := "P-" + paraOptUnderlying + "-" + str.tostring(SEStrike) + "-" + paraOptExpiry
        SXSym := "P-" + paraOptUnderlying + "-" + str.tostring(SEStrike[1]) + "-" + paraOptExpiry

        buyData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(BuyTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        sellData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(SellTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        shortData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(ShortTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        coverData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(CoverTradeQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
////======================================================

////======================================================
GetBaseQty(funcEntryPrice) =>
    var float resultQty = na
    if (paraQtyType == 'Exposure')
        resultQty := paraQtyEn / funcEntryPrice
        resultQty := math.round(resultQty / syminfo.pointvalue) 
    else
        resultQty := paraQtyEn

    if (resultQty < 1)
        resultQty := 1

    resultQty

GetTradeQty(funcPNL, funcQty, funcEntryPrice) =>
    var float result = na
    if funcPNL < 0 and paraMartingaleMode != "Off" and (not QtyResetF) // or not IsIntraday
        if (paraMartingaleMode == "+")
            result := funcQty + paraMartingaleQty
        else if (paraMartingaleMode == "*")
            result := funcQty * paraMartingaleQty
    else
        result := GetBaseQty(funcEntryPrice) //paraQtyEn

    result
////======================================================
GetMyBuyData(funcQty) =>
    _buyData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    if (paraOptMode)
        if (paraOptBuySellMode == "Seller")
            _buyData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        else
            _buyData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    _buyData

GetMySellData(funcQty) =>
    _sellData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    if (paraOptMode)
        if (paraOptBuySellMode == "Seller")
            _sellData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        else
            _sellData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + LXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    _sellData

GetMyShortData(funcQty) =>
    _shortData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    if (paraOptMode)
        if (paraOptBuySellMode == "Seller")
            _shortData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "SHORT", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        else
            _shortData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SESym + '", "price_type": "' + paraPriceType + '", "order_type": "BUY", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    _shortData

GetMyCoverData(funcQty) =>
    _coverData = '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    if (paraOptMode)
        if (paraOptBuySellMode == "Seller")
            _coverData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "COVER", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
        else
            _coverData := '{ "exchange": "' + paraExchange + '", "price": "' + str.tostring(close) + '", "chart_symbol": "' + SXSym + '", "price_type": "' + paraPriceType + '", "order_type": "SELL", "instrument_type": "NA", "quantity": "' + str.tostring(funcQty) + QtySuffix + '", "tp": "0", "sl": "0", "code": "'+paraCode+'", "stag": "'+paraSTAG+'"}'
    _coverData

////======================================================
var float BuyPrice = na
var float ShortPrice = na
varip float BuyPNL = na
varip float ShortPNL = na
var int tradeCtr = na

if (FC)
    tradeCtr := 0

if (strategy.position_size > 0)
    BuyPNL := strategy.opentrades.profit(strategy.opentrades - 1)
else if (strategy.position_size < 0)
    ShortPNL := strategy.opentrades.profit(strategy.opentrades - 1)
else 
    BuyPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)
    ShortPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)

if (strategy.position_size > 0 and strategy.position_size[1] <= 0)
    tradeCtr += 1
if (strategy.position_size < 0 and strategy.position_size[1] >= 0)
    tradeCtr +=  1

if BuySignal and strategy.position_size < 0  
    ShortPNL := strategy.opentrades.profit(strategy.opentrades - 1)
    BuyTradeQty := GetTradeQty(ShortPNL, ShortTradeQty, eBuyPrice)
    coverData := GetMyCoverData(ShortTradeQty)
    buyData := GetMyBuyData(BuyTradeQty)
    strategy.entry('BUY', strategy.long, comment='Buy', qty=BuyTradeQty, alert_message="["+coverData+","+buyData+"]")
else if BuySignal and strategy.position_size == 0  
    ShortPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)
    BuyTradeQty := GetTradeQty(ShortPNL, ShortTradeQty, eBuyPrice)
    buyData := GetMyBuyData(BuyTradeQty)
    strategy.entry('BUY', strategy.long, comment='Buy', qty=BuyTradeQty, alert_message="["+buyData+"]")

if ShortSignal and strategy.position_size > 0  
    BuyPNL := strategy.opentrades.profit(strategy.opentrades - 1)
    ShortTradeQty := GetTradeQty(BuyPNL, BuyTradeQty, eShortPrice)
    sellData := GetMySellData(BuyTradeQty)
    shortData := GetMyShortData(ShortTradeQty)
    strategy.entry('SHORT', strategy.short, comment='Short', qty=ShortTradeQty, alert_message="["+sellData+","+shortData+"]")
else if ShortSignal and strategy.position_size == 0  
    BuyPNL := strategy.closedtrades.profit(strategy.closedtrades - 1)
    ShortTradeQty := GetTradeQty(BuyPNL, BuyTradeQty, eShortPrice)
    shortData := GetMyShortData(ShortTradeQty)
    strategy.entry('SHORT', strategy.short, comment='Short', qty=ShortTradeQty, alert_message="["+shortData+"]")
////======================================================

////======================================================
var float BuyTGT = na
var float ShortTGT = na
var float BuySL = na
var float ShortSL = na
var float BuyTSL = na
var float ShortTSL = na

ut = (paraTGTMode != "Off")
us = (paraSLMode != "Off")

if (strategy.position_size > 0 and strategy.position_size[1] <= 0)

    BuyPrice := strategy.position_avg_price
    QtyResetF := false

    if (paraSLMode=="%")
        BuySL := BuyPrice * (1-(paraSL/100))
    else if (paraSLMode=="Pts")
        BuySL := BuyPrice - (paraSL)

    if (paraTGTMode=="%")
        BuyTGT := BuyPrice * (1+(paraTGT/100))
    else if (paraTGTMode=="Pts")
        BuyTGT := BuyPrice + (paraTGT)

if (strategy.position_size < 0 and strategy.position_size[1] >= 0)

    ShortPrice := strategy.position_avg_price
    QtyResetF := false

    if (paraSLMode=="%")
        ShortSL := ShortPrice * (1+(paraSL/100))
    else if (paraSLMode=="Pts")
        ShortSL := ShortPrice + (paraSL)

    if (paraTGTMode=="%")
        ShortTGT := ShortPrice * (1-(paraTGT/100))
    else if (paraTGTMode=="Pts")
        ShortTGT := ShortPrice - (paraTGT)

if (paraTSLMode != "Off")
    if (strategy.position_size > 0)
        if (paraTSLMode=="%")
            BuyTSL := high[1] * (1-(paraTSL/100))
        else if (paraTSLMode=="Pts")
            BuyTSL := high[1] - paraTSL
        if (BuySL < BuyTSL)
            BuySL := BuyTSL
    if (strategy.position_size < 0)
        if (paraTSLMode=="%")
            ShortTSL := low[1] * (1+(paraTSL/100))
        else if (paraTSLMode=="Pts")
            ShortTSL := low[1] + paraTSL
        if (ShortSL > ShortTSL)
            ShortSL := ShortTSL

if ut == true and us == false
    if (strategy.position_size > 0)
        strategy.exit(id='LongExit', comment="Exit", from_entry='BUY', limit=BuyTGT, alert_message="["+sellData+"]")
    if (strategy.position_size < 0)
        strategy.exit(id='ShortExit', comment="Exit", from_entry='SHORT', limit=ShortTGT, alert_message="["+coverData+"]")
if us == true and ut == false 
    if (strategy.position_size > 0)
        strategy.exit(id='LongExit', comment="Exit", from_entry='BUY', stop=BuySL, alert_message="["+sellData+"]")
    if (strategy.position_size < 0)
        strategy.exit(id='ShortExit', comment="Exit", from_entry='SHORT', stop=ShortSL, alert_message="["+coverData+"]")
if ut == true and us == true
    if (strategy.position_size > 0)
        strategy.exit(id='LongExit', comment="Exit", from_entry='BUY', limit=BuyTGT, stop=BuySL, alert_message="["+sellData+"]")
    if (strategy.position_size < 0)
        strategy.exit(id='ShortExit', comment="Exit", from_entry='SHORT', limit=ShortTGT, stop=ShortSL, alert_message="["+coverData+"]")

if (et or (SellSignal and (not ShortSignal))) and strategy.position_size > 0 
    strategy.cancel('LongExit')
    strategy.close(id='BUY', comment="Exit", alert_message="["+sellData+"]")

if (et or (CoverSignal and (not BuySignal))) and strategy.position_size < 0 
    strategy.cancel('ShortExit')
    strategy.close(id='SHORT', comment="Exit", alert_message="["+coverData+"]")

if (strategy.position_size <= 0)
    strategy.cancel('LongExit')
if (strategy.position_size >= 0)
    strategy.cancel('ShortExit')
////======================================================
plot(SuperTrend, color = STTrend==-1?color.green:color.red, linewidth = 1)

plot((strategy.position_size > 0)?BuyPrice:na, color=color.fuchsia, linewidth=1, style=plot.style_linebr)
plot((strategy.position_size > 0)?BuyTGT:na, color=color.blue, linewidth=1, style=plot.style_linebr)
plot((strategy.position_size > 0)?BuySL:na, color=color.orange, linewidth=1, style=plot.style_linebr)

plot((strategy.position_size < 0)?ShortPrice:na, color=color.fuchsia, linewidth=1, style=plot.style_linebr)
plot((strategy.position_size < 0)?ShortTGT:na, color=color.blue, linewidth=1, style=plot.style_linebr)
plot((strategy.position_size < 0)?ShortSL:na, color=color.orange, linewidth=1, style=plot.style_linebr)
////======================================================

////======================================================
totalCols = 2
totalRows = 5 
stgTGTFlag = paraTGTMode != "Off"
stgSLFlag = paraSLMode != "Off"

if stgTGTFlag
    totalRows += 1
if stgSLFlag
    totalRows += 1

var dashtable = table.new(position.bottom_left, totalCols, totalRows,
  frame_color=color.new(#000000,0),
  frame_width=1,
  border_color=color.new(#000000,0),
  border_width=1)

cell_up = #237a27 //input.color(#237a27,'Buy Cell Color'  ,group='Style Settings')
cell_dn = color.red //input.color(color.red,'Sell Cell Color'  ,group='Style Settings')
cell_Neut = color.gray //input.color(color.gray,'Neut Cell Color'  ,group='Style Settings')
txt_col = color.white

table_text_size = size.small

openProfit = strategy.openprofit
lastProfit = strategy.closedtrades.profit(strategy.closedtrades-1)
openProfitColor = openProfit >= 0 ? cell_up : cell_dn
lastProfitColor = lastProfit >= 0 ? cell_up : cell_dn

rowCtr = 0
colCtr = 0

if (barstate.islast and paraShowDashboard)
    table.cell(dashtable, 0, rowCtr, "Dashboard", text_color=txt_col, text_size=table_text_size, bgcolor=color.new(color.blue,80), tooltip="")  
    table.cell(dashtable, 1, rowCtr, '', text_color=txt_col, text_size=table_text_size, bgcolor=color.new(color.blue,80), tooltip="")
    table.merge_cells(dashtable, 0, 0, 1, 0)

    if strategy.position_size > 0
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Buy",text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(strategy.position_avg_price, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Qty.",text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(strategy.position_size, "#"),text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        if (stgTGTFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "TGT",text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
            table.cell(dashtable, 1, rowCtr, str.tostring(BuyTGT, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        if (stgSLFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "SL",text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
            table.cell(dashtable, 1, rowCtr, str.tostring(BuySL, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "P&L",text_color=txt_col,text_size=table_text_size,bgcolor=openProfitColor,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(openProfit, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=openProfitColor,tooltip="")

    if strategy.position_size < 0
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Short",text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(strategy.position_avg_price, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Qty.",text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(strategy.position_size, "#"),text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        if (stgTGTFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "TGT",text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
            table.cell(dashtable, 1, rowCtr, str.tostring(ShortTGT, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_up,tooltip="")
        if (stgSLFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "SL",text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
            table.cell(dashtable, 1, rowCtr, str.tostring(ShortSL, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=cell_dn,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "P&L",text_color=txt_col,text_size=table_text_size,bgcolor=openProfitColor,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(openProfit, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=openProfitColor,tooltip="")

    if strategy.position_size == 0
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "No Trade", text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        table.cell(dashtable, 1, rowCtr, "Relax", text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        table.cell(dashtable, 1, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        if (stgTGTFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
            table.cell(dashtable, 1, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        if (stgSLFlag)
            rowCtr += 1
            table.cell(dashtable, 0, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
            table.cell(dashtable, 1, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")
        table.cell(dashtable, 1, rowCtr, "",text_color=txt_col,text_size=table_text_size,bgcolor=cell_Neut,tooltip="")

    if strategy.position_size <= 0 and strategy.position_size[1] > 0
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Exit Buy",text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(lastProfit, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
    else if strategy.position_size >= 0 and strategy.position_size[1] < 0
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Exit Short",text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(lastProfit, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
    else    
        rowCtr += 1
        table.cell(dashtable, 0, rowCtr, "Last P&L",text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
        table.cell(dashtable, 1, rowCtr, str.tostring(lastProfit, format.mintick),text_color=txt_col,text_size=table_text_size,bgcolor=lastProfitColor,tooltip="")
////======================================================

The Core Concept

Most traders take every Supertrend reversal. This strategy does not. Instead, it tracks how many consecutive Supertrend trades have failed. Only after a predefined number of losing trades does it begin trading. The logic is based on the observation that:
Multiple consecutive failed Supertrend signals are often followed by a strong trending move.
By waiting for several failed signals, the strategy attempts to enter when the probability of a sustained trend becomes higher.

Key Parameter: Minimum ST Loss Trades

This is the most important setting in the strategy.

Example

Suppose: Min ST Loss Trades = 3 The strategy behaves as follows:

Trade 1

Supertrend Buy Signal Result: Loss Loss Count = 1 No trade taken.

Trade 2

Supertrend Sell Signal Result: Loss Loss Count = 2 No trade taken.

Trade 3

Supertrend Buy Signal Result: Loss Loss Count = 3 No trade taken.

Trade 4

Supertrend Sell Signal Loss count requirement satisfied. Strategy now enters the market. This becomes the first Martingale cycle trade.

Why This Works

Trending indicators struggle during sideways markets. During a range:
  • Buy signal fails
  • Sell signal fails
  • Buy signal fails
  • Sell signal fails
Eventually a breakout occurs. The strategy attempts to participate only after multiple failures have already occurred. This helps avoid many low-probability trades.

Martingale Recovery System

Once the strategy starts trading, it enters Martingale mode. If a trade loses, the next trade size increases according to the selected Martingale model. The objective is to recover previous losses when the next profitable trend emerges. The strategy remains in Martingale mode until:
  • A profitable trade occurs
  • Target is hit
  • Net cycle becomes profitable
After profit is achieved, the entire cycle resets. The strategy again waits for the specified number of failed Supertrend trades before entering a new cycle.

Arithmetic Martingale

In Arithmetic Martingale, position size increases linearly. Example:
Trade NumberMultiplier
Trade 11x
Trade 22x
Trade 33x
Trade 44x
Trade 55x
Trade 66x

Example

Base Size = $100 Sequence:
  • Trade 1 = $100
  • Trade 2 = $200
  • Trade 3 = $300
  • Trade 4 = $400
Advantages:
  • Lower capital requirements
  • Slower drawdown growth
  • More conservative
Best suited for:
  • Moderate risk traders
  • Smaller accounts
  • Volatile crypto markets

Geometric Martingale

In Geometric Martingale, size doubles after every loss. Example:
Trade NumberMultiplier
Trade 11x
Trade 22x
Trade 34x
Trade 48x
Trade 516x
Trade 632x

Example

Base Size = $100 Sequence:
  • Trade 1 = $100
  • Trade 2 = $200
  • Trade 3 = $400
  • Trade 4 = $800
  • Trade 5 = $1600
Advantages:
  • Faster recovery
  • Requires fewer winning trades
Disadvantages:
  • Higher capital requirement
  • Larger drawdowns
  • Greater liquidation risk if leverage is excessive
Best suited for:
  • Well-capitalized accounts
  • Strongly trending markets
  • Advanced traders

Cycle Reset Mechanism

One unique feature of this strategy is the reset logic. When a profitable trade occurs: ✓ Martingale cycle ends ✓ Position size resets to base size ✓ Consecutive loss counter resets ✓ Strategy waits again for new Supertrend failures This prevents unnecessary overtrading during favorable market conditions.

Stop Loss Configuration

Users can define custom stop losses. Available modes:

Fixed Point Stop Loss

Example: SL = 100 Points Long Entry = 50,000 Stop Loss = 49,900

Percentage Stop Loss

Example: SL = 2% Long Entry = 50,000 Stop Loss = 49,000 This allows the strategy to adapt to instruments with different volatility profiles.

Take Profit Configuration

Users can also define custom profit targets.

Fixed Point Target

Example: Target = 200 Points Entry = 50,000 Exit = 50,200

Percentage Target

Example: Target = 5% Entry = 50,000 Exit = 52,500 This provides additional flexibility beyond standard Supertrend exits.

Example Trade Sequence

Let’s assume:
  • Supertrend ATR Length = 10
  • Multiplier = 3
  • Minimum ST Loss Trades = 3
  • Martingale Type = Arithmetic

Market Condition

Signal 1 = Loss Signal 2 = Loss Signal 3 = Loss Loss requirement met.

Trade A

Position Size = 1x Result = Loss

Trade B

Position Size = 2x Result = Loss

Trade C

Position Size = 3x Result = Profit Cycle becomes profitable. Strategy resets. Wait for next 3 failed Supertrend trades.

Suitable Markets

This strategy performs best in:
  • Cryptocurrency Futures
  • Index Futures
  • Commodity Futures
  • Forex Markets
  • Trending Stocks
Markets with periodic breakout behavior generally provide the best results.

Risk Management Considerations

Although Martingale can improve recovery rates, it also increases risk. Before deploying:
  • Use sensible leverage
  • Define maximum Martingale levels
  • Test extensively using historical data
  • Understand worst-case drawdowns
  • Allocate sufficient capital
No Martingale system can guarantee profits. Proper risk management remains essential.

Mirrorpip Automation Setup

This strategy can be fully automated through Mirrorpip. Workflow: TradingView Strategy → TradingView Alert → Mirrorpip Webhook → Exchange Account → Trade Execution Users can:
  • Run the strategy 24/7
  • Connect multiple exchanges
  • Deploy across multiple symbols
  • Monitor performance from a unified dashboard
  • Analyze drawdown, win rate, Sharpe ratio, and profitability metrics

Conclusion

The Mirrorpip Supertrend Martingale Strategy combines the simplicity of the Supertrend indicator with intelligent trade filtering and automated recovery mechanisms. By waiting for multiple failed Supertrend signals before entering the market and applying configurable Martingale sizing, the strategy seeks to capitalize on the powerful trends that often emerge after prolonged periods of market indecision. With support for Arithmetic and Geometric Martingale modes, customizable stop losses and profit targets, and seamless automation through Mirrorpip, traders gain a flexible framework for trend-following across crypto, forex, stocks, and futures markets. As with any Martingale-based strategy, careful position sizing and risk management are critical to long-term success.