portfolioPricer

Syntax

portfolioPricer(instrument, amount, pricingDate, marketData)

Arguments

instrument is an INSTRUMENT object indicating the instrument(s) to be priced. It can be a single contract or multiple contracts.

amount is an INT scalar or a vector of the same length as instrument, indicating the amount of the contracts.

pricingDate is a DATE scalar specifying the pricing date.

marketData A MKTDATA vector or nested dictionary indicating the market data.

Details

Perform portfolio pricing for financial contract(s) (which can be of the same or different types).

Return value: A DOUBLE scalar.

Matching Rules of Instrument and MarketData

Currently, only instrument types illustrated as leaf nodes in the classification tree below are supported:

The system determines the market data according to the following priority when pricing:

  1. If the instrument explicitly specifies the market data, use the specified market data;

  2. If not, the system automatically matches suitable market data based on predefined rules.

The matching rules for different financial instruments are described in detail below.

Bond (Bond)

Bond pricing requires a discount curve. Specify the discount curve name via the "discountCurve" field, for example:

bond = {
    "productType": "Cash",
    "assetType": "Bond",
    "bondType": "FixedRateBond",
    "version": 0, 
    "instrumentId": "1382011.IB",
    "start": "2013.01.14",
    "maturity": "2028.01.14",
    "issuePrice": 100.0,
    "coupon": 0.058,
    "frequency": "Annual",
    "dayCountConvention": "ActualActualISDA"
    "currency": "CNY",              //optional
    "subType": "MTN",               //optional
    "creditRating": "AAA",          //optional
    "discountCurve": "CNY_MTN_AAA"  //optional
}

Rules for selecting the discount curve:

  • If "discountCurve" is specified, the function looks up the corresponding curve directly in the marketData parameter.

  • If "discountCurve" is not specified but "currency", "subType", and "creditRating" are specified, the system automatically generates a discount curve name of the form currency + "_" + subType + "_" + creditRating, where "currency" defaults to "CNY".

  • If none of the optional fields are provided, the discount curve defaults to "CNY_TREASURY_BOND".

Treasury Futures (BondFutures)

The deliverable basket of treasury futures are treasury bonds, the rules for selecting the discount curve when defining the instrument are:

  • If the "discountCurve" field is specified, use the specified curve for pricing.

  • If not, use the default discount curve "CNY_TREASURY_BOND".

Deposit (Deposit)

For deposit pricing, specify only the discount curve "discountCurve":

  • If the "discountCurve" field is specified, use the specified curve for pricing.

  • If not, the system automatically matches the discount curve based on the currency.

currency discountCurve
CNY CNY_FR_007
USD USD_SOFR
EUR EUR_EONIA

IR Fixed-Floating Swap (IrFixedFloatingSwap)

Pricing an IR Fixed-Floating Swap requires three curves: discountCurve, forwardCurve, and assetPriceCurve. The current version only supports swaps that use FR_007 or SHIBOR_3M as the floating reference rate.

  • If the curve is specified in the instrument parameter, use the specified curve for pricing.

  • If not, the system automatically selects default curves based on the currency and the floating reference rate.

currency iborIndex discountCurve forwardCurve assetPriceCurve
CNY FR_007 CNY_FR_007 CNY_FR_007 PRICE_FR_007
CNY SHIBOR_3M CNY_FR_007 CNY_SHIBOR_3M PRICE_SHIBOR_3M

The assetPriceCurve is the historical data of the floating reference rate, which is used to calculate the floating rate for the first cash flow of the pricing date.

Foreign Exchange Forward (FxForward) / Foreign Exchange Swap (FxSwap)

Pricing these two linear products requires binding "domesticCurve" and "foreignCurve", and retrieving the corresponding "FxSpot" based on the "currencyPair".

  • If the user specifies "domesticCurve" and "foreignCurve", use the specified curves.

  • If not, the system automatically selects default curves according to the "currencyPair".

currencyPair domesticCurve foreignCurve
USDCNY CNY_FR_007 USD_USDCNY_FX
EURCNY CNY_FR_007 EUR_EURCNY_FX
EURUSD USD_SOFR EUR_EURUSD_FX

