Parent: Object
OptionSynthetic is a static class with methods to obtain the calculated BarHistory of a synthetic option contract as well as OptionGreek calculations using the Black-Scholes model. An estimate of implied volatility is required as an input. The calculations are only truly representative of actual option pricing if the implied volatility is known.
OptionSynthetic is useful for devoloping strategies that trade options.
Calculates and returns a hypothetical price for the option contract symbol for the specified impliedVolatility assuming an underlyingPrice on the dateTime. If dateTime is on or after the contract expiration, the intrinsic value is returned.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using System.Collections.Generic; namespace WealthScript124 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) { double iv = 0.25; // estimate IV DateTime exDate = bars.NextOptionExpiryDate(bars.Count - 1); //atm call symbol for next monthly expiration string atmCall = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Call, bars.LastValue, bars.EndDate, 1); //find atm option atm contract value for a stock price 10% higher than current price 1 week before expiration. double stkprc = bars.LastValue * 1.1; double oprc = OptionSynthetic.CalculateOptionPrice(atmCall, iv, stkprc, exDate.AddDays(-7)); DrawHeaderText($"{atmCall} value on {exDate.AddDays(-7):yyyy-MM-dd}", WLColor.NeonGreen, 14); DrawHeaderText($"for {bars.Symbol} at {stkprc:N2} is {oprc:N2}", WLColor.NeonGreen, 14); } public override void Execute(BarHistory bars, int idx) { } } }
GetGreeks returns an OptionGreek object containing greeks calculated by the Black-Scholes model. Implied Volatility, iv, must be known or estimated for the values to accurate. The example uses a factor of Historic Volatility (HV) to estimate IV in a TimeSeries. Finally, the greeks are returned for the last bar.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript6 { public class OptionSyntheticGreeks : UserStrategyBase { public override void Initialize(BarHistory bars) { //estimate a varying IV using a factor of HV TimeSeries iv = HV.Series(bars.Close, 21, 5) / 10d; string symbol = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Call, bars.Close.LastValue, bars.DateTimes[bars.Count - 1], 3); _osyn = OptionSynthetic.GetHistory(bars, symbol, iv); PlotBarHistory(_osyn, "OSYN", WLColor.Cyan); // greeks at the last bar OptionGreek og = OptionSynthetic.GetGreeks(bars, bars.Count - 1, symbol, iv.LastValue); DrawHeaderText(og.Symbol + ": " + og.OptionPrice.ToString("$0.00"), WLColor.Cyan, 12, "OSYN"); DrawHeaderText("Delta: " + og.Delta.ToString("N2"), WLColor.Cyan, 12, "OSYN"); DrawHeaderText("Theta: " + og.Theta.ToString("N2"), WLColor.Cyan, 12, "OSYN"); DrawHeaderText("Gamma: " + og.Gamma.ToString("N2"), WLColor.Cyan, 12, "OSYN"); DrawHeaderText("Vega: " + og.Vega.ToString("N2"), WLColor.Cyan, 12, "OSYN"); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { } BarHistory _osyn; // the option's BarHistory } }
GetHistory returns a calculated BarHistory of a synthetic option contract using the Black Scholes model. The last parameter for iv, Implied Volatility, can be a constant or a TimeSeries for a varying iv. If using the optionSymbol overloads, the symbol must be in the format [underlier][yyMMdd][C/P][Strike] to be parsed correctly.
Remarks
OptionSynthetic.GetHistory
caches the BarHistory in the underlier's Bars.Cache using the option symbol as the key.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript6 { public class SyntheticOptionBars : UserStrategyBase { public override void Initialize(BarHistory bars) { // get the symbol for the Put with the closest strike to the last chart value string symbol = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Put, bars.Close.LastValue, bars.DateTimes[bars.Count - 1], 3); // get the synthetic history and plot it _osyn = OptionSynthetic.GetHistory(bars, symbol, 0.2); PlotBarHistory(_osyn, "OSYN", WLColor.LightCyan); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { } BarHistory _osyn; // the option's BarHistory } }
GetOptionsSymbol method to facilitate identifying a contract. Since synthetic options work without an option chain, strike prices are returned in $5 increments per the specified parameters.
Pass OptionType.Call
or OptionType.Put
for the optionType* parameter.
The price parameter should be near the desired strike. For an ATM (at-the-money) call, simply use the current closing price. For example, if price is 73.35, assuming $5 strike increments the $75 strike is returned for both call and put options if closestStrike is true. If closestStrike is false, the next strike lower than price is returned for a Put ($70) and the next higher strike for a Call ($75). Pass true for priceIsStrike to use the price value as the strike price without modification.
Option expiration is identified using a combination of the currentDate, minDaysAhead, useWeeklies, and allowExpired parameters. Specifically, the next expiration at least minDaysAhead after the currentDate is returned. If useWeeklies is false, only regular monthly expirations are considered, otherwise only the non-monthly expirations.
When backtesting synthetic options, specify true for allowExpired so that contracts with historical (past) expiration dates are identified.
Remarks
- This method uses the same parameters as the DataProvider's GetOptionsSymbol, excluding the optional multiplier parameter.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript5 { public class SyntheticOptionSymbol : UserStrategyBase { public override void Initialize(BarHistory bars) { double price = bars.Close[bars.Count - 1]; DateTime currentDate = bars.DateTimes[bars.Count - 1]; int minDaysToExpiry = 0; bool weeklies = false; bool closestStrike = true; bool allowExpired = true; string optSym = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Call, price, currentDate, minDaysToExpiry, weeklies, allowExpired, closestStrike); DrawHeaderText("ATM Call: " + optSym, WLColor.NeonGreen, 14); } public override void Execute(BarHistory bars, int idx) { } } }
Parses optionSymbol to return the expiration date as a DateTime.
Remarks
- Obsolete - Use
OptionsHelper.SymbolExpiry()
.
Parses optionSymbol to return the strike as a double value.
Remarks
- Obsolete - Use
OptionsHelper.SymbolStrike()
.
Symbol returns a synthetic option symbol, which by convention starts with "!" and has the format ![underlier symbol]yyMMdd[C/P][strike].
This Symbol()
function lets you specify each parameter exactly, whereas GetOptionsSymbol()
will always return a strike divisible by $5 and search for actual option expirations based on other parameters.
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript6 { public class SyntheticOptionSymbol : UserStrategyBase { public override void Initialize(BarHistory bars) { //a $5 strike double strike = Math.Floor(bars.LastValue / 5) * 5; DateTime expiry = bars.DateTimes[bars.Count - 1].AddDays(3).NextOptionExpiryDate(bars); string symbol = OptionSynthetic.Symbol(bars, OptionType.Call, strike, expiry); //show the symbol DrawHeaderText(symbol, WLColor.Gold, 12, "Price"); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { } } }