Conformal Prediction untuk Penentuan Saiz Posisi yang Sedar Risiko
Setiap formula penentuan saiz posisi memerlukan anggaran ketidakpastian. Kriteria Kelly memerlukan kebarangkalian menang dan nisbah ganjaran (lihat Kriteria Kelly untuk strategi). Pengoptimuman min-varians memerlukan matriks kovarians. VaR memerlukan taburan pulangan. Kesemuanya memerlukan andaian tentang proses penjana data — andaian yang lazimnya dilanggar oleh pasaran kewangan.
Conformal prediction menawarkan sesuatu yang berbeza: selang ramalan dengan jaminan liputan sampel terhingga, tanpa sebarang andaian taburan parametrik. Jika anda meminta liputan 90%, anda akan mendapat sekurang-kurangnya liputan 90% — tidak kira sama ada pulangan adalah Gaussian, berekor gemuk, terpencong, atau heteroskedastik. Satu-satunya syarat ialah kebolehtukaran (exchangeability), atau syarat yang lebih lemah, seperti yang akan kita lihat.
Catatan ini merangkumi teori, varian utama, dan pelaksanaan praktikal untuk penentuan saiz posisi dalam Python.
Idea Teras: Skor Nonconformity

Conformal prediction berfungsi dengan mengukur sejauh mana "pelik" sesuatu pemerhatian baharu berbanding data lampau. Tahap kepelikan ini dikuantifikasikan oleh skor nonconformity — sebarang fungsi yang mengukur sejauh mana lemah suatu titik data mematuhi corak yang dilihat dalam baki data.
Untuk regresi (meramalkan nilai berterusan seperti pulangan), skor nonconformity yang paling ringkas ialah residual mutlak:
di mana ialah sebarang peramal titik (regresi linear, random forest, rangkaian neural — ia tidak penting) dan ialah satu titik data.
Wawasan utamanya: jika titik data boleh ditukar (exchangeable), maka pangkat dalam kalangan adalah teragih seragam ke atas . Ini ialah fakta kombinatorik tulen — ia tidak memerlukan sebarang andaian tentang taburan atau .
Daripada keseragaman pangkat ini, kita boleh membina selang ramalan dengan liputan sampel terhingga.
Split Conformal Prediction

