
BS, GAMMA, DELTA, THETA, VEGA
Trong thế giới của giao dịch định lượng, có một sự mâu thuẫn dường như: các nhà đầu tư bán lẻ có thể làm cho thị trường trở nên ổn định khi họ lo lắng về sự biến động của thị trường. Bí mật đằng sau điều này là gì? Câu trả lời nằm trong chiến lược cạo lông ngựa dựa trên mô hình Black-Scholes mà chúng ta sẽ phân tích hôm nay.
Ý tưởng cốt lõi của chiến lược này là mô phỏng hành vi giao dịch của các nhà giao dịch quyền chọn: xây dựng danh mục đầu tư quyền chọn tổng hợp (long straddle), sử dụng hiệu ứng Puma để bảo vệ động lực và thu được lợi nhuận trong mạo hiểm tỷ lệ biến động. Nói một cách đơn giản, là để toán học làm việc cho chúng tôi thay vì chiến đấu với cảm xúc của thị trường.
Mô hình Black-Scholes không chỉ là một lý thuyết học thuật, nó là nền tảng của định giá quyền chọn hiện đại. Trong chiến lược này, chúng tôi tập trung vào năm chữ cái Hy Lạp:
Delta(Δ): đo sự nhạy cảm của giá quyền chọn đối với sự thay đổi của giá tài sản. Đối với danh mục đầu tư quyền chọn đa dạng, sự thay đổi của Delta cung cấp cho chúng tôi tín hiệu bảo hiểm.
Gamma(Γ): tỷ lệ biến đổi của delta, là cốt lõi của chiến lược. Đường thẳng đồng nghĩa với việc delta tăng khi giá tăng và giảm khi giá giảm, tạo ra cơ hội cho chúng ta “mua thấp, bán cao”.
Theta(Θ)Tiếp theo, chúng ta có thể sử dụng các phương pháp khác nhau để tạo ra các giá trị khác nhau, nhưng chúng ta cần phải biết rằng chúng ta có thể tạo ra các giá trị khác nhau.
Vega(ν)“Sự nhạy cảm với sự biến động của tỷ lệ, giúp chúng ta đánh giá môi trường biến động”.
Từ thực hiện mã, chiến lược sử dụng công thức Black-Scholes tiêu chuẩn để tính toán các chữ cái Hy Lạp và đảm bảo tính toán chính xác thông qua hàm phân phối chính xác tiêu chuẩn (thông dụng Abramowitz & Stegun).
Chiến lược này được thiết kế với ba lớp lọc tín hiệu:
Lớp 1: Nhận dạng hệ thống tỷ lệ biến động Xác định môi trường biến động hiện tại bằng cách so sánh tỷ lệ biến động lịch sử với tỷ lệ biến động tiềm ẩn. Khi tỷ lệ biến động lịch sử / tỷ lệ biến động tiềm ẩn > 1.2, cho thấy thị trường thực tế biến động vượt quá dự kiến định giá quyền chọn, đây là môi trường lý tưởng để cạo râu.
Lớp thứ hai: Máy kích hoạt lột da ngựa Thiết kế này rất khéo léo: nó đảm bảo rằng chúng ta chỉ giao dịch bảo vệ khi có đủ chuyển động giá, tránh giao dịch quá mức.
Lớp 3: Vùng bảo hiểm Delta Một tín hiệu bảo hiểm được tạo ra khi độ lệch của Delta từ vị trí trung lập của danh mục đầu tư tùy chọn chéo vượt quá ngưỡng thiết lập. Điều này mô phỏng hành vi của người làm thị trường duy trì trung lập của Delta.
Từ phân tích logic chiến lược, các trường hợp sử dụng tốt nhất bao gồm:
Môi trường có tỷ lệ biến động cao: Khi thị trường biến động thực tế liên tục cao hơn biến động tiềm ẩn, giao dịch Puma có thể tạo ra lợi nhuận vượt trội.
Sự thay đổi trong xu hướngTrong một xu hướng mạnh mẽ, một sự hồi phục ngắn hạn thường tạo ra một cơ hội tốt để bóc lông ngựa.
Sự biến động của sự kiệnSự biến động của tỷ lệ trước và sau các sự kiện như báo cáo tài chính, quyết định của ngân hàng trung ương cung cấp môi trường giao dịch lý tưởng cho chiến lược.
Cần lưu ý rằng chiến lược này có hiệu quả hạn chế trong thị trường thu hồi có mức biến động thấp, vì giá không đủ di chuyển để kích hoạt tín hiệu giao dịch hiệu quả của Puma.
Quản lý rủi ro của chiến lược này thể hiện mức độ chuyên nghiệp của giao dịch định lượng:
Quản lý vị trí động: Điều chỉnh kích thước vị trí theo tỷ lệ biến động, giảm vị trí khi có biến động cao và tăng vị trí khi có biến động thấp, điều này trái ngược với quản lý vị trí cố định truyền thống.
Cơ chế ngăn chặn nhiều tầngLưu ý: Kết hợp với ATR, bảo vệ rút tối đa và cơ chế rút lui dựa trên giá trị thời gian.
Hạn chế giao dịch đồng thời: Kiểm soát lỗ hổng rủi ro tổng thể bằng cách giới hạn số lượng vị trí duy nhất.
Sự đổi mới:
Hạn chế tiềm năng:
Dựa trên phân tích sâu về mã, tôi đề nghị:
Chiến lược này thể hiện sự hấp dẫn của giao dịch định lượng: mô hình toán học đơn giản hóa hành vi thị trường phức tạp thành các quy tắc giao dịch có thể thực hiện được. Mặc dù nó không đảm bảo rằng mỗi giao dịch đều có lợi nhuận, nhưng về lâu dài, nó cung cấp cho chúng ta một khung giao dịch có giá trị kỳ vọng tích cực.
Đối với các nhà giao dịch định lượng muốn hiểu sâu sắc về bản chất của giao dịch quyền chọn, chiến lược này chắc chắn là một trường hợp học tập tuyệt vời. Nó không chỉ cho thấy cách chuyển lý thuyết sang thực hành, nhưng quan trọng hơn, nó tiết lộ cách các nhà giao dịch chuyên nghiệp suy nghĩ về thị trường: không phải là dự đoán hướng đi, mà là quản lý rủi ro, để xác suất làm việc cho chúng ta.
/*backtest
start: 2025-01-04 00:00:00
end: 2026-01-02 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=6
strategy("Black-Scholes Gamma Scalping Strategy",
overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=10,
pyramiding=5)
// ============================================================================
// STRATEGY CONCEPT:
// This strategy simulates gamma scalping - a volatility arbitrage technique
// used by options market makers. The core idea:
//
// 1. We model a synthetic long straddle position (long call + long put)
// 2. The straddle has positive gamma, meaning delta changes as price moves
// 3. We continuously delta-hedge by trading the underlying
// 4. If realized volatility > implied volatility, hedging profits exceed theta decay
// 5. Trading signals generated when price moves create hedging opportunities
//
// The Black-Scholes equation provides: Delta, Gamma, Theta, Vega
// ============================================================================
// === INPUT PARAMETERS ===
string grp_opt = "Option Parameters"
strike_offset_pct = input.float(0.0, "Strike Offset from Current Price %", group=grp_opt, step=0.5)
days_to_expiry = input.int(30, "Days to Expiration", group=grp_opt, minval=1, maxval=365)
implied_vol = input.float(0.25, "Implied Volatility (Annual)", group=grp_opt, minval=0.05, maxval=2.0, step=0.01)
risk_free_rate = input.float(0.05, "Risk-Free Rate (Annual)", group=grp_opt, step=0.001)
dividend_yield = input.float(0.0, "Dividend Yield (Annual)", group=grp_opt, step=0.001)
string grp_vol = "Volatility Analysis"
hist_vol_period = input.int(20, "Historical Volatility Period", group=grp_vol, minval=5)
vol_ratio_threshold = input.float(1.2, "HV/IV Ratio for Long Vol Signal", group=grp_vol, minval=1.0, step=0.05)
vol_ratio_short = input.float(0.8, "HV/IV Ratio for Short Vol Signal", group=grp_vol, minval=0.1, maxval=1.0, step=0.05)
string grp_trade = "Trading Parameters"
gamma_scalp_threshold = input.float(0.5, "Gamma Scalp Threshold (ATR mult)", group=grp_trade, minval=0.1, step=0.1)
hedge_band_pct = input.float(2.0, "Delta Hedge Band %", group=grp_trade, minval=0.5, step=0.5)
use_vol_filter = input.bool(true, "Use Volatility Regime Filter", group=grp_trade)
max_positions = input.int(3, "Max Concurrent Positions", group=grp_trade, minval=1, maxval=10)
string grp_risk = "Risk Management"
stop_loss_atr_mult = input.float(2.0, "Stop Loss (ATR Multiple)", group=grp_risk, minval=0.5, step=0.5)
take_profit_atr_mult = input.float(3.0, "Take Profit (ATR Multiple)", group=grp_risk, minval=1.0, step=0.5)
max_drawdown_pct = input.float(15.0, "Max Drawdown % to Pause Trading", group=grp_risk, minval=5.0, step=1.0)
// ============================================================================
// BLACK-SCHOLES MATHEMATICAL FUNCTIONS
// ============================================================================
// --- Standard Normal CDF (Abramowitz & Stegun approximation) ---
norm_cdf(float x) =>
float result = 0.0
if na(x)
result := na
else
float ax = math.abs(x)
if ax > 10
result := x > 0 ? 1.0 : 0.0
else
float t = 1.0 / (1.0 + 0.2316419 * ax)
float d = 0.3989422804 * math.exp(-0.5 * x * x) // 1/sqrt(2*pi) * exp(-x²/2)
float p = t * (0.31938153 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))))
result := x >= 0 ? 1.0 - d * p : d * p
result
// --- Standard Normal PDF ---
norm_pdf(float x) =>
na(x) ? na : 0.3989422804 * math.exp(-0.5 * x * x)
// --- Black-Scholes d1 and d2 ---
bs_d1(float S, float K, float r, float q, float sigma, float T) =>
T > 0 and sigma > 0 ? (math.log(S / K) + (r - q + 0.5 * sigma * sigma) * T) / (sigma * math.sqrt(T)) : na
bs_d2(float S, float K, float r, float q, float sigma, float T) =>
float d1 = bs_d1(S, K, r, q, sigma, T)
na(d1) ? na : d1 - sigma * math.sqrt(T)
// --- Greeks ---
// Call Delta
call_delta(float S, float K, float r, float q, float sigma, float T) =>
T <= 0 ? (S >= K ? 1.0 : 0.0) : math.exp(-q * T) * norm_cdf(bs_d1(S, K, r, q, sigma, T))
// Put Delta
put_delta(float S, float K, float r, float q, float sigma, float T) =>
T <= 0 ? (S <= K ? -1.0 : 0.0) : math.exp(-q * T) * (norm_cdf(bs_d1(S, K, r, q, sigma, T)) - 1)
// Gamma (same for call and put)
option_gamma(float S, float K, float r, float q, float sigma, float T) =>
if T <= 0 or sigma <= 0
0.0
else
float d1 = bs_d1(S, K, r, q, sigma, T)
math.exp(-q * T) * norm_pdf(d1) / (S * sigma * math.sqrt(T))
// ============================================================================
// HISTORICAL VOLATILITY CALCULATION
// ============================================================================
// Calculate annualized historical volatility
calc_historical_vol(int period) =>
float log_return = math.log(close / close[1])
float std_dev = ta.stdev(log_return, period)
// Annualization factor based on timeframe
float periods_per_year = switch
timeframe.isdaily => 365.0
timeframe.isweekly => 52.0
timeframe.ismonthly => 12.0
=> 365.0 * 390.0 / (timeframe.isminutes ? timeframe.multiplier : 1440.0)
nz(std_dev * math.sqrt(periods_per_year), 0.20)
hist_vol = calc_historical_vol(hist_vol_period)
// ============================================================================
// STRATEGY CALCULATIONS
// ============================================================================
// Dynamic strike price (ATM or offset)
float atm_strike = math.round(close / syminfo.mintick) * syminfo.mintick
float strike_price = atm_strike * (1 + strike_offset_pct / 100)
// Time to expiration in years
float tau = days_to_expiry / 365.0
// Calculate Greeks for synthetic straddle (1 call + 1 put at same strike)
float c_delta = call_delta(close, strike_price, risk_free_rate, dividend_yield, implied_vol, tau)
float p_delta = put_delta(close, strike_price, risk_free_rate, dividend_yield, implied_vol, tau)
float straddle_delta = c_delta + p_delta // Net delta of straddle
float gamma = option_gamma(close, strike_price, risk_free_rate, dividend_yield, implied_vol, tau)
float straddle_gamma = 2 * gamma // Straddle has 2x gamma
// Volatility ratio: Historical / Implied
float vol_ratio = hist_vol / implied_vol
// ATR for position sizing and stops
float atr = ta.atr(14)
// ============================================================================
// TRADING SIGNALS
// ============================================================================
// --- Signal 1: Volatility Regime ---
// Long volatility when realized > implied (gamma scalping profitable)
// Short volatility when realized < implied (collect theta)
bool long_vol_regime = vol_ratio > vol_ratio_threshold
bool short_vol_regime = vol_ratio < vol_ratio_short
// --- Signal 2: Gamma Scalp Trigger ---
// When price moves significantly, delta changes. We trade to capture this.
float price_move = close - close[1]
float move_threshold = atr * gamma_scalp_threshold
bool significant_up_move = price_move > move_threshold
bool significant_down_move = price_move < -move_threshold
// --- Signal 3: Delta Hedge Bands ---
// Trade when straddle delta deviates from neutral
float delta_band = hedge_band_pct / 100
bool delta_long_signal = straddle_delta < -delta_band // Need to buy to hedge
bool delta_short_signal = straddle_delta > delta_band // Need to sell to hedge
// --- Combined Entry Signals ---
bool vol_filter = use_vol_filter ? long_vol_regime : true
// Long entry: Price dropped significantly OR delta needs positive hedge
bool long_entry = vol_filter and (significant_down_move or delta_long_signal)
// Short entry: Price rose significantly OR delta needs negative hedge
bool short_entry = vol_filter and (significant_up_move or delta_short_signal)
// ============================================================================
// RISK MANAGEMENT
// ============================================================================
// Track equity for drawdown protection
var float equity_peak = strategy.initial_capital
equity_peak := math.max(equity_peak, strategy.equity)
float current_drawdown = (equity_peak - strategy.equity) / equity_peak * 100
bool drawdown_exceeded = current_drawdown > max_drawdown_pct
// Position counting
int open_trades = strategy.opentrades
// ============================================================================
// STRATEGY EXECUTION
// ============================================================================
// Stop loss and take profit levels
float long_stop = close - atr * stop_loss_atr_mult
float long_target = close + atr * take_profit_atr_mult
float short_stop = close + atr * stop_loss_atr_mult
float short_target = close - atr * take_profit_atr_mult
// Entry conditions
bool can_trade = not drawdown_exceeded and open_trades < max_positions
if can_trade
// Long entries
if long_entry and strategy.position_size <= 0
strategy.entry("GammaLong", strategy.long,
comment="Δ:" + str.tostring(straddle_delta, "#.##") + " Γ:" + str.tostring(straddle_gamma, "#.###"))
strategy.exit("LongExit", "GammaLong", stop=long_stop, limit=long_target)
// Short entries
if short_entry and strategy.position_size >= 0
strategy.entry("GammaShort", strategy.short,
comment="Δ:" + str.tostring(straddle_delta, "#.##") + " Γ:" + str.tostring(straddle_gamma, "#.###"))
strategy.exit("ShortExit", "GammaShort", stop=short_stop, limit=short_target)
// Exit on extreme conditions
if drawdown_exceeded
strategy.close_all(comment="Drawdown Protection")
// Exit if volatility regime shifts against us
if use_vol_filter and short_vol_regime and strategy.position_size != 0
strategy.close_all(comment="Vol Regime Shift")
// ============================================================================
// VISUALIZATIONS
// ============================================================================
// Plot straddle delta
plot(straddle_delta, "Straddle Delta", color=color.blue, linewidth=2)
hline(0, "Zero Delta", color=color.gray, linestyle=hline.style_dashed)
hline(delta_band, "Upper Band", color=color.red, linestyle=hline.style_dotted)
hline(-delta_band, "Lower Band", color=color.green, linestyle=hline.style_dotted)
// Background color for volatility regime
bgcolor(long_vol_regime ? color.new(color.green, 90) : short_vol_regime ? color.new(color.red, 90) : na)
// Entry signals
plotshape(long_entry and can_trade, "Long Signal", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(short_entry and can_trade, "Short Signal", shape.triangledown, location.abovebar, color.red, size=size.small)
// ============================================================================
// ALERTS
// ============================================================================
alertcondition(long_entry and can_trade, "Gamma Long Entry", "BS Strategy: Long entry signal - Delta={{straddle_delta}}")
alertcondition(short_entry and can_trade, "Gamma Short Entry", "BS Strategy: Short entry signal - Delta={{straddle_delta}}")
alertcondition(drawdown_exceeded, "Drawdown Alert", "BS Strategy: Max drawdown exceeded - trading paused")