ข้ามไปยังเนื้อหา

ดูต้นฉบับ

BtcSpotDualTimeframeMomentumConfluenceLong

สมมติฐาน

BTC Spot Dual-Timeframe Momentum Confluence, LONG-ONLY 1x (BTCUSDT.BINANCE_SPOT, 4H Primary + 1D Confirm, Long Only When BOTH Timeframes Point UP, FLAT to Cash Otherwise, ATR-Trailing + Daily-Regime-Break Exit, Source-Optimised Parameters Retained)

สมมติฐาน

การพอร์ตแบบ LONG-ONLY, 1x, บัญชี CASH จากกลยุทธ์ที่ผ่านการโปรโมตและมีผลงานดีที่สุดของโรงงาน (BtcDualTimeframeMomentumConfluenceLS, Sharpe 1.99, การเทรด 458 รายการ, +$4,774 ตลอด 29 วันของการเทรดกระดาษ) มาสู่ BTCUSDT.BINANCE_SPOT ซึ่งสร้างขึ้นเฉพาะเพื่อเป็น FIRST LIVE-TRADING CANDIDATE เนื่องจากตลาดจริงเป็น spot-only เท่านั้น กลไกไม่เปลี่ยนแปลง เป็นแบบ pure-OHLCV ตราสารเดียว: ขา FAST = เครื่องหมายของผลตอบแทน trailing 18-bar บนแท่ง 4-HOUR; ขา SLOW = เครื่องหมายของผลตอบแทน trailing 15-bar บนแท่ง DAILY (อ่านผ่าน on_extra_bar เป็นขา context ไม่ใช่ตัว sync barrier) ทั้งสองขาต้อง AGREE การเปลี่ยนแปลงเชิงโครงสร้างเดียวที่บัญชี CASH บังคับให้เกิดขึ้นคือการยุบรวม {LONG/FLAT/SHORT} เข้ากับ {LONG/FLAT}: ในขณะที่ต้นฉบับ futures จะ SHORT เมื่อเกิด joint-down confluence เวอร์ชัน spot จะถือ 100% USDT แทน ส่วนที่เหลือทั้งหมดถูกรักษาไว้ตามต้นฉบับทุกประการ: trailing stop ATR(14) ที่ 3.033x ATR จากจุดสูงสุด/ต่ำสุดที่วิ่งไล่, exit จากการเปลี่ยนแปลง regime รายวัน, การกำหนดขนาดแบบปรับตามความผันผวนและสัมพันธ์กับเงินทุน (risk_pct 1.011% / ระยะ stop 3.033xATR), เพดาน max-notional 49.7% และเวกเตอร์พารามิเตอร์ที่การปรับให้เหมาะสมของต้นฉบับเลือกไว้แบบเดียวกันทุกประการ (fast_lookback 18, slow_lookback 15, trail_atr_mult 3.033) มีตัวปรับแต่งได้ (tunables) สามตัว ไม่มีข้อมูลเสริม ไม่มี short ไม่มี leverage การเปลี่ยนแปลงโค้ดเฉพาะสำหรับ spot: ตลาด BINANCE_SPOT CASH (ไม่มีตัวคูณ leverage ใน position_size), size_precision 5 / price_precision 2, min_notional $10 คำสั่งขายถูกกำหนดขนาดตามปริมาณ base ที่ถืออยู่เท่านั้น ข้อมูลที่ตรวจสอบแล้วว่ามีอยู่จริง: แท่ง BTCUSDT.BINANCE_SPOT 4-HOUR และ 1-DAY รันต่อเนื่องตั้งแต่ 2017-08-17 (ประมาณ 9 ปี, ประมาณ 19,800 แท่ง 4H)

สมมติฐาน