Split conformal prediction (Papadopoulos et al., 2002; Lei et al., 2018) ialah varian yang paling praktikal. Algoritmanya ringkas:
Langkah 1. Pecahkan data kepada set latihan dan set kalibrasi .
Langkah 2. Suaikan sebarang model pada .
Langkah 3. Kira skor nonconformity pada set kalibrasi:
Langkah 4. Untuk paras kesilapan liputan (miscoverage) yang dikehendaki , ambil sebagai kuantil empirik bagi . Secara konkrit, ini ialah residual terkecil ke- (dan apabila , iaitu untuk yang sangat kecil).
Langkah 5. Selang ramalan untuk titik baharu ialah:
Jaminan Liputan
Di bawah kebolehtukaran data kalibrasi dan titik ujian baharu:
Ini ialah jaminan sampel terhingga — bukan anggaran asimptot. Ia sah untuk sebarang model , sebarang taburan data, dan sebarang saiz sampel . Jika ialah peramal yang teruk, selang itu sekadar akan menjadi lebih lebar. Jaminan liputan masih tetap berlaku.
Terdapat juga batas atas apabila skor tidak mempunyai nilai seri: , jadi liputan itu tidak konservatif secara membazir.
Mengapa Ini Penting untuk Dagangan
Selang ramalan tradisional daripada, katakan, regresi linear mengandaikan ralat Gaussian. Selang Gaussian yang dikalibrasi pada majoriti data boleh tersalah anggap ekor dengan teruk apabila residual sebenar berekor berat (cth. Student- dengan beberapa darjah kebebasan): jisim tengah lebih nipis berbanding Gaussian, jadi selang Gaussian yang dipadankan-varians akan terlebih-liputan berhampiran pusat namun terkurang-liputan di ekor, dan selang yang disuaikan-ekor pula melakukan sebaliknya. Maksudnya bukan satu nombor ajaib tunggal — tetapi bahawa liputan teralami bagi selang parametrik bergantung pada andaian taburan yang belum anda sahkan.
Selang conformal prediction mengelakkan masalah ini. Ia secara automatik melebar apabila model tidak pasti, dan ia mengekalkan liputan marginal tanpa mengira taburan ralat sebenar. Bagi seorang pedagang, ini bermaksud:
- Jika anda menentukan saiz posisi secara berkadar songsang dengan lebar selang, anda secara automatik mengurangkan pendedahan apabila model tidak pasti.
- Jaminan liputan bermaksud anggaran risiko anda adalah jujur — jika anda berkata "90% pulangan teralami akan jatuh dalam selang ini," kenyataan itu sah secara statistik (secara marginal, di bawah kebolehtukaran).
Full Conformal dan Jackknife+
Split conformal adalah ringkas tetapi membazir data: set kalibrasi tidak boleh digunakan untuk latihan. Dua alternatif menangani perkara ini.
Full Conformal Prediction
Full conformal prediction (Vovk et al., 2005) menggunakan kesemua data untuk kedua-dua latihan dan kalibrasi. Bagi setiap nilai calon daripada :
- Tambah set data dengan .
- Suaikan semula model pada set data yang ditambah itu.
- Kira semua skor nonconformity.
- Sertakan dalam set ramalan jika skor untuk tidak terlalu melampau.
Set ramalannya ialah:
di mana ialah skor nonconformity yang dikira dengan set data yang ditambah.
Full conformal memberikan selang yang paling ketat tetapi terlalu mahal dari segi pengkomputeran untuk kebanyakan model — anda mesti menyuaikan semula model untuk setiap calon pada satu grid. Untuk ramalan pulangan, ini boleh bermaksud ribuan suaian semula bagi setiap ramalan.
Jackknife+ (Barber et al., 2021)
Jackknife+ mencapai keseimbangan. Ia menggunakan residual leave-one-out (LOO) tetapi mengambil kira variabiliti dalam model tersuai merentas lipatan LOO.
Biarkan melambangkan model yang dilatih pada kesemua data kecuali titik . Takrifkan skor nonconformity LOO dengan residual mutlak tunggal:
Selang ramalan jackknife+ kemudiannya dibina daripada ramalan LOO pada titik ujian, dilebarkan oleh residual ini:
Di sini melambangkan nilai terkecil ke- bagi set , dan pula nilai terkecil ke-. Batas bawah menolak residual daripada setiap ramalan LOO; batas atas menambah residual itu. Ketaksimetrian itulah intipatinya — meruntuhkan kedua-dua batas kepada akan meletakkan batas bawah di atas ramalan, yang merupakan satu kesilapan.
Jackknife+ memberikan jaminan liputan sekurang-kurangnya (sedikit lebih lemah berbanding split conformal), tetapi ia menggunakan kesemua data untuk kedua-dua latihan dan kalibrasi. Dalam amalan, liputan biasanya hampir dengan .
Untuk model dagangan yang dilatih pada data terhad (cth. model khusus rejim dengan hanya beberapa ratus pemerhatian), jackknife+ selalunya merupakan pilihan terbaik — ia tidak mengorbankan data yang langka untuk kalibrasi. Kosnya ialah suaian semula model.
Masalah dengan Siri Masa Kewangan: Bukan Kebolehtukaran

Jaminan conformal piawai memerlukan kebolehtukaran: taburan tercantum bagi adalah tak berubah di bawah pilih atur. Untuk data i.i.d., ini terpenuhi secara remeh.
Siri masa kewangan bukanlah boleh ditukar. Pulangan mempamerkan:
- Pengelompokan volatiliti: Tempoh volatiliti tinggi mengikuti tempoh volatiliti tinggi (kesan GARCH).
- Momentum dan pulangan kepada min: Autokorelasi dalam pulangan atau pulangan kuasa dua.
- Perubahan rejim: Taburan beralih dari semasa ke semasa (pasaran menaik vs. pasaran menurun).
Jika anda secara naif menerapkan split conformal pada siri masa — menggunakan pemecahan kalibrasi rawak — anda melanggar struktur temporal. Skor kalibrasi daripada tahun 2017 yang tenang tidak akan mencerminkan ketidakpastian tahun 2020 yang bergelora. Jaminan liputan anda terbongkar.
Adaptive Conformal Inference (ACI)

