Simple Dollar Cost Average
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RomainHaenni

//@version=5
indicator("Dollar Cost Average", "DCA")
float startingAmount = input.float(0.0, "Starting Investment")
float investmentAmount = input.float(500.0, "Repeating Investment")
int frequency = input.int(7, "Repeats every (in days)", inline="frequency")
float feeRatio = input.float(0.02, "Broker Fee")
int startDate = input.time(timestamp("Jan 01 2023"), "Starting Date")
int endDate = input.time(timestamp("Jan 01 2033"), "Ending Date")
float cellWidth = input.float(0.0, "Cell Width", group="advanced")
float cellHeight = input.float(10.0, "Cell Height", group="advanced")

var float assets = 0.0
var float feeAmount = 0.0
var float entryPrice = 0.0
var float invested = 0.0
var float netProfit = 0.0
var float totalFee = 0.0
var float grossProfit = 0.0
var float grossLoss = 0.0
var int totalTrades = 0
var float portfolioValue = 0.0

var table info = table.new(position.bottom_left, 1, 7, #212121, #313131, 1, #313131, 1)
table.cell(info, 0, 0, "$0.00 invested",      cellWidth, cellHeight, color.lime, text.align_left)
table.cell(info, 0, 1, "$0.00 (0.0%) PnL",    cellWidth, cellHeight, #BDBDBD, text.align_left)
table.cell(info, 0, 2, "$0.00 (0.0%) fee",    cellWidth, cellHeight, #BDBDBD, text.align_left)
table.cell(info, 0, 3, "$0.00 total",         cellWidth, cellHeight, color.yellow, text.align_left)
table.cell(info, 0, 4, "0.00 shares",         cellWidth, cellHeight, #BDBDBD, text.align_left)
table.cell(info, 0, 5, "$0.00 / share",       cellWidth, cellHeight, #BDBDBD, text.align_left)
table.cell(info, 0, 6, "0 trades",            cellWidth, cellHeight, #BDBDBD, text.align_left)

bool investmentWindow = time >= startDate and time < endDate

if investmentWindow
    if startingAmount > 0.0 and invested == 0.0
        totalTrades := totalTrades + 1
        feeAmount := startingAmount * feeRatio
        invested := startingAmount
        newAssets = (startingAmount - feeAmount) / close
        assets := newAssets
        entryPrice := close
        totalFee := feeAmount

    if math.floor((time - startDate) / 1000 / 60 / 60 / 24) % frequency == 0 and (timeframe.isdwm or (timeframe.isintraday and hour(time) == 12 and minute(time) == 0))
        totalTrades := totalTrades + 1
        feeAmount := investmentAmount * feeRatio
        invested := invested + investmentAmount
        newAssets = (investmentAmount - feeAmount) / close
        entryPrice := (entryPrice * assets + (investmentAmount - feeAmount)) / (assets + newAssets)
        assets := assets + newAssets
        totalFee := totalFee + feeAmount

    netProfit := close * assets - entryPrice * assets
    portfolioValue := entryPrice * assets + netProfit
    
    table.cell_set_text(info, 0, 0, str.tostring(math.round(invested, 2)) + " invested")
    table.cell_set_text(info, 0, 1, str.tostring(math.round(netProfit, 2)) + " (" + str.tostring(math.round(netProfit * 100 / invested, 2)) + "%) PnL")
    table.cell_set_text(info, 0, 2, "-" + str.tostring(math.round(totalFee, 2)) + " (-" + str.tostring(math.round(totalFee * 100 / invested, 3)) + "%) fees")
    table.cell_set_text(info, 0, 3, str.tostring(math.round(portfolioValue, 2)) + " total")
    table.cell_set_text(info, 0, 4, str.tostring(math.round(assets, 8)) + " shares")
    table.cell_set_text(info, 0, 5, str.tostring(math.round_to_mintick(entryPrice)) + " / share")
    table.cell_set_text(info, 0, 6, str.tostring(totalTrades) + " trades")
    
plot(investmentWindow ? portfolioValue : na, "Portfolio Value", color.yellow)   
plot(investmentWindow ? invested : na, "Invested Amount", color.lime, 2)