The "foreignCurve" is the implied foreign discount curve inferred using the covered interest rate parity formula based on foreign exchange swap.

Fx European Style Option (FxEuropeanOption)

In addition to "domesticCurve" and "foreignCurve", Fx European Style Option pricing also requires "FxSpot" and the "FxVolatilitySurface". Both of these market data can be automatically matched based on the "underlying" (the currency pair).

  • If the instrument explicitly specifies "domesticCurve", "foreignCurve", use them directly.

  • If not, the system automatically matches based on "underlying" (the currency pair).

currencyPair fxSpot domesticCurve foreignCurve volSurf
USDCNY USDCNY CNY_FR_007 USD_USDCNY_FX USDCNY
EURCNY EURCNY CNY_FR_007 EUR_EURCNY_FX EURCNY
EURUSD EURUSD USD_SOFR EUR_EURUSD_FX EURUSD

Examples

// instrument

//FX Forward
fxFwd1 = {
    "productType": "Forward",
    "forwardType": "FxForward",
    "version": 0,
    "expiry": 2025.10.08,
    "delivery": 2025.10.10,
    "currencyPair": "USDCNY",
    "direction": "Buy",
    "notional": ["USD", 1E6],
    "strike": 7.2
}

fxFwdUsdCny = parseInstrument(fxFwd1)

fxFwd2 = {
    "productType": "Forward",
    "forwardType": "FxForward",
    "version": 0,
    "expiry": 2025.10.08,
    "delivery": 2025.10.10,
    "currencyPair": "EURCNY",
    "direction": "Buy",
    "notional": ["EUR", 1E6],
    "strike": 8.2
}

fxFwdEurCny = parseInstrument(fxFwd2)

//FX Swap
fxSwap1 = {
    "productType": "Swap",
    "swapType": "FxSwap",
    "version": 0,
    "currencyPair": "USDCNY",
    "direction": "Buy",
    "notional": ["USD", 1E6],
    "nearStrike": 7.2,
    "nearExpiry": 2025.12.08,
    "nearDelivery": 2025.12.10,
    "farStrike": 7.3,
    "farExpiry": 2026.06.08,
    "farDelivery": 2026.06.10
}

fxSwapUsdCny = parseInstrument(fxSwap1)

fxSwap2 = {
    "productType": "Swap",
    "swapType": "FxSwap",
    "version": 0,
    "currencyPair": "EURCNY",
    "direction": "Buy",
    "notional": ["EUR", 1E6],
    "nearStrike": 8.2,
    "nearExpiry": 2025.12.08,
    "nearDelivery": 2025.12.10,
    "farStrike": 8.3,
    "farExpiry": 2026.06.08,
    "farDelivery": 2026.06.10
}

fxSwapEurCny = parseInstrument(fxSwap2)

//FX European Option
fxOption1 = {
    "productType": "Option",
    "optionType": "EuropeanOption",
    "assetType": "FxEuropeanOption",
    "version": 0,
    "notional": ["USD", 1E6],
    "strike": 7.0,
    "maturity": 2025.12.08,
    "payoffType": "Call",
    "dayCountConvention": "Actual365",
    "underlying": "USDCNY"
}

fxOptionUsdCny = parseInstrument(fxOption1)

fxOption2 = {
    "productType": "Option",
    "optionType": "EuropeanOption",
    "assetType": "FxEuropeanOption",
    "version": 0,
    "notional": ["EUR", 1E6],
    "strike": 8.0,
    "maturity": 2025.12.08,
    "payoffType": "Call",
    "dayCountConvention": "Actual365",
    "underlying": "EURCNY"
}

fxOptionEurCny= parseInstrument(fxOption2)

//Bond
bond1 = {
    "productType": "Cash",
    "assetType": "Bond",
    "bondType": "FixedRateBond",
    "version": 0, 
    "instrumentId": "220010.IB",
    "start": 2020.12.25,
    "maturity": 2031.12.25,
    "issuePrice": 100.0,
    "coupon": 0.0149,
    "frequency": "Annual",
    "dayCountConvention": "ActualActualISDA",
    "discountCurve": "CNY_TREASURY_BOND"
}

