Using DAX to Calculate Investment Returns and Portfolio Metrics

To Share 2026 - Content Fb + Web (5)

DAX calculate investment returns Power BI là kỹ năng cốt lõi của mọi Financial DA.

Biết kéo thả visual chưa đủ. Portfolio Manager cần các con số chính xác — HPR, TWR, Sharpe, Alpha, VaR.

Bài viết hướng dẫn viết DAX cho tất cả các chỉ số quan trọng nhất.

Từng measure đều có giải thích ngắn và code sẵn dùng. Tham khảo thêm tại Microsoft DAX Function Reference.

📌 Đây là bài số 7 trong series Power BI Financial Analytics tại MCNA:

1. Tại Sao Cần DAX Riêng Cho Financial Metrics?

Excel công thức khác DAX ở điểm nào?

Trong Excel, bạn kéo công thức xuống từng dòng.

Trong Power BI, DAX tính toán theo context filter. Một measure tự động thay đổi kết quả khi người dùng filter theo client, asset class hay thời gian.

Đây là sức mạnh cốt lõi — và cũng là lý do DAX cần được viết đúng từ đầu.

Các nhóm metric cần DAX

Nhóm Metrics Mục đích
Return Metrics HPR, TWR, MWR Đo lợi suất danh mục
Risk-Adjusted Sharpe, Sortino, Calmar Đánh giá return so với risk
Benchmark Alpha, Beta, Tracking Error So sánh với thị trường
Risk Metrics VaR, CVaR, Max Drawdown Đo mức độ rủi ro
Time Intelligence YTD, MTD, QTD, Rolling Phân tích theo kỳ thời gian

💡 Nguyên tắc: Tạo một bảng _Measures riêng. Đặt tất cả measures vào đó theo nhóm. Không để measures rải rác trong các Fact Tables.


2. Holding Period Return (HPR)

HPR cơ bản

HPR là chỉ số đơn giản nhất. Nó đo lợi suất từ khi mua đến hiện tại.

Không tính đến timing của dòng tiền. Phù hợp cho báo cáo nhanh.

-- HPR toàn danh mục
Portfolio HPR % =
DIVIDE(
    [Total Market Value] - [Total Cost Value],
    [Total Cost Value]
)

-- HPR từng tài sản
Asset HPR % =
DIVIDE(
    [Asset Market Value] - [Asset Cost Value],
    [Asset Cost Value]
)

-- HPR có tính cổ tức
HPR with Dividend % =
DIVIDE(
    [Total Market Value] - [Total Cost Value] + [Total Dividend],
    [Total Cost Value]
)

-- Log Return (dùng cho tính toán thống kê)
Log Return =
LN(DIVIDE([Current Price], [Entry Price]))

HPR theo từng kỳ thời gian

-- YTD Return
HPR YTD % =
VAR StartVal =
    CALCULATE([Total Market Value],
        STARTOFYEAR(DimDate[Date]))
RETURN DIVIDE([Total Market Value] - StartVal, StartVal)

-- MTD Return
HPR MTD % =
VAR StartVal =
    CALCULATE([Total Market Value],
        STARTOFMONTH(DimDate[Date]))
RETURN DIVIDE([Total Market Value] - StartVal, StartVal)

-- QTD Return
HPR QTD % =
VAR StartVal =
    CALCULATE([Total Market Value],
        STARTOFQUARTER(DimDate[Date]))
RETURN DIVIDE([Total Market Value] - StartVal, StartVal)

✅ Best practice: Luôn tạo đủ 3 phiên bản YTD, MTD, QTD. Portfolio Manager so sánh nhiều kỳ trong cùng một buổi họp.


3. Time-Weighted Return (TWR)

TWR khác HPR ở điểm nào?

TWR loại bỏ ảnh hưởng của dòng tiền vào/ra.

Nó chỉ đo hiệu quả của chiến lược đầu tư. Đây là chuẩn CFA/GIPS để đánh giá fund manager.

DAX cho TWR

-- Sub-period return cho mỗi ngày
Daily Sub-Period Return =
DIVIDE(
    [End of Day Value],
    [Beginning of Day Value] - [Net Cash Flow]
) - 1

