eqVolatilitySurfaceBuilder

Syntax

eqVolatilitySurfaceBuilder(referenceDate, optionExpiries, strikes, optionPrices, payoffTypes, spot, discountCurve, dividendCurve, [model='SVI'], [surfaceName])

Details

Constructs an equity option volatility surface.

Parameters

referenceDate: A DATE scalar specifying the reference date.

optionExpiries: A DATE vector specifying the option expiries.

strikes: A DOUBLE matrix specifying the option strikes. The number of columns must be the same as the length of optionExpiries .

optionPrices: A DOUBLE matrix specifying the option prices. The number of columns must be the same as the length of optionExpiries .

payoffTypes: A STRING matrix specifying the option payoff types. The number of columns must be the same as the length of optionExpiries . Supported values include "Call" and "Put". Note: strikes , optionPrices , and payoffTypes must have the same shape.

spot: ADOUBLE scalar specifying the spot price.

discountCurve: An IrYieldCurve object specifying the discount curve.

dividendCurve: A DividendCurve object specifying the underlying dividend curve.

model (optional): A STRING scalar specifying the model used to build the volatility smile. Valid values: "SVI" (default), "SABR", "Linear", "CubicSpline".

surfaceName (optional): A STRING scalar specifying the surface name.

Returns

A VolatilitySurface object.

Examples

The following code demonstrates the process of constructing the volatility surface for options based on the STAR Market 50 ETF (588080.SH).

referenceDate = 2026.02.11
spot = 1.5007

// 1. Term Structure
termDates = [2026.02.25, 2026.03.25, 2026.06.24, 2026.09.23]

// 2. Raw Data Matrices (Aligned)
callPrices = matrix(
    [0.2402, 0.1908, 0.1415, 0.0927, 0.0496, 0.0199, 0.0075, 0.0032, 0.0014, 0.0010, 0.0007, 0.0002],
    [0.2398, 0.1956, 0.1516, 0.1095, 0.0780, 0.0530, 0.0347, 0.0232, 0.0152, 0.0101, 0.0069, 0.0043],
    [0.2537, 0.2137, 0.1803, 0.1494, 0.1252, 0.1051, 0.0871, 0.0717, 0.0597, 0.0500, 0.0421, 0.0361],
    [0.2730, 0.2442, 0.2086, 0.1816, 0.1676, 0.1439, 0.1301, 0.1099, 0.0961, 0.0848, 0.0748, 0.0663]
)
putPrices = matrix(
    [0.0003, 0.0003, 0.0004, 0.0018, 0.0085, 0.0297, 0.0671, 0.1130, 0.1601, 0.2084, 0.2609, 0.3124],
    [0.0033, 0.0062, 0.0114, 0.0215, 0.0383, 0.0621, 0.0947, 0.1331, 0.1767, 0.2114, 0.2565, 0.3032],
    [0.0234, 0.0349, 0.0505, 0.0713, 0.0936, 0.1237, 0.1562, 0.1919, 0.2218, 0.2610, 0.3010, 0.3437],
    [0.0445, 0.0640, 0.0808, 0.1062, 0.1312, 0.1615, 0.1882, 0.2187, 0.2567, 0.2937, 0.3323, 0.3777]
)
strikes = matrix(
    [1.2500, 1.3000, 1.3500, 1.4000, 1.4500, 1.5000, 1.5500, 1.6000, 1.6500, 1.7000, 1.7500, 1.8000],
    [1.2500, 1.3000, 1.3500, 1.4000, 1.4500, 1.5000, 1.5500, 1.6000, 1.6500, 1.7000, 1.7500, 1.8000],
    [1.2500, 1.3000, 1.3500, 1.4000, 1.4500, 1.5000, 1.5500, 1.6000, 1.6500, 1.7000, 1.7500, 1.8000],
    [1.2500, 1.3000, 1.3500, 1.4000, 1.4500, 1.5000, 1.5500, 1.6000, 1.6500, 1.7000, 1.7500, 1.8000]
)

// 3. Discount Curve 
discountCurveDict = {
    "mktDataType": "Curve",
    "curveType": "IrYieldCurve",
    "curveName": "CNY_RF",
    "referenceDate": referenceDate,
    "currency": "CNY",
    "dayCountConvention": "Actual365",
    "compounding": "Continuous",
    "interpMethod": "Linear",
    "extrapMethod": "Flat",
    "dates": [referenceDate + 1, referenceDate + 3650],
    "values":[0.02, 0.02]
}
discountCurve = parseMktData(discountCurveDict)

// 4. Implied Dividend Curve
// Using Call-Put Parity on the full matrices
dividendCurve = eqDividendCurveBuilder(
    referenceDate, termDates, "CallPutParity", ,
    callPrices, putPrices, strikes, spot, discountCurve, "Actual365"
)

// 5. Volatility Surface Construction Data
// Selecting OTM options: Puts for Low Strikes, Calls for High Strikes
optionExpiries = termDates
optionPrices = matrix(
    [0.0003, 0.0003, 0.0004, 0.0018, 0.0085, 0.0297, 0.0075, 0.0032, 0.0014, 0.0010, 0.0007, 0.0002],
    [0.0033, 0.0062, 0.0114, 0.0215, 0.0383, 0.0621, 0.0347, 0.0232, 0.0152, 0.0101, 0.0069, 0.0043],
    [0.0234, 0.0349, 0.0505, 0.0713, 0.0936, 0.1237, 0.0871, 0.0717, 0.0597, 0.0500, 0.0421, 0.0361],
    [0.0445, 0.0640, 0.0808, 0.1062, 0.1312, 0.1615, 0.1301, 0.1099, 0.0961, 0.0848, 0.0748, 0.0663]
)
payoffTypes = matrix(
    ["Put", "Put", "Put", "Put", "Put", "Put", "Call", "Call", "Call", "Call", "Call", "Call"],
    ["Put", "Put", "Put", "Put", "Put", "Put", "Call", "Call", "Call", "Call", "Call", "Call"],
    ["Put", "Put", "Put", "Put", "Put", "Put", "Call", "Call", "Call", "Call", "Call", "Call"],
    ["Put", "Put", "Put", "Put", "Put", "Put", "Call", "Call", "Call", "Call", "Call", "Call"]
)

// 6. Build Surface.
surf = eqVolatilitySurfaceBuilder(
        referenceDate,
        optionExpiries,
        strikes,        // Matrix
        optionPrices,   // Matrix (OTM)
        payoffTypes,    // Matrix ("Call"/"Put")
        spot,
        discountCurve,
        dividendCurve,
        "SABR",         // Model
        "588080.SH"     // Name
)
print(surf)

// 波动率曲面可视化


dts = (0..20)*0.05
ks = (0..40)*((max(strikes[0])-min(strikes[0]))\40)+min(strikes[0])
m = optionVolPredict(surf, dts, ks).rename!(dts, ks)


plot(
    m,
    title=["Vol Surface", "K", "T", "vol"],
    chartType=SURFACE)
    

Related Functions: parseMktData, eqDividendCurveBuilder