Skip to main content

Mirrorpip Drawdown Scalping Strategy: Systematic Averaging with Dynamic Basket Exits

Introduction

The Mirrorpip Drawdown Scalping Strategy is a systematic averaging strategy designed to capitalize on temporary market pullbacks by building positions gradually as price moves against the initial entry. Unlike traditional trend-following systems that continuously reverse positions, this strategy focuses on accumulating positions during drawdowns and exiting the entire basket once a predefined profit target is achieved. The strategy supports both long and short trading modes and can be fully automated using TradingView alerts and Mirrorpip webhooks.

How the Strategy Works

The core idea is simple:
  1. Enter an initial position.
  2. If price moves against the trade, add another position after a predefined distance.
  3. Continue averaging until either:
    • The profit target is reached, or
    • The maximum number of averaging positions is reached.
  4. Exit the entire basket when the target is achieved.
The strategy continuously recalculates the average entry price and adjusts the basket target accordingly. 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 Drawdown Scalping v1.0", shorttitle="MirrorPip DD Scalping", overlay=true, default_qty_type=strategy.fixed, default_qty_value=1, pyramiding = 99, initial_capital=300000, process_orders_on_close=false, calc_on_every_tick=true, calc_on_order_fills=false, margin_long = 10, margin_short = 10)
 
////======================================================
paraSystemMode = input.session(defval="Positional", title="System Mode", options=["Intraday", "Positional"], group = "Trade Settings")
s = input.session(title='Intraday Start Session:', defval='0915-1515', group='Trade Settings')
e = input.session(title='Intraday End Session:', defval='1520-1521', group='Trade Settings')
 
paraScalpingStartDT = input.time(timestamp("01 Jun 2026 09:15 +0530"), "Scalping Start From", group = "Trade Settings")
paraScalpingTradeType = input.string(defval='Buy-Sell', title='Scalping Trade Type', options=['Buy-Sell', 'Short-Cover'], group='Trade Settings')
paraScalpingFirstTrade = input.float(0, title="Scalping First Entry Level", minval = 0, group='Trade Settings', tooltip = "0: to initial trade at specified date-time")
 
paraMaxScalpingPos = input.int(defval = 5, title="Max. Scalping Positions", minval = 0, maxval = 20, group='Trade Settings')
paraScalpingType = input.string(defval='%', title='Scalping Type', options=['%', 'Pts'], group='Trade Settings')
paraScalping = input.float(1, title="Scalping Value", minval = 0, group='Trade Settings')
 
paraQty = input.int(title='Qty. ', defval=1, minval=1, group='Trade Settings')
 
paraRestartMode = input.bool(true, "Restart On No Position", group='Trade Settings')
paraISTTimeZoneMode = input.bool(true, "IST Timezone?", group = "Trade Settings")
 
paraTGTMode = input.string(defval="%", title="Target : ", options=["%", "Pts"], inline = "TGT", group = "Target Settings")
paraTGT = input.float(5, "Value", minval = 0.1, inline = "TGT", group = "Target Settings")
 
paraShowDashboard = input.bool(true, "Show Strategy Dashboard")
////======================================================
 
////======================================================
grpAlgo = "Algo Setup"
paraExchange = input.string(title='Exchange', defval='delta', options=["delta", "coinswitch"], 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='Entry Qty.', defval=1, minval=0, group=grpAlgo, tooltip='Qty in Lots for Futures', inline = "Qty")
paraQtyEx = 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 float nextBuyLevel = na
varip float nextSellLevel = na
varip float nextShortLevel = na
varip float nextCoverLevel = na
 
FC = session.isfirstbar
LC = session.islastbar
BSFC = ta.barssince(FC)+1
 
startDateTime = time(timeframe.period, e)
StartDTCond = time >= paraScalpingStartDT
StartDTCandle = StartDTCond and not StartDTCond[1]
StartDTPrice = ta.valuewhen(StartDTCandle, open, 0)
 
