Skip to main content

Script Engine

MesoSim uses Lua expressions to select contracts, filter trades, size positions, and define adjustment and exit rules. Expressions return a number for quantities and thresholds, or a boolean for conditions.

This page covers the language and the values available to expressions. The Strategy Definition Reference explains which fields accept expressions and when they run. Names, dates, and enum settings remain literal values.

Write and validate expressions in the AI Job Editor, or work with AI Agents. For full strategies with analysis, visit the Deltaray blog.

Write an expression​

Enter the expression directly in the relevant Strategy Definition field. For example:

FieldExpressionPurpose
Entry.Conditions[]underlying_price < underlying_today_openAllow an entry on a down day
Entry.AbortConditions[]pos_theta < 20Reject a selected structure with insufficient Theta
Entry.VarDefines.initial_thetapos_thetaCapture Theta at entry
Exit.Conditions[]pos_theta < initial_theta * 0.25Exit when Theta falls below 25% of the captured value

The exit example assumes initial_theta was defined at entry as shown. Use the exact field and variable names, including capitalization. See Filter entries by Implied Volatility and Set quantities dynamically for more examples.

  • Comparisons use <, <=, >, >=, ==, and ~= (not equal).
  • Combine requirements with and, alternatives with or, and negate a condition with not.
  • Use parentheses to make grouping explicit, such as (a or b) and c.
  • Call functions with parentheses, such as abs(pos_delta).
Combine conditions deliberately

Separate items in Entry.Conditions are OR alternatives. To require several criteria at once, combine them with and in one expression. See Entry conditions.

For language syntax, see the official Lua reference. MesoSim exposes the functions and modules described below.

Operations​

Common arithmetic and logical operators for expressions.

OperatorCategoryDescription
+ArithmeticAddition
-ArithmeticSubtraction
*ArithmeticMultiplication
/ArithmeticFloat division
//ArithmeticFloor division
%ArithmeticModulo
^ArithmeticExponentiation
- (unary)ArithmeticUnary minus
andLogicalReturns the first operand if it is false or nil; otherwise returns the second
orLogicalReturns the first operand unless it is false or nil; otherwise returns the second
notLogicalNegates input (true → false, false → true)

In Lua logical expressions, only nil and false are false; even 0 is truthy. MesoSim converts a final numeric condition result of zero to false. Use explicit comparisons such as my_signal == 1 when combining numeric signals with and or or.

Built-in Functions​

Call these functions directly, for example abs(pos_delta) or min(leg_short_put_delta, 10). Replace short_put with a leg name in your strategy.

SignatureDescription
abs(x) -> numberAbsolute value
min(a, b, ...) -> numberMinimum of arguments
max(a, b, ...) -> numberMaximum of arguments
floor(x) -> numberLargest integer ≤ x
ceil(x) -> numberSmallest integer ≥ x
sqrt(x) -> numberSquare root
log(x[, base]) -> numberNatural logarithm by default; specify a base for another logarithm
exp(x) -> numbere raised to x
random() -> numberRandom number from 0 inclusive to 1 exclusive
random(n) -> integerRandom integer from 1 through positive integer n
random(m, n) -> integerRandom integer from m through n, including both bounds
int(x) -> integerTruncate toward zero: int(2.8) is 2 and int(-2.8) is −2

The constant pi is also available. Use ^ for powers, such as 2 ^ 3. For a base-10 logarithm, log(100, 10) returns 2. See Add randomness to entries for a trading example using random().

Variables​

Variable availability depends on the expression field and execution stage. Where a name contains placeholders, replace them with your own names (e.g., leg_<name>_delta).

Variable availability​

Expression stageAvailable values
Before selection: Entry.Conditions, ReentryDays, and ConcurrencyAccount, underlying, calendar/session timing, and loaded external-data values; selected legs, expirations, and position Greeks are not available yet
Expiration and leg selectionValues introduced by earlier selections, in definition order
Sizing and entry checksSelected-leg and position values; Entry.QtyMultiplier runs before Entry.VarDefines, then abort conditions can use the defined variables
Adjustment and exitCurrent position values and custom variables that have already been defined

