跳到主要內容

AI coding - Pine Script - 定期定額DCA年化報酬率XIRR


最近在嘗試用AI學習寫程式,想不到我這個coding能力很弱的資訊系逃兵,在有生之年還能和AI家教學習寫程式,真的是非常感動啊😍

以下是用AI寫的一個小工具,計算每月定期定額投資1萬元在指定的標的上,所能夠得到的年化報酬率結果。對於想要參與「金雞計劃」的朋友,就可以用這個工具來實測投資標的以往的績效,作為未來的參考。

我用的是TradingView pine script v6,有興趣的朋友可以複製以下的程式碼測試看看(若有疏漏謬誤之處也歡迎指教)

//@version=6
strategy("定期定額 DCA", overlay=true, initial_capital=0, currency=currency.USD, calc_on_order_fills=true, calc_on_every_tick=true)

//------------------------------------------------------------------
// 使用者輸入:設定投資的開始與結束日期
// 請依 ISO-8601 格式輸入 (例如 "2020-01-01T00:00:00")
//
// 注意:本策略僅於 startDate ~ endDate 區間內進行定期定額投資
//------------------------------------------------------------------
startDate = input.time(timestamp("2010-01-01T00:00:00"), "Start Date")
endDate   = input.time(timestamp("2024-12-31T23:59:59"), "End Date")

//------------------------------------------------------------------
// 定義 XIRR 函數:根據現金流及其發生時間,利用二分法求解 IRR
// XIRR 公式: Σ[ CF[i] / (1 + r)^((t[i]-t0)/365) ] = 0
//------------------------------------------------------------------
f_xirr(_flows, _times) =>
    n = array.size(_flows)
    if n < 2
        na
    else
        rLow = -0.99
        rHigh = 10.0
        // 以 50 次迭代達到足夠精度
        for i = 0 to 50
            rMid = (rLow + rHigh) / 2.0
            npv = 0.0
            t0 = array.get(_times, 0)
            for j = 0 to n - 1
                cf = array.get(_flows, j)
                t  = array.get(_times, j)
                // 將毫秒轉換為天數 (1 天 = 86,400,000 毫秒)
                days = (t - t0) / 86400000.0
                npv += cf / math.pow(1 + rMid, days / 365.0)
            if npv > 0
                rLow := rMid
            else
                rHigh := rMid
        (rLow + rHigh) / 2.0

//------------------------------------------------------------------
// 宣告全域變數:用來記錄每次投資的現金流與時間、累計買進的股數以及總投入金額
//------------------------------------------------------------------
var float[] cashFlows    = array.new_float()
var int[]   cashFlowTimes = array.new_int()
var float   totalShares   = 0.0
var float   totalInvested = 0.0

// 用來確保僅在設定期間結束後首次計算 XIRR 與累積報酬率
var bool computedResults = false

//------------------------------------------------------------------
// 判斷是否為新月份的第一根 K 線(month open)
// ta.change(time("M")) 回傳數值,需與 0 比較取得布林值
//------------------------------------------------------------------
is_new_month = ta.change(time("M")) != 0

//------------------------------------------------------------------
// 每月定期定額投資 10000 元:僅在使用者設定的期間內進行
//------------------------------------------------------------------
if is_new_month and time >= startDate and time <= endDate
    shares_to_buy = 10000 / open
    totalShares += shares_to_buy
    totalInvested += 10000
    // 記錄投入的現金流(支出以負值表示)
    array.push(cashFlows, -10000)
    array.push(cashFlowTimes, time)
    // 下單買入(strategy.entry 便於在策略測試器中觀察交易)
    strategy.entry("Buy", strategy.long, qty = shares_to_buy)

