计算基于先进先出的多票据损益

问题描述 投票:0回答:1

我正在努力处理我的 vba 代码,该代码计算股票交易中的已实现和未实现利润。我相信这个实用程序将对所有无力承担昂贵费用的小商人有很大帮助。我的代码可以正确计算某些数字,而在其他数字上却步履蹒跚。

设置: 交易文件由 6 列组成

scrip   b_s    date        qty  rate        Current price
ABC1    buy    12-09-2023   20  4609.69     4752.95
ABC1    sale   20-09-2023   20  4337.645    4752.95
ABC2    buy    13-09-2023   75  689.9513333 907.05
ABC2    buy    10-11-2023   65  885         907.05

宏以先进先出方式计算ColJ、K、L中的pre_qtr利润、qtr_profit、未实现利润。 qtr 周期在宏中定义为暂时的常数,但稍后它将基于输入。 股票的销售数量将为 <= total buy quantity. The sale date is used to decide in which column the result will go. The first sale will be setoff from first available quantity. The unsold quantity of a stock will be used for calculating Unrealized profit. The logic to be used is remaining quantity * market price minus the the total cost of remaining quantity.
在我的 Excel 工作表中,我通过手动计算在单独的列中给出了正确的数字。

面临的问题: 如果总销售数量 = 此类股票的总购买数量,则宏计算正确。 如果只买入而不卖出股票,那就错了。 如果一个股票有多个销售实例,它也会出错。 未实现利润计算错误。

我也在这里附上了我的代码,并附上了我的带有示例数据的 Excel 工作表。

我哪里出了问题,解决办法是什么?