-- TWR tích lũy (Linked Internal Rate of Return)
TWR Cumulative % =
PRODUCTX(
    DATESBETWEEN(
        DimDate[Date],
        [Portfolio Start Date],
        MAX(DimDate[Date])
    ),
    1 + [Daily Sub-Period Return]
) - 1

-- Annualized TWR
TWR Annualized % =
POWER(
    1 + [TWR Cumulative %],
    365 / [Days Held]
) - 1

⚠️ Lưu ý: TWR cần định giá danh mục mỗi khi có dòng tiền vào/ra. Thiếu dữ liệu điểm thì dùng Modified Dietz thay thế.


4. Money-Weighted Return (MWR)

MWR phản ánh điều gì?

MWR tính đến thời điểm nạp/rút tiền.

Nó phản ánh trải nghiệm thực tế của nhà đầu tư. Dùng để báo cáo cho client — không phải để đánh giá fund manager.

DAX xấp xỉ MWR

-- DAX không có hàm IRR built-in
-- Dùng Modified Dietz làm xấp xỉ tốt nhất

Modified Dietz Return % =
VAR EndValue    = [Total Market Value]
VAR StartValue  = [Beginning Market Value]
VAR NetCashFlow = [Total Cash Inflow] - [Total Cash Outflow]
VAR WeightedCF  = [Time-Weighted Cash Flow]
RETURN
    DIVIDE(
        EndValue - StartValue - NetCashFlow,
        StartValue + WeightedCF
    )

-- Annualized MWR (xấp xỉ đơn giản)
MWR Annualized % =
VAR Months = DATEDIFF([Start Date], TODAY(), MONTH)
RETURN
    POWER(
        DIVIDE([Total Market Value], [Total Cost Value]),
        12 / Months
    ) - 1

5. Sharpe Ratio và Sortino Ratio

Risk-adjusted return là gì?

Sharpe Ratio đo lợi suất vượt trội so với tài sản phi rủi ro, trên mỗi đơn vị risk.

Sharpe cao = return tốt hơn so với risk đang chịu. Đây là chỉ số quan trọng nhất để so sánh các portfolio khác nhau.

DAX cho Sharpe Ratio

-- Sharpe Ratio = (Portfolio Return - Risk-Free Rate) / Std Dev

-- Bước 1: Annualized Return
Annualized Return % =
POWER(1 + [HPR YTD %], 12 / [Months YTD]) - 1

-- Bước 2: Portfolio Volatility (Std Dev)
Portfolio Volatility % =
VAR DailyReturns =
    CALCULATETABLE(
        ADDCOLUMNS(
            DATESINPERIOD(DimDate[Date],
                LASTDATE(DimDate[Date]), -252, DAY),
            "DR", [Daily Portfolio Return %]
        )
    )
RETURN
    STDEVX.P(DailyReturns, [DR]) * SQRT(252)

-- Bước 3: Sharpe Ratio
Sharpe Ratio =
VAR RiskFreeRate = 0.045  -- 4.5% lãi suất phi rủi ro VN
RETURN
    DIVIDE(
        [Annualized Return %] - RiskFreeRate,
        [Portfolio Volatility %]
    )

DAX cho Sortino Ratio

Sortino chỉ phạt downside risk. Nó tốt hơn Sharpe khi portfolio có return không đối xứng.

-- Sortino = (Return - Risk-Free) / Downside Deviation

Downside Deviation % =
VAR DailyReturns =
    CALCULATETABLE(
        ADDCOLUMNS(
            DATESINPERIOD(DimDate[Date],
                LASTDATE(DimDate[Date]), -252, DAY),
            "DR", [Daily Portfolio Return %]
        )
    )
VAR NegativeReturns =
    FILTER(DailyReturns, [DR] < 0)
RETURN
    STDEVX.P(NegativeReturns, [DR]) * SQRT(252)

Sortino Ratio =
VAR RiskFreeRate = 0.045
RETURN
    DIVIDE(
        [Annualized Return %] - RiskFreeRate,
        [Downside Deviation %]
    )

💡 Nguyên tắc đọc: Sharpe > 1.0 là tốt. Sharpe > 2.0 là rất tốt. Dưới 0 nghĩa là thua tài sản phi rủi ro.


6. Alpha và Beta

Alpha và Beta đo lường gì?

Beta đo mức độ biến động của portfolio so với benchmark. Beta = 1 nghĩa là đi cùng thị trường.

