← กลับไปยังบทความ
July 2, 2026
อ่าน 5 นาที

การออกแบบ Objective Function: ตัวชี้วัดที่คุณ Optimize แอบเลือกกลยุทธ์ให้คุณ

การออกแบบ Objective Function: ตัวชี้วัดที่คุณ Optimize แอบเลือกกลยุทธ์ให้คุณ
#algotrading
#backtest
#overfitting
#objective function
#optimization
#sharpe
#การตรวจสอบ
🎯
Part 1 of 7 · Collection
Backtesting Without Fooling Yourself

เป็นส่วนหนึ่งของซีรีส์ "Backtests Without Illusions"

📄 บทความนี้ขยายกลายเป็นเปเปอร์วิจัย ตัวเลขทุกตัวด้านล่างมาจากสคริปต์ deterministic ตัวเดียวที่สร้าง ground truth ที่ควบคุมได้ — ตลาด synthetic ที่มี edge ที่ รู้ค่า อยู่ในย่านสัญญาณระดับกลางและมี noise แบบ fat-tailed อยู่ทุกที่ — แล้วรัน threshold search หนึ่งครั้งภายใต้ objective function หกแบบที่ต่างกัน และวัด out of sample ว่าแต่ละ objective เลือกกลยุทธ์ไหนจริง ๆ อ่านเปเปอร์ฉบับเต็มออนไลน์ (เวอร์ชันอินเทอร์แอกทีฟ + PDF) ได้ที่ objective-design.marketmaker.cc โค้ดและข้อมูลอยู่ที่ github.com/suenot/objective-design-degeneracy

คุณต้องการกลยุทธ์ที่ ดีที่สุด ดังนั้นคุณจึงรัน search: กวาดค่า threshold หนึ่งตัว, lookback หนึ่งตัว, stop distance หนึ่งตัว แล้วเก็บค่าที่ทำคะแนนได้สูงสุดไว้ การค้นหาเสร็จสิ้นแล้วมอบผู้ชนะให้คุณ ฟังดูสมเหตุสมผล เป็นมาตรฐาน มันคือสิ่งที่ optimizer, grid search และ hyperparameter tuner ทุกตัวบนโลกนี้ทำ

แต่ลองดูคำกริยา: ทำคะแนนได้สูงสุด สูงสุดในอะไร? ก่อนที่การค้นหาจะสวมมงกุฎให้ใครได้ คุณต้องมอบตัวเลขตัวเดียวให้มัน maximize ก่อน — objective function ตัวหนึ่ง PnL, Sharpe, Sharpe-บนแท่งที่คุณเทรด, Return-over-max-drawdown คุณพิมพ์หนึ่งในนี้ลงไป อาจจะโดยไม่ได้คิดอะไรมากนัก แล้วการค้นหาก็ใช้การประเมินนับล้านครั้งทำในสิ่งที่คุณขอเป๊ะ ๆ

ทางเลือกนั้นไม่ใช่แค่พิธีการ มันคือการตัดสินใจทั้งหมด การค้นหาไม่ได้หา "กลยุทธ์ที่ดี" — ไม่มีสิ่งนั้นอยู่ในเชิงนามธรรม มันหากลยุทธ์ที่ maximize สเกลาร์ที่คุณเลือก และสเกลาร์ต่างกันชี้ไปที่กลยุทธ์ที่ต่างกันโดยสิ้นเชิงบนข้อมูลชุดเดียวกัน objective คือมือลับที่กุมพวงมาลัย และส่วนใหญ่ไม่มีใครมองมันเลย

นี่คือบทความทั้งหมดในตารางเดียว: threshold search หนึ่งครั้ง, ตลาด synthetic หนึ่งตลาดที่มี edge จริงที่รู้ค่า, objective หกแบบ — และกลยุทธ์หกแบบที่พวกมันเลือก วัดบนข้อมูล held-out:

Objective (สิ่งที่การค้นหา maximize) Market exposure เฉลี่ย In-sample Sharpe Out-of-sample Sharpe ผู้ชนะที่ Degenerate
Raw PnL 0.859 1.76 1.61 0%
Full-timeline Sharpe 0.740 1.82 1.71 0%
Per-trade ("active") Sharpe 0.286 1.00 0.70 57%
Exposure floor (emin=0.20e_{\min}=0.20) 0.740 1.82 1.71 0%
Trade-count shrinkage (conf_k=40=40) 0.523 1.54 1.31 20.7%
Robust (floor + conf_k) 0.675 1.78 1.70 0.2%

600 seed ที่เป็นอิสระต่อกัน, T=2000T = 2000 แท่งต่อ seed, 80 threshold ที่เป็นตัวเลือกต่อการค้นหาหนึ่งครั้ง, in-sample และ out-of-sample ถูกดึงมาอย่างเป็นอิสระต่อกัน Sharpe ต่อปี (252 period/ปี) "Degenerate" = ผู้ชนะที่ถูกเลือกอยู่ในตลาดน้อยกว่า 5% ของเวลา หรือทำ out-of-sample Sharpe ที่ไม่เป็นบวก จุดที่เหมาะสมที่สุดที่แท้จริงของตลาดนี้คือ out-of-sample Sharpe ต่อปีที่ 1.77

