Share Notes

chundev

View the Project on GitHub latteouka/share-notes

DCA 階梯式買入的 tier 設計 — 從動態 base 到 tier-once 規則

日期:2026-04-20 情境:槓桿型 ETF 的深跌 DCA 策略設計


TL;DR

設計階梯式 DCA 策略時,三件事要一起決定:tier 倍數結構、base 金額、觸發規則。用固定 base 和「tier 可重複觸發」會導致資金無法掌控(深跌時單筆爆量、重複觸發累積超過帳戶餘額)。改成 「動態 base = 資金 × ratio」+「每個 tier 每週期只能觸發一次」,總投入就變成可預測的 Σ(multipliers) × base,數學上 總倍數 × ratio = 100% 就是 all-in 點。由此推導出清晰的 tier 設計:[1, 2, 3, 4, 5, 8, 10] 總 33x,搭配 3% ratio,最深跌時剛好 all-in。


背景

DCA(Dollar-Cost Averaging)在「深跌買進」策略中常見的變形是階梯式加碼:跌得越深,單筆買越多。常見配置:

tiers: [
  { dropPercent: -5,  multiplier: 1 },
  { dropPercent: -10, multiplier: 2 },
  { dropPercent: -15, multiplier: 4 },
  // ...
  { dropPercent: -50, multiplier: 40 },
]
// 某次買入金額 = baseBuyAmount × 該跌幅對應的 multiplier

乍看合理,但實際回測 + 實盤規劃時會踩到三個坑。


坑 1:固定 base 無法隨資金成長

設計 base=5 萬、maxTotalInvestment=500 萬時,策略最多投入 500 萬。帳戶從 300 萬漲到 3000 萬後,DCA 還是只投 500 萬(佔 17%),嚴重浪費資金。

修法:把 base 改成「當下資金 × ratio」

baseBuyAmount = currentCapital × dynamicRatio

投入規模自動跟著資金膨脹,省去手動調整。


坑 2:同一 tier 可重複觸發 → 資金失控

更深層的問題:engine 判斷買入金額時只看「當下跌幅屬於哪個 tier」,不檢查該 tier 是否已觸發。所以如果市場在 -35% 附近震盪 10 天,每天都會觸發 -35% tier(例如 5x),累積投入 = 50x 基準額

實際歷史案例(標的從高點跌 -50.3% 的那個月):

日期 跌幅 觸發 tier 倍數
D1 -36.9% -35% 5x
D2 -44.2% -40% 8x
D3 -50.3% -50% 20x
D4 -40.3% -40% 8x(重複!)
D5 ~ D13 -34 ~ -39% -35% 5x(重複 8 次!)

13 天總共買了 13 次,累計 multiplier = 87x,而不是「每 tier 一次」的 52x。

以 3% ratio + 1000 萬資金為例:

這種「資金預期無限放大」在回測看不出來(因為 engine 有 maxTotalInvestment 硬上限),但實盤按 marker 操作就會頻頻爆倉。

修法:加入 tier-once 規則

// engine 內部維護 Set,週期開始 reset,觸發過的 tier 記下
const triggeredTiers = new Set<number>();

function getScalingBuyAmount(...) {
  // 找到當前跌幅對應的 tier
  const activeTier = tiers.find(t => dropPct <= t.dropPercent);
  if (!activeTier) return null;

  // 已觸發過,直接略過
  if (triggeredTiers.has(activeTier.dropPercent)) return null;

  return { amount: baseBuyAmount * activeTier.multiplier, ... };
}

// buy 成功後
triggeredTiers.add(activeTier.dropPercent);

// 週期結束(出場時)
triggeredTiers.clear();

效果:同一天可以進場(若是新 tier),但 -35% tier 觸發後就不會在之後的 -35% 震盪時再觸發。


坑 3:tier multiplier 跳太快 → 高 ratio 下提早 all-in

有了 tier-once 後,總投入變可預測:

max 投入 = Σ(multipliers) × base = 總倍數 × capital × ratio

現在要設計 tier,讓「累計投入在最深跌時剛好 ≈ 100% 資金」。數學關係:

all-in at -50% ⟺ 總倍數 × ratio = 100%
ratio 最佳總倍數
1% 100x
2% 50x
3% 33x
5% 20x

舊 tier [1, 2, 4, 7, 11, 16, 25, 40]106x,只適合 1% ratio。拿它配 3% ratio → 理論累計 318%,實際上 -40% 就已經 all-in,深跌 tier 空轉。


解法:tier 結構設計原則

綜合三個修正後的完整設計流程:

1. 先決定預期 ratio

風格 ratio 特點
保守 1% 單筆 1% 資金,需非常深跌才 all-in
標準 3% 平衡,大多數情況
激進 5% 單筆 5%,較早 all-in

2. 計算目標總倍數

目標總倍數 = 100 / (ratio × 100) = 1 / ratio

3% → 33x,5% → 20x。

3. 分配到各 tier

原則:

相鄰 tier 倍數成長比控制在 1.25 ~ 2.0 倍,避免跳太快。

4. 成品範例(3% ratio,總 33x)

tiers: [
  { dropPercent: -20, multiplier: 1 },   // 3%
  { dropPercent: -25, multiplier: 2 },   // 累計 9%
  { dropPercent: -30, multiplier: 3 },   // 累計 18%
  { dropPercent: -35, multiplier: 4 },   // 累計 30%
  { dropPercent: -40, multiplier: 5 },   // 累計 45%
  { dropPercent: -45, multiplier: 8 },   // 累計 69%
  { dropPercent: -50, multiplier: 10 },  // 累計 99% ≈ all-in
]

成長比:2.0, 1.5, 1.33, 1.25, 1.6, 1.25 — 平滑漸增,沒有劇烈跳躍。

單筆最大買入(-50% tier)= 10 × base = 30% 資金,不會一天爆倉。


為何不直接設「總投入上限 = 當下餘額」

這是早期考慮過的方案:讓 engine 在 totalInvested >= capital 時停止買入。結果否決,因為:

  1. 不符合「越跌越買」的心智模型:使用者希望看到「還有剩餘容量」,不是「突然沒訊號」
  2. 最後一筆容易被截半:如果 remaining=21 萬但 tier 想買 266 萬,截到 21 萬之後 ratio 就亂掉
  3. tier-once + 對應 ratio 已經自然解決爆倉問題,加上 cap 是多餘的雙重保護

關鍵洞察:tier 結構 + ratio + tier-once 三者鎖好,不需要額外的資金上限。


學到的事


參考資料