IsIntraday = paraSystemMode=="Intraday"
st = (not IsIntraday ? true : not na(time(timeframe.period, s))) 
et = IsIntraday and not na(time(timeframe.period, e))
if (paraISTTimeZoneMode)
    st := not IsIntraday ? true : not na(time(timeframe.period, s, "UTC+5:30"))
    et := IsIntraday and not na(time(timeframe.period, e, "UTC+5:30"))
 
IsLong = paraScalpingTradeType == "Buy-Sell"
 
eBuyPos = 0
eShortPos = 0
eBuy = st and StartDTCond and StartDTCandle and IsLong and barstate.isconfirmed 
eShort = st and StartDTCond and StartDTCandle and not IsLong and barstate.isconfirmed 
eSell = strategy.position_size != 0
eCover = strategy.position_size != 0
eBuyPos := eBuy ? 1 : eSell and eBuyPos[1] > 0 ? 0 : eBuyPos[1]
eShortPos := eShort ? -1 : eCover and eShortPos[1] < 0 ? 0 : eShortPos[1]
////======================================================
 
////======================================================
symbol = syminfo.ticker
 
eBuyPrice = ta.valuewhen(eBuy, close, 0)
eShortPrice = ta.valuewhen(eShort, 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")
        LEStrike := BATM - (paraOptMulti * paraOptSteps)
        SEStrike := SATM + (paraOptMulti * paraOptSteps)
 
        if paraExchange == "coinswitch"
            LESym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(LEStrike)     + "-P-USDT" 
            LXSym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(LEStrike[1])  + "-P-USDT" 
            SESym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(SEStrike)     + "-C-USDT" 
            SXSym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(SEStrike[1])  + "-C-USDT" 
        else //"delta"
            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
        if paraExchange == "coinswitch"
            LESym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(LEStrike)     + "-C-USDT" 
            LXSym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(LEStrike[1])  + "-C-USDT" 
            SESym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(SEStrike)     + "-P-USDT" 
            SXSym := paraOptUnderlying + "-" + paraOptExpiry + "-" + str.tostring(SEStrike[1])  + "-P-USDT" 
        else //"delta"
            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+'"}'
////======================================================
 
////======================================================
GetMySellData(funcQty) =>
    _funcQty = funcQty
    if (paraQtyType=="$")
        _funcQty := funcQty * 2
    _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
 
GetMyCoverData(funcQty) =>
    _funcQty = funcQty
    if (paraQtyType=="$")
        _funcQty := funcQty * 2
    _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
 
GetMyLevel(_Price, _ValueType, _Value, _Dir) =>
    var float result = na
    if (_Dir > 0)
        if (_ValueType=="%")
            result := _Price * (1 + (_Value/100))
        else
            result := _Price + _Value
    else 
        if (_ValueType=="%")
            result := _Price * (1 - (_Value/100))
        else
            result := _Price - _Value
 
    result := math.round_to_mintick(result)
    result
 
////======================================================
varip int ScalpingCtr = na
varip float PosSize = na
 
var float BuyPrice = na
var float ShortPrice = na
var float BuyTGT = na
var float ShortTGT = na
var float BuySL = na
var float ShortSL = na
 
if (FC and IsIntraday)
    ScalpingCtr := 0
 
PosSize := math.abs(strategy.position_size)
 
BuyRE = paraRestartMode and strategy.closedtrades > 0 and strategy.position_size == 0 and IsLong and barstate.isconfirmed
ShortRE = paraRestartMode and strategy.closedtrades > 0 and strategy.position_size == 0 and not IsLong and barstate.isconfirmed
 
if (eBuy) and st and strategy.position_size <= 0 
 
    strategy.cancel_all()
    if (paraScalpingFirstTrade > 0)
        strategy.entry('BUY', strategy.long, qty=BuyTradeQty, comment="Buy", stop = paraScalpingFirstTrade, limit = paraScalpingFirstTrade, alert_message="["+buyData+"]")
        nextBuyLevel := GetMyLevel(paraScalpingFirstTrade, paraScalpingType, paraScalping, -1)
        nextSellLevel := GetMyLevel(paraScalpingFirstTrade, paraTGTMode, paraTGT, 1)
    else
        strategy.entry('BUY', strategy.long, qty=BuyTradeQty, comment="Buy", alert_message="["+buyData+"]")
        nextBuyLevel := GetMyLevel(close, paraScalpingType, paraScalping, -1)
        nextSellLevel := GetMyLevel(close, paraTGTMode, paraTGT, 1)
    ScalpingCtr := 1
 
else if (BuyRE) and st and strategy.position_size == 0 and strategy.position_size[1] > 0 
 
    strategy.entry('BUY', strategy.long, qty=BuyTradeQty, comment="Buy", alert_message="["+buyData+"]")
    nextBuyLevel := GetMyLevel(close, paraScalpingType, paraScalping, -1)
    nextSellLevel := GetMyLevel(close, paraTGTMode, paraTGT, 1)
    ScalpingCtr := 1
 
 
if (eShort) and st and strategy.position_size >= 0 
 
    strategy.cancel_all()
    if (paraScalpingFirstTrade > 0)
        strategy.entry('SHORT', strategy.short, qty=ShortTradeQty, comment="Short", stop = paraScalpingFirstTrade, limit = paraScalpingFirstTrade, alert_message="["+shortData+"]")
        nextShortLevel := GetMyLevel(paraScalpingFirstTrade, paraScalpingType, paraScalping, 1)
        nextCoverLevel := GetMyLevel(paraScalpingFirstTrade, paraTGTMode, paraTGT, -1)
    else
        strategy.entry('SHORT', strategy.short, qty=ShortTradeQty, comment="Short", alert_message="["+shortData+"]")
        nextShortLevel := GetMyLevel(close, paraScalpingType, paraScalping, 1)
        nextCoverLevel := GetMyLevel(close, paraTGTMode, paraTGT, -1)
    ScalpingCtr := 1
 
else if (ShortRE) and st and strategy.position_size == 0 
 
    strategy.entry('SHORT', strategy.short, qty=ShortTradeQty, comment="Short", alert_message="["+shortData+"]")
    nextShortLevel := GetMyLevel(close, paraScalpingType, paraScalping, 1)
    nextCoverLevel := GetMyLevel(close, paraTGTMode, paraTGT, -1)
    ScalpingCtr := 1
 
 
if st and strategy.position_size >= 0 and close <= nextBuyLevel and barstate.isconfirmed and ScalpingCtr < paraMaxScalpingPos and IsLong
    strategy.entry('BUY', strategy.long, qty=BuyTradeQty, comment="Buy", alert_message="["+buyData+"]")
    nextBuyLevel := GetMyLevel(close, paraScalpingType, paraScalping, -1)
    // nextSellLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, 1)
    ScalpingCtr += 1
if st and strategy.position_size <= 0 and close >= nextShortLevel and barstate.isconfirmed and ScalpingCtr < paraMaxScalpingPos and not IsLong
    strategy.entry('SHORT', strategy.short, qty=ShortTradeQty, comment="Short", alert_message="["+shortData+"]")
    nextShortLevel := GetMyLevel(close, paraScalpingType, paraScalping, 1)
    // nextCoverLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, -1)
    ScalpingCtr += 1
 
if (strategy.position_size > strategy.position_size[1])
    nextSellLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, 1)
