3

I'm dealing with a modeling system (financial) that has dozens of variables. Some of the variables are independent, and function as inputs to the system; most of them are calculated from other variables (independent and calculated) in the system.

What I'm looking for is a clean, elegant way to:

  1. define the function of each dependent variable in the system
  2. trigger a re-calculation, whenever a variable changes, of the variables that depend on it

A naive way to do this would be to write a single class that implements INotifyPropertyChanged, and uses a massive case statement that lists out all the variable names x1, x2, ... xn on which others depend, and, whenever a variable xi changes, triggers a recalculation of each of that variable's dependencies.

I feel that this naive approach is flawed, and that there must be a cleaner way. I started down the path of defining a CalculationManager<TModel> class, which would be used (in a simple example) something like as follows:

public class Model : INotifyPropertyChanged
{
    private CalculationManager<Model> _calculationManager = new CalculationManager<Model>(); 

    // each setter triggers a "PropertyChanged" event
    public double? Height { get; set; }
    public double? Weight { get; set; }
    public double? BMI { get; set; }

    public Model()
    {
        _calculationManager.DefineDependency<double?>(
            forProperty: model => model.BMI,
            usingCalculation: (height, weight) => weight / Math.Pow(height, 2),
            withInputs: model => model.Height, model.Weight);
    }

    // INotifyPropertyChanged implementation here
}

I won't reproduce CalculationManager<TModel> here, but the basic idea is that it sets up a dependency map, listens for PropertyChanged events, and updates dependent properties as needed. I still feel that I'm missing something major here, and that this isn't the right approach:

  1. the (mis)use of INotifyPropertyChanged seems to me like a code smell
  2. the withInputs parameter is defined as params Expression<Func<TModel, T>>[] args, which means that the argument list of usingCalculation is not checked at compile time
  3. the argument list (weight, height) is redundantly defined in both usingCalculation and withInputs

I am sure that this kind of system of dependent variables must be common in computational mathematics, physics, finance, and other fields. Does someone know of an established set of ideas that deal with what I'm grasping at here? Would this be a suitable application for a functional language like F#?


Edit

More context:

The model currently exists in an Excel spreadsheet, and is being migrated to a C# application. It is run on-demand, and the variables can be modified by the user from the application's UI. Its purpose is to retrieve variables that the business is interested in, given current inputs from the markets, and model parameters set by the business.

6
  • CalculationManager seems like a good way to do what you're trying to do, but... Are the calculations so intensive that it's worth the overhead of managing this dependency map? How often are the dependent variables going to be updated? Can you give us some idea what financial objects you're modeling?
    – axblount
    Oct 26, 2012 at 18:25
  • @axblount I suppose it's probably not worth the overhead -- the calculations are not intensive. But I'm more concerned about maintainability and DRY here -- performance isn't my primary concern, as this is a report that will only be run daily.
    – McGarnagle
    Oct 26, 2012 at 18:30
  • @axblount as far as the financial model, it's a kind of fund management model that tracks various business metrics.
    – McGarnagle
    Oct 26, 2012 at 18:32
  • I still think context is important here. Will this model be persisted? You are saying this model will be run once a day, yet you say variables change. Can you please explain in more detail where, how and why this model exists?
    – Euphoric
    Oct 26, 2012 at 18:46
  • 1
    You could just set a global dirty flag for each dependent variable (like dirty_BMI) whenever a variable it depends on is changed. Then the next time it's requested you can recalculate it if the dirty flag is set and reset the flag. This would also avoid recalculating the variable multiple times even if it hasn't been used. Honestly, I don't think there's anything easier to maintain than public double? BMI { get { return Weight / Math.Pow(Height, 2) } }
    – axblount
    Oct 26, 2012 at 18:52

2 Answers 2

2

Assuming you can model the dependencies as a directed acyclic graph, you can then use a Topological Sort to order them. My understanding is that spreadsheets use this idea.

Seems like F# would be a good fit.

1
  • Thanks, I think this is the answer to what I asked for -- a formal structure for a system of dependencies.
    – McGarnagle
    Oct 26, 2012 at 21:15
1

A cleaner way (depending on your usage pattern) is to not store the value of BMI. Just have a getter that looks at its dependencies and calculates the result when accessed. This is much better if the inputs are changed much more than the outputs are read.

That still leaves you with updating the UI when the state of a property (and/or its dependencies) changes. For some UIs a full refresh will be fine since almost everything is changing anyways. If not, then you're likely building your own graph (hopefully via reflection or attribute marking) and firing change events (hopefully not by hand) to the UI. I've done this for a similar setup and it actually works really well, though not in a high-change environment like financial modelling.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.