bond = parseInstrument(bond1)

//Government Bond Futures
bondFut1 = {
    "productType": "Futures",
    "futuresType": "BondFutures",
    "version": 0,
    "instrumentId": "T2509",
    "nominal": 100.0,
    "maturity": "2025.09.12",
    "settlement": "2025.09.16",
    "underlying": bond1,
    "nominalCouponRate": 0.03
}

bondFut = parseInstrument(bondFut1)

//Deposit
deposit1 = {
    "productType": "Cash",
    "assetType": "Deposit",
    "version": 0, 
    "start": 2025.06.15,
    "maturity": 2025.12.15,
    "rate": 0.02,
    "dayCountConvention": "Actual360",
    "notional":["CNY", 1E6],
    "payReceive": "Receive"
}

deposit = parseInstrument(deposit1)

//Interest Rate Swap
irs1 =  {
    "productType": "Swap",
    "swapType": "IrSwap",
    "irSwapType": "IrFixedFloatingSwap",
    "version": 0, 
    "start": 2025.06.16,
    "maturity": 2028.06.16,
    "frequency": "Quarterly",
    "fixedRate": 0.018,
    "calendar": "CFET", 
    "fixedDayCountConvention": "Actual365",
    "floatingDayCountConvention": "Actual365",
    "payReceive": "Pay",
    "iborIndex": "FR_007",
    "spread": 0.0001,
    "notional":["CNY", 1E8]
}

irs = parseInstrument(irs1)


//mktData
aod = 2025.08.18

fxSpot1 = {
    "mktDataType": "Spot",
    "spotType": "FxSpot",
    "version": 0, 
    "spotDate": aod+2 ,
    "referenceDate": aod ,
    "value": 7.1627,
    "unit": "USDCNY"
}

fxSpotUsdCny = parseMktData(fxSpot1)

fxSpot2 = {
    "mktDataType": "Spot",
    "spotType": "FxSpot",
    "version": 0, 
    "spotDate": aod+2 ,
    "referenceDate": aod ,
    "value": 8.3768,
    "unit": "EURCNY"
}

fxSpotEurCny = parseMktData(fxSpot2)

curve1 = {
    "mktDataType": "Curve",
    "curveType": "IrYieldCurve",
    "curveName": "CNY_FR_007",
    "referenceDate": aod,
    "currency": "CNY",
    "dayCountConvention": "ActualActualISDA",
    "compounding": "Continuous",
    "interpMethod": "Linear",
    "extrapMethod": "Flat",
    "dates":[2025.08.21, 2025.08.27, 2025.09.03, 2025.09.10, 2025.09.22, 2025.10.20, 2025.11.20, 
             2026.02.24,2026.05.20, 2026.08.20, 2027.02.22, 2027.08.20, 2028.08.21],
    "values":[1.4759, 1.5331, 1.5697, 1.5239, 1.4996, 1.5144, 1.5209, 
              1.5539, 1.5461, 1.5316, 1.5376, 1.5435, 1.5699] / 100.0
}

curveCnyFr007 = parseMktData(curve1)

curve2 = {
    "mktDataType": "Curve",
    "curveType": "IrYieldCurve",
    "curveName": "USD_USDCNY_FX",
    "referenceDate": aod ,
    "currency": "USD",
    "dayCountConvention": "ActualActualISDA",
    "compounding": "Continuous",
    "interpMethod": "Linear",
    "extrapMethod": "Flat",
    "dates":[2025.08.21, 2025.08.27, 2025.09.03, 2025.09.10, 2025.09.22, 2025.10.20, 2025.11.20, 
             2026.02.24,2026.05.20, 2026.08.20, 2027.02.22, 2027.08.20, 2028.08.21],
    "values":[4.3345, 4.3801, 4.3119, 4.3065, 4.2922, 4.2196, 4.1599, 
              4.0443, 4.0244, 3.9698, 3.7740, 3.6289, 3.5003] / 100.0
}