Alpha đo lợi suất vượt trội sau khi đã điều chỉnh theo Beta. Alpha dương = fund manager tạo thêm giá trị.

DAX cho Beta

-- Beta = Cov(Portfolio, Benchmark) / Var(Benchmark)

Portfolio Beta =
VAR N = 252  -- Số ngày tính toán

VAR PortReturns =
    CALCULATETABLE(
        ADDCOLUMNS(
            DATESINPERIOD(DimDate[Date], LASTDATE(DimDate[Date]), -N, DAY),
            "PR", [Daily Portfolio Return %]
        )
    )

VAR BmReturns =
    CALCULATETABLE(
        ADDCOLUMNS(
            DATESINPERIOD(DimDate[Date], LASTDATE(DimDate[Date]), -N, DAY),
            "BR", [Daily Benchmark Return %]
        )
    )

VAR CovPB = -- Simplified covariance
    AVERAGEX(PortReturns, [PR] * RELATED([BR]))
        - AVERAGEX(PortReturns, [PR])
            * AVERAGEX(BmReturns, [BR])

VAR VarBm =
    VARX.P(BmReturns, [BR])

RETURN DIVIDE(CovPB, VarBm)

DAX cho Alpha (Jensen's Alpha)

-- Jensen's Alpha = Rp - [Rf + Beta × (Rm - Rf)]

Jensen Alpha % =
VAR Rf   = 0.045  -- Risk-free rate
VAR Rp   = [Annualized Return %]
VAR Rm   = [Benchmark Annualized Return %]
VAR Beta = [Portfolio Beta]
RETURN
    Rp - (Rf + Beta * (Rm - Rf))

-- Alpha Status
Alpha Status =
IF([Jensen Alpha %] > 0,
    "✅ " & FORMAT([Jensen Alpha %], "+0.00%") & " Outperform",
    "❌ " & FORMAT([Jensen Alpha %],  "0.00%") & " Underperform")

7. Value at Risk (VaR)

VaR đo lường điều gì?

VaR trả lời câu hỏi: trong điều kiện bình thường, danh mục có thể mất tối đa bao nhiêu trong một ngày?

Ví dụ: VaR 95% = 2.5% nghĩa là có 95% khả năng danh mục không mất quá 2.5% trong ngày hôm nay.

DAX cho Historical VaR

-- Historical VaR (Parametric method)
-- VaR = Mean - Z-score × Std Dev

VaR 95% Daily =
VAR DailyReturns =
    CALCULATETABLE(
        ADDCOLUMNS(
            DATESINPERIOD(DimDate[Date],
                LASTDATE(DimDate[Date]), -252, DAY),
            "DR", [Daily Portfolio Return %]
        )
    )
VAR MeanReturn  = AVERAGEX(DailyReturns, [DR])
VAR StdDev      = STDEVX.P(DailyReturns, [DR])
VAR ZScore95    = 1.645  -- Z-score cho 95% confidence
RETURN
    ABS(MeanReturn - ZScore95 * StdDev)

-- VaR 99%
VaR 99% Daily =
VAR ZScore99 = 2.326
-- (Tương tự như trên, thay ZScore95 → ZScore99)
RETURN ABS([Mean] - ZScore99 * [StdDev])

-- VaR theo AUM (số tiền tuyệt đối)
VaR 95% Amount =
[Total Market Value] * [VaR 95% Daily]

DAX cho Maximum Drawdown

-- Maximum Drawdown = Mức giảm tối đa từ đỉnh cao nhất

Max Drawdown % =
VAR PeakValue =
    MAXX(
        FILTER(
            ALL(DimDate[Date]),
            DimDate[Date] <= MAX(DimDate[Date])
        ),
        CALCULATE([Total Market Value])
    )
VAR CurrentValue = [Total Market Value]
RETURN
    DIVIDE(CurrentValue - PeakValue, PeakValue)

⚠️ Lưu ý: VaR parametric giả định return phân phối chuẩn. Với thị trường Việt Nam có nhiều biến động đột ngột, nên kết hợp thêm Historical Simulation VaR.


8. Time Intelligence Measures

Tại sao Time Intelligence quan trọng?

Portfolio Manager luôn so sánh hiệu suất theo nhiều kỳ khác nhau.

Tháng này so với tháng trước. Năm nay so với năm ngoái. Quý này so với cùng kỳ.

DAX Time Intelligence cơ bản

-- AUM tháng trước
AUM Prior Month =
CALCULATE([Total Market Value],
    DATEADD(DimDate[Date], -1, MONTH))

-- MoM Change %
AUM MoM % =
DIVIDE(
    [Total Market Value] - [AUM Prior Month],
    [AUM Prior Month]
)

-- AUM cùng kỳ năm ngoái
AUM Prior Year =
CALCULATE([Total Market Value],
    SAMEPERIODLASTYEAR(DimDate[Date]))

-- YoY Change %
AUM YoY % =
DIVIDE(
    [Total Market Value] - [AUM Prior Year],
    [AUM Prior Year]
)

Rolling Averages

-- Rolling 30-Day Average AUM
AUM MA 30D =
AVERAGEX(
    DATESINPERIOD(DimDate[Date],
        LASTDATE(DimDate[Date]), -30, DAY),
    [Total Market Value]
)

-- Rolling 12-Month Return
Rolling 12M Return % =
VAR EndVal =
    [Total Market Value]
VAR StartVal =
    CALCULATE([Total Market Value],
        DATEADD(DimDate[Date], -12, MONTH))
RETURN DIVIDE(EndVal - StartVal, StartVal)

-- Cumulative Return từ ngày bắt đầu
Cumulative Return % =
DIVIDE(
    [Total Market Value] - [Initial Investment],
    [Initial Investment]
)

9. Tổ Chức Measures Theo Nhóm

Cách đặt tên chuẩn

Naming convention nhất quán giúp tìm measure nhanh hơn nhiều.

Khi model có 50+ measures, cách đặt tên kém có thể mất 10 phút chỉ để tìm đúng measure.

  • Return Metrics: prefix HPR_, TWR_, MWR_
  • Risk Metrics: prefix Risk_, VaR_
  • Benchmark: prefix BM_, Alpha_, Beta_
  • Time Intelligence: suffix _YTD, _MTD, _MoM
  • Display Measures: prefix Disp_ (format sẵn cho visual)

Display Measures — format sẵn cho visual

-- Luôn tạo Display version cho measures dùng trong card/KPI
-- Tránh format trực tiếp trong visual — dễ mất khi model thay đổi

Disp_HPR_YTD =
FORMAT([HPR YTD %], "+0.00%;-0.00%;0.00%")

Disp_Sharpe =
FORMAT([Sharpe Ratio], "0.00")
    & " (" & IF([Sharpe Ratio] >= 1, "Good", "Below Target") & ")"

Disp_VaR_95 =
"VaR 95%: " & FORMAT([VaR 95% Amount], "₫#,##0") & " / ngày"

Disp_Alpha =
IF([Jensen Alpha %] >= 0, "▲ ", "▼ ")
    & FORMAT(ABS([Jensen Alpha %]), "0.00%")

💡 Production tip: Tạo một trang riêng trong report tên "Measure Reference". Liệt kê tất cả measures với mô tả ngắn. Đây là tài liệu cho người maintain sau này.


10. Kết Luận

DAX là ngôn ngữ của Financial Analytics

DAX calculate investment returns Power BI không chỉ là viết công thức.

Đó là khả năng dịch nghiệp vụ tài chính thành logic tính toán chính xác.

Khi measures được viết đúng, mọi visual phía sau đều tự động đúng theo mọi context filter.

Ba điều cốt lõi cần nhớ

  1. Tách riêng Return Metrics và Risk Metrics. Chúng phục vụ hai mục đích khác nhau.
  2. Luôn tạo Display Measures riêng. Không format trực tiếp trong visual settings.
  3. Đặt tên có hệ thống ngay từ đầu. Sửa naming convention sau khi có 50 measures là cơn ác mộng.

Tài liệu tham khảo

Bài viết liên quan tại MCNA


Về tác giả

Triều Đặng — Middle Data Analyst tại MCNA Technology School. Chuyên về financial data analytics, Power BI và automated reporting trong Wealth Management.

MCNA Technology School là đơn vị tiên phong đào tạo AI, Big Data, Business Intelligence, Power BI, Python, SQL tại Việt Nam.

Đối tác đào tạo của 300+ doanh nghiệp: Viettel Global, Masan Group, Techcombank, VPBank, Daikin.

Chỉ mục