https://docs.google.com/spreadsheets/d/1DxcO78dgdz0AvdDgNDt4U0C2-_AQ7a0eMaUbkFjDwfU/edit?usp=drivesdk

    Sub CalculateFIFOProfit1()

        Const QTR_START_DATE As Date = #10/1/2023#  ' DD-MM-YYYY format
        Const QTR_END_DATE As Date = #12/31/2023# ' DD-MM-YYYY format
    
        Dim currentRow As Long
        Dim totalBought As Long
        Dim totalRemaining As Long ' Track remaining quantity from past buys
        Dim boughtPrice As Double
        Dim soldPrice As Double
        Dim preQtrProfit As Double
        Dim thisQtrProfit As Double
        Dim unrealizedProfit As Double
        Dim currentScrip As String
        Dim lastRow As Long
        Dim marketPrice As Double ' Add this variable to store current market price
        Dim lastBoughtPrice As Double ' Add this variable to store latest buy price
    
        currentRow = 2 ' Assuming headers in row 1
        lastRow = 2 ' Track last row for each scrip
        totalBought = 0
        totalRemaining = 0
        boughtPrice = 0
        preQtrProfit = 0
        thisQtrProfit = 0
        unrealizedProfit = 0
        currentScrip = ""
        lastBoughtPrice = 0 ' Initialize last buy price
        Dim lrow As Long
        lrow = Cells(Rows.Count, 1).End(xlUp).Row
        'Do While Cells(currentRow, 1).Value <> ""
        'Do While currentRow <= Cells(Rows.Count, 1).End(xlUp).Row 'Do While currentRow <= 173 '<= Cells(Rows.Count, 1).End(xlUp).Row
        Do While currentRow <= lrow
            If Cells(currentRow, 1).Value <> currentScrip Then
                ' New scrip, output profits for previous scrip
                
                If lastRow > 0 Then
                    Cells(lastRow, 10).Value = preQtrProfit
                    Cells(lastRow, 11).Value = thisQtrProfit
                    marketPrice = Cells(lastRow, 6).Value ' Retrieve market price from ColF
                    Cells(lastRow, 12).Value = unrealizedProfit + marketPrice * totalRemaining - lastBoughtPrice * totalRemaining ' Corrected unrealized profit calculation
                End If
                currentScrip = Cells(currentRow, 1).Value
                lastRow = currentRow ' Reset last row for new scrip
                totalBought = 0
                totalRemaining = 0
                boughtPrice = 0
                preQtrProfit = 0
                thisQtrProfit = 0
                unrealizedProfit = 0
                lastBoughtPrice = 0 ' Reset last buy price for new scrip
            End If
    
            If Cells(currentRow, 2).Value = "buy" Then
                totalBought = totalBought + Cells(currentRow, 4).Value ' Quantity in ColD
                boughtPrice = boughtPrice + Cells(currentRow, 5).Value * Cells(currentRow, 4).Value ' Rate in ColE
                totalRemaining = totalRemaining + Cells(currentRow, 4).Value
                lastBoughtPrice1 = Cells(currentRow, 5).Value ' Update last buy price
                ' Update lastBoughtPrice calculation
                'lastBoughtPrice = (totalBought * boughtPrice - Cells(currentRow, 4).Value * Cells(currentRow, 5).Value) / (totalBought - Cells(currentRow, 4).Value)
                If totalBought - Cells(currentRow, 4).Value <> 0 Then
                lastBoughtPrice = boughtPrice
                'lastBoughtPrice = (totalBought * boughtPrice - Cells(currentRow, 4).Value * Cells(currentRow, 5).Value) / (totalBought - Cells(currentRow, 4).Value)
                Else
                ' Handle the case when totalBought - sale quantity is zero
                lastBoughtPrice1 = Cells(currentRow, 5).Value  ' Set lastBoughtPrice to zero or any value you deem appropriate
    End If
    
            ElseIf Cells(currentRow, 2).Value = "sale" Then
                totalSold = totalSold + Cells(currentRow, 4).Value ' Quantity in ColD
                If totalSold = 0 Then unrealizedProfit = (Cells(currentRow, 6).Value * totalBought) - boughtPrice
                ' Compare dates in DD-MM-YYYY format
                If Cells(currentRow, 3).Value <= QTR_START_DATE Then ' Date in ColC
                    ' Pre-quarter sale
                    Dim remainingBeforeSale As Double ' Stores remaining quantity before this sale
                    remainingBeforeSale = totalRemaining
                    If remainingBeforeSale >= Cells(currentRow, 4).Value Then ' Enough pre-quarter stocks
                        preQtrProfit = preQtrProfit + (Cells(currentRow, 5).Value * Cells(currentRow, 4).Value) - (boughtPrice / totalBought) * Cells(currentRow, 4).Value
                        boughtPrice = boughtPrice - boughtPrice * Cells(currentRow, 4).Value / totalBought ' Adjust bought price for FIFO
                        totalRemaining = totalRemaining - Cells(currentRow, 4).Value
                    Else ' Not enough pre-quarter stocks, use remaining and adjust bought price proportionally
                        totalRemaining = 0
                        preQtrProfit = preQtrProfit + (Cells(currentRow, 5).Value * remainingBeforeSale) - (boughtPrice * remainingBeforeSale / totalBought)
                        boughtPrice = boughtPrice - boughtPrice * remainingBeforeSale / totalBought
                    End If
                ElseIf Cells(currentRow, 3).Value <= QTR_END_DATE Then ' Date in ColC
                    ' This-quarter sale
                    thisQtrProfit = thisQtrProfit + (Cells(currentRow, 5).Value * Cells(currentRow, 4).Value) - (boughtPrice / totalBought) * totalSold '(boughtPrice * Cells(currentRow, 4).Value / totalBought)
                    boughtPrice = boughtPrice - boughtPrice * Cells(currentRow, 4).Value / totalBought ' Adjust bought price for FIFO
                    totalRemaining = totalRemaining - Cells(currentRow, 4).Value
                Else ' Post-quarter sale
                    unrealizedProfit = unrealizedProfit - (boughtPrice * Cells(currentRow, 4).Value / totalBought) ' Adjust unrealized profit
                    boughtPrice = boughtPrice - boughtPrice * Cells(currentRow, 4).Value / totalBought
                    totalRemaining = totalRemaining - Cells(currentRow, 4).Value
                End If
            End If
            currentRow = currentRow + 1
        Loop
        If lrow > 0 Then
            Cells(lrow, 10).Value = preQtrProfit
            Cells(lrow, 11).Value = thisQtrProfit
            marketPrice = Cells(lrow, 6).Value
            Cells(lrow, 12).Value = unrealizedProfit + marketPrice * totalRemaining - lastBoughtPrice '* totalRemaining
        End If
    End Sub
stock fifo
1个回答
0
投票

您的代码中存在一些问题,包括 FIFO 逻辑的处理。

我已经更新了代码,试试吧:

Sub CalculateFIFOProfit1()

    Const QTR_START_DATE As Date = #10/1/2023#  ' DD-MM-YYYY format
    Const QTR_END_DATE As Date = #12/31/2023# ' DD-MM-YYYY format

    Dim currentRow As Long
    Dim totalBought As Double
    Dim totalRemaining As Double
    Dim boughtPrice As Double
    Dim preQtrProfit As Double
    Dim thisQtrProfit As Double
    Dim unrealizedProfit As Double
    Dim currentScrip As String
    Dim lastRow As Long
    Dim marketPrice As Double
    Dim lastBoughtPrice As Double

    currentRow = 2 ' Assuming headers in row 1
    lastRow = 2 ' Track last row for each scrip
    totalBought = 0
    totalRemaining = 0
    boughtPrice = 0
    preQtrProfit = 0
    thisQtrProfit = 0
    unrealizedProfit = 0
    currentScrip = ""
    lastBoughtPrice = 0 ' Initialize last buy price

    Dim lrow As Long
    lrow = Cells(Rows.Count, 1).End(xlUp).Row

    Do While currentRow <= lrow
        If Cells(currentRow, 1).Value <> currentScrip Then
            ' New scrip, output profits for previous scrip
            If lastRow > 0 Then
                Cells(lastRow, 10).Value = preQtrProfit
                Cells(lastRow, 11).Value = thisQtrProfit
                marketPrice = Cells(lastRow, 6).Value
                Cells(lastRow, 12).Value = unrealizedProfit + marketPrice * totalRemaining - lastBoughtPrice * totalRemaining
            End If
            currentScrip = Cells(currentRow, 1).Value
            lastRow = currentRow ' Reset last row for new scrip
            totalBought = 0
            totalRemaining = 0
            boughtPrice = 0
            preQtrProfit = 0
            thisQtrProfit = 0
            unrealizedProfit = 0
            lastBoughtPrice = 0 ' Reset last buy price for new scrip
        End If

        If Cells(currentRow, 2).Value = "buy" Then
            totalBought = totalBought + Cells(currentRow, 4).Value
            boughtPrice = boughtPrice + Cells(currentRow, 5).Value * Cells(currentRow, 4).Value
            totalRemaining = totalRemaining + Cells(currentRow, 4).Value
            lastBoughtPrice = Cells(currentRow, 5).Value ' Update last buy price
        ElseIf Cells(currentRow, 2).Value = "sale" Then
            If totalRemaining > 0 Then
                ' Sale logic
                Dim saleQuantity As Double
                saleQuantity = Cells(currentRow, 4).Value
                If saleQuantity <= totalRemaining Then
                    ' Enough remaining stocks for the sale
                    preQtrProfit = preQtrProfit + (Cells(currentRow, 5).Value * saleQuantity) - (boughtPrice / totalBought) * saleQuantity
                    boughtPrice = boughtPrice - boughtPrice * saleQuantity / totalBought
                    totalRemaining = totalRemaining - saleQuantity
                Else
                    ' Not enough remaining stocks, adjust profits and remaining quantity
                    preQtrProfit = preQtrProfit + (Cells(currentRow, 5).Value * totalRemaining) - (boughtPrice * totalRemaining / totalBought)
                    boughtPrice = 0 ' No remaining stocks
                    totalRemaining = 0
                End If
            End If
            ' Sale period logic
            If Cells(currentRow, 3).Value <= QTR_START_DATE Then
                ' Pre-quarter sale
                thisQtrProfit = thisQtrProfit + 0 ' No impact on this quarter profit
            ElseIf Cells(currentRow, 3).Value <= QTR_END_DATE Then
                ' This-quarter sale
                thisQtrProfit = thisQtrProfit + (Cells(currentRow, 5).Value * Cells(currentRow, 4).Value) - (boughtPrice / totalBought) * Cells(currentRow, 4).Value
                boughtPrice = boughtPrice - boughtPrice * Cells(currentRow, 4).Value / totalBought
                totalRemaining = totalRemaining - Cells(currentRow, 4).Value
            Else
                ' Post-quarter sale
                unrealizedProfit = unrealizedProfit - (boughtPrice * Cells(currentRow, 4).Value / totalBought)
                boughtPrice = 0 ' No remaining stocks
                totalRemaining = 0
            End If
        End If
        currentRow = currentRow + 1
    Loop

    ' Output for the last scrip
    If lastRow > 0 Then
        Cells(lastRow, 10).Value = preQtrProfit
        Cells(lastRow, 11).Value = thisQtrProfit
        marketPrice = Cells(lastRow, 6).Value
        Cells(lastRow, 12).Value = unrealizedProfit + marketPrice * totalRemaining - lastBoughtPrice * totalRemaining
    End If

End Sub
© www.soinside.com 2019 - 2024. All rights reserved.