curveUsdUsdCnyFx = parseMktData(curve2)

curve3 = {
    "mktDataType": "Curve",
    "curveType": "IrYieldCurve",
    "curveName": "EUR_EURCNY_FX",
    "referenceDate": aod,
    "currency": "EUR",
    "dayCountConvention": "ActualActualISDA",
    "compounding": "Continuous",
    "interpMethod": "Linear",
    "extrapMethod": "Flat",
    "dates":[2025.08.21, 2025.08.27, 2025.09.03, 2025.09.10, 2025.09.22, 2025.10.20, 2025.11.20, 
             2026.02.24,2026.05.20, 2026.08.20, 2027.02.22, 2027.08.20, 2028.08.21],
    "values":[1.9165, 1.9672, 1.8576, 1.8709, 1.8867, 1.8749,1.8700,
              1.8576, 1.9253, 1.9738, 1.9908, 1.9850, 2.0362] / 100.0
}

curveEurEurCnyFx = parseMktData(curve3)

surf1 = {
	"surfaceName": "USDCNY",
	"mktDataType": "Surface",
	"surfaceType": "FxVolatilitySurface",
	"version": 0,
	"referenceDate": "2025.08.18",
	"smileMethod": "Linear",
	"termDates": [
		"2025.08.21",
		"2026.08.20"
	],
	"volSmiles":[{"strikes": [6.5,7,7.5],"vols": [0.1,0.1,0.1]},{"strikes": [6.5,7,7.5],"vols": [0.1,0.1,0.1]}],
	"currencyPair": "USDCNY"
}

surfUsdCny = parseMktData(surf1)


surf2 = {
	"surfaceName": "EURCNY",
	"mktDataType": "Surface",
	"surfaceType": "FxVolatilitySurface",
	"version": 0,
	"referenceDate": "2025.08.18",
	"smileMethod": "Linear",
	"termDates": [
		"2025.08.21",
		"2026.08.20"
	],
	"volSmiles":[{"strikes": [7.5,8.0,8.5],"vols": [0.1,0.1,0.1]},{"strikes": [7.5,8.0,8.5],"vols": [0.1,0.1,0.1]}],
	"currencyPair": "EURCNY"
}

surfEurCny = parseMktData(surf2)

bondCurve =  {
    "mktDataType": "Curve",
    "curveType": "IrYieldCurve",
    "referenceDate": aod,
    "currency": "CNY",
    "curveName": "CNY_TREASURY_BOND",
    "dayCountConvention": "ActualActualISDA",
    "compounding": "Compounded",
    "interpMethod": "Linear",
    "extrapMethod": "Flat",
    "frequency": "Annual",
    // 0.083 0.25 0.5 1.0 2.0 3.0 5.0 7.0 10.0 15.0 20.0 30.0 40.0 50.0
    "dates":[2025.09.18, 2025.11.18, 2026.02.18, 2026.08.18, 2027.08.18, 2028.08.18, 2030.08.18,
             2032.08.18, 2035.08.18, 2040.08.18, 2045.08.18, 2055.08.18,2065.08.18, 2075.08.18],
    "values":[1.3000, 1.3700, 1.3898, 1.3865, 1.4299, 1.4471, 1.6401,
              1.7654, 1.7966, 1.9930, 2.1834, 2.1397, 2.1987, 2.2225] / 100.0
}

curveCnyTreasuryBond = parseMktData(bondCurve)