อ่านแถวที่สามจนกว่ามันจะแสบ per-trade Sharpe — ตัวแทนของตระกูล activity-conditional metric ทั้งหมด (per-trade Sharpe, expectancy, van Tharp's SQN, win rate) ที่คำนวณบนเฉพาะแท่งที่คุณเทรดเท่านั้น — เลือกกลยุทธ์ที่แย่กว่าครึ่งหนึ่งของตัวอื่น ๆ นอก sample และทำแบบ degenerate 57% ของเวลา มันไม่ใช่ objective ที่แย่กว่าเล็กน้อย บนข้อมูลนี้มันคือกับดัก และการค้นหาเดินเข้าไปในนั้นมากกว่าครึ่งหนึ่งของเวลา ทีนี้อ่านแถวที่อยู่ด้านบนมัน: full-timeline Sharpe ธรรมดา ไม่เคย degenerate เลยและทำคะแนนได้ 1.71 นอก sample นั่นคือจุดไคลแม็กซ์ของการซ่อมแซมทั้งหมด สปอยล์ไว้ตั้งแต่ต้น — การแก้ไขที่ซื่อสัตย์คือแค่วัดบน full timeline; การซ่อมแซมที่ซับซ้อนกว่าในแถวด้านล่าง อย่างดีที่สุดก็แค่เท่ากับตัวเลขนั้น ไม่เคยเอาชนะมันได้เลย บทความนี้คือกายวิภาคของกับดักนั้นและวิธีแก้ไข โดยที่ ground truth เป็นที่รู้ตลอดทั้งเรื่อง ดังนั้นคำถามที่ว่า "objective เลือกกลยุทธ์ที่ถูกต้องหรือไม่?" จึงเป็นข้อเท็จจริง ไม่ใช่ความเห็น

Act 1 — การตัดสินใจลับ: กฎของ Goodhart คือตัวการค้นหา

parameter search ที่วาดเป็นกรวยของเส้นกราฟกลยุทธ์ผู้ท้าชิงจำนวนมาก โดยมีเลนส์เดียวที่ติดป้าย OBJECTIVE ประทับตราเส้นหนึ่งให้เป็นผู้ชนะ ขณะที่เส้นที่มีหน้าตาเหมือนกันถูกทิ้งไป แสดงให้เห็นว่าการเลือกตัวชี้วัดเป็นผู้เลือกกลยุทธ์อย่างเงียบ ๆ

ในปี 1975 นักเศรษฐศาสตร์ Charles Goodhart เขียนประโยคหนึ่งที่อยู่ยั่งยืนกว่าผลงานอื่นทั้งหมดของเขา:

"กฎเกณฑ์ทางสถิติที่สังเกตได้ใด ๆ มีแนวโน้มที่จะล่มสลายเมื่อมีแรงกดดันถูกวางลงบนมันเพื่อวัตถุประสงค์ในการควบคุม"

การถอดความที่นิยม ซึ่งมักให้เครดิตกับ Marilyn Strathern นั้นกระชับกว่า: เมื่อตัววัดกลายเป็นเป้าหมาย มันก็หยุดเป็นตัววัดที่ดี

parameter search คือตัวอย่างที่บริสุทธิ์ที่สุดของกฎ Goodhart objective function คือตัววัด การค้นหาคือแรงกดดัน — ความพยายามนับพันนับล้านครั้งที่ผลักตัววัดนั้นให้สูงที่สุดเท่าที่จะทำได้ และการค้นหาไม่สนใจเลยแม้แต่น้อยว่าคุณตั้งใจอะไรด้วยตัววัดนั้น มันสนใจแค่ตัวเลข ถ้ามีทางใดที่จะทำให้ตัวเลขใหญ่ขึ้นได้โดยไม่เกี่ยวอะไรกับ edge จริงที่เทรดได้เลย — เทรดน้อยครั้ง อยู่เฉย ๆ ส่วนใหญ่ แล้วจับ outlier ที่โชคดีสองสามตัว — การค้นหาจะพบทางนั้น เพราะการหาค่าสูงสุดคือสิ่งเดียวที่มันถูกสร้างมาให้ทำ

นี่คือความล้มเหลวแบบเดียวกับที่วรรณกรรมด้าน AI-safety เรียกว่า reward hacking: agent ที่ optimize proxy สำหรับสิ่งที่คุณต้องการ จะใช้ประโยชน์จากทุกช่องว่างระหว่าง proxy กับเป้าหมายจริง การค้นหาของคุณคือ agent ตัวนั้น "Sharpe ratio" คือ proxy ตัวนั้น "กลยุทธ์ที่ฉันไว้ใจได้ให้เทรดเงินจริงในไตรมาสหน้า" คือเป้าหมาย ช่องว่างระหว่างทั้งสองคือที่ที่ทั้งวินัยนี้อาศัยอยู่

เพื่อดูช่องว่างนั้นเปิดออก เราต้องมีโลกที่เรารู้ความจริง ดังนั้นเราจึงสร้างมันขึ้นมา

ตลาด ในแต่ละ period ตัวทำนาย sts_t (สัญญาณแบบ standard-normal) จะมาถึง ตามด้วยผลตอบแทน rtr_t ที่มันทำนายได้บางส่วน edge เป็นของจริงแต่มีขอบเขต — มันมีอยู่แค่ภายในย่านสัญญาณระดับกลาง st1|s_t| \le 1 และหายไปนอกย่านนั้น:

rt=βst1[st1]+εt,β=0.3,εtt4 (unit variance).r_t = \beta\, s_t \cdot \mathbf{1}\big[\,|s_t| \le 1\,\big] + \varepsilon_t, \qquad \beta = 0.3, \qquad \varepsilon_t \sim t_{4}\ (\text{unit variance}).

ทางเลือกเชิงออกแบบสองอย่างสำคัญ อย่างแรก edge อยู่ในย่านระดับกลาง: สัญญาณสุดขั้วไม่มีข้อมูลเชิงทำนายเลย ดังนั้นกลยุทธ์ควรเทรดตรงกลางและข้าม tail ไป อย่างที่สอง noise εt\varepsilon_t เป็นแบบ fat-tailed (Student-tt ที่มี 4 degrees of freedom ซึ่งเป็นแบบ tail หนักที่ผลตอบแทนจริงมีอยู่จริง) — แต่ส่วนผสมนี้อยู่ที่นี่เพื่อความสมจริง ไม่ใช่กลไก มันน่าดึงดูดใจที่จะบอกว่า fat tail คือสิ่งที่ทำให้กับดักเกิดขึ้นได้ และเราสมมติแบบนั้นเป๊ะจนกระทั่งเรารัน control: ตลาดเวอร์ชัน Gaussian-noise (gaussian_control ในผลลัพธ์, 300 seed) สร้างกับดักซ้ำได้แทบไม่เปลี่ยนแปลง — objective แบบ per-trade ยัง degenerate 55.7% ของเวลาภายใต้ Gaussian noise เทียบกับ 57.0% ที่มี fat tail และ out-of-sample Sharpe ของมันคือ 0.71 เทียบกับ 0.70 ดังนั้นกับดักจึงไม่ใช่เรื่องของ fat tail มันคือปรากฏการณ์ small-sample-บวก-selection ล้วน ๆ: เอาค่าสูงสุด จาก threshold ที่มี exposure ต่ำประมาณ 20 ตัว ของ Sharpe ที่คำนวณบน observation หยิบมือหนึ่ง แล้วมุมที่โชคดีบางมุมจะดูงดงามเสมอ noise distribution แบบไหนก็ทำแบบนี้ได้; กลยุทธ์ที่อยู่ในตลาดแค่ไม่กี่แท่งสามารถ โดยความบังเอิญล้วน ๆ นั่งผ่านการเคลื่อนไหวที่เป็นบวกสองสามครั้งแล้วรายงานตัวเลข in-sample ที่ไม่มีความหมายอะไรเลย เราเก็บ fat tail ไว้เพราะผลตอบแทนจริงมีมัน ไม่ใช่เพราะกับดักต้องการมัน

กลยุทธ์ ตระกูลพารามิเตอร์เดียว เทรดในทิศทางของสัญญาณเมื่อขนาดของมันต่ำกว่า threshold θ\theta มิฉะนั้นอยู่เฉย:

post=sign(st)1[stθ].\text{pos}_t = \operatorname{sign}(s_t)\cdot \mathbf{1}\big[\,|s_t| \le \theta\,\big].

θ\theta เล็กจิ๋วเทรดเฉพาะสัญญาณที่เล็กที่สุดและธรรมดาที่สุด — เป็น rare-trade lottery ที่แทบไม่อยู่ในตลาดเลย θ\theta ใกล้ขอบย่านจับ edge จริงทั้งหมดและมี exposure ที่ดี θ\theta ใหญ่มากเทรดทุกอย่าง รวมถึงแท่งนอกย่านที่ไม่มี edge และเพิ่มแค่ noise

def gen_dataset(T, rng, beta=0.30, band=1.0, tail_df=4):
    s    = rng.standard_normal(T)
    edge = beta * np.where(np.abs(s) <= band, s, 0.0)          # edge ONLY inside |s| <= 1
    t    = rng.standard_t(tail_df, T) / np.sqrt(tail_df / (tail_df - 2.0))  # fat tails, unit var
    return s, edge + t

def simulate(s, r, theta):
    pos      = np.where(np.abs(s) <= theta, np.sign(s), 0.0)   # trade the band, skip outliers
    strat    = pos * r
    active   = pos != 0.0
    exposure = active.mean()                                   # fraction of bars in a position
    sharpe_full   = strat.mean()         / strat.std(ddof=1)            # on the WHOLE timeline
    sharpe_active = strat[active].mean() / strat[active].std(ddof=1)    # on ONLY the active bars
    return dict(exposure=exposure, n_trades=int(active.sum()),
                sharpe_full=sharpe_full, sharpe_active=sharpe_active, pnl=strat.sum())

เพราะเราสร้างตลาดขึ้นมาเอง เราจึงคำนวณความจริงได้โดยตรง — performance เฉลี่ยที่ทุก threshold ข้าม 600 seed ทั้งหมด นอก sample จุดที่เหมาะสมที่สุดที่แท้จริงอยู่ที่ θ1.04\theta \approx 1.04: ตรงขอบของย่านสัญญาณพอดี อยู่ในตลาดประมาณ 70% ของเวลา (คำนวณ: สัญญาณ standard-normal ตกอยู่ภายใน s1.04|s|\le 1.04 ด้วยความน่าจะเป็น P(s1.04)=0.70P(|s|\le 1.04)=0.70) ทำ out-of-sample Sharpe ต่อปีได้ 1.77 นั่นคือตัวเลขที่ทุก objective พยายามจะหา จำไว้: θ≈1.04, OOS Sharpe 1.77, อยู่ในตลาดประมาณ 70% ของ timeline สิ่งที่ objective เลือกซึ่งห่างจากนี้คือ objective ที่ล้มเหลว ไม่ใช่ตลาดที่ยาก

Act 2 — กับดัก: แปดเทรดที่โชคดี, Sharpe 21, มายา

สล็อตแมชชีนที่จ่ายเงินจากการหมุนที่โชคดีเพียงครั้งเดียว แสดงตั๋วเทรดแปดใบและ in-sample per-trade Sharpe ที่สูงตระหง่านถึง 21 ซึ่งยุบลงเหลือ 0.13 นอก sample แสดงละครของผู้ชนะแบบ rare-trade lottery ที่ถูกเลือกโดย objective แบบ naive

ทีนี้ปล่อยให้ objective แบบ naive ทำงานบนข้อมูลชุดหนึ่งของตลาดนี้ — seed 6 เปิดเผยทุกอย่างเกี่ยวกับ seed นี้: มันไม่ใช่ข้อมูลชุดแรกหรือสุ่มมา เราสแกน seed หาผู้ชนะแบบ per-trade ที่ degenerate อย่างชัดเจน แล้วเลือกตัวนี้ เพื่อให้กลไกนี้ไม่มีทางพลาดได้ ผลลัพธ์ที่มันแสดงเป็นเรื่องปกติทั่วไป — ตามที่ Act 3 จะยืนยัน objective แบบ per-trade เลือก lottery ที่ exposure ต่ำกว่า 5% ใน 56% ของ seed ทั้งหมด — แต่ขนาดของ seed 6 อยู่ที่ปลายสุดขั้วของการกระจายนั้น อ่านมันในฐานะตัวอย่างที่ชัดเจนเป็นพิเศษของความล้มเหลวทั่วไป ไม่ใช่ตัวอย่างค่ามัธยฐาน เรา optimize per-trade Sharpe: Sharpe ratio ที่คำนวณบนเฉพาะแท่งที่กลยุทธ์มีตำแหน่งอยู่จริงเท่านั้น นี่เป็นสิ่งที่รายงานได้อย่างเป็นธรรมชาติมาก "เวลาที่มันเทรด เทรดของมันดีแค่ไหน?" มันให้ความรู้สึกเหมือนแยกฝีมือออกจากความเฉื่อยชา แต่มันทำตรงกันข้าม

นี่คือกลยุทธ์ที่ per-trade Sharpe สวมมงกุฎให้บน seed 6:

  • Threshold θ=0.005\theta = 0.005 — มันเทรดเฉพาะสัญญาณที่เล็กที่สุดเท่านั้น
  • Market exposure 0.4% — มันอยู่เฉย 99.6% ของเวลา
  • แปดเทรด แปด จาก 2000 แท่ง
  • In-sample per-trade Sharpe ต่อปี: 21.09
  • In-sample full-timeline Sharpe: 0.82
  • Out-of-sample full-timeline Sharpe: 0.13

per-trade metric อ่านค่าได้ 21.09 — ตัวเลขที่ไม่มีกลยุทธ์จริงตัวไหนเคยทำได้ เป็นตัวเลขระดับที่จะทำให้กองทุนถูกเปิดตัว และมันคือมายาที่สมบูรณ์ แปดเทรดนั้นบังเอิญจับการเคลื่อนไหวที่เป็นบวกไปได้สองสามครั้ง วัดบนแค่แปดแท่งนั้น อัตราส่วนของค่าเฉลี่ยต่อ standard deviation จึงมหาศาล แต่บน full timeline — ที่กลยุทธ์อยู่เฉย 99.6% ของเวลา — "edge" นั้นแทบไม่มีส่วนช่วยอะไรเลย: full-timeline Sharpe แค่ 0.82 in sample ยุบลงเหลือ 0.13 บนข้อมูลใหม่ ผู้ชนะที่ objective เลือกไว้ เมื่อพูดถึงการเทรดจริง ก็เท่ากับ flat

และมันไม่ใช่ edge จริงด้วยซ้ำที่ threshold นั้น จำไว้ว่าตลาดนี้: edge อยู่ในย่าน s1|s|\le 1 และ θ=0.005\theta = 0.005 อยู่ตรงกลางเป๊ะที่สัญญาณอ่อนที่สุด เส้นโค้ง out-of-sample จริงที่ θ=0.005\theta = 0.005 คือ −0.01 — แยกไม่ออกจากศูนย์เลย (derived จากเส้นโค้ง ground-truth) การค้นหาไม่ได้พบ edge จริงเล็ก ๆ มันพบการสุ่มที่โชคดีแปดครั้งของ noise แล้วรายงานว่าเป็น Sharpe 21

นี่คือกับดักในรูปย่อ: per-trade Sharpe ให้รางวัลกลยุทธ์สำหรับการเทรดให้น้อยที่สุดเท่าที่จะทำได้ เพราะยิ่งคุณยืนอยู่บนแท่งน้อยเท่าไหร่ ยิ่งง่ายที่บางแท่งจะโชคดี และตัววัดไม่เคยถามเลยสักครั้งว่า "แต่คุณอยู่ในตลาดจริง ๆ หรือเปล่า?" ขนาดของ seed 6 ถูกเลือกมาโดยเจตนา — เราไปหาตัวที่ชัดเจน — แต่ชนิดของมันไม่ใช่ ตลอดทั้ง 600 seed per-trade Sharpe เลือกผู้ชนะแบบ degenerate (ที่แทบไม่เทรดหรือขาดทุนนอก sample) ใน 57% ของ seed และ lottery ที่ exposure ต่ำกว่า 5% โดยเฉพาะใน 56% การเลือกแบบ degenerate ทั่วไปนั้นอ่อนกว่า Sharpe 21 ของ seed 6 มาก: เฉลี่ยข้ามทั้ง 600 seed ผู้ชนะของ objective แบบ per-trade มี in-sample per-trade Sharpe เฉลี่ย 4.58 และ exposure เฉลี่ย 0.286 — ยังคงอยู่เฉยส่วนใหญ่ แค่ไม่ใช่ 99.6% flat seed 6 แสดงละครของกลไกนี้ ส่วน 56% คือส่วนที่ควรทำให้คุณกังวล มากกว่าครึ่งของเวลา ตัววัดที่ใช้กันทั่วไปตัวนี้มอบตั๋ว lottery ให้คุณและเรียกมันว่ากลยุทธ์

Act 3 — ความจริงเชิงสถิติ: หกวัตถุประสงค์, 600 seed

objective function หกแบบในฐานะผู้เข้าแข่งขันบน leaderboard โดย per-trade Sharpe เปล่งประกายที่สุด in sample แต่ถูกประทับตรา degenerate 57 เปอร์เซ็นต์ ขณะที่ objective ที่รู้จัก exposure ยืนหยัดอยู่ได้นอก sample แสดงให้เห็นว่าตัวเลข in-sample ที่ดีเยี่ยมไม่ได้แปลว่าเป็นการเลือกที่ดี

seed เดียวพิสูจน์อะไรไม่ได้ มันแค่แสดงให้เห็น การจะวัด objective เราต้องถามว่ามันเลือกอะไรโดยเฉลี่ย ข้ามตลาดที่เป็นอิสระต่อกันจำนวนมาก แล้วให้คะแนนการเลือกนั้นบนข้อมูลที่การค้นหาไม่เคยเห็น ดังนั้น: 600 seed แต่ละตัวเป็นการสุ่มตลาดที่เป็นอิสระต่อกัน บนแต่ละตัว รัน threshold search 80 ค่าภายใต้แต่ละ objective บันทึก exposure, in-sample และ out-of-sample Sharpe ของสิ่งที่มันเลือก และว่าตัวที่เลือกนั้น degenerate หรือไม่

Objective Exposure เฉลี่ย In-sample Sharpe Out-of-sample Sharpe IS→OOS drop (ค่าสัมบูรณ์) Degenerate
Raw PnL 0.859 1.76 1.61 0.15 0.0%
Full-timeline Sharpe 0.740 1.82 1.71 0.11 0.0%
Per-trade Sharpe 0.286 1.00 0.70 0.30 57%
Exposure floor (emin=0.20e_{\min}=0.20) 0.740 1.82 1.71 0.11 0.0%
conf_k shrinkage (k=40k=40) 0.523 1.54 1.31 0.23 20.7%
Robust (floor + conf_k) 0.675 1.78 1.70 0.08 0.2%

คอลัมน์ "IS→OOS drop" คือการตกแบบสัมบูรณ์ของ Sharpe ต่อปีจาก in-sample ไปยัง out-of-sample (เช่น 1.000.701.00\to0.70 คือการตก 0.30) ไม่ใช่เปอร์เซ็นต์ และสังเกตว่าแถว "Exposure floor" เหมือนกับแถว "Full-timeline Sharpe" ทุกบิต นั่นไม่ใช่เรื่องบังเอิญ และ Act 5 จะอธิบายว่าทำไม

สามข้อเท็จจริงที่โดดเด่นออกมา และแต่ละข้อคือบทเรียน

per-trade Sharpe เป็น objective แบบ naive ตัวเดียวที่ degenerate exposure เฉลี่ยของมันคือ 0.286 — มันเลือกกลยุทธ์ที่อยู่เฉยส่วนใหญ่ — และ in-sample Sharpe ของมันที่ 1.00 ตกลง 0.30 เหลือ out-of-sample 0.70 ซึ่งแย่ที่สุดในกลุ่ม สังเกตสัญญาณเตือน: ตัวเลข in-sample ของมัน (1.00) ไม่ได้น่าประทับใจด้วยซ้ำ แต่บน seed เดียว ใด ๆ มันจะรายงานตัวเลข per-trade ได้ถึง 21 อย่างมีความสุข ค่าเฉลี่ยถูกล้างออกเพราะหน้าต่างที่โชคดีชี้ไปในทิศทางสุ่ม สิ่งที่รอดมาถึง out-of-sample คือแค่ 0.70 และ 57% ของการเลือกแต่ละครั้งคือขยะล้วน ๆ

objective ที่รู้จัก exposure ปลอดภัยโดยธรรมชาติ Raw PnL และ full-timeline Sharpe ไม่เคย degenerate (0.0%) เหตุผลคือเชิงโครงสร้าง: ทั้งคู่ถูกวัดข้าม timelineทั้งหมด ดังนั้นกลยุทธ์ที่อยู่เฉย 99.6% ของเวลาแทบไม่ได้อะไรเลยภายใต้มัน คุณไม่สามารถโกง full-timeline metric ได้ด้วยการเทรดน้อย ๆ — การอยู่เฉยถูกลงโทษโดยตรงและอัตโนมัติ เพราะแท่งที่ flat อยู่ใน denominator นี่คือแนวคิดที่สำคัญที่สุดในบทความนี้ และเรากลับมาที่มันใน Act 6

Raw PnL ปลอดภัยแต่ไม่เหมาะสมที่สุด — มัน over-expose ดูใกล้ ๆ: exposure เฉลี่ยของ raw PnL คือ 0.859 สูงที่สุดในทั้งหมด และ out-of-sample Sharpe ของมัน (1.61) ต่ำกว่า full-timeline Sharpe (1.71) และจุดที่เหมาะสมที่สุดที่แท้จริง (1.77) หนึ่งขั้น PnL ให้รางวัลกับการอยู่ในตลาด ดังนั้นการค้นหาจึงดัน θ\theta สูงเกินไป (บน seed 6, raw PnL เลือก θ=1.84\theta=1.84 เทียบกับค่าที่เหมาะสมที่สุด 1.04) ลากแท่งนอกย่านที่ไม่มี edge เข้ามาและเพิ่มแค่ noise มันไม่ระเบิด — แต่มันเลื่อนผ่านจุดที่เหมาะสมที่สุดจริงไปในทิศทางตรงข้ามกับกับดักแบบ per-trade objective ต่างกัน bias ต่างกัน บทเรียนเดียวกัน: ตัววัดเลือกกลยุทธ์

สองแถวที่เรายังไม่ได้พูดถึง — exposure floor และ conf_k — คือการซ่อมแซม นั่นคือ act ถัดไป

Act 4 — ทำไมแปดเทรดถึงไม่มีวันเชื่อถือได้

point estimate ของ Sharpe ตัวเดียวที่มี error bar ของ confidence interval ขนาดมหึมา เพราะมันตั้งอยู่บนแค่แปด observation เคียงข้างไม้บรรทัดที่ติดป้าย minimum track record length แสดงให้เห็นว่าอัตราส่วนที่วัดบนเทรดหยิบมือหนึ่งไม่มีความหมายทางสถิติเลย

ก่อนจะซ่อมกับดัก คุ้มค่าที่จะแม่นยำว่าทำไมแปดเทรดถึงผลิต Sharpe 21 ที่ไม่มีความหมายอะไรเลย — เพราะการแก้ไขตามมาโดยตรงจากเหตุผลนั้น

Sharpe ratio คือค่าประมาณ และค่าประมาณมี error bar ผลลัพธ์ปี 2002 ของ Andrew Lo ให้ standard error ของ Sharpe ratio ที่ประมาณจาก TT observation ภายใต้สมมติฐานที่ใจกว้างที่สุดเท่าที่จะเป็นไปได้ (ผลตอบแทนแบบ IID Gaussian):

SE(SR^)1+SR^2/2T.\operatorname{SE}\big(\widehat{SR}\big) \approx \sqrt{\frac{1 + \widehat{SR}^{\,2}/2}{T}}.

error หดตัวแค่ในอัตรา 1/T1/\sqrt{T} ป้อนมันเข้ากับกับดัก per-trade Sharpe บน seed 6 คือ 21.0921.09 ต่อปี ซึ่งคือ 1.331.33 ต่อ observation คำนวณบน T=8T = 8 แท่ง standard error คือ

SE1+1.332/280.49 per observation = 7.7 annualized\operatorname{SE} \approx \sqrt{\frac{1 + 1.33^2/2}{8}} \approx 0.49 \ \text{per observation} \ = \ \textbf{7.7 annualized}

(derived จากสูตรของ Lo) point estimate คือ 21.0921.09; error bar หนึ่ง sigma ของมันอยู่ในระดับ ±7.7\pm 7.7 — อ่านสิ่งนี้เป็นระดับขนาดเชิงภาพประกอบ ไม่ใช่ confidence interval ที่ calibrate แล้ว เพราะสูตรนี้สมมติผลตอบแทนแบบ IID Gaussian ซึ่ง fat-tailed t4t_4 noise ของเราละเมิด ถึงอย่างนั้น ข้อความก็ชัดเจน: "Sharpe 21" คือตัวเลขที่ดึงมาจาก distribution ที่กว้างมากจนแทบไม่มีข้อมูลเลย — และนั่นคือการคำนวณแบบใจกว้างด้วยซ้ำ เพราะส่วนขยายของ Mertens แสดงว่า fat tail และ skew มีแต่จะพอง standard error ให้ใหญ่ขึ้นอีก Sharpe ของ backtest แบบ rare-trade เชื่อถือได้น้อยกว่าค่า point value ของมันในทุกทิศทางพร้อมกัน: observation น้อยเกินไป และ distribution ที่ผิด

นี่คือสิ่งที่ Minimum Track Record Length สร้างเป็นทฤษฎีอย่างเป๊ะ (Bailey & López de Prado, 2012) มันกลับคำถาม — ฉันต้องมี observation กี่ตัวก่อนที่ฉันจะได้รับอนุญาตให้เชื่อ Sharpe ขนาดนี้ที่ confidence pp?

MinTRL=1+[1γ^3SR^+γ^414SR^2](Z1pSR^SR)2,\text{MinTRL} = 1 + \Big[\,1 - \hat\gamma_3\,\widehat{SR} + \tfrac{\hat\gamma_4 - 1}{4}\,\widehat{SR}^{\,2}\,\Big]\left(\frac{Z_{1-p}}{\widehat{SR} - SR^*}\right)^{2},

เปลี่ยน "เชื่อ backtest ที่มีเทรดน้อยให้น้อยลง" ให้เป็นตัวเลขที่ชัดเจนและตรวจสอบได้ของจำนวนเทรด ประเด็นที่ลึกซึ้งสำหรับการออกแบบ objective คือนี้: objective ที่ดีควรบังคับใช้ track record ขั้นต่ำจากภายใน แทนที่จะปล่อยให้มนุษย์สังเกตเห็นภายหลังว่าผู้ชนะตั้งอยู่บนแค่แปด observation per-trade Sharpe ทำตรงกันข้าม — มันถูกmaximizeโดยการดันจำนวน observation ลงไปสู่ขั้นต่ำ objective ใด ๆ ที่จุดที่เหมาะสมที่สุดของมันอยู่ที่ "เทรดให้น้อยที่สุดเท่าที่จะทำได้" คือ objective ที่ตามโครงสร้างแล้ว แสวงหาค่าประมาณที่เชื่อถือได้น้อยที่สุดของตัวเอง

ความล้มเหลวสองอย่างประกอบกันในกับดัก และการเรียกชื่อทั้งคู่บอกเราว่าจะแก้ไขมันอย่างไร อย่างแรก small-sample noise: แปด observation ไม่สามารถระบุอัตราส่วนใด ๆ ได้แน่ชัด อย่างที่สอง selection: แปดแท่งนั้นไม่ได้ถูกมอบให้เรา — การค้นหาเลือก threshold ที่ตกลงบนพวกมัน บางส่วนเพราะพวกมันโชคดี การค้นหาคือ maximizer มันจะหามุมของ space ที่ noise บังเอิญดูเหมือน signal เสมอ คุณไม่สามารถเอาชนะสิ่งนี้ได้ด้วย point estimate ที่ฉลาดกว่า คุณต้องเปลี่ยนความหมายของ "ดีที่สุด" เพื่อให้มุมที่โชคดีนั้นไม่ใช่ค่าสูงสุดอีกต่อไป

Act 5 — การซ่อมแซม: exposure floor และ trade-count shrinkage

แผงควบคุมที่มีปุ่มหมุนสองปุ่มติดป้าย exposure floor และ conf_k shrinkage ทั้งคู่ยก out-of-sample performance surface ขึ้นสู่ที่ราบสูงแบนราบ ขณะที่ตัวชี้วัด degeneracy ดับลง แสดงให้เห็นการแก้ไขที่เป็นอิสระต่อกันสองแบบที่รวมกันแล้วกู้คืนจุดที่เหมาะสมที่สุดที่แท้จริงได้

เรามีโรคที่ตั้งชื่อไว้สองโรค — เทรดน้อยเกินไป และ ตั้งอยู่บน observation น้อยเกินไป — ดังนั้นเราจึงเขียนยาสองตัว แต่ละตัวเล็งไปที่โรคหนึ่ง

ยาที่ 1: exposure floor การแก้ไขที่ง่ายที่สุดเท่าที่จะเป็นไปได้ ปฏิเสธกลยุทธ์ใด ๆ ที่ไม่อยู่ในตลาดอย่างน้อย emine_{\min} ของเวลาโดยตรง — ถ้าคุณแทบไม่เทรด คะแนนของคุณคือ -\infty และการค้นหาไม่สามารถเลือกคุณได้ แต่มี subtlety ที่ซื่อสัตย์อยู่ในสิ่งที่คุณ floor และนี่คือบทเรียนที่เงียบที่สุดของบทความทั้งหมดนี้ ในฐานะ objective แบบ standalone เรา floor full-timeline Sharpe และบนตลาดนี้มันไม่เปลี่ยนอะไรเลย: ผู้ชนะของ full-timeline Sharpe เองก็อยู่ที่ exposure ~74% อยู่แล้ว ดังนั้น floor 20% จึงไม่เคย bind เลยสักครั้ง นั่นคือเหตุผลเป๊ะที่แถว "exposure floor" และ "full-timeline Sharpe" ในตารางด้านบนเหมือนกันทุกบิต — bolt floor เข้ากับ metric ที่ปลอดภัยอยู่แล้ว แล้วคุณก็แค่ derive full Sharpe ขึ้นมาใหม่ floor จะทำงานที่มองเห็นได้ก็ต่อเมื่อมันปกป้อง metric ที่จะวิ่งไปที่มุมโดยไม่มีมัน: metric แบบ per-trade อย่างใน robust objective ด้านล่าง กล่าวอีกนัยหนึ่ง "ต้องการ exposure" และ "วัดบน full timeline" คือ บนข้อมูลนี้ ชื่อสองชื่อของการแทรกแซงเดียวกัน

ยาที่ 2: trade-count shrinkage — "conf_k" สำหรับตอนที่คุณติดอยู่กับ per-trade metric และต้องการการแก้ไขแบบนุ่มนวลแทนการตัดขาดแบบแข็ง: discount Sharpe อย่างต่อเนื่อง ตามจำนวนเทรดที่มันตั้งอยู่ คูณด้วย n/(n+k)n/(n+k) โดยที่ nn คือจำนวนเทรดและ kk คือ "confidence constant" คงที่ — trades-equivalent prior strength ที่เลือกไว้ก่อนการค้นหา:

score(θ)=SR^(θ)n(θ)n(θ)+k.\text{score}(\theta) = \widehat{SR}(\theta)\cdot \frac{n(\theta)}{n(\theta) + k}.

เมื่อ n0n \to 0 คะแนนถูกบีบให้เป็นศูนย์ไม่ว่า raw Sharpe จะใหญ่แค่ไหน; เมื่อ nn \to \infty คะแนนลู่เข้าหา raw Sharpe นี่คือตรรกะการแก้ไขแบบเดียวกับ MinTRL และ standard error ของ Act 4 — shrink ค่าประมาณแบบ small-sample เข้าหาศูนย์เป็นฟังก์ชันลดลงของขนาด sample — พับเข้าไปโดยตรงใน objective แทนที่จะใช้เป็น filter แบบ post-hoc บรรพบุรุษที่มีชื่อใกล้ที่สุดคือ System Quality Number ของ van Tharp (SQN=Ntrade/σtrade\text{SQN} = \sqrt{N}\cdot \overline{\text{trade}}/\sigma_{\text{trade}}) ซึ่งทำให้ per-trade quality metric สเกลตามจำนวนเทรด NN เช่นกัน — แม้ว่ารูปแบบฟังก์ชันจะต่างกัน (N\sqrt{N} โตไม่มีขอบเขต ในขณะที่ n/(n+k)n/(n+k) อิ่มตัวที่ 1) ในรูปแบบ ของเราคือ Bayesian precision-weighted / แบบ empirical-Bayes-style shrinkage มันคือสิ่งที่เราสร้างขึ้นสำหรับปัญหานี้ ไม่ใช่ estimator ที่มีชื่อที่ยกมาจากวรรณกรรม

def obj_active_sharpe(m):                  # the trap: Sharpe on only the active bars
    return m["sharpe_active"]

def _shrink(n, conf_k):                     # trade-count shrinkage n / (n + k)
    return n / (n + conf_k) if (n + conf_k) > 0 else 0.0

def obj_confk(m, conf_k=40.0):              # few trades -> little credit
    return m["sharpe_active"] * _shrink(m["n_trades"], conf_k)

def obj_robust(m, e_min=0.20, conf_k=40.0): # both cures at once
    if m["exposure"] < e_min:               # floor: reject strategies that barely trade
        return -np.inf
    return m["sharpe_active"] * _shrink(m["n_trades"], conf_k)

ทีนี้ส่วนที่ซื่อสัตย์: floor เท่าไหร่, shrinkage เท่าไหร่? กวาดทั้งสองแล้วอ่าน surface ทั้งหมด แต่ละ cell คือ out-of-sample Sharpe เฉลี่ยข้าม 200 seed (หนึ่งในสามของ 600 seed เพื่อให้การกวาดสองมิติถูกลง) พร้อม degeneracy rate อยู่ข้าง ๆ:

emine_{\min} \ conf_k k=0k=0 k=40k=40 k=80k=80
0.00 0.66 (59.5%) 1.26 (22.5%) 1.47 (11.5%)
0.05 1.43 (10.0%) 1.53 (6.0%) 1.60 (4.0%)
0.10 1.64 (1.5%) 1.65 (1.0%) 1.67 (1.0%)
0.20 1.71 (0.0%) 1.71 (0.0%) 1.71 (0.0%)
0.35 1.73 (0.0%) 1.73 (0.0%) 1.73 (0.0%)

Sharpe ต่อปีเฉลี่ยแบบ out-of-sample พร้อม degeneracy rate ในวงเล็บ cell บนซ้าย (0,0)(0,0) คือ per-trade Sharpe ดิบ — ไม่มี floor ไม่มี shrinkage: OOS 0.66, degenerate 59.5% นั่นคือ objective เดียวกับแถว per-trade ใน Act 3 ที่อ่านได้ 0.70 / 57% ความต่างเล็กน้อยมาจาก seed set ล้วน ๆ — การกวาดนี้ใช้ 200 seed, Monte Carlo ใช้ทั้ง 600 metric เดียวกัน sample เล็กกว่า

surface บอกเล่าเรื่องราวที่ชัดเจนในสามการอ่าน

แต่ละยาทำงานได้ด้วยตัวเอง เคลื่อนไปทางขวาตามแถวบน (เพิ่ม shrinkage ไม่มี floor): OOS ไต่ขึ้น 0.661.261.470.66 \to 1.26 \to 1.47 และ degeneracy ตก 59.5%22.5%11.5%59.5\% \to 22.5\% \to 11.5\% เคลื่อนลงคอลัมน์ซ้าย (เพิ่ม floor ไม่มี shrinkage): OOS ไต่ขึ้น 0.661.431.641.710.66 \to 1.43 \to 1.64 \to 1.71 และ degeneracy ตก 59.5%10%1.5%0%59.5\% \to 10\% \to 1.5\% \to 0\% ปุ่มไหนก็ตาม เมื่อหมุนเดี่ยว ๆ จะยก out-of-sample performance ขึ้นและฆ่า degeneracy อย่างเป็นอิสระ exposure floor คือคันโยกเดี่ยวที่แข็งแกร่งกว่าที่นี่ เพราะมันโจมตีลักษณะที่นิยาม trap โดยตรง — exposure ที่เกือบเป็นศูนย์

รวมกันแล้วไปถึงที่ราบสูง — และที่ราบสูงนั้นก็คือ full-timeline Sharpe นั่นเอง ที่ emin=0.20e_{\min} = 0.20 แถวแบนราบที่ OOS 1.71 พร้อม 0% degeneracy ในทุกระดับ shrinkage; ดันไปที่ emin=0.35e_{\min}=0.35 มันขยับไปที่ 1.73 แต่ดูให้ดีว่า 1.71 นั้นคืออะไร: มันคือคะแนนเป๊ะที่ full-timeline Sharpe ธรรมดาทำได้ใน Act 3 โดยไม่มี floor และไม่มี shrinkage เลย ที่ดีที่สุด การซ่อมแซมไม่เอาชนะ full-timeline Sharpe ได้ — มันสร้างมันขึ้นมาใหม่ และ robust objective ที่ซ่อมเต็มที่แล้วยังไปไม่ถึงด้วยซ้ำ: ข้ามทั้ง 600 seed มันลงเอยที่ OOS 1.70 พร้อม degeneracy ที่เหลืออยู่ 0.17% ต่ำกว่า full Sharpe เล็กน้อยที่ 1.71 / 0% — มันถูกdominateแบบอ่อนโดย metric ที่ง่ายกว่า การตั้งค่ากลาง ๆ emin=0.10e_{\min}=0.10 กับ k=40k=40 ไปถึง OOS 1.65 ที่ 1% degeneracy — มีประโยชน์ถ้า per-trade metric ถูกบังคับให้คุณใช้ แต่ไม่เคยเป็นเหตุผลที่จะเลือกมัน

ตัวเลขที่แน่นอนขึ้นอยู่กับสเกล — รูปทรงคือผลลัพธ์ ค่าที่เฉพาะเจาะจง emin=0.20e_{\min}=0.20, k=40k=40 ที่ซ่อมตลาดนี้ได้เต็มที่ถูกปรับให้เข้ากับ data-generating process นี้โดยเฉพาะ; บนตลาดที่ต่างกันที่มีความถี่การเทรดและความหนาของ tail ต่างกัน ที่ราบสูงจะอยู่ที่อื่น สิ่งที่ generalize ได้ไม่ใช่พิกัดแต่คือ surface: การยกขึ้นแบบ monotone ในทั้งสองทิศทาง degeneracy ถูกดันไปที่ศูนย์ ที่ราบสูงอยู่ที่ความจริง คุณหาพิกัดของคุณเองได้ด้วยการกวาด เหมือนที่ทำข้างบน

รวมยาทั้งสองเข้าด้วยกัน — objective แบบ robust floor 0.20 บวก conf_k 40 — แล้วกลับไปที่ seed 6 กับดักสวมมงกุฎให้ θ=0.005\theta = 0.005 แปดเทรด full-timeline OOS Sharpe 0.13 robust objective เลือก θ=0.979\theta = 0.979 แทน: market exposure 0.66, 447 เทรด, out-of-sample Sharpe ต่อปี 1.77 θ=0.979\theta = 0.979 นั้นอยู่หนึ่ง grid pointต่ำกว่าจุดที่เหมาะสมที่สุดที่แท้จริง θ=1.04\theta = 1.04 ดังนั้นมันจึงกู้คืน threshold ที่เกือบเหมาะสมที่สุดและมี exposure ที่ดี แทนที่จะลงตรงเป้าเป๊ะ — out-of-sample Sharpe ของ seed เดียวนี้ (1.77) บังเอิญตรงกับจุดที่เหมาะสมที่สุดของประชากร ข้อมูลเดียวกัน การค้นหาเดียวกัน threshold ตัวเลือก 80 ตัวเดียวกัน มีแค่นิยามของ "ดีที่สุด" เปลี่ยนไป และมันย้ายผู้ชนะจากมายาแปดเทรดที่ flat ไปเป็น edge จริงที่มี exposure ดี — ซึ่งบังเอิญเป็น threshold เดียวกันเป๊ะที่ full-timeline Sharpe ธรรมดาเลือกบน seed นี้

ข้อควรระวังหนึ่งที่การกวาดทำให้ชัดเจน: conf_k เพียงอย่างเดียวไม่พอ บนตลาดนี้ ที่ k=40k=40 ไม่มี floor degeneracy ยังคงอยู่ที่ 22.5% ข้าม seed — และบน seed 6 โดยเฉพาะ conf_k อย่างเดียวเลือก θ=0.015\theta = 0.015, 35 เทรด, out-of-sample Sharpe −0.06 สามสิบห้าเทรดรอดจาก shrinkage ของ 35/(35+40)0.4735/(35+40) \approx 0.47 พร้อมคะแนนเหลือพอที่จะชนะ exposure floor คือสิ่งที่ปิดช่องว่างสุดท้ายนั้น เพราะมันเล็งไปที่ลักษณะเฉพาะที่แท้จริงของ trap — การอยู่ flat — โดยตรง แทนที่จะไว้ใจจำนวนเทรดเป็น proxy สำหรับมัน

Act 6 — บทเรียนที่ลึกกว่า: วัดบน timeline ทั้งหมด

สองวิธีในการให้คะแนนกลยุทธ์เดียวกันถูกเปรียบเทียบ: สปอตไลต์แคบที่ส่องแค่ไม่กี่แท่งที่กลยุทธ์เทรด เทียบกับไฟฟลัดไลต์ที่วัด timeline ทั้งหมดรวมถึงช่วงที่ flat แสดงให้เห็นว่า objective ที่รู้จัก exposure ไม่สามารถถูกโกงได้ด้วยเทรดที่โชคดีนาน ๆ ครั้ง

ถอยกลับจากการซ่อมแซมแล้วสังเกตว่าอะไรที่แยก objective ที่ปลอดภัยออกจากกับดักจริง ๆ มันไม่ใช่ความซับซ้อน Raw PnL และ full-timeline Sharpe ง่ายกว่า per-trade Sharpe และพวกมันไม่เคย degenerate — 0% ข้ามทั้ง 600 seed — โดยไม่มี floor ไม่มี shrinkage ไม่มีการปรับแต่งเลยแม้แต่นิดเดียว

เส้นแบ่งคือคุณสมบัติเดียว: metric วัดหน้าต่างไหน? per-trade Sharpe วัดแค่แท่งที่กลยุทธ์เลือกที่จะยืนอยู่ — หน้าต่างแบบเลือกเองที่การค้นหาสามารถหดให้เล็กลงได้ตามใจ Full-timeline Sharpe และ total PnL วัด timelineทั้งหมด รวมถึงแท่งที่ flat และคุณไม่สามารถทำให้ full-timeline metric ใหญ่ขึ้นได้ด้วยการเทรดน้อย ๆ เพราะทุกชั่วโมงที่คุณนั่งเฉยคือชั่วโมงที่อยู่ใน denominator ที่ไม่ได้อะไรเลย exposure floor และ conf_k ท้ายที่สุดแล้วก็เป็นแค่วิธีซ่อมแซมให้ per-trade metric มี exposure-awareness ที่ full-timeline metric มีให้ฟรีอยู่แล้ว — และการกวาดก็บอกเราแล้วว่าเพดานของการซ่อมแซมนั้นคือเท่าไหร่: ที่ดีที่สุดมันแค่เท่ากับ full-timeline Sharpe (OOS 1.70 เทียบกับ 1.71) ไม่เคยเอาชนะมันได้ ถ้าคุณเลือกหน้าต่างได้อย่างอิสระ ให้เลือก timeline ทั้งหมดแล้วข้ามการซ่อมแซมไปเลย

ดังนั้นหลักการออกแบบ กล่าวอย่างตรงไปตรงมา:

ออกแบบ objective ให้ไม่สามารถถูกโกงได้ด้วยเทรดที่โชคดีนาน ๆ ครั้ง คุณมีเครื่องมือสามอย่าง เรียงตามลำดับความสำคัญคร่าว ๆ:

  1. วัดบน full timeline ค่าเริ่มต้นที่แทบไม่ควรออกจากมันเลย Full-timeline Sharpe และ total return รู้จัก exposure โดยธรรมชาติ — ความเฉื่อยชาถูกลงโทษโดยอัตโนมัติเพราะแท่งที่ flat ถูกนับด้วย ถ้าคุณพบว่าตัวเองกำลังรายงาน metric ที่คำนวณบน "เฉพาะแท่งที่เราแอคทีฟ" หยุดแล้วถามว่าการค้นหาจะทำอะไรกับอิสระในการเลือกแท่งเหล่านั้น
  2. ต้องการ exposure ถ้าคุณต้องใช้ activity-conditional metric floor exposure เพื่อให้การค้นหาไม่สามารถเลือกกลยุทธ์ที่แทบไม่เทรดได้ นี่คือคันโยกเดี่ยวที่แข็งแกร่งที่สุดต่อกับดักนี้โดยเฉพาะ
  3. Shrink ด้วยจำนวนเทรด discount อัตราส่วนใด ๆ ด้วย n/(n+k)n/(n+k) เพื่อให้ Sharpe ที่ตั้งอยู่บน observation หยิบมือหนึ่งได้เครดิตแค่เศษส่วนของตัวที่ตั้งอยู่บนหลายพัน นี่คือการบังคับใช้ Minimum Track Record Length ในระดับ objective: ตัวเลขจาก observation น้อยไม่น่าเชื่อถือ (Act 4) ดังนั้น objective ที่ซื่อสัตย์จึงตั้งราคาความไม่น่าเชื่อถือนั้นเข้าไปด้วย แทนที่จะไว้ใจให้มนุษย์จับได้ในภายหลัง

ไม่มีสิ่งใดในนี้ทำให้การค้นหาฉลาดขึ้น มันทำให้เป้าหมายซื่อสัตย์ ดังนั้นเมื่อการค้นหาทำในสิ่งที่มันทำเสมอ — หาค่าสูงสุด — ค่าสูงสุดนั้นคือกลยุทธ์ที่คุณต้องการจริง ๆ

หมายเหตุความซื่อสัตย์

ข้อควรระวังสามข้อ กล่าวอย่างตรงไปตรงมา เพราะการศึกษาแบบควบคุมจะได้ข้อสรุปมาก็ต่อเมื่อมันบอกขอบเขตของตัวเองด้วย

  • ตลาดเป็น synthetic และตั้งใจให้เป็นแบบนั้น สัญญาณ standard-normal, edge เชิงเส้นที่จำกัดอยู่ใน s1|s|\le 1, noise แบบ Student-tt(44) ที่ fat-tailed — เลือกมาเพื่อ controlled ground truth ไม่ใช่เพื่อความสมจริงของตลาด เราพิสูจน์ได้ว่า objective เลือกกลยุทธ์ผิดก็ต่อเมื่อรันมันบนข้อมูลที่เรารู้ว่ากลยุทธ์ไหนถูกต้องเท่านั้น ตลาดจริงเป็นแบบ non-stationary, autocorrelated และเปลี่ยน regime fat tail คือส่วนผสมที่สมจริงที่เราเก็บไว้ แต่ — ตรงข้ามกับการเดาแรกที่เป็นธรรมชาติ และตรงข้ามกับร่างก่อนหน้าของบทความนี้เอง — มันไม่ใช่สิ่งที่ขับเคลื่อนกับดัก: control แบบ Gaussian-noise (300 seed) degenerate 55.7% ของเวลา เทียบกับ 57.0% ที่นี่ พร้อม out-of-sample Sharpe 0.71 เทียบกับ 0.70 กับดักเป็น artifact แบบ small-sample-บวก-selection ที่รอดอยู่ได้ไม่ว่าจะมี tail หนักหรือไม่ สิ่งที่ส่งมอบคือการวินิจฉัยและรูปแบบการซ่อมแซม ไม่ใช่กลยุทธ์และไม่ใช่ค่าคงที่แบบสากล
  • ค่าที่ใช้ซ่อมแซมขึ้นอยู่กับสเกล floor emin=0.20e_{\min}=0.20 และ shrinkage k=40k=40 ที่เฉพาะเจาะจงซึ่งปิดกับดักได้เต็มที่ถูกปรับให้เข้ากับ data-generating processนี้ — ความถี่การเทรดของมัน ความหนาของ tail ของมัน ขนาด edge ของมัน บนข้อมูลอื่นที่ราบสูงจะเคลื่อนที่ สิ่งที่ transfer ได้คือรูปทรงของ surface การกวาด (การยกขึ้นแบบ monotone ในทั้งสองปุ่ม degeneracy ไปที่ศูนย์ ที่ราบสูงอยู่ที่ความจริง) และวิธีการหาพิกัดของคุณเอง: กวาดทั้งสองแล้วอ่าน surface อย่าลอกตัวเลข
  • conf_k คือสิ่งที่เราสร้างขึ้นเอง ไม่ใช่ estimator ที่มีชื่อ trade-count shrinkage SR^n/(n+k)\widehat{SR}\cdot n/(n+k) คืออุปกรณ์แบบ Bayesian precision-weighted / empirical-Bayes-style ที่เราสร้างขึ้นสำหรับปัญหานี้; เหตุผลของมันมีรากฐานอยู่ในผล standard-error ของ Lo/Mertens ที่ผ่านการตรวจสอบแล้ว และ MinTRL ของ Bailey–López de Prado และญาติที่มีชื่อใกล้ที่สุดของมันคือ System Quality Number ของ van Tharp (Ntrade/σtrade\sqrt{N}\cdot \overline{\text{trade}}/\sigma_{\text{trade}} ซึ่งเป็นรูปแบบฟังก์ชันที่ต่างกัน) แต่เราไม่ได้อ้างว่า n/(n+k)n/(n+k) เองปรากฏภายใต้ชื่อในวรรณกรรม ยาคู่หูของมัน — exposure floor, การวัดแบบ full-timeline — คือแนวปฏิบัติมาตรฐานที่กล่าวไว้อย่างแม่นยำ และสังเกตว่า objective ไหนที่ปลอดภัยอยู่แล้วที่นี่: raw PnL และ full-timeline Sharpe ไม่เคยต้องการการซ่อมแซมเลย เพราะพวกมันรู้จัก exposure ตั้งแต่ต้น — มากจนการ floor full-timeline Sharpe ลดรูปเหลือแค่ full-timeline Sharpe ผู้ชนะของมันชนะ floor ที่สมเหตุสมผลใด ๆ อยู่แล้ว กับดักคือ Sharpe แบบ per-trade / active โดยเฉพาะ — และแม้แต่ per-trade objective ที่ซ่อมเต็มที่แล้วก็แค่เท่ากับ full-timeline Sharpe (OOS 1.70 เทียบกับ 1.71) ไม่เคยเอาชนะมันได้ บทเรียนหลักไม่ใช่การซ่อมแซม แต่คือการวัดบน full timeline ตั้งแต่แรก

สรุปประเด็นสำคัญ

  1. objective คือการตัดสินใจ ไม่ใช่พิธีการ การค้นหาไม่ได้หา "กลยุทธ์ที่ดี" — มันหาตัว maximizer ของสเกลาร์ใดก็ตามที่คุณมอบให้มัน และสเกลาร์ต่างกันเลือกกลยุทธ์ที่ต่างกันโดยสิ้นเชิงบนข้อมูลเดียวกัน การเลือก objective คือการเลือกกลยุทธ์ ทุกอย่างที่ตามมาคือ bookkeeping นั่นคือกฎของ Goodhart: ในวินาทีที่ metric ของคุณกลายเป็นเป้าหมายของการค้นหา การค้นหาจะใช้ประโยชน์จากทุกช่องว่างระหว่างมันกับสิ่งที่คุณตั้งใจ
  2. per-trade Sharpe คือกับดัก วัดบนเฉพาะแท่งที่กลยุทธ์เทรด มันถูก maximizeโดยการเทรดให้น้อยที่สุดเท่าที่จะทำได้ — observation ยิ่งน้อย ยิ่งง่ายที่การเคลื่อนไหวที่โชคดีสองสามครั้งจะพองอัตราส่วนขึ้น (control แบบ Gaussian ยืนยันว่า fat tail ไม่ใช่สิ่งจำเป็น มันคือปรากฏการณ์ small-sample-บวก-selection) ข้ามทั้ง 600 seed มันเลือก lottery ที่ exposure ต่ำกว่า 5% ใน 56% ของ seed และ degenerate ใน 57% การเลือกแบบ degenerate ทั่วไปมี in-sample per-trade Sharpe เฉลี่ย 4.58 บน seed หนึ่งที่ตั้งใจเลือกให้ชัดเจนเป็นพิเศษ มันสวมมงกุฎให้กลยุทธ์แปดเทรด exposure 0.4% ด้วย in-sample per-trade Sharpe ที่ 21.09 ยุบลงเหลือ full-timeline out-of-sample Sharpe ที่ 0.13 อัตราส่วนที่สร้างจากแปด observation มี standard error ระดับ ±7.7 ต่อปี (Act 4) — มันไม่เคยเป็นข้อมูลเลย
  3. objective ที่รู้จัก exposure ปลอดภัยโดยธรรมชาติ Raw PnL และ full-timeline Sharpe ไม่เคย degenerate เลย (0%) เพราะพวกมันวัด timelineทั้งหมดและความเฉื่อยชาถูกลงโทษโดยอัตโนมัติ คุณไม่สามารถโกง full-timeline metric ได้ด้วยการเทรดน้อย ๆ จุดอ่อนเดียวของ raw PnL คือ bias ตรงข้าม — มัน over-expose (exposure เฉลี่ย 0.859, OOS 1.61 เทียบกับความจริงที่ 1.77) เลื่อน θ\theta ผ่านจุดที่เหมาะสมที่สุดไปเพื่ออยู่ในตลาดมากขึ้น
  4. การซ่อมแซมได้ผล — แต่มันแค่พาคุณกลับไปที่ full-timeline Sharpe exposure floor และ trade-count (conf_k) shrinkage แต่ละตัวยก out-of-sample Sharpe ขึ้นอย่างเป็นอิสระและดัน degeneracy เข้าใกล้ศูนย์; รวมกันแล้วไปถึงที่ราบสูง แต่ที่ราบสูงนั้นคือ full-timeline Sharpe: degeneracy ตกจาก 59.5% ที่ (emin,k)=(0,0)(e_{\min},k)=(0,0) เหลือ 0% ที่ emin=0.20e_{\min}=0.20 และ OOS Sharpe ไต่จาก 0.66 ไปที่ 1.71 — ตัวเลขเป๊ะที่ full Sharpe ธรรมดาทำได้โดยไม่ต้องช่วย และ robust objective ที่ซ่อมเต็มที่แล้วลงเอยต่ำกว่ามันเล็กน้อย (OOS 1.70, degeneracy 0.17%: ถูก dominate แบบอ่อน) บน seed 6 robust objective กู้คืน threshold ที่เกือบเหมาะสมที่สุดและมี exposure ดี (θ=0.979\theta = 0.979 หนึ่ง grid point ต่ำกว่า 1.041.04 ที่แท้จริง; 447 เทรด; OOS Sharpe 1.77) มองว่า conf_k เป็นทางเลือกสำรองสำหรับตอนที่ per-trade metric ถูกบังคับให้คุณ ไม่ใช่การอัปเกรดเหนือการวัด full timeline พิกัดที่แน่นอนขึ้นอยู่กับสเกล; รูปทรงของ surface คือผลลัพธ์ที่ transfer ได้
  5. ออกแบบ objective ให้ไม่สามารถถูกโกงได้ด้วยเทรดที่โชคดีนาน ๆ ครั้ง เรียงตามลำดับความสำคัญ: วัดบน full timeline (ค่าเริ่มต้น), ต้องการ exposure (คันโยกเดี่ยวที่แข็งแกร่งที่สุด), shrink ด้วยจำนวนเทรด (Minimum Track Record Length ระดับ objective) ไม่มีข้อไหนทำให้การค้นหาฉลาดขึ้น — มันทำให้เป้าหมายซื่อสัตย์ ดังนั้นค่าสูงสุดที่การค้นหาพบอย่างหลีกเลี่ยงไม่ได้จึงเป็นกลยุทธ์ที่คุณจะเทรดจริง ๆ

parameter search คือ genie ที่เชื่อฟัง มันให้พรตามที่คุณพูดเป๊ะ ไม่ใช่พรที่คุณตั้งใจ — และ "maximize metric นี้" คือคำขอพร พูดมันเป็น per-trade Sharpe แล้วมันจะเสกแปดเทรดที่โชคดีขึ้นมาแล้วเรียกมันว่าโชคลาภ พูดมันในแบบที่การอยู่เฉยถูกลงโทษและเทรดหยิบมือหนึ่งได้เครดิตแค่หยิบมือหนึ่ง แล้ว genie ตัวเดียวกัน บนข้อมูลเดียวกัน จะมอบ edge จริงให้คุณ กลยุทธ์ที่คุณ deploy ถูกเลือกไปแล้วตั้งแต่วินาทีที่คุณพิมพ์ objective เลือกมันอย่างตั้งใจ

การทดลองแบบเต็ม — ตลาด synthetic, objective หกแบบ, Monte Carlo 600-seed และ surface การกวาดซ่อมแซม ตัวเลขทุกตัวสร้างซ้ำได้จากสคริปต์ deterministic ตัวเดียว — อยู่ในเปเปอร์คู่หูที่ objective-design.marketmaker.cc พร้อมโค้ดและข้อมูลที่ github.com/suenot/objective-design-degeneracy

นี่คือแนวรบหนึ่งในสงครามเดียวกันที่การศึกษาอื่น ๆ ของเราต่อสู้จากมุมที่ต่างกัน Deflated Sharpe Ratio ตั้งราคาให้ผู้ชนะของการค้นหาหลัง multiple testing — ในขณะที่บทความนี้ถามว่า objective เลือกกลยุทธ์ที่ถูกต้องหรือไม่ตั้งแต่แรก DSR ถามว่ากลยุทธ์ที่มันเลือกเอาชนะสิ่งที่ความโชคดีล้วน ๆ จะผลิตได้หรือไม่ การศึกษา probability of backtest overfitting ที่กำลังจะมาถึงโจมตี selection bias เดียวกันจากฝั่ง resampling ให้คะแนนกระบวนการแทนที่จะเป็นผู้ชนะ และ look-ahead bias taxonomy จัดหมวดหมู่ผู้ผลิต Sharpe ปลอมรายใหญ่อีกตัว — การรั่วไหลจากอนาคต — ซึ่งผลิตอาการเดียวกันเป๊ะ (backtest ที่งดงามแต่ตายตอนเทรดจริง) ผ่านกลไกที่ต่างกันโดยสิ้นเชิง Objective design, deflation, overfitting probability, look-ahead: สี่ชื่อสำหรับวินัยเดียว — การไม่ถูกหลอกโดย backtest ของตัวเอง

ข้อจำกัดความรับผิดชอบ: ข้อมูลที่ให้ไว้ในบทความนี้มีไว้เพื่อการศึกษาและให้ข้อมูลเท่านั้น และไม่ถือเป็นคำแนะนำทางการเงิน การลงทุน หรือการเทรด การเทรดสกุลเงินดิจิทัลมีความเสี่ยงสูงที่จะขาดทุน

ผู้เขียน

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

ก้าวนำหน้าตลาด

สมัครรับจดหมายข่าวของเราเพื่อรับข้อมูลเชิงลึกการเทรดด้วย AI เฉพาะ การวิเคราะห์ตลาด และการอัปเดตแพลตฟอร์ม

เราเคารพความเป็นส่วนตัวของคุณ ยกเลิกการสมัครได้ทุกเมื่อ