Gibbs dan Candes (2021, NeurIPS) memperkenalkan Adaptive Conformal Inference (ACI) untuk menangani anjakan taburan dan data bukan-kebolehtukaran. Ideanya elegan: daripada menggunakan paras liputan tetap, sesuaikan paras kesilapan liputan sasaran secara dalam talian berdasarkan sama ada selang terkini meliputi keputusan sebenar, dan terbitkan semula kuantil daripada taburan skor pada setiap langkah.
Algoritma ACI
ACI tidak menolak lebar selang secara langsung. Ia mengekalkan parameter kesilapan liputan adaptif dan mengira semula kuantil conformal daripadanya. Pada setiap langkah masa :
- Kira ambang conformal sebagai kuantil empirik bagi set residual semasa (skor kalibrasi, ditambah sebarang skor teralami setakat ini): .
- Perhatikan ciri , hasilkan selang .
- Perhatikan nilai sebenar dan kira penunjuk ralat .
- Kemas kini paras (bukan lebar):
di mana ialah saiz langkah dan ialah kesilapan liputan sasaran. Jika satu selang tersasar (), mengecut, yang menolak kuantil seterusnya lebih tinggi dan melebarkan selang; jika ia meliputi, membesar dan selang mengetat. Yang pentingnya, di sini berada dalam unit kebarangkalian — ia menolak satu paras dalam , bukan ambang dalam unit pulangan mentah — jadi yang sama berkelakuan munasabah sama ada residual berada pada susunan atau tidak.
Jaminan Liputan untuk ACI
ACI memberikan jaminan liputan jangka panjang yang tidak bergantung pada model taburan:
Oleh sebab diapit kepada , pengangka terbatas oleh darab suatu pemalar, jadi sebelah kanan ialah dan kekerapan kesilapan liputan empirik menumpu kepada . Kenyataan tepatnya: ACI menjamin kekerapan kesilapan liputan empirik jangka panjang menumpu kepada untuk jujukan sebarangan (termasuk yang bermusuhan), dengan syarat paras tersuai kekal terbatas — yang ditegakkan oleh pengapitan. Ia merupakan jaminan terhadap kekerapan liputan, bukan terhadap keinformatifan selang: di bawah jujukan yang benar-benar bermusuhan, selang boleh membesar menjadi lebar tanpa maklumat sambil masih mencapai sasaran liputan.
Dynamically-Tuned ACI (DtACI)
Gibbs dan Candes (2024, JMLR) memperhalusi ACI dengan penalaan dinamik saiz langkah . Daripada menetapkan , mereka mengekalkan set calon dan menggabungkannya melalui peraturan agregasi pakar, mengutamakan yang liputan terkininya paling hampir dengan sasaran.
Ini menangani satu masalah praktikal: yang besar menyesuaikan dengan cepat kepada perubahan rejim tetapi menghasilkan lebar selang yang tidak stabil; yang kecil adalah stabil tetapi lambat menyesuaikan. DtACI mengimbangi kedua-duanya secara automatik.
Mengapa Ini Penting untuk Dagangan
Pertimbangkan satu strategi pembuatan pasaran (market-making) yang menggunakan model ramalan pulangan. Semasa pasaran tenang, selang conformal adalah ketat — model yakin, dan anda boleh mengambil posisi yang lebih besar. Apabila volatiliti melonjak (musim pendapatan, pengumuman FOMC, kejutan geopolitik), paras ACI menyesuaikan dan selang melebar dalam beberapa langkah masa. Penentuan saiz posisi anda mengecut sebagai tindak balas, tanpa sebarang model volatiliti eksplisit atau logik pengesanan rejim.
Inilah kuantifikasi ketidakpastian sebagai isyarat kelas pertama, bukan renungan kemudian.
Penentuan Saiz Posisi dengan Selang Conformal