Entry.VarDefines evaluates definitions in order before abort checks and again after entry fills. Entry.QtyMultiplier is evaluated again when an adjustment adds legs. See QtyMultiplier and Variable update timing for the detailed sequence.

Variables introduced by a conditional adjustment are available only after that adjustment runs. For example, if an adjustment defines adjusted_delta, an exit condition can check it safely with:

adjusted_delta ~= nil and abs(adjusted_delta) > 10

Choose custom names such as initial_delta and initial_theta; avoid simulator variables, module names, and reserved keywords. Use Entry.VarDefines to capture values needed later, and Events export for guidance on recording them for analysis.

Settings expressions have their own context. For example, order-based slippage uses order.leg_spread, rather than general strategy variables.

Expiration​

Variables related to expiration selection. Replace EXPNAME with the expiration alias, such as front.

NameDescription
expiration_EXPNAME_dteDays to expiration for alias EXPNAME (auto‑updated)
expiration_EXPNAME_minMinimum DTE constraint for EXPNAME; available only during selection
expiration_EXPNAME_maxMaximum DTE constraint for EXPNAME; available only during selection

Leg​

Quotes, Greeks, and properties for legs defined in the structure and adjustments. Replace LEGNAME with the leg name, such as short_put.

NameDescription
leg_LEGNAME_priceCurrent price used to value closing the leg, according to the fill model
leg_LEGNAME_bidCurrent bid price
leg_LEGNAME_askCurrent ask price
leg_LEGNAME_qtySigned quantity: negative for short legs, positive for long legs, 0 for marker legs
leg_LEGNAME_countNumber of legs represented by this name in the current evaluation context
leg_LEGNAME_ivImplied Volatility in percent; 20 means 20%
leg_LEGNAME_deltaLeg delta (qty‑scaled; per‑1‑unit for marker legs)
leg_LEGNAME_gammaLeg gamma (qty‑scaled; per‑1‑unit for marker legs)
leg_LEGNAME_thetaLeg theta (qty‑scaled; per‑1‑unit for marker legs)
leg_LEGNAME_vegaLeg vega (qty‑scaled; per‑1‑unit for marker legs)
leg_LEGNAME_wvegaDTE-weighted vega (quantity-scaled; per contract for marker legs)
leg_LEGNAME_rhoLeg rho (qty‑scaled; per‑1‑unit for marker legs)
leg_LEGNAME_ditDays in trade for this leg since creation (decimal days)
leg_LEGNAME_dteDays to expiration for this leg (decimal days)
leg_LEGNAME_strikeStrike price for the option contract
leg_LEGNAME_pnlPnL for the current leg

Leg Greeks include quantity and direction. Marker Legs expose per-contract Greeks despite having zero quantity; they contribute zero to position Greeks. If one name represents multiple legs, quantity and Greeks are aggregated, while single-contract values such as price and strike are unavailable.

Position​

Position Greeks, PnL, and exit thresholds are commonly used in exit conditions and conditional adjustments.

NameDescription
profit_targetProfit target initialized at entry, when configured
stop_lossStop loss initialized at entry, when configured
max_days_in_tradeMaximum days-in-trade threshold initialized at entry, when configured
pos_pnlTotal position PnL (open + realized)
pos_realized_pnlCumulative realized PnL for the position
pos_deltaSum of leg deltas (qty‑scaled)
pos_gammaSum of leg gammas (qty‑scaled)
pos_thetaSum of leg thetas (qty‑scaled)
pos_vegaSum of leg vegas (qty‑scaled)
pos_wvegaPosition weighted vega (DTE‑weighted)
pos_rhoSum of leg rhos (qty‑scaled)
pos_marginEstimated position margin using the configured Reg-T or PM-like model, when enabled
open_legs_cntNumber of currently open legs in the position

Account​

Account-level balances and counts useful for sizing, gating, and concurrency; often applied in Entry sizing (QtyMultiplier) and concurrency

