Search Framework:
OptionSynthetic
Namespace: WealthLab.Backtest
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.

Backtest Related
CalculateOptionPrice
public static double CalculateOptionPrice(string optionSymbol, double impliedVolatility, double underlyingPrice, DateTime dateTime)

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.

Example Code
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
public static OptionGreek GetGreeks(BarHistory underlier, int bar, OptionType optionType, double strike, DateTime expiration, double iv = 0.2)
public static OptionGreek GetGreeks(BarHistory underlier, int bar, string optionSymbol, double iv = 0.2)

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.

Example Code
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
public static BarHistory GetHistory(BarHistory underlier, OptionType optionType, double strike, DateTime expiration, double iv = 0.2)
public static BarHistory GetHistory(BarHistory underlier, OptionType optionType, double strike, DateTime expiration, TimeSeries iv)
public static BarHistory GetHistory(BarHistory underlier, string optionSymbol, double iv = 0.2)
public static BarHistory GetHistory(BarHistory underlier, string optionSymbol, TimeSeries iv)

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.
Example Code
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
public static string GetOptionsSymbol(BarHistory underlierBars, OptionType optionType, double price, DateTime currentDate, int minDaysAhead = 0, bool useWeeklies = false, bool allowExpired = false, bool closestStrike = true, bool priceIsStrike = false)

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.
Example Code
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)
        { }
		
    }
}

GetSymbolExpiry
public static DateTime GetSymbolExpiry(string optionSymbol)

Parses optionSymbol to return the expiration date as a DateTime.

Remarks

  • Obsolete - Use OptionsHelper.SymbolExpiry().

GetSymbolStrike
public static double GetSymbolStrike(string optionSymbol)

Parses optionSymbol to return the strike as a double value.

Remarks

  • Obsolete - Use OptionsHelper.SymbolStrike().

Symbol
public static string Symbol(BarHistory underlier, OptionType optionType, double strike, DateTime expiration)

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.

Example Code
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)
		{ }
	}
}