Less is More: Opinionated Software

For the uninitiated, opinionated software is software that works the way its authors think it should work, instead of trying to please everybody. That means a lot of people will not like it, but the ones that do will love it.

I first came across this term after reading Getting Real from 37 Signals.They strongly advocate the development of opinionated software. Quoting from their guide:

Your app should take sides

Some people argue software should be agnostic. They say it's arrogant for developers to limit features or ignore feature requests. They say software should always be as flexible as possible.

We think that's bullshit. The best software has a vision. The best software takes sides. When someone uses software, they're not just looking for features, they're looking for an approach. They're looking for a vision. Decide what your vision is and run with it.

Sounds like another case of the "Paradox of Choice".

Bookmark and Share

The Brevity of Functional Languages

QuickSort is a well-known, efficient, sort algorithm. In previous posts I've discussed the runtime and space complexity of this algorithm, but there are some other factors that are rather important: brevity and clarity of code. Let's examine this by looking at the implementation of quicksort in C#, Java, C++ and F#.

Here is my version of quick sort in non-generic Java:

   1:      public static void quickSort(int[] input, int start, int finish)
   2:      {
   3:          if (finish-start < 2)
   4:              return;
   5:          
   6:          //pick a pivot
   7:          int pivotIndex = (finish+start)/2;
   8:          
   9:          //partition about the pivot
  10:          int i=start, j=finish;
  11:          while(i<=j)
  12:          {
  13:              while(input[i] < input[pivotIndex])
  14:                  i++;
  15:              
  16:              while(input[j] > input[pivotIndex])
  17:                  j--;
  18:              
  19:              if(i<=j)
  20:              {
  21:                  int temp = input[i];
  22:                  input[i]=input[j];
  23:                  input[j]=temp;
  24:                  i++;
  25:                  j--;
  26:              }
  27:          }
  28:          
  29:          if (start < i-1)
  30:              quickSort(input, start, i-1);
  31:          
  32:          if (i < finish)
  33:              quickSort(input, i, finish);        
  34:      }

And here it is in a generic C# flavour:

   1:          public static void QuickSort<T>(T[] input)
   2:                      where T : IComparable<T>
   3:          {
   4:              QuickSort(input, 0, input.Length - 1);
   5:          }
   6:   
   7:          public static void QuickSort<T>(T[] input, int start, int finish)
   8:              where T:IComparable<T>
   9:          {
  10:              if (finish - start < 2)
  11:                  return;
  12:   
  13:              //pick a pivot
  14:              int pivotIndex = (finish + start) / 2;
  15:   
  16:              //partition about the pivot
  17:              int i = start, j = finish;
  18:              while (i <= j)
  19:              {
  20:                  while (input[i].CompareTo(input[pivotIndex]) < 0)
  21:                      i++;
  22:   
  23:                  while (input[j].CompareTo(input[pivotIndex]) > 0)
  24:                      j--;
  25:   
  26:                  if (i <= j)
  27:                  {
  28:                      T temp = input[i];
  29:                      input[i] = input[j];
  30:                      input[j] = temp;
  31:                      i++;
  32:                      j--;
  33:                  }
  34:              }
  35:   
  36:              if (start < i - 1)
  37:                  QuickSort(input, start, i - 1);
  38:   
  39:              if (i < finish)
  40:                  QuickSort(input, i, finish);
  41:          }

Here's my C++ code :

   1:  void quickSort(int arr[], int left, int right) {
   2:        int i = left, j = right;
   3:        int tmp;
   4:        int pivot = arr[(left + right) / 2];
   5:   
   6:        /* partition */
   7:        while (i <= j) {
   8:              while (arr[i] < pivot)
   9:                    i++;
  10:              while (arr[j] > pivot)
  11:                    j--;
  12:              if (i <= j) {
  13:                    tmp = arr[i];
  14:                    arr[i] = arr[j];
  15:                    arr[j] = tmp;
  16:                    i++;
  17:                    j--;
  18:              }
  19:        };
  20:   
  21:        /* recursion */
  22:        if (left < j)
  23:              quickSort(arr, left, j);
  24:        if (i < right)
  25:              quickSort(arr, i, right);
  26:  }

Here's some Erlang code to do the same:

qsort([]) -> [];
qsort([Pivot|T]) ->
	qsort([X || X <- T, X =< Pivot])
	++ [Pivot] ++
	qsort([X || X <- T, X > Pivot]).