เป็นการพอร์ตโดยตรงจากกลยุทธ์ต้นฉบับ futures ที่ผ่านการโปรโมตแล้ว BtcDualTimeframeMomentumConfluenceLS มาสู่ตลาด spot เนื่องจากตลาดที่ตั้งใจใช้งานจริงเป็น spot-only เท่านั้น กลไกถูกรักษาไว้ตามต้นฉบับทุกประการ: ขาโมเมนตัมสองขาแบบเดียวกัน, เกท AGREE-หรือ-flat แบบเดียวกัน, trailing stop แบบ ATR(14) 3.033x จากจุดสูงสุด/ต่ำสุดที่วิ่งไล่แบบเดียวกัน, exit จากการเปลี่ยนแปลง regime รายวันแบบเดียวกัน, การกำหนดขนาดโดยปรับตามความผันผวน risk_pct / ระยะ stop-distance พร้อมเพดาน notional 49.7% แบบเดียวกัน และเวกเตอร์พารามิเตอร์ที่การปรับให้เหมาะสมของต้นฉบับเลือกไว้แบบเดียวกันทุกประการ (fast_lookback 18, slow_lookback 15, trail_atr_mult 3.033) บัญชี CASH บังคับให้เกิดการเปลี่ยนแปลงเชิงโครงสร้างเพียงจุดเดียวตามที่สมมติฐานระบุไว้: {LONG,FLAT,SHORT} ยุบรวมเหลือ {LONG,FLAT} — should_enter คืนค่า BUY เฉพาะกรณี joint-up และ None ในกรณีอื่น ดังนั้น joint-down จะกลายเป็น 100% USDT แทนที่จะเป็นการ short การแก้ไขเฉพาะสำหรับ spot: ตลาด BINANCE_SPOT ด้วย leverage 1.0 และไม่มีเทอม leverage ใน position_size, size_precision 5 / price_precision 2 (BTCUSDT spot), min_notional ปรับขึ้นเป็น $10 และ exit ทั้งหมดถูกส่งผ่าน reduce-only close_position ของเทมเพลตฐาน ดังนั้น SELL จะสามารถลดปริมาณ base ที่ถืออยู่เท่านั้น (การ short spot แบบ naked เป็นไปไม่ได้โดยโครงสร้าง และ guard _would_open_spot_short ของเทมเพลตฐานจะไม่ถูกกระตุ้นเลย) calculate_signal คืนค่าผลตอบแทน 18-bar 4H แบบต่อเนื่องในทุกแท่ง (ค่าเปลี่ยนแปลงในแต่ละแท่ง) ส่วนเกทการยืนยันแบบไม่ต่อเนื่องอยู่ใน should_enter ตามที่กำหนด ต้นทุนต่อแท่งคือ O(1): ATR ใช้หน้าต่างขนาดคงที่ 15-bar และผลตอบแทน fast เป็นการ lookup แบบระบุ index เดียว จึงไม่มีงานที่ scale ตามประวัติข้อมูล ข้อควรระวังที่ควรบอกนักวิเคราะห์อย่างตรงไปตรงมา: ต้นทุน round-trip ของ spot อยู่ที่ประมาณ 0.20% เทียบกับประมาณ 0.10% ของต้นฉบับ futures ดังนั้นความได้เปรียบต่อการเทรดต้องเอาชนะแรงเสียดทานเป็นสองเท่า — โครงสร้าง exit แบบ trend-following (trail + regime break โดยไม่มี take-profit แบบตายตัว) คือสิ่งที่ทำให้ระยะเวลาถือครองเฉลี่ยนานพอที่จะเป็นไปได้ แต่ก็เป็นตัวชี้วัดที่ควรจับตาดูเป็นอันดับแรก

การนำไปใช้

LONG-ONLY 1x BTCUSDT spot (BINANCE_SPOT, CASH) การยืนยันโมเมนตัมสองกรอบเวลา ขา FAST = เครื่องหมายของผลตอบแทน trailing 18-bar บนแท่ง 4-HOUR (primary); ขา SLOW = เครื่องหมายของผลตอบแทน trailing 15-bar บนแท่ง 1-DAY ซึ่งถูกใช้งานผ่าน on_extra_bar เป็นขา context ของกรอบเวลาที่ช้ากว่า (คนละกรอบเวลา ดังนั้น cross-leg alignment barrier ของเทมเพลตฐานจึงไม่มีวันเลื่อนสัญญาณ 4H ออกไป) ทั้งสองขาต้องชี้ UP เพื่อให้ถือ BTC; joint-down (จุดที่ต้นฉบับ futures จะ short) และกรณีที่ไม่ตรงกันทั้งคู่หมายถึงการถือ 100% USDT Exit: trailing stop ATR(14) ที่ 3.033x ATR ต่ำกว่าจุดสูงสุดที่วิ่งไล่ของโพซิชัน, OR เมื่อขารายวันพลิกลงภายใต้สถานะ long (การเปลี่ยนแปลง regime ในกรอบเวลาที่สูงกว่า) การกำหนดขนาดปรับตามความผันผวนและสัมพันธ์กับเงินทุน: equity * 1.011% / (3.033 * ATR) โดยมีเพดานอยู่ที่ 49.7% ของยอดคงเหลือ USDT ในรูปแบบ notional พร้อมตัวคูณ leverage NO (บัญชี CASH ไม่สามารถกู้ยืมได้) ปัดเศษเป็น size_precision 5 และถูกปฏิเสธหาก notional ต่ำกว่าขั้นต่ำของ spot ที่ $10 มีตัวปรับแต่งได้ (tunables) สามตัว เป็นแบบ pure OHLCV ไม่มีข้อมูลเสริม ไม่มี short

ผลการตรวจสอบ

ให้ใช้ self._atr (ค่าปัจจุบัน) ในการเปรียบเทียบ trail ของ should_exit เพื่อให้ตรงกับต้นฉบับทุกประการ หรือระบุอย่างชัดเจนในคำอธิบายว่า trail ถูกยึดกับ ATR ของแท่งที่เข้าเทรด เพื่อไม่ให้นักวิเคราะห์เข้าใจผิดว่าความแตกต่างจากต้นฉบับเกิดจากการเปลี่ยนตลาด

ผลการตรวจสอบ

ATR ของ trailing stop คือ FROZEN ที่จุดเข้าเทรด (self._entry_atr ที่ถูกบันทึกไว้ใน should_enter / เมื่อรับโพซิชัน) และไม่เคยถูกรีเฟรชอีก ดังนั้นระยะ trail จึงเป็น 3.033 x ATR-ที่จุดเข้าเทรด แทนที่จะเป็น 3.033 x ATR(14) ปัจจุบัน ต้นฉบับ futures ที่ผ่านการโปรโมตแล้ว (BtcDualTimeframeMomentumConfluenceLS4H) จะปรับ trail ตาม CURRENT ATR ในทุกแท่ง ถ้อยคำของสมมติฐาน ('trailing stop แบบ ATR(14) ที่ 3.033x ATR จากจุดสูงสุด/ต่ำสุดที่วิ่งไล่') ได้รับการตอบสนองในทั้งสองกรณี และเนื่องจาก _extreme เป็นแบบ monotone ระดับ stop จึงยังคงปรับขึ้นได้เพียงทางเดียว จึงไม่ถือเป็นข้อบกพร่องด้านความถูกต้อง — แต่เมื่อความผันผวนขยายตัวหลังจากเข้าเทรด stop ที่ใช้งานจริงจะแคบกว่าของต้นฉบับ ซึ่งเป็นความแตกต่างเชิงพฤติกรรมที่แท้จริงจากกลยุทธ์ที่อ้างว่าพอร์ตมาแบบ 'ตามต้นฉบับทุกประการ'

ผลการตรวจสอบ

กำหนดสถานะการเทรดจากการ fill (on_order_filled / แท่งแรกที่มีโพซิชันเปิดอยู่) แทนที่จะทำภายใน should_enter หรือรีเซ็ตแบบป้องกันไว้ก่อนที่ด้านบนของ calculate_signal ก่อนการ lookup โพซิชัน

ผลการตรวจสอบ

should_enter() เปลี่ยนแปลงสถานะการเทรด (_in_long = True, _extreme, _entry_atr) BEFORE ที่เทมเพลตฐานได้กำหนดขนาดคำสั่งและใช้เกท min-notional แล้ว หาก position_size() คืนค่า 0 หรือการตรวจสอบ min-notional ที่ $10 ทำให้คำสั่งเข้าถูกดรอปไป กลยุทธ์จะยังคงถูกตั้งค่าสถานะว่าอยู่ใน-long พร้อม trail ที่ถูกเตรียมไว้ ทั้งที่ไม่มีโพซิชันจริง ในทางปฏิบัติสิ่งนี้จะแก้ไขตัวเองได้ในแท่งถัดไป (calculate_signal เห็นว่าโพซิชันเป็น None และรีเซ็ตแฟล็ก และ should_exit จะไม่ถูกเรียกใช้เลยขณะไม่มีโพซิชัน) จึงไม่มีบั๊กเชิงพฤติกรรมที่สังเกตเห็นได้ — แต่ invariant นี้เปราะบางหากมีการเปลี่ยนแปลงเส้นทาง exit ในอนาคต

ผลการตรวจสอบ

ไม่จำเป็นต้องแก้ไขเพื่อความถูกต้อง หากต้องการให้การนำไปใช้ในแท่งเดียวกันเป๊ะ ให้คำนวณ _slow_dir แบบ lazy ใหม่จาก self._extra_bars[...] ภายใน calculate_signal แทนการแคชไว้ใน on_extra_bar

ผลการตรวจสอบ

ความหน่วงหนึ่งแท่งบนขารายวัน: แท่ง DAILY และแท่งสุดท้ายของวันที่ 4H มี timestamp ปิดร่วมกัน หากเอนจินส่งแท่งหลัก 4H มาก่อน _maybe_process_primary() จะรันและประทับ _last_processed_ts และการอัปเดต _slow_dir ของแท่งรายวัน (ที่มาถึงพร้อม ts เดียวกัน) จะถูกนำไปใช้เฉพาะจากแท่ง NEXT 4H เท่านั้น ลักษณะนี้เป็นแบบระมัดระวัง (สามารถทำให้สัญญาณล่าช้าได้เท่านั้น ไม่มีทางรั่วไหลข้อมูลอนาคต) แต่หมายความว่า exit จากการเปลี่ยนแปลง regime รายวันอาจเกิดขึ้นช้ากว่าการปิดรายวันได้ถึง 4 ชั่วโมงในประมาณครึ่งหนึ่งของกรณี และความสอดคล้องระหว่าง backtest กับการเทรดกระดาษขึ้นอยู่กับลำดับการส่งข้อมูลที่ต้องคงที่

ผลการตรวจสอบ

การนำไปใช้งานเป็นไปอย่างซื่อตรงตามต้นฉบับ แต่มีสามประเด็นที่นักวิเคราะห์ควรพิจารณาบนประวัติข้อมูลแบบเต็ม: (1) ต้นทุนไปกลับ (round-trip) ของ spot อยู่ที่ประมาณ 0.20% เทียบกับประมาณ 0.10% ของกลยุทธ์ต้นฉบับที่เป็น futures ดังนั้นความได้เปรียบขั้นต้นเท่ากันแต่ผลสุทธิจะลดลงเกือบครึ่งหนึ่ง — sandbox แสดงค่าคอมมิชชันอยู่ที่ 10.03% ของยอดขั้นต้นแล้ว; (2) เวกเตอร์พารามิเตอร์ (fast 18 / slow 15 / trail 3.033) ถูกเลือกจากการรันการปรับให้เหมาะสมบนตลาด DIFFERENT, กรอบเวลา และชุดทิศทางที่ต่างออกไป (LONG/SHORT futures) ดังนั้นนี่คือการถ่ายโอนแบบ out-of-sample ไม่ใช่การตั้งค่าที่ผ่านการปรับให้เหมาะสมแล้ว — Sharpe ของ sandbox อยู่ที่ 0.527 โดยมี sharpe_ci_low -0.233 และ information_ratio -0.760 เทียบกับ benchmark กล่าวคือเป็นพอร์ต BTC แบบ long-only ที่ด้อยกว่าการถือ BTC ในช่วง smoke window; (3) การตัดขา short ออกทำให้เสียกลุ่มการเทรดของต้นฉบับไปเกือบครึ่งหนึ่ง (250 การเทรด ล้วนเป็น long, 43.6% exposure) ดังนั้นควรคาดว่า Sharpe ที่เกิดขึ้นจริงจะต่ำกว่าของต้นฉบับที่ 1.99 อย่างมีนัยสำคัญ ไม่ใช่ใกล้เคียงกัน สิ่งแรกที่ควรตรวจสอบใน backtest จริง: avg_trade_return_pct เทียบกับพื้นต้นทุนขั้นต่ำของ spot ที่ 0.25% (sandbox แสดง 0.82% แต่ช่วงเวลานั้นไม่รวม 2017 และมีเพียง 2401 วันเท่านั้น) และว่ากลุ่ม tercile ความผันผวนระดับ 'ปกติ' (-8.77% ใน sandbox) ยังคงเป็นลบตลอดประวัติข้อมูลแบบเต็มหรือไม่

ทบทวนผลทดสอบย้อนหลัง

การเทรดที่ปิดแล้ว 314 รายการ ในช่วง 3146 วัน (2017-08 → 2026-03), metrics_reliable=true, ส่งคำสั่งเข้า entry_diag 314/314 รายการ โดยถูกดรอปไป 0 รายการ

ทบทวนผลทดสอบย้อนหลัง

การเทรดสอดคล้องกับสมมติฐาน: ทั้งหมดเป็น 314 LONG / 0 short (การยุบรวม CASH ของ LONG/FLAT/SHORT ต้นฉบับถูกต้อง), max notional/equity 0.50 เทียบกับเพดาน 0.497, ระยะเวลาถือครองเฉลี่ย 4d8h และ 43.6% exposure สะท้อนต้นฉบับ futures

ทบทวนผลทดสอบย้อนหลัง

avg_trade_return_pct 1.20% เทียบกับต้นทุน round trip ของ BINANCE_SPOT ที่ประมาณ 0.20%; ค่าคอมมิชชันเป็นเพียง 8.97% ของยอดขั้นต้น ผลกระทบ 4.33% — ไม่ได้อยู่ในระดับก้ำกึ่งเรื่องค่าธรรมเนียม

ทบทวนผลทดสอบย้อนหลัง

max_drawdown 10.3% (ภายใต้ค่าเริ่มต้นของ spot 15%), PF 1.41, payoff 2.07 บนอัตราชนะ 40.4% (รูปแบบเทรนด์ถูกต้อง), tercile ความผันผวนที่ถูกกดดัน +28.0%

ทบทวนผลทดสอบย้อนหลัง

ความกระจุกตัวสูงมาก: การเทรด top 10 จาก 314 รายการ = 93.8% ของผลตอบแทนสะสมต่อการเทรด, top 20 = 141% (การเทรดลำดับที่ 21–314 เป็นลบสุทธิ)

ทบทวนผลทดสอบย้อนหลัง

มีเพียง 6/10 ปีปฏิทินที่เป็นบวก — ซึ่งอยู่ที่ขีดจำกัดขั้นต่ำพอดี — และทั้งสองปีล่าสุดเป็นลบ (2025 −10.5%, 2026 −9.9%)

ทบทวนผลทดสอบย้อนหลัง

Sharpe 0.664 โดยมี sharpe_ci_low 0.0042 และ PSR 0.924 (<0.95): อยู่ในระดับก้ำกึ่งอยู่แล้วก่อนที่จะผ่านขั้นตอนการคัดเลือกจากการทดลองประมาณ 225 ครั้ง

ทบทวนผลทดสอบย้อนหลัง

ข้อกังวลของ QA ได้รับการยืนยันบางส่วน: กลุ่ม tercile ความผันผวนระดับ 'ปกติ' ยังคงเป็นลบ (−7.70%, 16.1% DD), information_ratio −0.757, alpha เพียง +2.4%/ปี — ด้อยกว่าการถือ BTC และเนื่องจาก benchmark_meaningful=true ส่วนต่างที่ขาดหายไปนี้จึงเป็นเรื่องจริง

ทบทวนผลทดสอบย้อนหลัง

พารามิเตอร์เป็นการถ่ายโอนแบบ out-of-sample จากตลาด/ชุดทิศทางอื่น — ไม่ใช่การ overfit แต่ก็ยังไม่เคยผ่านการทดสอบในบริบทนี้
รายงานกลยุทธ์

Stratmill เป็นเครื่องมือสำหรับการวิจัยและ paper trading ไม่ใช่คำแนะนำทางการเงินหรือโบรกเกอร์ ผลการทดสอบย้อนหลังและ paper trading เป็นเพียงสมมติฐาน การเทรดมีความเสี่ยงที่จะขาดทุน