if (strategy.position_size < strategy.position_size[1])
    nextCoverLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, -1)
 
if strategy.position_size > 0 and close >= nextSellLevel and barstate.isconfirmed 
    sellDataAll = GetMySellData(PosSize)
    strategy.close("BUY", immediately = true, comment="Sell", alert_message="["+sellDataAll+"]") //, qty=BuyTradeQty
    nextBuyLevel := GetMyLevel(close, paraScalpingType, paraScalping, -1)
    nextSellLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, 1)
    ScalpingCtr := 0
if strategy.position_size < 0 and close <= nextCoverLevel and barstate.isconfirmed 
    coverDataAll = GetMyCoverData(PosSize)
    strategy.close("SHORT", immediately = true, comment="Cover", alert_message="["+coverDataAll+"]") //, qty=ShortTradeQty
    nextShortLevel := GetMyLevel(close, paraScalpingType, paraScalping, 1)
    nextCoverLevel := GetMyLevel(strategy.position_avg_price, paraTGTMode, paraTGT, -1)
    ScalpingCtr := 0
 
PosSize := math.abs(strategy.position_size)
 
if (et) and strategy.position_size > 0 
    sellDataAll = GetMySellData(PosSize)
    strategy.close(id='BUY', comment="Sell", alert_message="["+sellDataAll+"]")