And finally, here's my F# code, that admittedly does it slightly differently in that it selects the first items as the pivot:

#light
open System
 
let rec quickSort ls =
  match ls with
  | [] -> []
  | p::r -> 
     quickSort [for i in r do if (compare i p) <= 0 then yield i] 
     @ [p] 
     @ quickSort [for i in r do if (compare i p) > 0 then yield i]          
 

I know I've mentioned it before on this site, but despite my deep admiration for C++ , Java and C# - they are all great languages - it's painfully clear that, with their advanced list comprehension syntax, functional languages are great at producing succinct code that is very easy to turn into highly parallelized code! With multi-core servers the norm these days these features of functional languages are extremely attractive.

Bookmark and Share

Stochastic Volatility Modelling

Understanding volatility is critical to many players in finance. Risk managers need to know the likelihood that their financial instruments are going to decline in value in the future, option traders need to know the volatility that can be expected over the life of the contract since it affects the chance of it being exercised, and marker makers need to understand the future volatility so the bid/ask spread can be set accordingly.

Known Behaviour
There have been many studies to examine volatility in financial markets and several common factors usually result:

  1. Volatility is mean reverting. In other words, regardless of the current volatility there is evidence to suggest that it will tend towards some long-term average value. If you think about it this makes sense. If the price/barrel of WTI fell to US$7 due to overproduction you would expect the price to eventually rise as producers decrease supply. These expectations are intuitive in nature and are supported by many empirical studies.

  2. Exogenous variables may affect volatility. For example, in FX the GBPUSD cross rate price and volatility will likely be affected by the release of macroeconomic data from either the UK or the States.

  3. Market events may have asymmetric impact on volatility. Specifically negative "shocks" such as major market corrections tend to have a greater impact on volatility than do optimistic announcements and market rallies.

Modelling
Modelling volatility can be done in many ways. The most simplistic is the assumption of constant volatility. Here you use historical volatility observed from data to provide your estimate of future volatility. Whilst simplistic and easy, this approach is not applicable to instruments that are heteroskedastic (have differing variance/volatility over time).

If you don't think historical volatility is a good predictor of future volatility in, say, an option or an instrument with embedded optionality like an interest rate cap used to hedge interest rate risk, you can look at the implied volatility of the option contract/instrument. That is the volatility that needs to be plugged into the Black-Scholes formula, or whatever pricing model you are using, such that the model yields a theoretical value for the option equal to the current market value.

As an aside...for portfolios of options that also contain their underlying assets it's possible to construct delta-neutral portfolios meaning that the portfolio as a whole is relatively insensitive to changes in the price of the underlying asset. Delta, of course, is the option value change relative to the change in the underlying asset. By executing a delta neutral position, one can profit from a change in volatility with no directional risk when the underlying stock moves insignificantly. This option trading strategy is extremely useful when implied volatility is expected to change drastically soon. But you got to have a forecast of volatility to make that call right? So let's get back on track regarding volatility models that you might consider...

Geometric Brownian Motion
Many financial models employ "random walks" (Geometric Brownian Motion) but clearly the Markov memoryless property of such are at odds with our mean reversion property. To address this, a GBM model with Mean Reversion can be used. The pure GBM-based models will obviously produce a much greater spread of values since each deviation is independent as the following 2 graphs show (source = Financial Engineering Associates):



Whilst the mean-reverting GBM model is a better fit to reality the downside is you now have to estimate a few more parameters: the long-run mean price and the rate at which prices revert to this value.

In fact, the famous Black-Scholes option pricing model assumes the underlying asset has constant volatility over the life of the contract. Clearly this assumption is egregious in many cases. The volatility smiles prevalent in implied volatility surfaces in FX are testament to this.

GARCH
An alternative to GBM is the Generalized Autoregressive Conditional Heteroskedasticity (GARCH) model. From what I've read, it seems the GARCH model continues to substantially outperform the Black-Scholes model even when the Black-Scholes model is updated every period while the parameters of the GARCH model are held constant. The improvement is due largely to the ability of the GARCH model to describe the correlation of volatility with spot returns. This allows the GARCH model to capture strike price biases in the Black-Scholes model that give rise to the skew in implied volatilities in the index options market.

As well, GARCH option pricing models have the inherent advantage that volatility is observable from discrete asset price data and only a few parameters need to be estimated even in a long time series of options records.

The details around GARCH models are varied and complex, so I'll defer that to a future post...

Bookmark and Share

« Prev - Next »