//------------------------------------------------------------------
// 當 bar 的時間大於或等於使用者設定的結束日期,且尚未計算結果時:
// 1. 計算最終組合價值 (持有股數 * 當前收盤價)
// 2. 加入正向現金流並計算 XIRR
// 3. 計算總累積報酬率 = (最終組合價值 - 總投入金額) / 總投入金額 * 100%
// 4. 利用 label 顯示結果
//------------------------------------------------------------------
if not computedResults and time >= endDate
    finalValue = totalShares * close
    array.push(cashFlows, finalValue)
    array.push(cashFlowTimes, time)
    irr = f_xirr(cashFlows, cashFlowTimes)
    computedResults := true
   
    // 總累積報酬率 (%)
    cumulativeReturn = (finalValue - totalInvested) / totalInvested * 100.0

    // 顯示 XIRR,轉換為百分比格式
    label.new(bar_index, high, text="XIRR: " + str.format("{0,number,#.##}%", irr * 100), style=label.style_label_up, color=color.green, textcolor=color.white)
   
    // 顯示總累積報酬率
    label.new(bar_index, high * 0.95, text="累積報酬率: " + str.format("{0,number,#.##}%", cumulativeReturn), style=label.style_label_up, color=color.blue, textcolor=color.white)

留言

這個網誌中的熱門文章

讀書心得:超級績效

超級績效:金融怪傑交易之道 Trade like a Stock Market Wizard https://www.books.com.tw/products/0010673733 作者 Mark Minervini 【第二章 必要知識】 我做了一項關鍵決策,使讓自己的績效從平凡踏入傑出,我開始 迅速認賠 ,盡可能保障大部分資本,我覺得自己又掌握了控制權。這種新的態度,讓我能客觀分析自己的表現。過去我總是忽略失敗經驗,現在我願意從失敗中汲取教訓。交易並不是要判斷價格的高低點,也不是要證明自己有多精明,而是為了 賺錢 !不要把交易和自尊搞在一起!重點是 賺錢 ,面子不重要。 當你發現在某些市場期間,自己的交易風格表現的優於其他風格,就表示你的交易風格可能不適合其他市場期間,沒有人可以同時是價值投資人又是成長交易者,或者同時是長期投資人又是短線當沖客,想成為某個領域的頂尖,就必須專精、 專注 ! 剛開始做股票時,我連續六年沒有賺錢,現在我一星期賺的錢,甚至超過許多人的年收入。大膽放手追求你想要的,雖然會碰到一些挫敗、失望和慘澹的時光。請擁抱這一切,把他們當作珍貴過程的一部分,學著說「感謝你,老師」!對於失敗,請不要覺得懊惱, 絕不要讓慘澹經歷打倒你 ! 【第四章 價值的價格】 價值不會驅動股價,行情是由人們下單造成的,價值只代表一部分,最終還是取決於供需。只有價值感能影響人們買進,如果沒人願意買,再優質的股票也只是一張紙。 本益比與超級強勢股之間顯然不存在任何適當數據,我建議根本不要理會本益比,直接尋找盈餘成長潛能最高股票。 【第五章 順勢交易】 我希望看到股票 吸引大型機構買盤 ,我不必當第一個到場的客人,但我要確定宴會如期舉行。 股價四階段:整理、上升、做頭、下跌 我並不是要以最低價買進,而是要以正確的價格買進,也就是股價正要大幅走高前,猜測底部是沒必要的,我們必須鎖定「第二階段」上升趨勢。 第二階段特徵: 1、股價高於200日均線 2、200日均線處於上升趨勢 3、150日均線高於200日均線 4、股價處於明顯階梯式上升趨勢 5、短均線位於長均線之上 (多頭排列) 6、價漲量增、價跌量縮 【第九章 追隨領導股】 市場領導股通常會領先上漲,等到大盤明顯起漲時,領導股往往已經創52週...

不看盤,每年輕鬆賺20%

月入22K的新鮮人,如何 提高每月投資自己的金額,降低財務自由的門檻,同時學習不看盤獲利20%的方法,設定財務自由的目標...讓豬力安按部就班告訴您 !

豬力安的台股統計

  資料來源:公開資訊觀測站,豬力安整理。