fr007HistCurve = {
    "mktDataType": "Curve",
    "curveType": "AssetPriceCurve",
    "curveName": "PRICE_FR_007",
    "version": 0,
    "referenceDate": aod,
    "currency": "CNY",
    "dates":[2025.05.09, 2025.05.12, 2025.05.13, 2025.05.14, 2025.05.15, 2025.05.16, 2025.05.19, 2025.05.20, 2025.05.21, 2025.05.22,
             2025.05.23, 2025.05.26, 2025.05.27, 2025.05.28, 2025.05.29, 2025.05.30, 2025.06.03, 2025.06.04, 2025.06.05, 2025.06.06,
             2025.06.09, 2025.06.10, 2025.06.11, 2025.06.12, 2025.06.13, 2025.06.16, 2025.06.17, 2025.06.18, 2025.06.19, 2025.06.20,
             2025.06.23, 2025.06.24, 2025.06.25, 2025.06.26, 2025.06.27, 2025.06.30, 2025.07.01, 2025.07.02, 2025.07.03, 2025.07.04,
             2025.07.07, 2025.07.08, 2025.07.09, 2025.07.10, 2025.07.11, 2025.07.14, 2025.07.15, 2025.07.16, 2025.07.17, 2025.07.18,
             2025.07.21, 2025.07.22, 2025.07.23, 2025.07.24, 2025.07.25, 2025.07.28, 2025.07.29, 2025.07.30, 2025.07.31, 2025.08.01,
             2025.08.04, 2025.08.05, 2025.08.06, 2025.08.07, 2025.08.08, 2025.08.11, 2025.08.12, 2025.08.13, 2025.08.14, 2025.08.15
       ],
    "values":[1.6000, 1.5600, 1.5300, 1.5500, 1.5500, 1.6300, 1.6500, 1.6000, 1.5900, 1.5800, 
              1.6300, 1.7000, 1.7000, 1.7000, 1.7500, 1.7500, 1.5900, 1.5800, 1.5700, 1.5600, 
              1.5500, 1.5500, 1.5600, 1.5900, 1.5900, 1.5700, 1.5500, 1.5600, 1.5679, 1.6000, 
              1.5700, 1.8500, 1.8300, 1.8400, 1.8500, 1.9500, 1.6036, 1.5800, 1.5200, 1.5000, 
              1.5000, 1.5100, 1.5100, 1.5300, 1.5200, 1.5500, 1.6000, 1.5400, 1.5400, 1.5000, 
              1.5000, 1.4800, 1.5000, 1.6000, 1.7500, 1.6400, 1.6200, 1.6300, 1.6000, 1.5000, 
              1.4800, 1.4700, 1.4800, 1.4900, 1.4600, 1.4600, 1.4600, 1.4800, 1.4800, 1.4900  
               ]\100
}

priceCurveFr007 = parseMktData(fr007HistCurve)

instrument = [fxFwdUsdCny, fxFwdEurCny, fxSwapUsdCny, fxSwapEurCny, 
              fxOptionUsdCny, fxOptionEurCny, bond, bondFut, deposit, irs]
mktData= [fxSpotUsdCny, fxSpotEurCny, curveCnyFr007, 
          curveUsdUsdCnyFx, curveEurEurCnyFx, surfUsdCny, 
          surfEurCny, curveCnyTreasuryBond, priceCurveFr007]

pricingDate = aod

amount = [1, 2, 3, 4, 5, 6, -7, -8, 9, 10]

// case1: mktData is a vector
results1 = portfolioPricer(instrument, amount, pricingDate, mktData)
print(results1)

// case2: mktData is a dict
spots = dict(string, MKTDATA)
spots["USDCNY"] = fxSpotUsdCny
spots["EURCNY"] = fxSpotEurCny

curves = dict(string, MKTDATA)
curves["CNY_FR_007"] = curveCnyFr007
curves["USD_USDCNY_FX"] = curveUsdUsdCnyFx
curves["EUR_EURCNY_FX"] = curveEurEurCnyFx
curves["CNY_TREASURY_BOND"] = curveCnyTreasuryBond
curves["PRICE_FR_007"] = priceCurveFr007

surfs = dict(string, MKTDATA)
surfs["USDCNY"] = surfUsdCny
surfs["EURCNY"] = surfEurCny

dSpots = dict(DATE, ANY)
dSpots[aod] = spots

dCurves = dict(DATE, ANY)
dCurves[aod] = curves

dSurfs = dict(DATE, ANY)
dSurfs[aod] = surfs

mktData2 = dict(STRING, ANY)
mktData2 = {"Spot": dSpots,
            "Curve": dCurves,
            "Surface": dSurfs}

results2 = portfolioPricer(instrument, amount, pricingDate, mktData2)
print(results2)

Related function: instrumentPricer