using System.Collections.Generic;
public class ExerciseRequest {
public AwardExerciseConfig ExerciseConfig { get; set; }
public AwardShareClass ShareClass { get; set; }
public class AwardShareClass {
public string Name { get; set; }
public decimal? ParValue { get; set; }
public class AwardExerciseConfig {
public string? MinExercisePrice { get; set; }
public string? MaxExercisePrice { get; set; }
public string? MinExerciseAmount { get; set; }
public string? MaxExerciseAmount { get; set; }
public decimal ConversionRatio { get; set; }
public record Computations {
public IReadOnlyList<AwardComputations> Awards { get; init; }
public record AwardComputations {
public PriceRange ExercisePrice { get; init; }
public PriceRange ExerciseAmount { get; init; }
public string ShareClass { get; init; }
public decimal? SharesToIssue { get; init; }
public decimal? SharesParValueAmount { get; init; }
public record PriceRange(decimal? Min, decimal? Max){
public bool IsInRange(decimal value) {
public override string ToString(){
return $"[{Min}, {Max}]";
public DateOnly Date { get; set; }
public List<Award> Awards { get; set; }
public Computations GetComputations(){
var awardComputations = Awards.Select(GetAwardComputations).ToArray();
Awards = awardComputations
private AwardComputations GetAwardComputations(Award award){
ArgumentNullException.ThrowIfNull(award);
decimal? minExercisePrice = Evaluate(award, award.ExerciseConfig.MinExercisePrice);
decimal? maxExercisePrice = Evaluate(award, award.ExerciseConfig.MaxExercisePrice);
PriceRange exercisePriceRange = new PriceRange(minExercisePrice, maxExercisePrice);
decimal? minExerciseAmount = Evaluate(award, award.ExerciseConfig.MinExerciseAmount);
decimal? maxExerciseAmount = Evaluate(award, award.ExerciseConfig.MaxExerciseAmount);
PriceRange exerciseAmountRange = new PriceRange(minExerciseAmount, maxExerciseAmount);
return new AwardComputations {
ExercisePrice = exercisePriceRange,
ExerciseAmount = exerciseAmountRange
private decimal? Evaluate(Award? award, string formula){
decimal? result = default;
if(string.IsNullOrWhiteSpace(formula)){
var expression = new Expression(formula);
ConfigureParameters(award, expression);
var evaluationResult = expression.Evaluate();
result = Convert.ToDecimal(evaluationResult);
private void ConfigureParameters(Award? award, Expression expression){
expression.Parameters["ShareClass.ParValue"] = award?.ShareClass.ParValue;
expression.Parameters["ConversionRatio"] = award?.ExerciseConfig.ConversionRatio;
public static void Main()
var request1 = new ExerciseRequest {
Date = new DateOnly(2024, 08, 15),
new ExerciseRequest.Award {
ShareClass = new ExerciseRequest.AwardShareClass{
ExerciseConfig = new ExerciseRequest.AwardExerciseConfig {
MinExercisePrice = "[ShareClass.ParValue] * [ConversionRatio]"
ProcessRequest(request1);
private static void ProcessRequest(ExerciseRequest request){
ArgumentNullException.ThrowIfNull(request);
var requestComputations = request.GetComputations();
foreach(var award in requestComputations.Awards){
Console.WriteLine("ExercisePrice=" + award.ExercisePrice);
Console.WriteLine("ExerciseAmount=" + award.ExerciseAmount);