Kini mari kita hubungkan conformal prediction dengan penentuan saiz posisi yang konkrit. Pemboleh ubah utama ialah separuh-lebar selang ramalan berbanding kes residual-mutlak simetri. Dengan selang simetri , lebar penuhnya ialah . Untuk memastikan formula dan kod konsisten, kita mengukur segala-galanya terhadap lebar penuh di sepanjang catatan ini.
Penentuan Saiz Songsang-Lebar
Pendekatan paling ringkas: tentukan saiz berkadar songsang dengan lebar selang.
di mana ialah pemalar penskalaan yang dikalibrasi kepada belanjawan risiko anda. Apabila model yakin (selang sempit), anda mengambil posisi yang lebih besar. Apabila tidak pasti (selang lebar), anda mengambil posisi yang lebih kecil.
Ini analog dengan penyasaran volatiliti (), tetapi dengan perbezaan penting: lebar selang conformal ialah ukuran ketidakpastian bebas-taburan, bukan anggaran volatiliti parametrik. Ia menangkap ketidakpastian ramalan di bawah jaminan liputan, bukan sekadar varians pulangan.
Penentuan Saiz Nisbah-Kelebihan dan Penapis Tanpa-Dagang
Penentuan saiz songsang-lebar tulen mengabaikan kekuatan isyarat itu sendiri. Penghalusan yang semula jadi menskalakan dengan nisbah kelebihan (edge ratio) — ramalan titik berbanding lebar selang:
Ini ialah analog conformal bagi nisbah isyarat-ke-hingar: pulangan jangkaan dibahagi dengan ukuran ketidakpastian bebas-taburan. Kita menggunakannya untuk kedua-dua penentuan saiz dan untuk penapis tanpa-dagang.
Penapis itu berprinsip. Jika selang menongkah sifar,
maka selang ramalan merangkumi kedua-dua pulangan positif dan negatif — pulangan teralami boleh secara munasabah mempunyai tanda yang bertentangan dengan ramalan anda. Takrifkan ambang kelebihan minimum dan berdagang hanya apabila . Perhatikan bahawa kandungan geometri " cukup besar sehingga selang tidak lagi menongkah sifar" adalah tepatnya (kerana selang melepasi sifar apabila ). Pilih pada skala sebenar melalui backtesting; untuk residual pulangan harian, biasanya jauh di bawah , jadi yang kecil mungkin membenarkan hampir semua dagangan dan yang besar mungkin tidak membenarkan satu pun. Kalibrasikannya kepada data anda.
Tentang "Conformal Kelly"
Adalah menggoda untuk menggandingkan selang conformal kepada pecahan Kelly . Tetapi sudah pun merupakan pecahan lengkap dan terbatas yang diterbitkan daripada kebarangkalian menang dan nisbah ganjaran ; mendarabkannya dengan nisbah tak terbatas seperti tidak mempunyai justifikasi teori-keputusan — ia boleh melebihi 1 atau membalikkan tanda secara bebas daripada , dan ia mengira dua kali kelebihan yang telah pun dikodkan oleh . Maka kami tidak mempersembahkan pendarab "conformal Kelly".
Jika anda ingin memacu Kelly daripada selang itu, anda mesti benar-benar menerbitkan dan daripadanya, yang memerlukan andaian eksplisit tentang taburan dalam selang (selang conformal sengaja tidak mengatakan apa-apa tentang itu — lihat Batasan). Sebagai contoh, di bawah bentuk dalam-selang yang diandaikan anda boleh menghampiri dan nisbah ganjaran daripada geometri selang — tetapi tonjolkan andaian itu dengan lantang, kerana ia memperkenalkan semula tepatnya komitmen parametrik yang sepatutnya dielakkan oleh conformal prediction.
Alternatif yang jujur dan ringan-andaian ialah menggunakan nisbah kelebihan sebagai pengecutan pecahan-Kelly: besarkan saiz apabila pulangan jangkaan besar berbanding selang, kecilkan saiz apabila ia kecil, dan terapkan ini di atas had keras — secara eksplisit sebagai heuristik, bukan sebagai "pecahan Kelly".
Pelaksanaan Python
Berikut ialah pelaksanaan praktikal. Kami menunjukkan kedua-dua laluan split/prefit dan laluan temporal (EnbPI), kerana inti catatan ini ialah bahawa data kewangan bukanlah boleh ditukar.
Penyediaan dan Persediaan Data
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import KFold
from mapie.regression import MapieRegressor, MapieTimeSeriesRegressor
from mapie.subsample import BlockBootstrap
def prepare_features(prices: pd.Series, lookback: int = 20) -> pd.DataFrame:
"""Create features from a price series."""
df = pd.DataFrame()
returns = prices.pct_change()
for lag in range(1, lookback + 1):
df[f"ret_lag_{lag}"] = returns.shift(lag)
for window in [5, 10, 20]:
df[f"ret_mean_{window}"] = returns.rolling(window).mean().shift(1)
df[f"ret_std_{window}"] = returns.rolling(window).std().shift(1)
df[f"ret_skew_{window}"] = returns.rolling(window).skew().shift(1)
df["target"] = returns.shift(-1)
return df.dropna()
Split Conformal dengan MAPIE (Prefit)
Untuk conformal split/prefit, cv="prefit" memerlukan method="base" (penganggar split-conformal naif). Pilihan method="plus" ialah penganggar CV+/jackknife+ dan tidak serasi dengan cv="prefit" — ia memerlukan objek pengesahan silang sebaliknya. Kami menggunakan gabungan yang betul di sini, dan menyeragamkan penentuan saiz pada lebar penuh.
def split_conformal_sizing(
prices: pd.Series,
alpha: float = 0.1,
k: float = 1e-3, # scaling constant, in width units
max_position: float = 1.0,
min_edge: float = 0.05, # threshold on |pred| / width
) -> pd.DataFrame:
"""
Position sizing using split (prefit) conformal prediction intervals.
Sizing rule (consistent with the prose):
edge_t = |pred_t| / width_t
size_t = clip(k / width_t, 0, max_position) # inverse-width
size_t = 0 if edge_t < min_edge # no-trade filter
"""
df = prepare_features(prices)
X = df.drop(columns=["target"])
y = df["target"]
n_train = int(len(X) * 0.6)
n_cal = int(len(X) * 0.2)
X_train, y_train = X.iloc[:n_train], y.iloc[:n_train]
X_cal, y_cal = X.iloc[n_train:n_train + n_cal], y.iloc[n_train:n_train + n_cal]
X_test, y_test = X.iloc[n_train + n_cal:], y.iloc[n_train + n_cal:]
base_model = GradientBoostingRegressor(
n_estimators=200, max_depth=3, learning_rate=0.05, random_state=42,
)
base_model.fit(X_train, y_train)
mapie = MapieRegressor(estimator=base_model, cv="prefit", method="base")
mapie.fit(X_cal, y_cal)
y_pred, y_intervals = mapie.predict(X_test, alpha=alpha)
lower = y_intervals[:, 0, 0]
upper = y_intervals[:, 1, 0]
width = upper - lower
raw_size = k / np.where(width > 0, width, np.inf)
position_size = np.clip(raw_size, 0.0, max_position)
edge_ratio = np.abs(y_pred) / np.where(width > 0, width, np.inf)
position_size = np.where(edge_ratio < min_edge, 0.0, position_size)
position_size = position_size * np.sign(y_pred)
return pd.DataFrame({
"prediction": y_pred,
"lower": lower,
"upper": upper,
"width": width,
"edge_ratio": edge_ratio,
"position_size": position_size,
"actual": y_test.values,
}, index=X_test.index)
Conformal Siri Masa dengan EnbPI
Oleh sebab pulangan bukanlah boleh ditukar, pemecahan rawak/prefit di atas hanyalah satu garis dasar. MapieTimeSeriesRegressor daripada MAPIE dengan method="enbpi" (Xu & Xie, 2021) menggunakan block bootstrap dan pengemaskinian residual yang direka untuk kebergantungan temporal. Inilah alat yang sepadan dengan hujah catatan ini sendiri.
def enbpi_sizing(
prices: pd.Series,
alpha: float = 0.1,
k: float = 1e-3,
max_position: float = 1.0,
min_edge: float = 0.05,
) -> pd.DataFrame:
"""Position sizing with EnbPI (block-bootstrap, time-series conformal)."""
df = prepare_features(prices)
X = df.drop(columns=["target"])
y = df["target"]
n_train = int(len(X) * 0.7)
X_train, y_train = X.iloc[:n_train], y.iloc[:n_train]
X_test, y_test = X.iloc[n_train:], y.iloc[n_train:]
base_model = GradientBoostingRegressor(
n_estimators=200, max_depth=3, learning_rate=0.05, random_state=42,
)
cv = BlockBootstrap(n_resamplings=30, length=20, overlapping=False, random_state=42)
mapie_ts = MapieTimeSeriesRegressor(base_model, method="enbpi", cv=cv, agg_function="mean")
mapie_ts.fit(X_train, y_train)
y_pred, y_intervals = mapie_ts.predict(X_test, alpha=alpha, ensemble=True)
lower = y_intervals[:, 0, 0]
upper = y_intervals[:, 1, 0]
width = upper - lower
raw_size = k / np.where(width > 0, width, np.inf)
position_size = np.clip(raw_size, 0.0, max_position)
edge_ratio = np.abs(y_pred) / np.where(width > 0, width, np.inf)
position_size = np.where(edge_ratio < min_edge, 0.0, position_size)
position_size = position_size * np.sign(y_pred)
return pd.DataFrame({
"prediction": y_pred, "lower": lower, "upper": upper,
"width": width, "edge_ratio": edge_ratio,
"position_size": position_size, "actual": y_test.values,
}, index=X_test.index)
Adaptive Conformal Inference (Dalam Talian)
Untuk dagangan langsung kami melaksanakan ACI sebenar dari awal: kekalkan paras kesilapan liputan , kemas kininya secara aditif, dan terbitkan semula kuantil daripada set residual pada setiap langkah. Dua butiran sampel terhingga penting:
- Gunakan statistik tertib (order statistic), bukan kuantil terinterpolasi.
np.quantilemelakukan interpolasi secara lalai, yang boleh jatuh sedikit di bawah pangkat yang diperlukan dan terkurang-liputan; hantarmethod="higher"(setara dengan"inverted_cdf"). - Apabila pangkat yang diperlukan melebihi ( kecil, liputan sasaran tinggi), ambang yang betul ialah (selang = keseluruhan garis), bukan apitan kepada residual terbesar. Mengapit secara senyap mematahkan jaminan .
class AdaptiveConformalSizer:
"""
Online position sizing with Adaptive Conformal Inference (Gibbs & Candes,
2021). Updates the miscoverage LEVEL alpha_t and re-derives the quantile
from the residual set each step -- gamma is in probability units.
"""
def __init__(self, base_model, alpha=0.1, gamma=0.02,
max_position=1.0, min_edge=0.05, k=1e-3):
self.base_model = base_model
self.alpha_target = alpha # target miscoverage
self.alpha_t = alpha # adaptive miscoverage level
self.gamma = gamma # step size, in [0, 1] units
self.max_position = max_position
self.min_edge = min_edge
self.k = k
self.residuals = []
self.q_hat = np.inf
self.coverage_history = []
@staticmethod
def _conformal_quantile(residuals, alpha_t):
"""(1 - alpha_t) conformal quantile via the order statistic."""
n = len(residuals)
if n == 0:
return np.inf
rank = int(np.ceil((1.0 - alpha_t) * (n + 1)))
if rank > n: # required order statistic does not exist
return np.inf # -> interval is the whole line
level = rank / n
return float(np.quantile(residuals, min(level, 1.0), method="higher"))
def calibrate(self, X_cal, y_cal):
preds = self.base_model.predict(X_cal)
self.residuals = list(np.abs(np.asarray(y_cal) - preds))
self.q_hat = self._conformal_quantile(self.residuals, self.alpha_t)
def predict_and_size(self, X_t) -> dict:
mu_hat = self.base_model.predict(np.asarray(X_t).reshape(1, -1))[0]
lower, upper = mu_hat - self.q_hat, mu_hat + self.q_hat
width = upper - lower # = 2 * q_hat
edge_ratio = abs(mu_hat) / width if np.isfinite(width) and width > 0 else 0.0
if edge_ratio < self.min_edge:
size = 0.0
else:
size = min(self.k / width, self.max_position) if width > 0 else 0.0
return {
"prediction": mu_hat, "lower": lower, "upper": upper,
"width": width, "edge_ratio": edge_ratio,
"position_size": size * np.sign(mu_hat),
"alpha_t": self.alpha_t, "q_hat": self.q_hat,
}
def update(self, X_t, y_t: float):
"""ACI update: adapt the LEVEL, then re-derive the quantile."""
mu_hat = self.base_model.predict(np.asarray(X_t).reshape(1, -1))[0]
residual = abs(y_t - mu_hat)
covered = int(residual <= self.q_hat)
err_t = 1 - covered
self.alpha_t = float(np.clip(
self.alpha_t + self.gamma * (self.alpha_target - err_t), 0.0, 1.0
))
self.residuals.append(residual)
self.q_hat = self._conformal_quantile(self.residuals, self.alpha_t)
self.coverage_history.append(covered)
@property
def running_coverage(self) -> float:
if not self.coverage_history:
return float("nan")
return float(np.mean(self.coverage_history))
Menyatukannya: Gelung Backtest
def backtest_aci_sizing(prices: pd.Series, alpha=0.1, gamma=0.02) -> pd.DataFrame:
"""Backtest position sizing with Adaptive Conformal Inference."""
df = prepare_features(prices)
X = df.drop(columns=["target"]).values
y = df["target"].values
index = df.index
n_train = int(len(X) * 0.5)
n_cal = int(len(X) * 0.2)
X_train, y_train = X[:n_train], y[:n_train]
X_cal, y_cal = X[n_train:n_train + n_cal], y[n_train:n_train + n_cal]
X_test, y_test = X[n_train + n_cal:], y[n_train + n_cal:]
test_index = index[n_train + n_cal:]
model = GradientBoostingRegressor(
n_estimators=200, max_depth=3, learning_rate=0.05, random_state=42,
)
model.fit(X_train, y_train)
sizer = AdaptiveConformalSizer(base_model=model, alpha=alpha, gamma=gamma)
sizer.calibrate(X_cal, y_cal)
records = []
for i in range(len(X_test)):
result = sizer.predict_and_size(X_test[i])
result["actual"] = y_test[i]
result["pnl"] = result["position_size"] * y_test[i]
records.append(result)
sizer.update(X_test[i], y_test[i]) # online residual + level update
results = pd.DataFrame(records, index=test_index)
results["cumulative_pnl"] = results["pnl"].cumsum()
results["running_coverage"] = (
((results["lower"] <= results["actual"]) &
(results["actual"] <= results["upper"])).expanding().mean()
)
return results
Menilai Keputusan
def evaluate(results: pd.DataFrame, alpha: float = 0.1):
"""Print evaluation metrics for conformal position sizing."""
covered = ((results["actual"] >= results["lower"]) &
(results["actual"] <= results["upper"]))
print(f"Target coverage: {1 - alpha:.1%}")
print(f"Empirical coverage: {covered.mean():.1%}")
print(f"Mean interval width: {results['width'].mean():.6f}")
print(f"Median position size: {results['position_size'].abs().median():.4f}")
print(f"Fraction no-trade: {(results['position_size'] == 0).mean():.1%}")
print(f"Total PnL (bps): {results['pnl'].sum() * 10000:.1f}")
sd = results['pnl'].std()
sharpe = results['pnl'].mean() / sd * np.sqrt(252) if sd > 0 else float('nan')
print(f"Sharpe (annualized): {sharpe:.2f}")
Pertimbangan Praktikal
Memilih Skor Nonconformity
Residual mutlak ialah pilihan lalai, tetapi ia mengandaikan selang ramalan sepatutnya simetri di sekeliling ramalan titik. Untuk pulangan kewangan, selang tak simetri selalunya lebih masuk akal:
- Conformalized Quantile Regression (CQR): Suaikan peregres kuantil pada paras dan , kemudian conformalize (Romano et al., 2019). Selang itu menyesuaikan bentuknya kepada taburan setempat — lebih lebar di sebelah bawah semasa drawdown, lebih lebar di sebelah atas semasa lonjakan. (Dengan CQR selang itu tidak lagi simetri, jadi ialah lebar atas-tolak-bawah yang tulen — terus gunakan sebagai penyebut di mana-mana sahaja.)
- Skor ternormal: , di mana ialah anggaran volatiliti setempat. Ini menghasilkan selang yang menyesuaikan secara bersyarat — lebih ketat semasa rejim volatiliti rendah, lebih lebar semasa rejim volatiliti tinggi — sambil mengekalkan liputan marginal.
Saiz Set Kalibrasi
Jaminan liputan split conformal sah untuk sebarang saiz set kalibrasi , tetapi lebar selang berkurangan apabila meningkat. Untuk yang sangat kecil, statistik tertib yang diperlukan mungkin tidak wujud, dalam keadaan itu ambang yang jujur ialah (selang yang tidak informatif tetapi sah) — mengapit kepada residual terbesar secara senyap membatalkan jaminan. Untuk dagangan praktikal:
- titik kalibrasi memberikan selang yang agak ketat.
- lebih disukai untuk anggaran kuantil yang stabil.
- Dengan ACI, set kalibrasi hanya untuk pemulaan; pengemaskinian paras dalam talian menguruskan selebihnya.
Kekerapan Latihan Semula
Model asas boleh menjadi basi. Dua pendekatan:
- Latih semula secara berkala (cth. bulanan) dan kalibrasi semula kuantil conformal.
- Gunakan ACI dan biarkan paras adaptif mengimbangi kebasian model — selang melebar secara automatik apabila residual model membesar.
Pilihan 2 lebih ringkas dan mengejutkan keberkesanannya. Lapisan conformal bertindak sebagai jaring keselamatan: walaupun model merosot, kekerapan liputan ACI jangka panjang masih menumpu kepada sasaran.
Kos Transaksi
Selang conformal berinteraksi dengan kos transaksi dengan cara yang berguna. Apabila selang lebar (ketidakpastian tinggi), posisi adalah kecil, jadi pusing ganti (turnover) adalah rendah. Apabila selang menyempit (model yakin), posisi membesar — tetapi model lebih berkemungkinan betul, jadi pusing ganti itu berbaloi untuk dibayar.
Anda juga boleh menggabungkan kos transaksi secara langsung ke dalam penapis tanpa-dagang:
Ini memastikan anda hanya berdagang apabila kelebihan bersih jangkaan melebihi satu ambang yang diskalakan oleh lebar conformal — menggunakan penyebut yang sama seperti di mana-mana sahaja.
Perbandingan dengan Kaedah Tradisional
| Sifat | Gaussian CI | Bootstrap CI | Conformal PI |
|---|---|---|---|
| Andaian taburan | Ralat normal | i.i.d. + asimptot | Tiada (kebolehtukaran) |
| Jaminan sampel terhingga | Tidak | Tidak | Ya |
| Berfungsi dengan sebarang model | Tidak | Ya | Ya |
| Menyesuaikan dengan heteroskedastisiti | Tidak | Sebahagian | Dengan CQR / skor ternormal |
| Mengendalikan anjakan taburan | Tidak | Tidak | Varian ACI / EnbPI |
| Kos pengkomputeran | Rendah | Sederhana | Split: rendah; jackknife+: suaian semula; full: terlalu mahal |
Bootstrap adalah "asimptot" hanya dalam jaminannya; ia masih mengandaikan data i.i.d./boleh ditukar dan kelicinan, jadi sel andaian-taburannya bukanlah "bebas-andaian". Dan lajur tunggal "conformal" itu menyembunyikan kos yang sangat berbeza merentas varian, yang kini dijelaskan oleh baris kos.
Batasan
Conformal prediction bukanlah sihir. Batasan utama untuk dagangan:
-
Liputan marginal, bukan bersyarat. Jaminannya ialah secara marginal — dipuratakan ke atas kerawakan dalam kedua-dua dan . Untuk nilai pensyaratan tertentu , liputan setempat boleh berada di atas atau di bawah . Conformalized quantile regression menangani perkara ini sebahagiannya.
-
Kebolehtukaran ialah syarat sebenar. Untuk split conformal, data kalibrasi dan titik ujian mesti boleh ditukar. Data kewangan tidak. ACI dan EnbPI melonggarkan ini kepada jaminan jangka panjang, tetapi liputan jangka pendek boleh menyimpang.
-
Lebar selang bukan ketumpatan kebarangkalian. Selang conformal memberitahu anda di mana akan jatuh dengan kebarangkalian , tetapi ia tidak mengatakan apa-apa tentang taburan dalam selang itu. Ia bukan pengganti bagi taburan ramalan penuh — yang merupakan tepatnya sebab menerbitkan dan Kelly daripadanya memerlukan andaian tambahan yang eksplisit.
-
Sampah masuk, lebih lebar keluar. Model asas yang buruk menghasilkan selang yang lebar. Conformal prediction menjamin liputan tetapi bukan kegunaan. Jika model anda tiada kuasa ramalan, selang akan menjadi begitu lebar sehingga penentu saiz posisi tidak pernah berdagang.
Ringkasan
Conformal prediction menyediakan rangka kerja yang teliti dan bebas-taburan untuk kuantifikasi ketidakpastian yang menyelit secara semula jadi ke dalam penentuan saiz posisi:
- Split conformal untuk kalibrasi statik luar talian dengan liputan sampel terhingga.
- Jackknife+ apabila data kalibrasi langka dan anda ingin menggunakan kesemua pemerhatian (dengan kos suaian semula).
- Adaptive conformal inference / EnbPI untuk dagangan dalam talian dengan pasaran tak pegun.
- Penentuan saiz posisi melalui lebar selang songsang dan penapis tanpa-dagang nisbah-kelebihan — dan, jika anda pergi ke Kelly, hanya selepas menerbitkan dan secara jujur, bukan melalui pendarab yang tidak berjustifikasi.
Kelebihan utama berbanding alternatif parametrik: anda tidak pernah perlu menentukan atau mengesahkan andaian taburan parametrik. Selang itu jujur secara binaan (secara marginal, di bawah kebolehtukaran). Bagi seorang pedagang sistematik, ini bermaksud satu lagi sumber risiko model yang berkurang — dan dalam perniagaan yang risiko modelnya bersifat eksistensial, itu penting.
Rujukan:
- Papadopoulos, H., Proedrou, K., Vovk, V., Gammerman, A. (2002). Inductive confidence machines for regression. ECML.
- Vovk, V., Gammerman, A., Shafer, G. (2005). Algorithmic Learning in a Random World. Springer.
- Lei, J., G'Sell, M., Rinaldo, A., Tibshirani, R.J., Wasserman, L. (2018). Distribution-free predictive inference for regression. JASA.
- Xu, C., Xie, Y. (2021). Conformal prediction interval for dynamic time-series (EnbPI). ICML.
- Barber, R.F., Candes, E.J., Ramdas, A., Tibshirani, R.J. (2021). Predictive inference with the jackknife+. Annals of Statistics.
- Gibbs, I., Candes, E.J. (2021). Adaptive conformal inference under distribution shift. NeurIPS.
- Gibbs, I., Candes, E.J. (2024). Conformal inference for online prediction with arbitrary distribution shifts. JMLR.
- Romano, Y., Patterson, E., Candes, E.J. (2019). Conformalized quantile regression. NeurIPS.
- Cordier, T. et al. (2022). MAPIE: an open-source library for distribution-free uncertainty quantification. arXiv:2207.12274.
Pengarang
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.