DEV Community

shakti tiwari
shakti tiwari

Posted on • Originally published at optiontradingwithai.in

AI Options Trading on the TAIEX

AI Options Trading on the TAIEX

Answer-first: Build an AI-assisted options-trading bot for the TAIEX by combining a feature pipeline (options chain, implied volatility, PCR), a gradient-boosting classifier for directional probability, and a backtest that enforces Greeks-based risk limits. The model emits a probability; a rules engine decides whether to act. Here is a runnable Python scaffold.

Written for retail quants targeting the TAIEX market (Taiwan Stock Exchange (TWSE), regulator FSC (Taiwan)).

Educational only. Not investment advice. Options can lose their full value. Consult FSC (Taiwan) and a licensed advisor.

Why TAIEX options are a strong AI target

  • Concentrated liquidity at major strikes -> cleaner labels than broad ETFs.
  • TAIEX Volatility Index -> a native regime signal.
  • FSC (Taiwan) clarity -> transparent cost disclosure.

Architecture (three layers)

1. Data/Feature Pipeline -> chain, IV, PCR
2. Model (gradient boosting) -> P(direction | features)
3. Rules + Greeks Engine -> sizing, stop, DTE limit
Enter fullscreen mode Exit fullscreen mode

Layer 1 — Features (Python)

# Mac / Linux / Termux
python3 features.py
# Windows CMD
py features.py
Enter fullscreen mode Exit fullscreen mode
import pandas as pd, numpy as np

def build_features(chain: pd.DataFrame, pcr: float) -> pd.DataFrame:
    df = chain.copy()
    df["mid"] = (df["bid"] + df["ask"]) / 2.0
    df["spread_pct"] = (df["ask"] - df["bid"]) / df["mid"].clip(lower=1e-9)
    df["moneyness"] = df["strike"] / df["spot"] - 1.0
    atm_iv = df.loc[(df["moneyness"].abs()).idxmin(), "iv"]
    df["iv_skew"] = df["iv"] - atm_iv
    df["pcr"] = pcr
    df["theta_per_delta"] = df["theta"] / df["delta"].clip(lower=1e-9)
    return df

if __name__ == "__main__":
    demo = pd.DataFrame([{"strike": 22000.0, "bid": 22000.0*0.004, "ask": 22000.0*0.0044,
        "iv": 0.18, "delta": 0.5, "gamma": 0.002, "theta": -25.0, "vega": 60.0,
        "oi": 50000, "volume": 3000, "spot": 21900.0, "dte": 10}])
    f = build_features(demo, pcr=0.95)
    print(f[["mid","spread_pct","moneyness","iv_skew","theta_per_delta"]].to_string())
Enter fullscreen mode Exit fullscreen mode

Layer 2 — Model (HistGradientBoosting)

# Mac / Linux / Termux
python3 train.py
# Windows CMD
py train.py
Enter fullscreen mode Exit fullscreen mode
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import TimeSeriesSplit, roc_auc_score
import pandas as pd

FEATURES = ["spread_pct","moneyness","iv_skew","pcr",
            "theta_per_delta","gamma","vega","dte","oi","volume"]

def train(X: pd.DataFrame, y: pd.Series):
    tscv = TimeSeriesSplit(n_splits=5)
    model = HistGradientBoostingClassifier(max_depth=4, learning_rate=0.05, max_iter=300)
    for tr, te in tscv.split(X):
        model.fit(X.iloc[tr], y.iloc[tr])
        pred = model.predict_proba(X.iloc[te])[:, 1]
        print("fold AUC:", round(roc_auc_score(y.iloc[te], pred), 3))
    model.fit(X, y)
    return model
Enter fullscreen mode Exit fullscreen mode

Time-series split, never random — random leaks the future and inflates AUC.

Layer 3 — Greeks rules engine

def decide(prob_up, greeks, max_capital, risk_per_trade=0.01):
    if not (0.58 <= prob_up <= 0.80):
        return {}
    if greeks["dte"] <= 1:
        return {}
    if abs(greeks["vega"]) > 8.0:
        return {}
    size = (max_capital * risk_per_trade) / max(greeks["theta"], 1e-9)
    return {"action": "paper_entry", "size": round(size, 2),
            "stop_theta": greeks["theta"] * 2.5}
Enter fullscreen mode Exit fullscreen mode

Backtest (pandas vectorized)

def backtest(signals: pd.DataFrame, fees_bps=2.0) -> float:
    s = signals.copy()
    s["position"] = ((s["prob_up"] >= 0.60) & (s["dte"] > 1)).astype(int)
    s["pnl"] = s["position"] * (s["delta"] * s["spot_ret"] * 100
                                - s["theta"] + s["prob_up"] - 0.5)
    s["pnl"] -= (s["position"] * fees_bps / 10000.0)
    return s["pnl"].sum()
Enter fullscreen mode Exit fullscreen mode

TAIEX Volatility Index regime filter

  • Vol low: favor longer-DTE structures.
  • Vol mid: baseline.
  • Vol high: halve size, widen band.

Worked Example (TAIEX, strike 22000.0, DTE 10)