if (et) and strategy.position_size < 0 
    coverDataAll = GetMyCoverData(PosSize)
    strategy.close(id='SHORT', comment="Cover", alert_message="["+coverDataAll+"]")
////======================================================
 
////======================================================
BuyTGT := nextSellLevel
ShortTGT := nextCoverLevel
 
plot(IsLong ? nextBuyLevel : na, "NextBuyLevel", color = color.green, style = plot.style_steplinebr)
plot(IsLong ? nextSellLevel : na, "NextSellLevel", color = color.red, style = plot.style_steplinebr)
plot(not IsLong ? nextShortLevel : na, "NextShortLevel", color = color.red, style = plot.style_steplinebr)
plot(not IsLong ? nextCoverLevel : na, "NextCoverLevel", color = color.green, style = plot.style_steplinebr)
 
//plotshape(strategy.position_size<=0?eBuy:na, style=shape.diamond , location=location.belowbar, color=color.green, size=size.tiny)
//plotshape(strategy.position_size>=0?eShort:na, style=shape.diamond, location=location.abovebar, color=color.red, size=size.tiny)
 
plot((strategy.position_size > 0)?strategy.position_avg_price:na, "BuyPrice", color=color.fuchsia, linewidth=1, style=plot.style_linebr)
plot((strategy.position_size < 0)?strategy.position_avg_price:na, "ShortPrice", color=color.fuchsia, linewidth=1, style=plot.style_linebr)
 
// 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)?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)
////======================================================
 
////======================================================
totalCols = 2
totalRows = 5 
stgTGTFlag = true
stgSLFlag = false
 
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="")
////======================================================
\

Core Components

Initial Entry

The strategy begins with a single entry position. Users can choose:
  • Buy → Sell Mode
  • Short → Cover Mode
The first trade can be:
  • Market entry
  • Specific trigger price
  • Date and time based activation
This provides flexibility for both discretionary and fully automated deployments.

Drawdown Averaging Logic

Once the initial position is opened, the strategy monitors price movement. If the market moves against the position by a predefined amount, another trade is added. This process repeats until:
  • Price recovers and reaches target
  • Maximum averaging positions are reached

Example: Long Trade

Initial Buy: BTCUSDT = $100,000 Position Size: 1 Lot
Scalping Distance: 1%
Price Falls to: $99,000 Strategy Adds: +1 Lot
Price Falls Again: $98,010 Strategy Adds: +1 Lot
Average Entry Price decreases significantly. A smaller recovery is now required to reach profitability.

Example: Short Trade

Initial Short: BTCUSDT = $100,000
Scalping Distance: 1%
Price Rises: $101,000 Strategy Adds: Additional Short Position
Price Rises Again: $102,010 Strategy Adds: Additional Short Position
Average short price improves. The basket exits when price falls back to the target level.

Scalping Distance Configuration

Users can define averaging intervals in two ways.

Percentage Mode

