Get The Code! (Option 2)

1

Complete Pine Script

Below is the complete Pine Script code.

2

Copy the code

Click the "copy" icon in the top-right corner of the code block.

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © CapitalCodersLLC
//@version=6

// --- Strategy Definition ---
strategy('Capital Coders DCA Bot', 
     overlay = true, 
     margin_long = 0,                   // No margin used for long positions
     margin_short = 0,                  // No margin used for short positions
     pyramiding = 999,                  // Allow many entries, but we'll cap it with our 'Pyramid' input
     default_qty_type = strategy.percent_of_equity, 
     default_qty_value = 10,            // Each trade (initial or DCA) will use 10% of equity
     initial_capital = 1000)

// --- Input Groups ---
grSS = 'Strategy Settings'
grInd = 'Indicator Settings'
g_time = '=================🕒|Live Trading|🕒================='

// --- Strategy Inputs ---
// 'Pyramid' controls the maximum number of open trades (1 initial + (n-1) safety trades)
Pyramid = input.int(10, 'Safety Trades', maxval = 999, group = grSS, 
     tooltip = 'Maximum number of DCA (safety) trades allowed.')
// 'exitLevelInput' is the profit target. We divide by 100 to convert it to a decimal (e.g., 5.0 -> 0.05)
exitLevelInput = input.float(5.0, 'Exit Level (%)', group = grSS, 
     tooltip = 'Profit target based on Average Entry Price') / 100 

// --- Indicator Inputs ---
SMA1Input = input.int(14, 'Moving Average - Fast:', minval = 1, group = grInd, inline = 'SMA1')
SMA2Input = input.int(28, 'Slow:', minval = 1, group = grInd, inline = 'SMA1')
Type = input.string('Crossunder', title = 'Type', options = ['Crossunder', 'Crossover'], group = grInd)

SMA1Color = input.color(color.new(#d2cde9, 40), 'Color - Fast:', inline = 'SMA1Color', group = grInd)
SMA2Color = input.color(color.new(#2962ff, 40), 'Slow:', inline = 'SMA1Color', group = grInd)

// --- Live Trading Filter Inputs ---
LIVE = input.bool(false, 'LIVE MODE', confirm = true, group = g_time, 
     tooltip = 'Enable this to start trading from a fresh state at the \'Start Date/Time\'. Disables historical backtesting.')
liveDate = input.time(timestamp('24 Oct 2025'), 'Start Date/Time', group = g_time, 
     tooltip = 'Date/time when Live trading begins. Strategy will be flat before this time if LIVE MODE is on.')
timeZone = input.string('GMT+0', 'Time Zone', group = g_time, 
     tooltip = 'GMT and UTC is the same thing \nMatch this setting to bottom right time', 
     options = ['GMT-10', 'GMT-9', 'GMT-8', 'GMT-7', 'GMT-6', 'GMT-5', 'GMT-4', 'GMT-3', 'GMT+0', 'GMT+1', 'GMT+2', 'GMT+3', 'GMT+4', 'GMT+5', 'GMT+6', 'GMT+7', 'GMT+8', 'GMT+9', 'GMT+10', 'GMT+10:30', 'GMT+11', 'GMT+12', 'GMT+13', 'GMT+13:45'])

// --- Calculations ---

// 1. Live Trading Time Filter
// Deconstruct the input time to correctly build a timestamp with the selected timezone
startTimeYear   = year(liveDate, timeZone)
startTimeMonth  = month(liveDate, timeZone)
startTimeDay    = dayofmonth(liveDate, timeZone)
starthour       = hour(liveDate, timeZone)
startmin        = minute(liveDate, timeZone)

// This is the precise start time in UNIX format, adjusted for the chosen timezone
startTime = timestamp(timeZone, startTimeYear, startTimeMonth, startTimeDay, starthour, startmin)

// 'LiveTrading' is true if LIVE mode is OFF (i.e., backtesting)
// OR if LIVE mode is ON *and* the current bar's time is after the specified start time.
LiveTrading = LIVE ? time > startTime : true

// 2. Indicator Calculations
SMA1 = ta.sma(close, SMA1Input)
SMA2 = ta.sma(close, SMA2Input)

// 3. Entry Condition Calculation
// Determine the entry signal based on the user's "Type" selection
cond = switch Type
    'Crossover'  => ta.crossover(SMA1, SMA2)
    'Crossunder' => ta.crossunder(SMA1, SMA2)

// 4. Exit Level Calculation
// Calculate the Take Profit price based on the current average entry price
// This value is recalculated on every bar that the position is open.
ExitLevel = strategy.position_avg_price * (1 + exitLevelInput)

// --- Strategy Logic ---

// 1. Entry Logic
// This is the master condition for placing any long entry (initial or DCA)
longCondition = cond and                                  // The SMA cross condition must be met
     strategy.opentrades < Pyramid and                    // We haven't exceeded our max number of safety trades
     (close <= strategy.position_avg_price or             // The price is at/below our avg price (DCA logic)
     strategy.position_size == 0) and                     // OR this is the very first entry
     LiveTrading                                          // The time filter must be true

// If all conditions are true, enter a long position
if longCondition
    strategy.entry('Long Entry', strategy.long)

// 2. Exit Logic
// This block checks if we are currently in a position
if strategy.position_size > 0
    // If yes, place/update a limit exit order at the calculated take profit level
    // This order will adjust automatically every time a new DCA entry fills
    strategy.exit('DCA Exit', 'Long Entry', limit = ExitLevel)

// --- Plotting ---

// Plot the SMAs
plot(SMA1, color = SMA1Color, title = 'Fast SMA')
plot(SMA2, color = SMA2Color, title = 'Slow SMA')

// Plot the average entry price (only when in a position)
plot(strategy.position_size > 0 ? strategy.position_avg_price : na, 
     title = 'Average Entry Price', 
     color = color.blue, 
     style = plot.style_linebr)

// Plot the take profit target level (only when in a position)
plot(strategy.position_size > 0 ? ExitLevel : na, 
     title = 'DCA Exit Level', 
     color = color.green, // This was orange in the v5, green here as per your v6 code
     style = plot.style_linebr)

// Highlight the background when a new entry condition is met
bgcolor(longCondition ? color.new(color.green, 80) : na, 
     title = 'Entry Signal')

Last updated