NameDescription
navNet Asset Value of the account
initial_cashInitial cash configured for the backtest run
pos_in_flightNumber of currently open positions

Underlying​

Current underlying price and volatility measures available throughout the run; often used in Entry and Adjustment conditions. See also: Implied and Historical Volatility.

NameDescription
underlying_priceCurrent underlying price
underlying_today_openSession-opening reference price from the selected market-data resolution (if available)
underlying_prevday_closePrevious trading day’s closing price (if available)
underlying_ivUnderlying Implied Volatility (percent)
underlying_iv_rankIV rank (0–100) at current Implied Volatility
underlying_iv_pctIV percentile (0–100) versus lookback window
underlying_hvUnderlying historical volatility (percent)

External Data Variables​

Load a CSV through ExternalData.CsvUrl to use its numeric columns as named variables. Each value becomes available according to the CSV timestamp. See Use External Data for preparation, publishing, and availability rules.

The AI Job Editor lists the loaded variables under External Data. To explore how a captured entry variable relates to final position PnL, see Analytics with DataVoyager.

Modules​

The Timing and Options Valuation modules provide calendar calculations and scenario analysis. The Slippage settings describe the separate order context.

Timing​

Timing functions help you count trading or calendar days relative to key anchors (weeks, months, option expirations, and other events) to build rules like “enter only in the first N trading days of the month.”

Read current timing values as properties: timing.day_of_week, timing.year, timing.month, timing.day, timing.minutes_after_open, timing.minutes_before_close, and timing.days_in_trade. For example, an exit condition can use:

timing.days_in_trade >= 5

timing.days_in_trade requires an open position and can be fractional. Property access has no parentheses; calendar calculations below are function calls. See Timing for anchors and boundaries.

Available Functions:

SignatureDescription
timing.trading_days_until(anchor, [boundary]) -> decimalTrading days from now until the selected anchor boundary
timing.trading_days_after(anchor, [boundary]) -> decimalTrading days elapsed since the selected anchor boundary, including fractional sessions
timing.calendar_days_until(anchor, [boundary]) -> decimalCalendar days from now until the selected anchor boundary
timing.calendar_days_after(anchor, [boundary]) -> decimalCalendar days elapsed since the selected anchor boundary, including fractional days
timing.trading_days_in(anchorA, [anchorB], [a_boundary], [b_boundary]) -> decimalTrading‑day count within a window
timing.calendar_days_in(anchorA, [anchorB], [a_boundary], [b_boundary]) -> decimalCalendar‑day count within a window

For period anchors, boundary defaults to first. Both *_days_after functions return 0 until the selected boundary is reached; both *_days_until functions return 0 once it is reached.

For example, timing.trading_days_until(monthly_opex) counts trading days until the monthly options expiration. See Timing for more examples.

Options Valuation​

Project Greeks and PnL at a time anchor or a number of days from now, or scan an underlying-price range to find a target value or an extremum. Useful for gating entries, shaping adjustments, or early exits based on how the Risk Graph changes.

See Options Valuation Model for parameter definitions, supported metrics, and examples.

Available Functions:

SignatureDescription
options.model(target, dteDaysOrAnchor, underlyingPrice, metric[, model_params]) -> number or nilEvaluate position/leg at a time anchor or a number of days from now using a scenario underlying price and return the selected metric
options.model_solver(target, dteOrKey, start, end, metric, goal, result[, solver_params]) -> number or nilScan a price range to minimize/maximize/zero a metric and return value or price per result

Check an expression​

  1. Validate in the editor. Check spelling, capitalization, parentheses, and the expected result type.
  2. Check variable availability. A valid name may still be unavailable at the field’s execution stage. Use Entry.AbortConditions for filters that need selected legs, and guard values introduced by conditional adjustments.
  3. Inspect a focused backtest. Use the Events Viewer to inspect selected legs, entry and exit signals, and captured values. Change one rule at a time using Clone.

For assistance writing an expression, see AI Assistant. For full strategies with analysis, visit the Deltaray blog.