Example: Scalping Value = 1% New positions are added every 1% adverse move.

Points Mode

Example: Scalping Value = 500 Points New positions are added every 500-point move against the position.
This flexibility allows optimization across different markets and volatility environments.

Maximum Position Control

Risk management is controlled using:

Maximum Scalping Positions

Example: Max Positions = 5 The strategy can build:
  • Initial Entry
  • Averaging 1
  • Averaging 2
  • Averaging 3
  • Averaging 4
After reaching the limit, no further positions are added. This prevents unlimited averaging and helps control risk exposure.

Dynamic Basket Target

One of the most powerful features of this strategy is its dynamic target calculation. Every time a new position is added:
  • Average entry price changes
  • Basket target is recalculated
The strategy exits the entire position when price reaches the target level based on the updated average cost.

Example

Entries: 100,000 99,000 98,000
Average Entry: 99,000
Target: 2%
Exit Level: 100,980 Instead of requiring price to recover back to 100,000, the strategy only needs to reach the target calculated from the new average entry.

Target Configuration

Users can configure targets using:

Percentage Targets

Example: Target = 3%

Fixed Point Targets

Example: Target = 1000 Points
The target automatically adjusts as additional positions are added.

Intraday and Positional Modes

The strategy supports two execution styles.

Intraday Mode

All positions are closed before market close. Suitable for:
  • Intraday traders
  • Day traders
  • Markets with overnight risk

Positional Mode

Trades can remain open indefinitely until:
  • Target is achieved
  • Manual intervention occurs
Suitable for:
  • Swing traders
  • Crypto markets
  • 24/7 trading environments

Restart Mode

The strategy includes an automatic restart feature. When enabled:
  • Basket closes in profit
  • Strategy immediately prepares for the next cycle
This allows continuous operation without manual intervention.

Position Sizing Options

Users can configure:

Fixed Quantity

Example: 1 Lot per Entry

Dollar-Based Exposure

Example: $1,000 per Entry The strategy automatically converts capital allocation into quantity.
This allows consistent risk management across different instruments.

Long and Short Trading Support

The strategy can operate in:

Buy → Sell Mode

Designed for bullish markets. The system averages during declines and exits during recoveries.

Short → Cover Mode

Designed for bearish markets. The system averages during rallies and exits during pullbacks.

Suitable Markets

This strategy performs best in:
  • Bitcoin Futures
  • Ethereum Futures
  • Range-Bound Crypto Markets
  • Index Futures
  • Forex Markets
  • High-Liquidity Instruments
Markets that frequently experience pullbacks and mean reversion behavior tend to provide the best opportunities.

Risk Management Considerations

Although averaging strategies can improve recovery probability, they require careful capital management. Before deploying:
  • Limit maximum averaging positions
  • Avoid excessive leverage
  • Use realistic target values
  • Test across different market regimes
  • Ensure sufficient capital reserves
Like any averaging system, prolonged one-directional trends can create significant drawdowns.

Mirrorpip Automation Setup

The strategy can be fully automated through Mirrorpip. Workflow: TradingView Strategy → TradingView Alert → Mirrorpip Webhook → Exchange Account → Trade Execution Users can deploy the strategy across multiple exchanges and monitor performance through a unified dashboard. Mirrorpip analytics provide:
  • Win Rate
  • Maximum Drawdown
  • Sharpe Ratio
  • Average Holding Time
  • Profit Factor
  • Live Equity Curve

Conclusion

The Mirrorpip Drawdown Scalping Strategy is designed for traders who want a systematic approach to averaging positions during adverse price movements. By gradually building positions at predefined intervals and dynamically recalculating profit targets based on average entry price, the strategy seeks to capitalize on market pullbacks while maintaining a structured risk framework. With configurable averaging distance, maximum position limits, flexible targets, long and short support, and full Mirrorpip automation integration, the strategy provides a powerful framework for traders looking to exploit mean-reverting market behavior.