Suppose the model outputs prob_up = 0.63, Greeks delta=0.5, theta=-25.0, vega=60.0. Capital 10,000 TWD, risk 1%:

  1. risk_per_trade = 0.01.
  2. `size = (10_000 * 0.01) / max(25.0, 1e-9) = 4.0 TWD budget.
  3. Stop at theta * 2.5 = -62.5.
  4. Open only if dte > 1 and vega <= 8 — both satisfied. Result: paper_entry, size 4.0 TWD, stop at -62.5 theta.

Market Data Sources (FSC (Taiwan))

  • Taiwan Stock Exchange (TWSE): official options chain, IV surface, OI.
  • TAIEX Volatility Index: regime signal.
  • FSC (Taiwan) publications: conduct rules, product governance.
  • Broker APIs (Yuanta, Fubon, KGI): forward Taiwan Stock Exchange (TWSE) prices.

Local Market Structure

Taiwan index options are among the most actively traded globally; the order book is deep but its OTC overshadow means broker quotes need cleaning.

Position Sizing Calculator (runnable)

`python
def position_size(capital, risk_pct, theta, vega, vega_cap=8.0):
base = capital * risk_pct
if abs(vega) > vega_cap:
base *= vega_cap / abs(vega)
lots = base / max(abs(theta), 1e-9)
return round(lots, 2)

if name == "main":
print("calm :", position_size(10000, 0.01, 25.0, 3.0))
print("stress:", position_size(10000, 0.01, 25.0, 24.0))
`

The stress case shows the calculator automatically cuts exposure when vega blows past the cap — exactly the behaviour the rules engine enforces.

Strategy Variations

  • Vertical spread: caps max loss, favourite in high-vega regimes.
  • Calendar spread: profits from term-structure slope.
  • Iron condor: collects theta, watch gamma at short strikes.
  • Naked long call/put: highest convex payoff, only with prob_up 0.70-0.80 and dte > 5.

Walk-Forward Evaluation

A single TimeSeriesSplit is honest, but production needs walk-forward: retrain on a rolling window, test on the next, slide forward. This catches model decay that static splits hide.

Feature Importance

On options data the ranking is usually: (1) theta_per_delta, (2) iv_skew, (3) moneyness, (4) vol-index, (5) pcr. If your model ranks oi or volume first, suspect leakage — those are post-hoc liquidity, not predictive. Drop them and re-check.

Glossary

  • Delta: directional exposure per 1 unit of underlying.
  • Gamma: rate of change of delta; high gamma = convex risk.
  • Theta: daily time decay; cost of holding.
  • Vega: sensitivity to implied volatility; dominant risk in stress.
  • IV skew: strike IV minus ATM IV; cheapness signal.
  • PCR: put-call ratio; sentiment extreme indicator.
  • DTE: days to expiry; hard stop before assignment.
  • Moneyness: strike / spot - 1; negative = ITM, positive = OTM.

Deployment Checklist

Before any paper trade:

  • [ ] TimeSeriesSplit AUC printed, not random-split.
  • [ ] Walk-forward mean AUC stable across windows.
  • [ ] Feature importance sane (no leakage features ranked top).
  • [ ] Rules engine hard limits active (dte, vega, prob band).
  • [ ] Backtest includes fees and theta accrual.
  • [ ] Position size calculator wired to the rules layer.

Monitoring and Alerting (production hygiene)

A model that is not monitored decays silently. Wire three alerts:

  1. AUC drift: retrain daily; if rolling 5-day AUC drops more than 3% from the 30-day mean, halt paper entries and flag for review.
  2. Fill divergence: compare expected mid (from your predicted probability band) to actual fill; a persistent gap means the broker quote is wider than your assumption — tighten spread_pct.
  3. Vol-regime flip: if the local volatility index moves more than 1.5 standard deviations in a session, force the risk layer into the high-vol branch regardless of model output.

These three alerts catch the failures that a backtest, by definition, cannot — because the backtest already assumed the regime you are now living in.

Regime-Switching Model (optional upgrade)

Instead of a single classifier, train two: one on low-vol windows, one on high-vol windows, and route each live row to the matching model by the current volatility-index z-score. This typically adds 1-3 AUC points over a monolithic model because the IV-skew feature behaves oppositely in the two regimes. The routing code is trivial:

python
def route(model_low, model_high, row, vol_z):
m = model_high if vol_z > 0 else model_low
return m.predict_proba(row)[:, 1]

Keep the rules engine identical — the routing only changes which probability the engine receives, never the hard limits.

Why This Beats a Black-Box Net

A gradient-boosting model on ten transparent features is explainable: you can show a regulator or a client exactly which input moved the decision. A deep net cannot. For retail options — where a single bad fill ends the week — explainability is not a nicety, it is the difference between surviving a regime change and blowing up inside it. Build the boring model, enforce the boring risk layer, and let compounding do the rest.

Common mistakes

  1. Random split on time-series.
  2. Ignoring bid/ask spread.
  3. Naked short options for "high probability".
  4. Overfitting IV skew to one regime.
  5. No position sizing.

Weekly routine

  • Mon: rebuild features, retrain if AUC drift > 3%.
  • Tue–Thu: paper-trade, log fills vs prediction.
  • Fri: review false positives, tighten rules.

FAQ

Q1. Do I need a neural network for TAIEX options?
No. Gradient-boosting on well-built features typically matches or beats nets on tabular options data and is easier to audit.

Q2. Is this legal under FSC (Taiwan) rules?
Building and paper-trading your own model is legal. Live automation triggers broker review. Consult a compliance professional.

Q3. How much capital per trade?
<=1% of capital per trade, scaled by Greeks. Never risk what you can't lose.

Q4. Can I run this from a phone?
Yes. Pure Python/pandas runs on Termux or a Raspberry Pi.

Q5. Biggest edge — model or risk layer?
The risk layer. A mediocre model with strict Greek limits survives; a great model without them does not.

Footer

Shakti Tiwari — Options Trader, XGBoost Expert.
Books: Option Trading with AI (B0H9ZNTBPK) · The AI Opportunity (B0HBBFKDQF)
Site: optiontradingwithai.in · Free help: shaktitiwari715@gmail.com
Dev.to: @shaktitiwari · X: @shaktitiwari

Top comments (0)